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