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