1#!/usr/bin/env python 2 3from rpc.client import print_dict, JSONRPCException 4 5import argparse 6import rpc 7 8try: 9 from shlex import quote 10except ImportError: 11 from pipes import quote 12 13 14def print_array(a): 15 print(" ".join((quote(v) for v in a))) 16 17 18def call_cmd(func): 19 def rpc_cmd(*args, **kwargs): 20 try: 21 func(*args, **kwargs) 22 except JSONRPCException as ex: 23 print(ex.message) 24 exit(1) 25 return rpc_cmd 26 27 28if __name__ == "__main__": 29 parser = argparse.ArgumentParser( 30 description='SPDK RPC command line interface') 31 parser.add_argument('-s', dest='server_addr', 32 help='RPC server address', default='/var/tmp/spdk.sock') 33 parser.add_argument('-p', dest='port', 34 help='RPC port number (if server_addr is IP address)', 35 default=5260, type=int) 36 parser.add_argument('-t', dest='timeout', 37 help='Timout as a floating point number expressed in seconds waiting for reponse. Default: 60.0', 38 default=60.0, type=float) 39 parser.add_argument('-v', dest='verbose', 40 help='Verbose mode', action='store_true') 41 subparsers = parser.add_subparsers(help='RPC methods') 42 43 @call_cmd 44 def start_subsystem_init(args): 45 rpc.start_subsystem_init(args.client) 46 47 p = subparsers.add_parser('start_subsystem_init', help='Start initialization of subsystems') 48 p.set_defaults(func=start_subsystem_init) 49 50 @call_cmd 51 def get_rpc_methods(args): 52 print_dict(rpc.get_rpc_methods(args.client, 53 current=args.current)) 54 55 p = subparsers.add_parser('get_rpc_methods', help='Get list of supported RPC methods') 56 p.add_argument('-c', '--current', help='Get list of RPC methods only callable in the current state.', action='store_true') 57 p.set_defaults(func=get_rpc_methods) 58 59 @call_cmd 60 def save_config(args): 61 rpc.save_config(args.client, 62 filename=args.filename, 63 indent=args.indent) 64 65 p = subparsers.add_parser('save_config', help="""Write current (live) configuration of SPDK subsystems and targets. 66 If no filename is given write configuration to stdout.""") 67 p.add_argument('-f', '--filename', help="""File where to save JSON configuration to.""") 68 p.add_argument('-i', '--indent', help="""Indent level. Value less than 0 mean compact mode. If filename is not given default 69 indent level is 2. If writing to file of filename is '-' then default is compact mode.""", type=int, default=2) 70 p.set_defaults(func=save_config) 71 72 @call_cmd 73 def load_config(args): 74 rpc.load_config(args.client, 75 filename=args.filename) 76 77 p = subparsers.add_parser('load_config', help="""Configure SPDK subsystems and tagets using JSON RPC. If no file is 78 provided or file is '-' read configuration from stdin.""") 79 p.add_argument('-f', '--filename', help="""JSON Configuration file.""") 80 p.set_defaults(func=load_config) 81 82 @call_cmd 83 def save_subsystem_config(args): 84 rpc.save_subsystem_config(args.client, 85 filename=args.filename, 86 indent=args.indent, 87 name=args.name) 88 89 p = subparsers.add_parser('save_subsystem_config', help="""Write current (live) configuration of SPDK subsystem. 90 If no filename is given write configuration to stdout.""") 91 p.add_argument('-f', '--filename', help='File where to save JSON configuration to.') 92 p.add_argument('-i', '--indent', help="""Indent level. Value less than 0 mean compact mode. If filename is not given default 93 indent level is 2. If writing to file of filename is '-' then default is compact mode.""", type=int, default=2) 94 p.add_argument('-n', '--name', help='Name of subsystem', required=True) 95 p.set_defaults(func=save_subsystem_config) 96 97 @call_cmd 98 def load_subsystem_config(args): 99 rpc.load_subsystem_config(args.client, 100 filename=args.filename) 101 102 p = subparsers.add_parser('load_subsystem_config', help="""Configure SPDK subsystem using JSON RPC. If no file is 103 provided or file is '-' read configuration from stdin.""") 104 p.add_argument('-f', '--filename', help="""JSON Configuration file.""") 105 p.set_defaults(func=load_subsystem_config) 106 107 # app 108 @call_cmd 109 def kill_instance(args): 110 rpc.app.kill_instance(args.client, 111 sig_name=args.sig_name) 112 113 p = subparsers.add_parser('kill_instance', help='Send signal to instance') 114 p.add_argument('sig_name', help='signal will be sent to server.') 115 p.set_defaults(func=kill_instance) 116 117 @call_cmd 118 def context_switch_monitor(args): 119 enabled = None 120 if args.enable: 121 enabled = True 122 if args.disable: 123 enabled = False 124 print_dict(rpc.app.context_switch_monitor(args.client, 125 enabled=enabled)) 126 127 p = subparsers.add_parser('context_switch_monitor', help='Control whether the context switch monitor is enabled') 128 p.add_argument('-e', '--enable', action='store_true', help='Enable context switch monitoring') 129 p.add_argument('-d', '--disable', action='store_true', help='Disable context switch monitoring') 130 p.set_defaults(func=context_switch_monitor) 131 132 # bdev 133 @call_cmd 134 def set_bdev_options(args): 135 rpc.bdev.set_bdev_options(args.client, 136 bdev_io_pool_size=args.bdev_io_pool_size, 137 bdev_io_cache_size=args.bdev_io_cache_size) 138 139 p = subparsers.add_parser('set_bdev_options', help="""Set options of bdev subsystem""") 140 p.add_argument('-p', '--bdev-io-pool-size', help='Number of bdev_io structures in shared buffer pool', type=int) 141 p.add_argument('-c', '--bdev-io-cache-size', help='Maximum number of bdev_io structures cached per thread', type=int) 142 p.set_defaults(func=set_bdev_options) 143 144 @call_cmd 145 def construct_malloc_bdev(args): 146 num_blocks = (args.total_size * 1024 * 1024) // args.block_size 147 print(rpc.bdev.construct_malloc_bdev(args.client, 148 num_blocks=int(num_blocks), 149 block_size=args.block_size, 150 name=args.name, 151 uuid=args.uuid)) 152 153 p = subparsers.add_parser('construct_malloc_bdev', 154 help='Add a bdev with malloc backend') 155 p.add_argument('-b', '--name', help="Name of the bdev") 156 p.add_argument('-u', '--uuid', help="UUID of the bdev") 157 p.add_argument( 158 'total_size', help='Size of malloc bdev in MB (float > 0)', type=float) 159 p.add_argument('block_size', help='Block size for this bdev', type=int) 160 p.set_defaults(func=construct_malloc_bdev) 161 162 @call_cmd 163 def delete_malloc_bdev(args): 164 rpc.bdev.delete_malloc_bdev(args.client, 165 name=args.name) 166 167 p = subparsers.add_parser('delete_malloc_bdev', help='Delete a malloc disk') 168 p.add_argument('name', help='malloc bdev name') 169 p.set_defaults(func=delete_malloc_bdev) 170 171 @call_cmd 172 def construct_null_bdev(args): 173 num_blocks = (args.total_size * 1024 * 1024) // args.block_size 174 print(rpc.bdev.construct_null_bdev(args.client, 175 num_blocks=num_blocks, 176 block_size=args.block_size, 177 name=args.name, 178 uuid=args.uuid)) 179 180 p = subparsers.add_parser('construct_null_bdev', 181 help='Add a bdev with null backend') 182 p.add_argument('name', help='Block device name') 183 p.add_argument('-u', '--uuid', help='UUID of the bdev') 184 p.add_argument( 185 'total_size', help='Size of null bdev in MB (int > 0)', type=int) 186 p.add_argument('block_size', help='Block size for this bdev', type=int) 187 p.set_defaults(func=construct_null_bdev) 188 189 @call_cmd 190 def delete_null_bdev(args): 191 rpc.bdev.delete_null_bdev(args.client, 192 name=args.name) 193 194 p = subparsers.add_parser('delete_null_bdev', help='Delete a null bdev') 195 p.add_argument('name', help='null bdev name') 196 p.set_defaults(func=delete_null_bdev) 197 198 @call_cmd 199 def construct_aio_bdev(args): 200 print(rpc.bdev.construct_aio_bdev(args.client, 201 filename=args.filename, 202 name=args.name, 203 block_size=args.block_size)) 204 205 p = subparsers.add_parser('construct_aio_bdev', 206 help='Add a bdev with aio backend') 207 p.add_argument('filename', help='Path to device or file (ex: /dev/sda)') 208 p.add_argument('name', help='Block device name') 209 p.add_argument('block_size', help='Block size for this bdev', type=int, nargs='?', default=0) 210 p.set_defaults(func=construct_aio_bdev) 211 212 @call_cmd 213 def delete_aio_bdev(args): 214 rpc.bdev.delete_aio_bdev(args.client, 215 name=args.name) 216 217 p = subparsers.add_parser('delete_aio_bdev', help='Delete an aio disk') 218 p.add_argument('name', help='aio bdev name') 219 p.set_defaults(func=delete_aio_bdev) 220 221 @call_cmd 222 def construct_nvme_bdev(args): 223 print_array(rpc.bdev.construct_nvme_bdev(args.client, 224 name=args.name, 225 trtype=args.trtype, 226 traddr=args.traddr, 227 adrfam=args.adrfam, 228 trsvcid=args.trsvcid, 229 subnqn=args.subnqn)) 230 231 p = subparsers.add_parser('construct_nvme_bdev', 232 help='Add bdev with nvme backend') 233 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 234 p.add_argument('-t', '--trtype', 235 help='NVMe-oF target trtype: e.g., rdma, pcie', required=True) 236 p.add_argument('-a', '--traddr', 237 help='NVMe-oF target address: e.g., an ip address or BDF', required=True) 238 p.add_argument('-f', '--adrfam', 239 help='NVMe-oF target adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 240 p.add_argument('-s', '--trsvcid', 241 help='NVMe-oF target trsvcid: e.g., a port number') 242 p.add_argument('-n', '--subnqn', help='NVMe-oF target subnqn') 243 p.set_defaults(func=construct_nvme_bdev) 244 245 @call_cmd 246 def construct_rbd_bdev(args): 247 print(rpc.bdev.construct_rbd_bdev(args.client, 248 name=args.name, 249 pool_name=args.pool_name, 250 rbd_name=args.rbd_name, 251 block_size=args.block_size)) 252 253 p = subparsers.add_parser('construct_rbd_bdev', 254 help='Add a bdev with ceph rbd backend') 255 p.add_argument('-b', '--name', help="Name of the bdev", required=False) 256 p.add_argument('pool_name', help='rbd pool name') 257 p.add_argument('rbd_name', help='rbd image name') 258 p.add_argument('block_size', help='rbd block size', type=int) 259 p.set_defaults(func=construct_rbd_bdev) 260 261 @call_cmd 262 def delete_rbd_bdev(args): 263 rpc.bdev.delete_rbd_bdev(args.client, 264 name=args.name) 265 266 p = subparsers.add_parser('delete_rbd_bdev', help='Delete a rbd bdev') 267 p.add_argument('name', help='rbd bdev name') 268 p.set_defaults(func=delete_rbd_bdev) 269 270 @call_cmd 271 def construct_error_bdev(args): 272 print(rpc.bdev.construct_error_bdev(args.client, 273 base_name=args.base_name)) 274 275 p = subparsers.add_parser('construct_error_bdev', 276 help='Add bdev with error injection backend') 277 p.add_argument('base_name', help='base bdev name') 278 p.set_defaults(func=construct_error_bdev) 279 280 @call_cmd 281 def delete_error_bdev(args): 282 rpc.bdev.delete_error_bdev(args.client, 283 name=args.name) 284 285 p = subparsers.add_parser('delete_error_bdev', help='Delete an error bdev') 286 p.add_argument('name', help='error bdev name') 287 p.set_defaults(func=delete_error_bdev) 288 289 @call_cmd 290 def construct_iscsi_bdev(args): 291 print(rpc.bdev.construct_iscsi_bdev(args.client, 292 name=args.name, 293 url=args.url, 294 initiator_iqn=args.initiator_iqn)) 295 296 p = subparsers.add_parser('construct_iscsi_bdev', 297 help='Add bdev with iSCSI initiator backend') 298 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 299 p.add_argument('-i', '--initiator-iqn', help="Initiator IQN", required=True) 300 p.add_argument('--url', help="iSCSI Lun URL", required=True) 301 p.set_defaults(func=construct_iscsi_bdev) 302 303 @call_cmd 304 def delete_iscsi_bdev(args): 305 rpc.bdev.delete_iscsi_bdev(args.client, 306 name=args.name) 307 308 p = subparsers.add_parser('delete_iscsi_bdev', help='Delete an iSCSI bdev') 309 p.add_argument('name', help='iSCSI bdev name') 310 p.set_defaults(func=delete_iscsi_bdev) 311 312 @call_cmd 313 def construct_pmem_bdev(args): 314 print(rpc.bdev.construct_pmem_bdev(args.client, 315 pmem_file=args.pmem_file, 316 name=args.name)) 317 318 p = subparsers.add_parser('construct_pmem_bdev', help='Add a bdev with pmem backend') 319 p.add_argument('pmem_file', help='Path to pmemblk pool file') 320 p.add_argument('-n', '--name', help='Block device name', required=True) 321 p.set_defaults(func=construct_pmem_bdev) 322 323 @call_cmd 324 def delete_pmem_bdev(args): 325 rpc.bdev.delete_pmem_bdev(args.client, 326 name=args.name) 327 328 p = subparsers.add_parser('delete_pmem_bdev', help='Delete a pmem bdev') 329 p.add_argument('name', help='pmem bdev name') 330 p.set_defaults(func=delete_pmem_bdev) 331 332 @call_cmd 333 def construct_passthru_bdev(args): 334 print(rpc.bdev.construct_passthru_bdev(args.client, 335 base_bdev_name=args.base_bdev_name, 336 passthru_bdev_name=args.passthru_bdev_name)) 337 338 p = subparsers.add_parser('construct_passthru_bdev', 339 help='Add a pass through bdev on existing bdev') 340 p.add_argument('-b', '--base-bdev-name', help="Name of the existing bdev", required=True) 341 p.add_argument('-p', '--passthru-bdev-name', help="Name of the pass through bdev", required=True) 342 p.set_defaults(func=construct_passthru_bdev) 343 344 @call_cmd 345 def delete_passthru_bdev(args): 346 rpc.bdev.delete_passthru_bdev(args.client, 347 name=args.name) 348 349 p = subparsers.add_parser('delete_passthru_bdev', help='Delete a pass through bdev') 350 p.add_argument('name', help='pass through bdev name') 351 p.set_defaults(func=delete_passthru_bdev) 352 353 @call_cmd 354 def get_bdevs(args): 355 print_dict(rpc.bdev.get_bdevs(args.client, 356 name=args.name)) 357 358 p = subparsers.add_parser( 359 'get_bdevs', help='Display current blockdev list or required blockdev') 360 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 361 p.set_defaults(func=get_bdevs) 362 363 @call_cmd 364 def get_bdevs_config(args): 365 print_dict(rpc.bdev.get_bdevs_config(args.client, 366 name=args.name)) 367 368 p = subparsers.add_parser( 369 'get_bdevs_config', help='Display current (live) blockdev configuration list or required blockdev') 370 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 371 p.set_defaults(func=get_bdevs_config) 372 373 @call_cmd 374 def get_bdevs_iostat(args): 375 print_dict(rpc.bdev.get_bdevs_iostat(args.client, 376 name=args.name)) 377 378 p = subparsers.add_parser( 379 'get_bdevs_iostat', help='Display current I/O statistics of all the blockdevs or required blockdev.') 380 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 381 p.set_defaults(func=get_bdevs_iostat) 382 383 @call_cmd 384 def delete_bdev(args): 385 rpc.bdev.delete_bdev(args.client, 386 bdev_name=args.bdev_name) 387 388 p = subparsers.add_parser('delete_bdev', help='Delete a blockdev') 389 p.add_argument( 390 'bdev_name', help='Blockdev name to be deleted. Example: Malloc0.') 391 p.set_defaults(func=delete_bdev) 392 393 @call_cmd 394 def set_bdev_qd_sampling_period(args): 395 rpc.bdev.set_bdev_qd_sampling_period(args.client, 396 name=args.name, 397 period=args.period) 398 399 p = subparsers.add_parser('set_bdev_qd_sampling_period', help="Enable or disable tracking of a bdev's queue depth.") 400 p.add_argument('name', help='Blockdev name. Example: Malloc0') 401 p.add_argument('period', help='Period with which to poll the block device queue depth in microseconds.' 402 ' If set to 0, polling will be disabled.', 403 type=int) 404 p.set_defaults(func=set_bdev_qd_sampling_period) 405 406 @call_cmd 407 def set_bdev_qos_limit_iops(args): 408 rpc.bdev.set_bdev_qos_limit_iops(args.client, 409 name=args.name, 410 ios_per_sec=args.ios_per_sec) 411 412 p = subparsers.add_parser('set_bdev_qos_limit_iops', help='Set QoS IOPS limit on a blockdev') 413 p.add_argument('name', help='Blockdev name to set QoS. Example: Malloc0') 414 p.add_argument('ios_per_sec', 415 help='IOs per second limit (>=10000, example: 20000). 0 means unlimited.', type=int) 416 p.set_defaults(func=set_bdev_qos_limit_iops) 417 418 @call_cmd 419 def bdev_inject_error(args): 420 rpc.bdev.bdev_inject_error(args.client, 421 name=args.name, 422 io_type=args.io_type, 423 error_type=args.error_type, 424 num=args.num) 425 426 p = subparsers.add_parser('bdev_inject_error', help='bdev inject error') 427 p.add_argument('name', help="""the name of the error injection bdev""") 428 p.add_argument('io_type', help="""io_type: 'clear' 'read' 'write' 'unmap' 'flush' 'all'""") 429 p.add_argument('error_type', help="""error_type: 'failure' 'pending'""") 430 p.add_argument( 431 '-n', '--num', help='the number of commands you want to fail', type=int, default=1) 432 p.set_defaults(func=bdev_inject_error) 433 434 @call_cmd 435 def apply_firmware(args): 436 print_dict(rpc.bdev.apply_firmware(args.client, 437 bdev_name=args.bdev_name, 438 filename=args.filename)) 439 440 p = subparsers.add_parser('apply_firmware', help='Download and commit firmware to NVMe device') 441 p.add_argument('filename', help='filename of the firmware to download') 442 p.add_argument('bdev_name', help='name of the NVMe device') 443 p.set_defaults(func=apply_firmware) 444 445 # iSCSI 446 def set_iscsi_options(args): 447 rpc.iscsi.set_iscsi_options( 448 args.client, 449 auth_file=args.auth_file, 450 node_base=args.node_base, 451 nop_timeout=args.nop_timeout, 452 nop_in_interval=args.nop_in_interval, 453 no_discovery_auth=args.no_discovery_auth, 454 req_discovery_auth=args.req_discovery_auth, 455 req_discovery_auth_mutual=args.req_discovery_auth_mutual, 456 discovery_auth_group=args.discovery_auth_group, 457 max_sessions=args.max_sessions, 458 max_connections_per_session=args.max_connections_per_session, 459 default_time2wait=args.default_time2wait, 460 default_time2retain=args.default_time2retain, 461 immediate_data=args.immediate_data, 462 error_recovery_level=args.error_recovery_level, 463 allow_duplicated_isid=args.allow_duplicated_isid, 464 min_connections_per_session=args.min_connections_per_session) 465 466 p = subparsers.add_parser('set_iscsi_options', help="""Set options of iSCSI subsystem""") 467 p.add_argument('-f', '--auth-file', help='Path to CHAP shared secret file for discovery session') 468 p.add_argument('-b', '--node-base', help='Prefix of the name of iSCSI target node') 469 p.add_argument('-o', '--nop-timeout', help='Timeout in seconds to nop-in request to the initiator', type=int) 470 p.add_argument('-n', '--nop-in-interval', help='Time interval in secs between nop-in requests by the target', type=int) 471 p.add_argument('-d', '--no-discovery-auth', help="""CHAP for discovery session should be disabled. 472 *** Mutually exclusive with --req-discovery-auth""", action='store_true') 473 p.add_argument('-r', '--req-discovery-auth', help="""CHAP for discovery session should be required. 474 *** Mutually exclusive with --no-discovery-auth""", action='store_true') 475 p.add_argument('-m', '--req-discovery-auth-mutual', help='CHAP for discovery session should be mutual', action='store_true') 476 p.add_argument('-g', '--discovery-auth-group', help="""Authentication group ID for discovery session. 477 *** Authentication group must be precreated ***""", type=int) 478 p.add_argument('-a', '--max-sessions', help='Maximum number of sessions in the host.', type=int) 479 p.add_argument('-c', '--max-connections-per-session', help='Negotiated parameter, MaxConnections.', type=int) 480 p.add_argument('-w', '--default-time2wait', help='Negotiated parameter, DefaultTime2Wait.', type=int) 481 p.add_argument('-v', '--default-time2retain', help='Negotiated parameter, DefaultTime2Retain.', type=int) 482 p.add_argument('-i', '--immediate-data', help='Negotiated parameter, ImmediateData.', action='store_true') 483 p.add_argument('-l', '--error-recovery-level', help='Negotiated parameter, ErrorRecoveryLevel', type=int) 484 p.add_argument('-p', '--allow-duplicated-isid', help='Allow duplicated initiator session ID.', action='store_true') 485 p.add_argument('-u', '--min-connections-per-session', help='Allocation unit of connections per core', type=int) 486 p.set_defaults(func=set_iscsi_options) 487 488 @call_cmd 489 def get_portal_groups(args): 490 print_dict(rpc.iscsi.get_portal_groups(args.client)) 491 492 p = subparsers.add_parser( 493 'get_portal_groups', help='Display current portal group configuration') 494 p.set_defaults(func=get_portal_groups) 495 496 @call_cmd 497 def get_initiator_groups(args): 498 print_dict(rpc.iscsi.get_initiator_groups(args.client)) 499 500 p = subparsers.add_parser('get_initiator_groups', 501 help='Display current initiator group configuration') 502 p.set_defaults(func=get_initiator_groups) 503 504 @call_cmd 505 def get_target_nodes(args): 506 print_dict(rpc.iscsi.get_target_nodes(args.client)) 507 508 p = subparsers.add_parser('get_target_nodes', help='Display target nodes') 509 p.set_defaults(func=get_target_nodes) 510 511 @call_cmd 512 def construct_target_node(args): 513 luns = [] 514 for u in args.bdev_name_id_pairs.strip().split(" "): 515 bdev_name, lun_id = u.split(":") 516 luns.append({"bdev_name": bdev_name, "lun_id": int(lun_id)}) 517 518 pg_ig_maps = [] 519 for u in args.pg_ig_mappings.strip().split(" "): 520 pg, ig = u.split(":") 521 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 522 523 rpc.iscsi.construct_target_node( 524 args.client, 525 luns=luns, 526 pg_ig_maps=pg_ig_maps, 527 name=args.name, 528 alias_name=args.alias_name, 529 queue_depth=args.queue_depth, 530 chap_group=args.chap_group, 531 disable_chap=args.disable_chap, 532 require_chap=args.require_chap, 533 mutual_chap=args.mutual_chap, 534 header_digest=args.header_digest, 535 data_digest=args.data_digest) 536 537 p = subparsers.add_parser('construct_target_node', 538 help='Add a target node') 539 p.add_argument('name', help='Target node name (ASCII)') 540 p.add_argument('alias_name', help='Target node alias name (ASCII)') 541 p.add_argument('bdev_name_id_pairs', help="""Whitespace-separated list of <bdev name:LUN ID> pairs enclosed 542 in quotes. Format: 'bdev_name0:id0 bdev_name1:id1' etc 543 Example: 'Malloc0:0 Malloc1:1 Malloc5:2' 544 *** The bdevs must pre-exist *** 545 *** LUN0 (id = 0) is required *** 546 *** bdevs names cannot contain space or colon characters ***""") 547 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 548 Whitespace separated, quoted, mapping defined with colon 549 separated list of "tags" (int > 0) 550 Example: '1:1 2:2 2:1' 551 *** The Portal/Initiator Groups must be precreated ***""") 552 p.add_argument('queue_depth', help='Desired target queue depth', type=int) 553 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 554 *** Authentication group must be precreated ***""", type=int, default=0) 555 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 556 *** Mutually exclusive with --require-chap ***""", action='store_true') 557 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 558 *** Mutually exclusive with --disable-chap ***""", action='store_true') 559 p.add_argument( 560 '-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', action='store_true') 561 p.add_argument('-H', '--header-digest', 562 help='Header Digest should be required for this target node.', action='store_true') 563 p.add_argument('-D', '--data-digest', 564 help='Data Digest should be required for this target node.', action='store_true') 565 p.set_defaults(func=construct_target_node) 566 567 @call_cmd 568 def target_node_add_lun(args): 569 rpc.iscsi.target_node_add_lun( 570 args.client, 571 name=args.name, 572 bdev_name=args.bdev_name, 573 lun_id=args.lun_id) 574 575 p = subparsers.add_parser('target_node_add_lun', help='Add LUN to the target node') 576 p.add_argument('name', help='Target node name (ASCII)') 577 p.add_argument('bdev_name', help="""bdev name enclosed in quotes. 578 *** bdev name cannot contain space or colon characters ***""") 579 p.add_argument('-i', dest='lun_id', help="""LUN ID (integer >= 0) 580 *** If LUN ID is omitted or -1, the lowest free one is assigned ***""", type=int, required=False) 581 p.set_defaults(func=target_node_add_lun) 582 583 @call_cmd 584 def add_pg_ig_maps(args): 585 pg_ig_maps = [] 586 for u in args.pg_ig_mappings.strip().split(" "): 587 pg, ig = u.split(":") 588 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 589 rpc.iscsi.add_pg_ig_maps( 590 args.client, 591 pg_ig_maps=pg_ig_maps, 592 name=args.name) 593 594 p = subparsers.add_parser('add_pg_ig_maps', help='Add PG-IG maps to the target node') 595 p.add_argument('name', help='Target node name (ASCII)') 596 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 597 Whitespace separated, quoted, mapping defined with colon 598 separated list of "tags" (int > 0) 599 Example: '1:1 2:2 2:1' 600 *** The Portal/Initiator Groups must be precreated ***""") 601 p.set_defaults(func=add_pg_ig_maps) 602 603 @call_cmd 604 def delete_pg_ig_maps(args): 605 pg_ig_maps = [] 606 for u in args.pg_ig_mappings.strip().split(" "): 607 pg, ig = u.split(":") 608 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 609 rpc.iscsi.delete_pg_ig_maps( 610 args.client, pg_ig_maps=pg_ig_maps, name=args.name) 611 612 p = subparsers.add_parser('delete_pg_ig_maps', help='Delete PG-IG maps from the target node') 613 p.add_argument('name', help='Target node name (ASCII)') 614 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 615 Whitespace separated, quoted, mapping defined with colon 616 separated list of "tags" (int > 0) 617 Example: '1:1 2:2 2:1' 618 *** The Portal/Initiator Groups must be precreated ***""") 619 p.set_defaults(func=delete_pg_ig_maps) 620 621 @call_cmd 622 def add_portal_group(args): 623 portals = [] 624 for p in args.portal_list: 625 ip, separator, port_cpumask = p.rpartition(':') 626 split_port_cpumask = port_cpumask.split('@') 627 if len(split_port_cpumask) == 1: 628 port = port_cpumask 629 portals.append({'host': ip, 'port': port}) 630 else: 631 port = split_port_cpumask[0] 632 cpumask = split_port_cpumask[1] 633 portals.append({'host': ip, 'port': port, 'cpumask': cpumask}) 634 rpc.iscsi.add_portal_group( 635 args.client, 636 portals=portals, 637 tag=args.tag) 638 639 p = subparsers.add_parser('add_portal_group', help='Add a portal group') 640 p.add_argument( 641 'tag', help='Portal group tag (unique, integer > 0)', type=int) 642 p.add_argument('portal_list', nargs=argparse.REMAINDER, help="""List of portals in 'host:port@cpumask' format, separated by whitespace 643 (cpumask is optional and can be skipped) 644 Example: '192.168.100.100:3260' '192.168.100.100:3261' '192.168.100.100:3262@0x1""") 645 p.set_defaults(func=add_portal_group) 646 647 @call_cmd 648 def add_initiator_group(args): 649 initiators = [] 650 netmasks = [] 651 for i in args.initiator_list.strip().split(' '): 652 initiators.append(i) 653 for n in args.netmask_list.strip().split(' '): 654 netmasks.append(n) 655 rpc.iscsi.add_initiator_group( 656 args.client, 657 tag=args.tag, 658 initiators=initiators, 659 netmasks=netmasks) 660 661 p = subparsers.add_parser('add_initiator_group', 662 help='Add an initiator group') 663 p.add_argument( 664 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 665 p.add_argument('initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 666 enclosed in quotes. Example: 'ANY' or '127.0.0.1 192.168.200.100'""") 667 p.add_argument('netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 668 Example: '255.255.0.0 255.248.0.0' etc""") 669 p.set_defaults(func=add_initiator_group) 670 671 @call_cmd 672 def add_initiators_to_initiator_group(args): 673 initiators = None 674 netmasks = None 675 if args.initiator_list: 676 initiators = [] 677 for i in args.initiator_list.strip().split(' '): 678 initiators.append(i) 679 if args.netmask_list: 680 netmasks = [] 681 for n in args.netmask_list.strip().split(' '): 682 netmasks.append(n) 683 rpc.iscsi.add_initiators_to_initiator_group( 684 args.client, 685 tag=args.tag, 686 initiators=initiators, 687 netmasks=netmasks) 688 689 p = subparsers.add_parser('add_initiators_to_initiator_group', 690 help='Add initiators to an existing initiator group') 691 p.add_argument( 692 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 693 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 694 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 695 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 696 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 697 p.set_defaults(func=add_initiators_to_initiator_group) 698 699 @call_cmd 700 def delete_initiators_from_initiator_group(args): 701 initiators = None 702 netmasks = None 703 if args.initiator_list: 704 initiators = [] 705 for i in args.initiator_list.strip().split(' '): 706 initiators.append(i) 707 if args.netmask_list: 708 netmasks = [] 709 for n in args.netmask_list.strip().split(' '): 710 netmasks.append(n) 711 rpc.iscsi.delete_initiators_from_initiator_group( 712 args.client, 713 tag=args.tag, 714 initiators=initiators, 715 netmasks=netmasks) 716 717 p = subparsers.add_parser('delete_initiators_from_initiator_group', 718 help='Delete initiators from an existing initiator group') 719 p.add_argument( 720 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 721 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 722 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 723 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 724 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 725 p.set_defaults(func=delete_initiators_from_initiator_group) 726 727 @call_cmd 728 def delete_target_node(args): 729 rpc.iscsi.delete_target_node( 730 args.client, target_node_name=args.target_node_name) 731 732 p = subparsers.add_parser('delete_target_node', 733 help='Delete a target node') 734 p.add_argument('target_node_name', 735 help='Target node name to be deleted. Example: iqn.2016-06.io.spdk:disk1.') 736 p.set_defaults(func=delete_target_node) 737 738 @call_cmd 739 def delete_portal_group(args): 740 rpc.iscsi.delete_portal_group(args.client, tag=args.tag) 741 742 p = subparsers.add_parser('delete_portal_group', 743 help='Delete a portal group') 744 p.add_argument( 745 'tag', help='Portal group tag (unique, integer > 0)', type=int) 746 p.set_defaults(func=delete_portal_group) 747 748 @call_cmd 749 def delete_initiator_group(args): 750 rpc.iscsi.delete_initiator_group(args.client, tag=args.tag) 751 752 p = subparsers.add_parser('delete_initiator_group', 753 help='Delete an initiator group') 754 p.add_argument( 755 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 756 p.set_defaults(func=delete_initiator_group) 757 758 @call_cmd 759 def get_iscsi_connections(args): 760 print_dict(rpc.iscsi.get_iscsi_connections(args.client)) 761 762 p = subparsers.add_parser('get_iscsi_connections', 763 help='Display iSCSI connections') 764 p.set_defaults(func=get_iscsi_connections) 765 766 @call_cmd 767 def get_iscsi_global_params(args): 768 print_dict(rpc.iscsi.get_iscsi_global_params(args.client)) 769 770 p = subparsers.add_parser('get_iscsi_global_params', help='Display iSCSI global parameters') 771 p.set_defaults(func=get_iscsi_global_params) 772 773 @call_cmd 774 def get_scsi_devices(args): 775 print_dict(rpc.iscsi.get_scsi_devices(args.client)) 776 777 p = subparsers.add_parser('get_scsi_devices', help='Display SCSI devices') 778 p.set_defaults(func=get_scsi_devices) 779 780 # log 781 @call_cmd 782 def set_trace_flag(args): 783 rpc.log.set_trace_flag(args.client, args) 784 785 p = subparsers.add_parser('set_trace_flag', help='set trace flag') 786 p.add_argument( 787 'flag', help='trace mask we want to set. (for example "nvme").') 788 p.set_defaults(func=set_trace_flag) 789 790 @call_cmd 791 def clear_trace_flag(args): 792 rpc.log.clear_trace_flag(args.client, args) 793 794 p = subparsers.add_parser('clear_trace_flag', help='clear trace flag') 795 p.add_argument( 796 'flag', help='trace mask we want to clear. (for example "nvme").') 797 p.set_defaults(func=clear_trace_flag) 798 799 @call_cmd 800 def get_trace_flags(args): 801 print_dict(rpc.log.get_trace_flags(args.client, args)) 802 803 p = subparsers.add_parser('get_trace_flags', help='get trace flags') 804 p.set_defaults(func=get_trace_flags) 805 806 @call_cmd 807 def set_log_level(args): 808 rpc.log.set_log_level(args.client, args) 809 810 p = subparsers.add_parser('set_log_level', help='set log level') 811 p.add_argument('level', help='log level we want to set. (for example "DEBUG").') 812 p.set_defaults(func=set_log_level) 813 814 @call_cmd 815 def get_log_level(args): 816 print_dict(rpc.log.get_log_level(args.client, args)) 817 818 p = subparsers.add_parser('get_log_level', help='get log level') 819 p.set_defaults(func=get_log_level) 820 821 @call_cmd 822 def set_log_print_level(args): 823 rpc.log.set_log_print_level(args.client, args) 824 825 p = subparsers.add_parser('set_log_print_level', help='set log print level') 826 p.add_argument('level', help='log print level we want to set. (for example "DEBUG").') 827 p.set_defaults(func=set_log_print_level) 828 829 @call_cmd 830 def get_log_print_level(args): 831 print_dict(rpc.log.get_log_print_level(args.client, args)) 832 833 p = subparsers.add_parser('get_log_print_level', help='get log print level') 834 p.set_defaults(func=get_log_print_level) 835 836 # lvol 837 @call_cmd 838 def construct_lvol_store(args): 839 print(rpc.lvol.construct_lvol_store(args.client, 840 bdev_name=args.bdev_name, 841 lvs_name=args.lvs_name, 842 cluster_sz=args.cluster_sz)) 843 844 p = subparsers.add_parser('construct_lvol_store', help='Add logical volume store on base bdev') 845 p.add_argument('bdev_name', help='base bdev name') 846 p.add_argument('lvs_name', help='name for lvol store') 847 p.add_argument('-c', '--cluster-sz', help='size of cluster (in bytes)', type=int, required=False) 848 p.set_defaults(func=construct_lvol_store) 849 850 @call_cmd 851 def rename_lvol_store(args): 852 rpc.lvol.rename_lvol_store(args.client, 853 old_name=args.old_name, 854 new_name=args.new_name) 855 856 p = subparsers.add_parser('rename_lvol_store', help='Change logical volume store name') 857 p.add_argument('old_name', help='old name') 858 p.add_argument('new_name', help='new name') 859 p.set_defaults(func=rename_lvol_store) 860 861 @call_cmd 862 def construct_lvol_bdev(args): 863 print(rpc.lvol.construct_lvol_bdev(args.client, 864 lvol_name=args.lvol_name, 865 size=args.size * 1024 * 1024, 866 thin_provision=args.thin_provision, 867 uuid=args.uuid, 868 lvs_name=args.lvs_name)) 869 870 p = subparsers.add_parser('construct_lvol_bdev', help='Add a bdev with an logical volume backend') 871 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 872 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 873 p.add_argument('-t', '--thin-provision', action='store_true', help='create lvol bdev as thin provisioned') 874 p.add_argument('lvol_name', help='name for this lvol') 875 p.add_argument('size', help='size in MiB for this bdev', type=int) 876 p.set_defaults(func=construct_lvol_bdev) 877 878 @call_cmd 879 def snapshot_lvol_bdev(args): 880 print(rpc.lvol.snapshot_lvol_bdev(args.client, 881 lvol_name=args.lvol_name, 882 snapshot_name=args.snapshot_name)) 883 884 p = subparsers.add_parser('snapshot_lvol_bdev', help='Create a snapshot of an lvol bdev') 885 p.add_argument('lvol_name', help='lvol bdev name') 886 p.add_argument('snapshot_name', help='lvol snapshot name') 887 p.set_defaults(func=snapshot_lvol_bdev) 888 889 @call_cmd 890 def clone_lvol_bdev(args): 891 print(rpc.lvol.clone_lvol_bdev(args.client, 892 snapshot_name=args.snapshot_name, 893 clone_name=args.clone_name)) 894 895 p = subparsers.add_parser('clone_lvol_bdev', help='Create a clone of an lvol snapshot') 896 p.add_argument('snapshot_name', help='lvol snapshot name') 897 p.add_argument('clone_name', help='lvol clone name') 898 p.set_defaults(func=clone_lvol_bdev) 899 900 @call_cmd 901 def rename_lvol_bdev(args): 902 rpc.lvol.rename_lvol_bdev(args.client, 903 old_name=args.old_name, 904 new_name=args.new_name) 905 906 p = subparsers.add_parser('rename_lvol_bdev', help='Change lvol bdev name') 907 p.add_argument('old_name', help='lvol bdev name') 908 p.add_argument('new_name', help='new lvol name') 909 p.set_defaults(func=rename_lvol_bdev) 910 911 @call_cmd 912 def inflate_lvol_bdev(args): 913 rpc.lvol.inflate_lvol_bdev(args.client, 914 name=args.name) 915 916 p = subparsers.add_parser('inflate_lvol_bdev', help='Make thin provisioned lvol a thick provisioned lvol') 917 p.add_argument('name', help='lvol bdev name') 918 p.set_defaults(func=inflate_lvol_bdev) 919 920 @call_cmd 921 def decouple_parent_lvol_bdev(args): 922 rpc.lvol.decouple_parent_lvol_bdev(args.client, 923 name=args.name) 924 925 p = subparsers.add_parser('decouple_parent_lvol_bdev', help='Decouple parent of lvol') 926 p.add_argument('name', help='lvol bdev name') 927 p.set_defaults(func=decouple_parent_lvol_bdev) 928 929 @call_cmd 930 def resize_lvol_bdev(args): 931 rpc.lvol.resize_lvol_bdev(args.client, 932 name=args.name, 933 size=args.size * 1024 * 1024) 934 935 p = subparsers.add_parser('resize_lvol_bdev', help='Resize existing lvol bdev') 936 p.add_argument('name', help='lvol bdev name') 937 p.add_argument('size', help='new size in MiB for this bdev', type=int) 938 p.set_defaults(func=resize_lvol_bdev) 939 940 @call_cmd 941 def destroy_lvol_bdev(args): 942 rpc.lvol.destroy_lvol_bdev(args.client, 943 name=args.name) 944 945 p = subparsers.add_parser('destroy_lvol_bdev', help='Destroy a logical volume') 946 p.add_argument('name', help='lvol bdev name') 947 p.set_defaults(func=destroy_lvol_bdev) 948 949 @call_cmd 950 def destroy_lvol_store(args): 951 rpc.lvol.destroy_lvol_store(args.client, 952 uuid=args.uuid, 953 lvs_name=args.lvs_name) 954 955 p = subparsers.add_parser('destroy_lvol_store', help='Destroy an logical volume store') 956 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 957 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 958 p.set_defaults(func=destroy_lvol_store) 959 960 @call_cmd 961 def get_lvol_stores(args): 962 print_dict(rpc.lvol.get_lvol_stores(args.client, 963 uuid=args.uuid, 964 lvs_name=args.lvs_name)) 965 966 p = subparsers.add_parser('get_lvol_stores', help='Display current logical volume store list') 967 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 968 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 969 p.set_defaults(func=get_lvol_stores) 970 971 @call_cmd 972 def get_raid_bdevs(args): 973 print_array(rpc.bdev.get_raid_bdevs(args.client, 974 category=args.category)) 975 976 p = subparsers.add_parser('get_raid_bdevs', help="""This is used to list all the raid bdev names based on the input category 977 requested. Category should be one of 'all', 'online', 'configuring' or 'offline'. 'all' means all the raid bdevs whether 978 they are online or configuring or offline. 'online' is the raid bdev which is registered with bdev layer. 'configuring' 979 is the raid bdev which does not have full configuration discovered yet. 'offline' is the raid bdev which is not registered 980 with bdev as of now and it has encountered any error or user has requested to offline the raid bdev""") 981 p.add_argument('category', help='all or online or configuring or offline') 982 p.set_defaults(func=get_raid_bdevs) 983 984 @call_cmd 985 def construct_raid_bdev(args): 986 base_bdevs = [] 987 for u in args.base_bdevs.strip().split(" "): 988 base_bdevs.append(u) 989 990 rpc.bdev.construct_raid_bdev(args.client, 991 name=args.name, 992 strip_size=args.strip_size, 993 raid_level=args.raid_level, 994 base_bdevs=base_bdevs) 995 p = subparsers.add_parser('construct_raid_bdev', help='Construct new raid bdev') 996 p.add_argument('-n', '--name', help='raid bdev name', required=True) 997 p.add_argument('-s', '--strip-size', help='strip size in KB', type=int, required=True) 998 p.add_argument('-r', '--raid-level', help='raid level, only raid level 0 is supported', type=int, required=True) 999 p.add_argument('-b', '--base-bdevs', help='base bdevs name, whitespace separated list in quotes', required=True) 1000 p.set_defaults(func=construct_raid_bdev) 1001 1002 @call_cmd 1003 def destroy_raid_bdev(args): 1004 rpc.bdev.destroy_raid_bdev(args.client, 1005 name=args.name) 1006 p = subparsers.add_parser('destroy_raid_bdev', help='Destroy existing raid bdev') 1007 p.add_argument('name', help='raid bdev name') 1008 p.set_defaults(func=destroy_raid_bdev) 1009 1010 # split 1011 @call_cmd 1012 def construct_split_vbdev(args): 1013 print_array(rpc.bdev.construct_split_vbdev(args.client, 1014 base_bdev=args.base_bdev, 1015 split_count=args.split_count, 1016 split_size_mb=args.split_size_mb)) 1017 1018 p = subparsers.add_parser('construct_split_vbdev', help="""Add given disk name to split config. If bdev with base_name 1019 name exist the split bdevs will be created right away, if not split bdevs will be created when base bdev became 1020 available (during examination process).""") 1021 p.add_argument('base_bdev', help='base bdev name') 1022 p.add_argument('-s', '--split-size-mb', help='size in MiB for each bdev', type=int, default=0) 1023 p.add_argument('split_count', help="""Optional - number of split bdevs to create. Total size * split_count must not 1024 exceed the base bdev size.""", type=int) 1025 p.set_defaults(func=construct_split_vbdev) 1026 1027 @call_cmd 1028 def destruct_split_vbdev(args): 1029 rpc.bdev.destruct_split_vbdev(args.client, 1030 base_bdev=args.base_bdev) 1031 1032 p = subparsers.add_parser('destruct_split_vbdev', help="""Delete split config with all created splits.""") 1033 p.add_argument('base_bdev', help='base bdev name') 1034 p.set_defaults(func=destruct_split_vbdev) 1035 1036 # nbd 1037 @call_cmd 1038 def start_nbd_disk(args): 1039 print(rpc.nbd.start_nbd_disk(args.client, 1040 bdev_name=args.bdev_name, 1041 nbd_device=args.nbd_device)) 1042 1043 p = subparsers.add_parser('start_nbd_disk', help='Export a bdev as a nbd disk') 1044 p.add_argument('bdev_name', help='Blockdev name to be exported. Example: Malloc0.') 1045 p.add_argument('nbd_device', help='Nbd device name to be assigned. Example: /dev/nbd0.') 1046 p.set_defaults(func=start_nbd_disk) 1047 1048 @call_cmd 1049 def stop_nbd_disk(args): 1050 rpc.nbd.stop_nbd_disk(args.client, 1051 nbd_device=args.nbd_device) 1052 1053 p = subparsers.add_parser('stop_nbd_disk', help='Stop a nbd disk') 1054 p.add_argument('nbd_device', help='Nbd device name to be stopped. Example: /dev/nbd0.') 1055 p.set_defaults(func=stop_nbd_disk) 1056 1057 @call_cmd 1058 def get_nbd_disks(args): 1059 print_dict(rpc.nbd.get_nbd_disks(args.client, 1060 nbd_device=args.nbd_device)) 1061 1062 p = subparsers.add_parser('get_nbd_disks', help='Display full or specified nbd device list') 1063 p.add_argument('-n', '--nbd-device', help="Path of the nbd device. Example: /dev/nbd0", required=False) 1064 p.set_defaults(func=get_nbd_disks) 1065 1066 # net 1067 @call_cmd 1068 def add_ip_address(args): 1069 rpc.net.add_ip_address(args.client, args) 1070 1071 p = subparsers.add_parser('add_ip_address', help='Add IP address') 1072 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1073 p.add_argument('ip_addr', help='ip address will be added.') 1074 p.set_defaults(func=add_ip_address) 1075 1076 @call_cmd 1077 def delete_ip_address(args): 1078 rpc.net.delete_ip_address(args.client, args) 1079 1080 p = subparsers.add_parser('delete_ip_address', help='Delete IP address') 1081 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1082 p.add_argument('ip_addr', help='ip address will be deleted.') 1083 p.set_defaults(func=delete_ip_address) 1084 1085 @call_cmd 1086 def get_interfaces(args): 1087 print_dict(rpc.net.get_interfaces(args.client, args)) 1088 1089 p = subparsers.add_parser( 1090 'get_interfaces', help='Display current interface list') 1091 p.set_defaults(func=get_interfaces) 1092 1093 # NVMe-oF 1094 @call_cmd 1095 def set_nvmf_target_options(args): 1096 rpc.nvmf.set_nvmf_target_options(args.client, 1097 max_queue_depth=args.max_queue_depth, 1098 max_qpairs_per_ctrlr=args.max_qpairs_per_ctrlr, 1099 in_capsule_data_size=args.in_capsule_data_size, 1100 max_io_size=args.max_io_size, 1101 max_subsystems=args.max_subsystems, 1102 io_unit_size=args.io_unit_size) 1103 1104 p = subparsers.add_parser('set_nvmf_target_options', help='Set NVMf target options') 1105 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int) 1106 p.add_argument('-p', '--max-qpairs-per-ctrlr', help='Max number of SQ and CQ per controller', type=int) 1107 p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int) 1108 p.add_argument('-i', '--max-io-size', help='Max I/O size (bytes)', type=int) 1109 p.add_argument('-x', '--max-subsystems', help='Max number of NVMf subsystems', type=int) 1110 p.add_argument('-u', '--io-unit-size', help='I/O unit size (bytes)', type=int) 1111 p.set_defaults(func=set_nvmf_target_options) 1112 1113 @call_cmd 1114 def set_nvmf_target_config(args): 1115 rpc.nvmf.set_nvmf_target_config(args.client, 1116 acceptor_poll_rate=args.acceptor_poll_rate) 1117 1118 p = subparsers.add_parser('set_nvmf_target_config', help='Set NVMf target config') 1119 p.add_argument('-r', '--acceptor-poll-rate', help='Polling interval of the acceptor for incoming connections (usec)', type=int) 1120 p.set_defaults(func=set_nvmf_target_config) 1121 1122 @call_cmd 1123 def get_nvmf_subsystems(args): 1124 print_dict(rpc.nvmf.get_nvmf_subsystems(args.client)) 1125 1126 p = subparsers.add_parser('get_nvmf_subsystems', 1127 help='Display nvmf subsystems') 1128 p.set_defaults(func=get_nvmf_subsystems) 1129 1130 @call_cmd 1131 def construct_nvmf_subsystem(args): 1132 listen_addresses = None 1133 hosts = None 1134 namespaces = None 1135 if args.listen: 1136 listen_addresses = [ 1137 dict( 1138 u.split( 1139 ":", 1140 1) for u in a.split(" ")) for a in args.listen.split(",")] 1141 1142 if args.hosts: 1143 hosts = [] 1144 for u in args.hosts.strip().split(" "): 1145 hosts.append(u) 1146 1147 if args.namespaces: 1148 namespaces = [] 1149 for u in args.namespaces.strip().split(" "): 1150 bdev_name = u 1151 nsid = 0 1152 if ':' in u: 1153 (bdev_name, nsid) = u.split(":") 1154 1155 ns_params = {'bdev_name': bdev_name} 1156 1157 nsid = int(nsid) 1158 if nsid != 0: 1159 ns_params['nsid'] = nsid 1160 1161 namespaces.append(ns_params) 1162 1163 rpc.nvmf.construct_nvmf_subsystem(args.client, 1164 nqn=args.nqn, 1165 listen_addresses=listen_addresses, 1166 hosts=hosts, 1167 allow_any_host=args.allow_any_host, 1168 serial_number=args.serial_number, 1169 namespaces=namespaces, 1170 max_namespaces=args.max_namespaces) 1171 1172 p = subparsers.add_parser('construct_nvmf_subsystem', help='Add a nvmf subsystem') 1173 p.add_argument('nqn', help='Target nqn(ASCII)') 1174 p.add_argument('listen', help="""comma-separated list of Listen <trtype:transport_name traddr:address trsvcid:port_id> pairs enclosed 1175 in quotes. Format: 'trtype:transport0 traddr:traddr0 trsvcid:trsvcid0,trtype:transport1 traddr:traddr1 trsvcid:trsvcid1' etc 1176 Example: 'trtype:RDMA traddr:192.168.100.8 trsvcid:4420,trtype:RDMA traddr:192.168.100.9 trsvcid:4420'""") 1177 p.add_argument('hosts', help="""Whitespace-separated list of host nqn list. 1178 Format: 'nqn1 nqn2' etc 1179 Example: 'nqn.2016-06.io.spdk:init nqn.2016-07.io.spdk:init'""") 1180 p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce host NQN whitelist)") 1181 p.add_argument("-s", "--serial-number", help=""" 1182 Format: 'sn' etc 1183 Example: 'SPDK00000000000001'""", default='0000:00:01.0') 1184 p.add_argument("-n", "--namespaces", help="""Whitespace-separated list of namespaces 1185 Format: 'bdev_name1[:nsid1] bdev_name2[:nsid2] bdev_name3[:nsid3]' etc 1186 Example: '1:Malloc0 2:Malloc1 3:Malloc2' 1187 *** The devices must pre-exist ***""") 1188 p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed to added during active connection", 1189 type=int, default=0) 1190 p.set_defaults(func=construct_nvmf_subsystem) 1191 1192 @call_cmd 1193 def delete_nvmf_subsystem(args): 1194 rpc.nvmf.delete_nvmf_subsystem(args.client, 1195 nqn=args.subsystem_nqn) 1196 1197 p = subparsers.add_parser('delete_nvmf_subsystem', 1198 help='Delete a nvmf subsystem') 1199 p.add_argument('subsystem_nqn', 1200 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 1201 p.set_defaults(func=delete_nvmf_subsystem) 1202 1203 @call_cmd 1204 def nvmf_subsystem_add_listener(args): 1205 rpc.nvmf.nvmf_subsystem_add_listener(args.client, 1206 nqn=args.nqn, 1207 trtype=args.trtype, 1208 traddr=args.traddr, 1209 adrfam=args.adrfam, 1210 trsvcid=args.trsvcid) 1211 1212 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 1213 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1214 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1215 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1216 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1217 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1218 p.set_defaults(func=nvmf_subsystem_add_listener) 1219 1220 @call_cmd 1221 def nvmf_subsystem_remove_listener(args): 1222 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, 1223 nqn=args.nqn, 1224 trtype=args.trtype, 1225 traddr=args.traddr, 1226 adrfam=args.adrfam, 1227 trsvcid=args.trsvcid) 1228 1229 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 1230 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1231 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1232 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1233 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1234 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1235 p.set_defaults(func=nvmf_subsystem_remove_listener) 1236 1237 @call_cmd 1238 def nvmf_subsystem_add_ns(args): 1239 rpc.nvmf.nvmf_subsystem_add_ns(args.client, 1240 nqn=args.nqn, 1241 bdev_name=args.bdev_name, 1242 nsid=args.nsid, 1243 nguid=args.nguid, 1244 eui64=args.eui64, 1245 uuid=args.uuid) 1246 1247 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 1248 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1249 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 1250 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 1251 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 1252 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 1253 p.add_argument('-u', '--uuid', help='Namespace UUID (optional)') 1254 p.set_defaults(func=nvmf_subsystem_add_ns) 1255 1256 @call_cmd 1257 def nvmf_subsystem_remove_ns(args): 1258 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, 1259 nqn=args.nqn, 1260 nsid=args.nsid) 1261 1262 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 1263 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1264 p.add_argument('nsid', help='The requested NSID', type=int) 1265 p.set_defaults(func=nvmf_subsystem_remove_ns) 1266 1267 @call_cmd 1268 def nvmf_subsystem_add_host(args): 1269 rpc.nvmf.nvmf_subsystem_add_host(args.client, 1270 nqn=args.nqn, 1271 host=args.host) 1272 1273 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 1274 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1275 p.add_argument('host', help='Host NQN to allow') 1276 p.set_defaults(func=nvmf_subsystem_add_host) 1277 1278 @call_cmd 1279 def nvmf_subsystem_remove_host(args): 1280 rpc.nvmf.nvmf_subsystem_remove_host(args.client, 1281 nqn=args.nqn, 1282 host=args.host) 1283 1284 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 1285 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1286 p.add_argument('host', help='Host NQN to remove') 1287 p.set_defaults(func=nvmf_subsystem_remove_host) 1288 1289 @call_cmd 1290 def nvmf_subsystem_allow_any_host(args): 1291 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, 1292 nqn=args.nqn, 1293 disable=args.disable) 1294 1295 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 1296 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1297 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 1298 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 1299 p.set_defaults(func=nvmf_subsystem_allow_any_host) 1300 1301 # pmem 1302 @call_cmd 1303 def create_pmem_pool(args): 1304 num_blocks = int((args.total_size * 1024 * 1024) / args.block_size) 1305 rpc.pmem.create_pmem_pool(args.client, 1306 pmem_file=args.pmem_file, 1307 num_blocks=num_blocks, 1308 block_size=args.block_size) 1309 1310 p = subparsers.add_parser('create_pmem_pool', help='Create pmem pool') 1311 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1312 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 1313 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 1314 p.set_defaults(func=create_pmem_pool) 1315 1316 @call_cmd 1317 def pmem_pool_info(args): 1318 print_dict(rpc.pmem.pmem_pool_info(args.client, 1319 pmem_file=args.pmem_file)) 1320 1321 p = subparsers.add_parser('pmem_pool_info', help='Display pmem pool info and check consistency') 1322 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1323 p.set_defaults(func=pmem_pool_info) 1324 1325 @call_cmd 1326 def delete_pmem_pool(args): 1327 rpc.pmem.delete_pmem_pool(args.client, 1328 pmem_file=args.pmem_file) 1329 1330 p = subparsers.add_parser('delete_pmem_pool', help='Delete pmem pool') 1331 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1332 p.set_defaults(func=delete_pmem_pool) 1333 1334 # subsystem 1335 @call_cmd 1336 def get_subsystems(args): 1337 print_dict(rpc.subsystem.get_subsystems(args.client)) 1338 1339 p = subparsers.add_parser('get_subsystems', help="""Print subsystems array in initialization order. Each subsystem 1340 entry contain (unsorted) array of subsystems it depends on.""") 1341 p.set_defaults(func=get_subsystems) 1342 1343 @call_cmd 1344 def get_subsystem_config(args): 1345 print_dict(rpc.subsystem.get_subsystem_config(args.client, args.name)) 1346 1347 p = subparsers.add_parser('get_subsystem_config', help="""Print subsystem configuration""") 1348 p.add_argument('name', help='Name of subsystem to query') 1349 p.set_defaults(func=get_subsystem_config) 1350 1351 # vhost 1352 @call_cmd 1353 def set_vhost_controller_coalescing(args): 1354 rpc.vhost.set_vhost_controller_coalescing(args.client, 1355 ctrlr=args.ctrlr, 1356 delay_base_us=args.delay_base_us, 1357 iops_threshold=args.iops_threshold) 1358 1359 p = subparsers.add_parser('set_vhost_controller_coalescing', help='Set vhost controller coalescing') 1360 p.add_argument('ctrlr', help='controller name') 1361 p.add_argument('delay_base_us', help='Base delay time', type=int) 1362 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 1363 p.set_defaults(func=set_vhost_controller_coalescing) 1364 1365 @call_cmd 1366 def construct_vhost_scsi_controller(args): 1367 rpc.vhost.construct_vhost_scsi_controller(args.client, 1368 ctrlr=args.ctrlr, 1369 cpumask=args.cpumask) 1370 1371 p = subparsers.add_parser( 1372 'construct_vhost_scsi_controller', help='Add new vhost controller') 1373 p.add_argument('ctrlr', help='controller name') 1374 p.add_argument('--cpumask', help='cpu mask for this controller') 1375 p.set_defaults(func=construct_vhost_scsi_controller) 1376 1377 @call_cmd 1378 def add_vhost_scsi_lun(args): 1379 rpc.vhost.add_vhost_scsi_lun(args.client, 1380 ctrlr=args.ctrlr, 1381 scsi_target_num=args.scsi_target_num, 1382 bdev_name=args.bdev_name) 1383 1384 p = subparsers.add_parser('add_vhost_scsi_lun', 1385 help='Add lun to vhost controller') 1386 p.add_argument('ctrlr', help='conntroller name where add lun') 1387 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 1388 p.add_argument('bdev_name', help='bdev name') 1389 p.set_defaults(func=add_vhost_scsi_lun) 1390 1391 @call_cmd 1392 def remove_vhost_scsi_target(args): 1393 rpc.vhost.remove_vhost_scsi_target(args.client, 1394 ctrlr=args.ctrlr, 1395 scsi_target_num=args.scsi_target_num) 1396 1397 p = subparsers.add_parser('remove_vhost_scsi_target', help='Remove target from vhost controller') 1398 p.add_argument('ctrlr', help='controller name to remove target from') 1399 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 1400 p.set_defaults(func=remove_vhost_scsi_target) 1401 1402 @call_cmd 1403 def construct_vhost_blk_controller(args): 1404 rpc.vhost.construct_vhost_blk_controller(args.client, 1405 ctrlr=args.ctrlr, 1406 dev_name=args.dev_name, 1407 cpumask=args.cpumask, 1408 readonly=args.readonly) 1409 1410 p = subparsers.add_parser('construct_vhost_blk_controller', help='Add a new vhost block controller') 1411 p.add_argument('ctrlr', help='controller name') 1412 p.add_argument('dev_name', help='device name') 1413 p.add_argument('--cpumask', help='cpu mask for this controller') 1414 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 1415 p.set_defaults(func=construct_vhost_blk_controller) 1416 1417 @call_cmd 1418 def construct_vhost_nvme_controller(args): 1419 rpc.vhost.construct_vhost_nvme_controller(args.client, 1420 ctrlr=args.ctrlr, 1421 io_queues=args.io_queues, 1422 cpumask=args.cpumask) 1423 1424 p = subparsers.add_parser('construct_vhost_nvme_controller', help='Add new vhost controller') 1425 p.add_argument('ctrlr', help='controller name') 1426 p.add_argument('io_queues', help='number of IO queues for the controller', type=int) 1427 p.add_argument('--cpumask', help='cpu mask for this controller') 1428 p.set_defaults(func=construct_vhost_nvme_controller) 1429 1430 @call_cmd 1431 def add_vhost_nvme_ns(args): 1432 rpc.vhost.add_vhost_nvme_ns(args.client, 1433 ctrlr=args.ctrlr, 1434 bdev_name=args.bdev_name) 1435 1436 p = subparsers.add_parser('add_vhost_nvme_ns', help='Add a Namespace to vhost controller') 1437 p.add_argument('ctrlr', help='conntroller name where add a Namespace') 1438 p.add_argument('bdev_name', help='block device name for a new Namespace') 1439 p.set_defaults(func=add_vhost_nvme_ns) 1440 1441 @call_cmd 1442 def get_vhost_controllers(args): 1443 print_dict(rpc.vhost.get_vhost_controllers(args.client)) 1444 1445 p = subparsers.add_parser('get_vhost_controllers', help='List vhost controllers') 1446 p.set_defaults(func=get_vhost_controllers) 1447 1448 @call_cmd 1449 def remove_vhost_controller(args): 1450 rpc.vhost.remove_vhost_controller(args.client, 1451 ctrlr=args.ctrlr) 1452 1453 p = subparsers.add_parser('remove_vhost_controller', help='Remove a vhost controller') 1454 p.add_argument('ctrlr', help='controller name') 1455 p.set_defaults(func=remove_vhost_controller) 1456 1457 @call_cmd 1458 def construct_virtio_dev(args): 1459 print_array(rpc.vhost.construct_virtio_dev(args.client, 1460 name=args.name, 1461 trtype=args.trtype, 1462 traddr=args.traddr, 1463 dev_type=args.dev_type, 1464 vq_count=args.vq_count, 1465 vq_size=args.vq_size)) 1466 1467 p = subparsers.add_parser('construct_virtio_dev', help="""Construct new virtio device using provided 1468 transport type and device type. In case of SCSI device type this implies scan and add bdevs offered by 1469 remote side. Result is array of added bdevs.""") 1470 p.add_argument('name', help="Use this name as base for new created bdevs") 1471 p.add_argument('-t', '--trtype', 1472 help='Virtio target transport type: pci or user', required=True) 1473 p.add_argument('-a', '--traddr', 1474 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 1475 p.add_argument('-d', '--dev-type', 1476 help='Device type: blk or scsi', required=True) 1477 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 1478 p.add_argument('--vq-size', help='Size of each queue', type=int) 1479 p.set_defaults(func=construct_virtio_dev) 1480 1481 @call_cmd 1482 def construct_virtio_user_scsi_bdev(args): 1483 print_array(rpc.vhost.construct_virtio_user_scsi_bdev(args.client, 1484 path=args.path, 1485 name=args.name, 1486 vq_count=args.vq_count, 1487 vq_size=args.vq_size)) 1488 1489 p = subparsers.add_parser('construct_virtio_user_scsi_bdev', help="""Connect to virtio user scsi device. 1490 This imply scan and add bdevs offered by remote side. 1491 Result is array of added bdevs.""") 1492 p.add_argument('path', help='Path to Virtio SCSI socket') 1493 p.add_argument('name', help="""Use this name as base instead of 'VirtioScsiN' 1494 Base will be used to construct new bdev's found on target by adding 't<TARGET_ID>' sufix.""") 1495 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 1496 p.add_argument('--vq-size', help='Size of each queue', type=int) 1497 p.set_defaults(func=construct_virtio_user_scsi_bdev) 1498 1499 @call_cmd 1500 def construct_virtio_pci_scsi_bdev(args): 1501 print_array(rpc.vhost.construct_virtio_pci_scsi_bdev(args.client, 1502 pci_address=args.pci_address, 1503 name=args.name)) 1504 1505 p = subparsers.add_parser('construct_virtio_pci_scsi_bdev', help="""Create a Virtio 1506 SCSI device from a virtio-pci device.""") 1507 p.add_argument('pci_address', help="""PCI address in domain:bus:device.function format or 1508 domain.bus.device.function format""") 1509 p.add_argument('name', help="""Name for the virtio device. 1510 It will be inhereted by all created bdevs, which are named n the following format: <name>t<target_id>""") 1511 p.set_defaults(func=construct_virtio_pci_scsi_bdev) 1512 1513 @call_cmd 1514 def get_virtio_scsi_devs(args): 1515 print_dict(rpc.vhost.get_virtio_scsi_devs(args.client)) 1516 1517 p = subparsers.add_parser('get_virtio_scsi_devs', help='List all Virtio-SCSI devices.') 1518 p.set_defaults(func=get_virtio_scsi_devs) 1519 1520 @call_cmd 1521 def remove_virtio_scsi_bdev(args): 1522 rpc.vhost.remove_virtio_scsi_bdev(args.client, 1523 name=args.name) 1524 1525 p = subparsers.add_parser('remove_virtio_scsi_bdev', help="""Remove a Virtio-SCSI device 1526 This will delete all bdevs exposed by this device""") 1527 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 1528 p.set_defaults(func=remove_virtio_scsi_bdev) 1529 1530 @call_cmd 1531 def construct_virtio_user_blk_bdev(args): 1532 print(rpc.vhost.construct_virtio_user_blk_bdev(args.client, 1533 path=args.path, 1534 name=args.name, 1535 vq_count=args.vq_count, 1536 vq_size=args.vq_size)) 1537 1538 p = subparsers.add_parser('construct_virtio_user_blk_bdev', help='Connect to a virtio user blk device.') 1539 p.add_argument('path', help='Path to Virtio BLK socket') 1540 p.add_argument('name', help='Name for the bdev') 1541 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 1542 p.add_argument('--vq-size', help='Size of each queue', type=int) 1543 p.set_defaults(func=construct_virtio_user_blk_bdev) 1544 1545 @call_cmd 1546 def construct_virtio_pci_blk_bdev(args): 1547 print(rpc.vhost.construct_virtio_pci_blk_bdev(args.client, 1548 pci_address=args.pci_address, 1549 name=args.name)) 1550 1551 p = subparsers.add_parser('construct_virtio_pci_blk_bdev', help='Create a Virtio Blk device from a virtio-pci device.') 1552 p.add_argument('pci_address', help="""PCI address in domain:bus:device.function format or 1553 domain.bus.device.function format""") 1554 p.add_argument('name', help='Name for the bdev') 1555 p.set_defaults(func=construct_virtio_pci_blk_bdev) 1556 1557 # ioat 1558 @call_cmd 1559 def scan_ioat_copy_engine(args): 1560 pci_whitelist = [] 1561 if args.pci_whitelist: 1562 for w in args.pci_whitelist.strip().split(" "): 1563 pci_whitelist.append(w) 1564 rpc.ioat.scan_ioat_copy_engine(args.client, pci_whitelist) 1565 1566 p = subparsers.add_parser('scan_ioat_copy_engine', help='Set scan and enable IOAT copy engine offload.') 1567 p.add_argument('-w', '--pci-whitelist', help="""Whitespace-separated list of PCI addresses in 1568 domain:bus:device.function format or domain.bus.device.function format""") 1569 p.set_defaults(func=scan_ioat_copy_engine) 1570 1571 args = parser.parse_args() 1572 1573 try: 1574 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.verbose, args.timeout) 1575 except JSONRPCException as ex: 1576 print(ex.message) 1577 exit(1) 1578 args.func(args) 1579