1#!/usr/bin/env python3 2 3 4import os 5import os.path 6import re 7import sys 8import time 9import json 10import random 11from subprocess import check_call, call, check_output, Popen, PIPE, CalledProcessError 12 13if (len(sys.argv) == 7): 14 target_ip = sys.argv[2] 15 initiator_ip = sys.argv[3] 16 port = sys.argv[4] 17 netmask = sys.argv[5] 18 namespace = sys.argv[6] 19 20ns_cmd = 'ip netns exec ' + namespace 21other_ip = '127.0.0.6' 22initiator_name = 'ANY' 23portal_tag = '1' 24initiator_tag = '1' 25 26rpc_param = { 27 'target_ip': target_ip, 28 'initiator_ip': initiator_ip, 29 'port': port, 30 'initiator_name': initiator_name, 31 'netmask': netmask, 32 'lun_total': 3, 33 'malloc_bdev_size': 64, 34 'malloc_block_size': 512, 35 'queue_depth': 64, 36 'target_name': 'Target3', 37 'alias_name': 'Target3_alias', 38 'disable_chap': True, 39 'mutual_chap': False, 40 'require_chap': False, 41 'chap_group': 0, 42 'header_digest': False, 43 'data_digest': False, 44 'log_flag': 'rpc', 45 'cpumask': 0x1 46} 47 48 49class RpcException(Exception): 50 51 def __init__(self, retval, msg): 52 super(RpcException, self).__init__(msg) 53 self.retval = retval 54 self.message = msg 55 56 57class spdk_rpc(object): 58 59 def __init__(self, rpc_py): 60 self.rpc_py = rpc_py 61 62 def __getattr__(self, name): 63 def call(*args): 64 cmd = "{} {}".format(self.rpc_py, name) 65 for arg in args: 66 cmd += " {}".format(arg) 67 return check_output(cmd, shell=True).decode("utf-8") 68 return call 69 70 71def verify(expr, retcode, msg): 72 if not expr: 73 raise RpcException(retcode, msg) 74 75 76def verify_log_flag_rpc_methods(rpc_py, rpc_param): 77 rpc = spdk_rpc(rpc_py) 78 output = rpc.log_get_flags() 79 jsonvalue = json.loads(output) 80 verify(not jsonvalue[rpc_param['log_flag']], 1, 81 "log_get_flags returned {}, expected false".format(jsonvalue)) 82 rpc.log_set_flag(rpc_param['log_flag']) 83 output = rpc.log_get_flags() 84 jsonvalue = json.loads(output) 85 verify(jsonvalue[rpc_param['log_flag']], 1, 86 "log_get_flags returned {}, expected true".format(jsonvalue)) 87 rpc.log_clear_flag(rpc_param['log_flag']) 88 output = rpc.log_get_flags() 89 jsonvalue = json.loads(output) 90 verify(not jsonvalue[rpc_param['log_flag']], 1, 91 "log_get_flags returned {}, expected false".format(jsonvalue)) 92 93 print("verify_log_flag_rpc_methods passed") 94 95 96def verify_iscsi_connection_rpc_methods(rpc_py): 97 rpc = spdk_rpc(rpc_py) 98 output = rpc.iscsi_get_connections() 99 jsonvalue = json.loads(output) 100 verify(not jsonvalue, 1, 101 "iscsi_get_connections returned {}, expected empty".format(jsonvalue)) 102 103 rpc.bdev_malloc_create(rpc_param['malloc_bdev_size'], rpc_param['malloc_block_size']) 104 rpc.iscsi_create_portal_group(portal_tag, "{}:{}".format(rpc_param['target_ip'], str(rpc_param['port']))) 105 rpc.iscsi_create_initiator_group(initiator_tag, rpc_param['initiator_name'], rpc_param['netmask']) 106 107 lun_mapping = "Malloc" + str(rpc_param['lun_total']) + ":0" 108 net_mapping = portal_tag + ":" + initiator_tag 109 rpc.iscsi_create_target_node(rpc_param['target_name'], rpc_param['alias_name'], lun_mapping, 110 net_mapping, rpc_param['queue_depth'], '-d') 111 check_output('iscsiadm -m discovery -t st -p {}'.format(rpc_param['target_ip']), shell=True) 112 check_output('iscsiadm -m node --login', shell=True) 113 name = json.loads(rpc.iscsi_get_target_nodes())[0]['name'] 114 output = rpc.iscsi_get_connections() 115 jsonvalues = json.loads(output) 116 verify(jsonvalues[0]['target_node_name'] == rpc_param['target_name'], 1, 117 "target node name vaule is {}, expected {}".format(jsonvalues[0]['target_node_name'], rpc_param['target_name'])) 118 verify(jsonvalues[0]['initiator_addr'] == rpc_param['initiator_ip'], 1, 119 "initiator address values is {}, expected {}".format(jsonvalues[0]['initiator_addr'], rpc_param['initiator_ip'])) 120 verify(jsonvalues[0]['target_addr'] == rpc_param['target_ip'], 1, 121 "target address values is {}, expected {}".format(jsonvalues[0]['target_addr'], rpc_param['target_ip'])) 122 123 check_output('iscsiadm -m node --logout', shell=True) 124 check_output('iscsiadm -m node -o delete', shell=True) 125 rpc.iscsi_delete_initiator_group(initiator_tag) 126 rpc.iscsi_delete_portal_group(portal_tag) 127 rpc.iscsi_delete_target_node(name) 128 output = rpc.iscsi_get_connections() 129 jsonvalues = json.loads(output) 130 verify(not jsonvalues, 1, 131 "iscsi_get_connections returned {}, expected empty".format(jsonvalues)) 132 133 print("verify_iscsi_connection_rpc_methods passed") 134 135 136def verify_scsi_devices_rpc_methods(rpc_py): 137 rpc = spdk_rpc(rpc_py) 138 output = rpc.scsi_get_devices() 139 jsonvalue = json.loads(output) 140 verify(not jsonvalue, 1, 141 "scsi_get_devices returned {}, expected empty".format(jsonvalue)) 142 143 rpc.bdev_malloc_create(rpc_param['malloc_bdev_size'], rpc_param['malloc_block_size']) 144 rpc.iscsi_create_portal_group(portal_tag, "{}:{}".format(rpc_param['target_ip'], str(rpc_param['port']))) 145 rpc.iscsi_create_initiator_group(initiator_tag, rpc_param['initiator_name'], rpc_param['netmask']) 146 147 lun_mapping = "Malloc" + str(rpc_param['lun_total']) + ":0" 148 net_mapping = portal_tag + ":" + initiator_tag 149 rpc.iscsi_create_target_node(rpc_param['target_name'], rpc_param['alias_name'], lun_mapping, 150 net_mapping, rpc_param['queue_depth'], '-d') 151 check_output('iscsiadm -m discovery -t st -p {}'.format(rpc_param['target_ip']), shell=True) 152 check_output('iscsiadm -m node --login', shell=True) 153 name = json.loads(rpc.iscsi_get_target_nodes())[0]['name'] 154 output = rpc.iscsi_get_options() 155 jsonvalues = json.loads(output) 156 nodebase = jsonvalues['node_base'] 157 output = rpc.scsi_get_devices() 158 jsonvalues = json.loads(output) 159 verify(jsonvalues[0]['device_name'] == nodebase + ":" + rpc_param['target_name'], 1, 160 "device name vaule is {}, expected {}".format(jsonvalues[0]['device_name'], rpc_param['target_name'])) 161 verify(jsonvalues[0]['id'] == 0, 1, 162 "device id value is {}, expected 0".format(jsonvalues[0]['id'])) 163 164 check_output('iscsiadm -m node --logout', shell=True) 165 check_output('iscsiadm -m node -o delete', shell=True) 166 rpc.iscsi_delete_initiator_group(initiator_tag) 167 rpc.iscsi_delete_portal_group(portal_tag) 168 rpc.iscsi_delete_target_node(name) 169 output = rpc.scsi_get_devices() 170 jsonvalues = json.loads(output) 171 verify(not jsonvalues, 1, 172 "scsi_get_devices returned {}, expected empty".format(jsonvalues)) 173 174 print("verify_scsi_devices_rpc_methods passed") 175 176 177def create_malloc_bdevs_rpc_methods(rpc_py, rpc_param): 178 rpc = spdk_rpc(rpc_py) 179 180 for i in range(1, rpc_param['lun_total'] + 1): 181 rpc.bdev_malloc_create(rpc_param['malloc_bdev_size'], rpc_param['malloc_block_size']) 182 183 print("create_malloc_bdevs_rpc_methods passed") 184 185 186def verify_portal_groups_rpc_methods(rpc_py, rpc_param): 187 rpc = spdk_rpc(rpc_py) 188 output = rpc.iscsi_get_portal_groups() 189 jsonvalues = json.loads(output) 190 verify(not jsonvalues, 1, 191 "iscsi_get_portal_groups returned {} groups, expected empty".format(jsonvalues)) 192 193 lo_ip = (target_ip, other_ip) 194 for idx, value in enumerate(lo_ip): 195 # The portal group tag must start at 1 196 tag = idx + 1 197 rpc.iscsi_create_portal_group(tag, "{}:{}".format(value, rpc_param['port'])) 198 output = rpc.iscsi_get_portal_groups() 199 jsonvalues = json.loads(output) 200 verify(len(jsonvalues) == tag, 1, 201 "iscsi_get_portal_groups returned {} groups, expected {}".format(len(jsonvalues), tag)) 202 203 tag_list = [] 204 for idx, value in enumerate(jsonvalues): 205 verify(value['portals'][0]['host'] == lo_ip[idx], 1, 206 "host value is {}, expected {}".format(value['portals'][0]['host'], rpc_param['target_ip'])) 207 verify(value['portals'][0]['port'] == str(rpc_param['port']), 1, 208 "port value is {}, expected {}".format(value['portals'][0]['port'], str(rpc_param['port']))) 209 tag_list.append(value['tag']) 210 verify(value['tag'] == idx + 1, 1, 211 "tag value is {}, expected {}".format(value['tag'], idx + 1)) 212 213 for idx, value in enumerate(tag_list): 214 rpc.iscsi_delete_portal_group(value) 215 output = rpc.iscsi_get_portal_groups() 216 jsonvalues = json.loads(output) 217 verify(len(jsonvalues) == (len(tag_list) - (idx + 1)), 1, 218 "get_portal_group returned {} groups, expected {}".format(len(jsonvalues), (len(tag_list) - (idx + 1)))) 219 if not jsonvalues: 220 break 221 222 for jidx, jvalue in enumerate(jsonvalues): 223 verify(jvalue['portals'][0]['host'] == lo_ip[idx + jidx + 1], 1, 224 "host value is {}, expected {}".format(jvalue['portals'][0]['host'], lo_ip[idx + jidx + 1])) 225 verify(jvalue['portals'][0]['port'] == str(rpc_param['port']), 1, 226 "port value is {}, expected {}".format(jvalue['portals'][0]['port'], str(rpc_param['port']))) 227 verify(jvalue['tag'] != value or jvalue['tag'] == tag_list[idx + jidx + 1], 1, 228 "tag value is {}, expected {} and not {}".format(jvalue['tag'], tag_list[idx + jidx + 1], value)) 229 230 print("verify_portal_groups_rpc_methods passed") 231 232 233def verify_initiator_groups_rpc_methods(rpc_py, rpc_param): 234 rpc = spdk_rpc(rpc_py) 235 output = rpc.iscsi_get_initiator_groups() 236 jsonvalues = json.loads(output) 237 verify(not jsonvalues, 1, 238 "iscsi_get_initiator_groups returned {}, expected empty".format(jsonvalues)) 239 for idx, value in enumerate(rpc_param['netmask']): 240 # The initiator group tag must start at 1 241 tag = idx + 1 242 rpc.iscsi_create_initiator_group(tag, rpc_param['initiator_name'], value) 243 output = rpc.iscsi_get_initiator_groups() 244 jsonvalues = json.loads(output) 245 verify(len(jsonvalues) == tag, 1, 246 "iscsi_get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), tag)) 247 248 tag_list = [] 249 for idx, value in enumerate(jsonvalues): 250 verify(value['initiators'][0] == rpc_param['initiator_name'], 1, 251 "initiator value is {}, expected {}".format(value['initiators'][0], rpc_param['initiator_name'])) 252 tag_list.append(value['tag']) 253 verify(value['tag'] == idx + 1, 1, 254 "tag value is {}, expected {}".format(value['tag'], idx + 1)) 255 verify(value['netmasks'][0] == rpc_param['netmask'][idx], 1, 256 "netmasks value is {}, expected {}".format(value['netmasks'][0], rpc_param['netmask'][idx])) 257 258 for idx, value in enumerate(rpc_param['netmask']): 259 tag = idx + 1 260 rpc.iscsi_initiator_group_remove_initiators(tag, '-n', rpc_param['initiator_name'], '-m', value) 261 262 output = rpc.iscsi_get_initiator_groups() 263 jsonvalues = json.loads(output) 264 verify(len(jsonvalues) == tag, 1, 265 "iscsi_get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), tag)) 266 267 for idx, value in enumerate(jsonvalues): 268 verify(value['tag'] == idx + 1, 1, 269 "tag value is {}, expected {}".format(value['tag'], idx + 1)) 270 initiators = value.get('initiators') 271 verify(len(initiators) == 0, 1, 272 "length of initiator list is {}, expected 0".format(len(initiators))) 273 netmasks = value.get('netmasks') 274 verify(len(netmasks) == 0, 1, 275 "length of netmask list is {}, expected 0".format(len(netmasks))) 276 277 for idx, value in enumerate(rpc_param['netmask']): 278 tag = idx + 1 279 rpc.iscsi_initiator_group_add_initiators(tag, '-n', rpc_param['initiator_name'], '-m', value) 280 output = rpc.iscsi_get_initiator_groups() 281 jsonvalues = json.loads(output) 282 verify(len(jsonvalues) == tag, 1, 283 "iscsi_get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), tag)) 284 285 tag_list = [] 286 for idx, value in enumerate(jsonvalues): 287 verify(value['initiators'][0] == rpc_param['initiator_name'], 1, 288 "initiator value is {}, expected {}".format(value['initiators'][0], rpc_param['initiator_name'])) 289 tag_list.append(value['tag']) 290 verify(value['tag'] == idx + 1, 1, 291 "tag value is {}, expected {}".format(value['tag'], idx + 1)) 292 verify(value['netmasks'][0] == rpc_param['netmask'][idx], 1, 293 "netmasks value is {}, expected {}".format(value['netmasks'][0], rpc_param['netmask'][idx])) 294 295 for idx, value in enumerate(tag_list): 296 rpc.iscsi_delete_initiator_group(value) 297 output = rpc.iscsi_get_initiator_groups() 298 jsonvalues = json.loads(output) 299 verify(len(jsonvalues) == (len(tag_list) - (idx + 1)), 1, 300 "iscsi_get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), (len(tag_list) - (idx + 1)))) 301 if not jsonvalues: 302 break 303 for jidx, jvalue in enumerate(jsonvalues): 304 verify(jvalue['initiators'][0] == rpc_param['initiator_name'], 1, 305 "initiator value is {}, expected {}".format(jvalue['initiators'][0], rpc_param['initiator_name'])) 306 verify(jvalue['tag'] != value or jvalue['tag'] == tag_list[idx + jidx + 1], 1, 307 "tag value is {}, expected {} and not {}".format(jvalue['tag'], tag_list[idx + jidx + 1], value)) 308 verify(jvalue['netmasks'][0] == rpc_param['netmask'][idx + jidx + 1], 1, 309 "netmasks value is {}, expected {}".format(jvalue['netmasks'][0], rpc_param['netmask'][idx + jidx + 1])) 310 311 print("verify_initiator_groups_rpc_method passed.") 312 313 314def verify_target_nodes_rpc_methods(rpc_py, rpc_param): 315 rpc = spdk_rpc(rpc_py) 316 output = rpc.iscsi_get_options() 317 jsonvalues = json.loads(output) 318 nodebase = jsonvalues['node_base'] 319 output = rpc.iscsi_get_target_nodes() 320 jsonvalues = json.loads(output) 321 verify(not jsonvalues, 1, 322 "iscsi_get_target_nodes returned {}, expected empty".format(jsonvalues)) 323 324 rpc.bdev_malloc_create(rpc_param['malloc_bdev_size'], rpc_param['malloc_block_size']) 325 rpc.iscsi_create_portal_group(portal_tag, "{}:{}".format(rpc_param['target_ip'], str(rpc_param['port']))) 326 rpc.iscsi_create_initiator_group(initiator_tag, rpc_param['initiator_name'], rpc_param['netmask']) 327 328 lun_mapping = "Malloc" + str(rpc_param['lun_total']) + ":0" 329 net_mapping = portal_tag + ":" + initiator_tag 330 rpc.iscsi_create_target_node(rpc_param['target_name'], rpc_param['alias_name'], lun_mapping, 331 net_mapping, rpc_param['queue_depth'], '-d') 332 output = rpc.iscsi_get_target_nodes() 333 jsonvalues = json.loads(output) 334 verify(len(jsonvalues) == 1, 1, 335 "iscsi_get_target_nodes returned {} nodes, expected 1".format(len(jsonvalues))) 336 bdev_name = jsonvalues[0]['luns'][0]['bdev_name'] 337 verify(bdev_name == "Malloc" + str(rpc_param['lun_total']), 1, 338 "bdev_name value is {}, expected Malloc{}".format(jsonvalues[0]['luns'][0]['bdev_name'], str(rpc_param['lun_total']))) 339 name = jsonvalues[0]['name'] 340 verify(name == nodebase + ":" + rpc_param['target_name'], 1, 341 "target name value is {}, expected {}".format(name, nodebase + ":" + rpc_param['target_name'])) 342 verify(jsonvalues[0]['alias_name'] == rpc_param['alias_name'], 1, 343 "target alias_name value is {}, expected {}".format(jsonvalues[0]['alias_name'], rpc_param['alias_name'])) 344 verify(jsonvalues[0]['luns'][0]['lun_id'] == 0, 1, 345 "lun id value is {}, expected 0".format(jsonvalues[0]['luns'][0]['lun_id'])) 346 verify(jsonvalues[0]['pg_ig_maps'][0]['ig_tag'] == int(initiator_tag), 1, 347 "initiator group tag value is {}, expected {}".format(jsonvalues[0]['pg_ig_maps'][0]['ig_tag'], initiator_tag)) 348 verify(jsonvalues[0]['queue_depth'] == rpc_param['queue_depth'], 1, 349 "queue depth value is {}, expected {}".format(jsonvalues[0]['queue_depth'], rpc_param['queue_depth'])) 350 verify(jsonvalues[0]['pg_ig_maps'][0]['pg_tag'] == int(portal_tag), 1, 351 "portal group tag value is {}, expected {}".format(jsonvalues[0]['pg_ig_maps'][0]['pg_tag'], portal_tag)) 352 verify(jsonvalues[0]['disable_chap'] == rpc_param['disable_chap'], 1, 353 "disable chap value is {}, expected {}".format(jsonvalues[0]['disable_chap'], rpc_param['disable_chap'])) 354 verify(jsonvalues[0]['mutual_chap'] == rpc_param['mutual_chap'], 1, 355 "chap mutual value is {}, expected {}".format(jsonvalues[0]['mutual_chap'], rpc_param['mutual_chap'])) 356 verify(jsonvalues[0]['require_chap'] == rpc_param['require_chap'], 1, 357 "chap required value is {}, expected {}".format(jsonvalues[0]['require_chap'], rpc_param['require_chap'])) 358 verify(jsonvalues[0]['chap_group'] == rpc_param['chap_group'], 1, 359 "chap auth group value is {}, expected {}".format(jsonvalues[0]['chap_group'], rpc_param['chap_group'])) 360 verify(jsonvalues[0]['header_digest'] == rpc_param['header_digest'], 1, 361 "header digest value is {}, expected {}".format(jsonvalues[0]['header_digest'], rpc_param['header_digest'])) 362 verify(jsonvalues[0]['data_digest'] == rpc_param['data_digest'], 1, 363 "data digest value is {}, expected {}".format(jsonvalues[0]['data_digest'], rpc_param['data_digest'])) 364 lun_id = '1' 365 rpc.iscsi_target_node_add_lun(name, bdev_name, "-i", lun_id) 366 output = rpc.iscsi_get_target_nodes() 367 jsonvalues = json.loads(output) 368 verify(jsonvalues[0]['luns'][1]['bdev_name'] == "Malloc" + str(rpc_param['lun_total']), 1, 369 "bdev_name value is {}, expected Malloc{}".format(jsonvalues[0]['luns'][0]['bdev_name'], str(rpc_param['lun_total']))) 370 verify(jsonvalues[0]['luns'][1]['lun_id'] == 1, 1, 371 "lun id value is {}, expected 1".format(jsonvalues[0]['luns'][1]['lun_id'])) 372 373 rpc.iscsi_delete_target_node(name) 374 output = rpc.iscsi_get_target_nodes() 375 jsonvalues = json.loads(output) 376 verify(not jsonvalues, 1, 377 "iscsi_get_target_nodes returned {}, expected empty".format(jsonvalues)) 378 379 rpc.iscsi_create_target_node(rpc_param['target_name'], rpc_param['alias_name'], lun_mapping, 380 net_mapping, rpc_param['queue_depth'], '-d') 381 382 rpc.iscsi_delete_portal_group(portal_tag) 383 rpc.iscsi_delete_initiator_group(initiator_tag) 384 rpc.iscsi_delete_target_node(name) 385 output = rpc.iscsi_get_target_nodes() 386 jsonvalues = json.loads(output) 387 if not jsonvalues: 388 print("This issue will be fixed later.") 389 390 print("verify_target_nodes_rpc_methods passed.") 391 392 393def help_get_interface_ip_list(rpc_py, nic_name): 394 rpc = spdk_rpc(rpc_py) 395 nics = json.loads(rpc.net_get_interfaces()) 396 nic = list([x for x in nics if x["name"] == nic_name]) 397 verify(len(nic) != 0, 1, 398 "Nic name: {} is not found in {}".format(nic_name, [x["name"] for x in nics])) 399 return nic[0]["ip_addr"] 400 401 402if __name__ == "__main__": 403 404 rpc_py = sys.argv[1] 405 406 try: 407 verify_log_flag_rpc_methods(rpc_py, rpc_param) 408 create_malloc_bdevs_rpc_methods(rpc_py, rpc_param) 409 verify_portal_groups_rpc_methods(rpc_py, rpc_param) 410 verify_initiator_groups_rpc_methods(rpc_py, rpc_param) 411 verify_target_nodes_rpc_methods(rpc_py, rpc_param) 412 verify_scsi_devices_rpc_methods(rpc_py) 413 verify_iscsi_connection_rpc_methods(rpc_py) 414 except RpcException as e: 415 print("{}. Exiting with status {}".format(e.message, e.retval)) 416 raise e 417 except Exception as e: 418 raise e 419 420 sys.exit(0) 421