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