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