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