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