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