1#!/usr/bin/env python3 2 3from rpc.client import print_dict, print_json, JSONRPCException 4from rpc.helpers import deprecated_aliases 5 6import logging 7import argparse 8import rpc 9import sys 10import shlex 11import json 12 13try: 14 from shlex import quote 15except ImportError: 16 from pipes import quote 17 18 19def print_array(a): 20 print(" ".join((quote(v) for v in a))) 21 22 23if __name__ == "__main__": 24 parser = argparse.ArgumentParser( 25 description='SPDK RPC command line interface') 26 parser.add_argument('-s', dest='server_addr', 27 help='RPC domain socket path or IP address', default='/var/tmp/spdk.sock') 28 parser.add_argument('-p', dest='port', 29 help='RPC port number (if server_addr is IP address)', 30 default=5260, type=int) 31 parser.add_argument('-t', dest='timeout', 32 help='Timeout as a floating point number expressed in seconds waiting for response. Default: 60.0', 33 default=60.0, type=float) 34 parser.add_argument('-v', dest='verbose', action='store_const', const="INFO", 35 help='Set verbose mode to INFO', default="ERROR") 36 parser.add_argument('--verbose', dest='verbose', choices=['DEBUG', 'INFO', 'ERROR'], 37 help="""Set verbose level. """) 38 parser.add_argument('--dry_run', dest='dry_run', action='store_true', help="Display request and exit") 39 parser.set_defaults(dry_run=False) 40 subparsers = parser.add_subparsers(help='RPC methods', dest='called_rpc_name') 41 42 def framework_start_init(args): 43 rpc.framework_start_init(args.client) 44 45 p = subparsers.add_parser('framework_start_init', aliases=['start_subsystem_init'], 46 help='Start initialization of subsystems') 47 p.set_defaults(func=framework_start_init) 48 49 def framework_wait_init(args): 50 rpc.framework_wait_init(args.client) 51 52 p = subparsers.add_parser('framework_wait_init', aliases=['wait_subsystem_init'], 53 help='Block until subsystems have been initialized') 54 p.set_defaults(func=framework_wait_init) 55 56 def rpc_get_methods(args): 57 print_dict(rpc.rpc_get_methods(args.client, 58 current=args.current, 59 include_aliases=args.include_aliases)) 60 61 p = subparsers.add_parser('rpc_get_methods', aliases=['get_rpc_methods'], 62 help='Get list of supported RPC methods') 63 p.add_argument('-c', '--current', help='Get list of RPC methods only callable in the current state.', action='store_true') 64 p.add_argument('-i', '--include-aliases', help='include RPC aliases', action='store_true') 65 p.set_defaults(func=rpc_get_methods) 66 67 def spdk_get_version(args): 68 print_json(rpc.spdk_get_version(args.client)) 69 70 p = subparsers.add_parser('spdk_get_version', aliases=['get_spdk_version'], 71 help='Get SPDK version') 72 p.set_defaults(func=spdk_get_version) 73 74 def save_config(args): 75 rpc.save_config(args.client, 76 sys.stdout, 77 indent=args.indent) 78 79 p = subparsers.add_parser('save_config', help="""Write current (live) configuration of SPDK subsystems and targets to stdout. 80 """) 81 p.add_argument('-i', '--indent', help="""Indent level. Value less than 0 mean compact mode. Default indent level is 2. 82 """, type=int, default=2) 83 p.set_defaults(func=save_config) 84 85 def load_config(args): 86 rpc.load_config(args.client, sys.stdin, 87 include_aliases=args.include_aliases) 88 89 p = subparsers.add_parser('load_config', help="""Configure SPDK subsystems and targets using JSON RPC read from stdin.""") 90 p.add_argument('-i', '--include-aliases', help='include RPC aliases', action='store_true') 91 p.set_defaults(func=load_config) 92 93 def save_subsystem_config(args): 94 rpc.save_subsystem_config(args.client, 95 sys.stdout, 96 indent=args.indent, 97 name=args.name) 98 99 p = subparsers.add_parser('save_subsystem_config', help="""Write current (live) configuration of SPDK subsystem to stdout. 100 """) 101 p.add_argument('-i', '--indent', help="""Indent level. Value less than 0 mean compact mode. Default indent level is 2. 102 """, type=int, default=2) 103 p.add_argument('-n', '--name', help='Name of subsystem', required=True) 104 p.set_defaults(func=save_subsystem_config) 105 106 def load_subsystem_config(args): 107 rpc.load_subsystem_config(args.client, 108 sys.stdin) 109 110 p = subparsers.add_parser('load_subsystem_config', help="""Configure SPDK subsystem using JSON RPC read from stdin.""") 111 p.set_defaults(func=load_subsystem_config) 112 113 # app 114 def spdk_kill_instance(args): 115 rpc.app.spdk_kill_instance(args.client, 116 sig_name=args.sig_name) 117 118 p = subparsers.add_parser('spdk_kill_instance', aliases=['kill_instance'], 119 help='Send signal to instance') 120 p.add_argument('sig_name', help='signal will be sent to server.') 121 p.set_defaults(func=spdk_kill_instance) 122 123 def framework_monitor_context_switch(args): 124 enabled = None 125 if args.enable: 126 enabled = True 127 if args.disable: 128 enabled = False 129 print_dict(rpc.app.framework_monitor_context_switch(args.client, 130 enabled=enabled)) 131 132 p = subparsers.add_parser('framework_monitor_context_switch', aliases=['context_switch_monitor'], 133 help='Control whether the context switch monitor is enabled') 134 p.add_argument('-e', '--enable', action='store_true', help='Enable context switch monitoring') 135 p.add_argument('-d', '--disable', action='store_true', help='Disable context switch monitoring') 136 p.set_defaults(func=framework_monitor_context_switch) 137 138 def framework_get_reactors(args): 139 print_dict(rpc.app.framework_get_reactors(args.client)) 140 141 p = subparsers.add_parser( 142 'framework_get_reactors', help='Display list of all reactors') 143 p.set_defaults(func=framework_get_reactors) 144 145 # bdev 146 def bdev_set_options(args): 147 rpc.bdev.bdev_set_options(args.client, 148 bdev_io_pool_size=args.bdev_io_pool_size, 149 bdev_io_cache_size=args.bdev_io_cache_size) 150 151 p = subparsers.add_parser('bdev_set_options', aliases=['set_bdev_options'], 152 help="""Set options of bdev subsystem""") 153 p.add_argument('-p', '--bdev-io-pool-size', help='Number of bdev_io structures in shared buffer pool', type=int) 154 p.add_argument('-c', '--bdev-io-cache-size', help='Maximum number of bdev_io structures cached per thread', type=int) 155 p.set_defaults(func=bdev_set_options) 156 157 def bdev_compress_create(args): 158 print_json(rpc.bdev.bdev_compress_create(args.client, 159 base_bdev_name=args.base_bdev_name, 160 pm_path=args.pm_path)) 161 162 p = subparsers.add_parser('bdev_compress_create', aliases=['construct_compress_bdev'], 163 help='Add a compress vbdev') 164 p.add_argument('-b', '--base_bdev_name', help="Name of the base bdev") 165 p.add_argument('-p', '--pm_path', help="Path to persistent memory") 166 p.set_defaults(func=bdev_compress_create) 167 168 def bdev_compress_delete(args): 169 rpc.bdev.bdev_compress_delete(args.client, 170 name=args.name) 171 172 p = subparsers.add_parser('bdev_compress_delete', aliases=['delete_compress_bdev'], 173 help='Delete a compress disk') 174 p.add_argument('name', help='compress bdev name') 175 p.set_defaults(func=bdev_compress_delete) 176 177 def set_compress_pmd(args): 178 rpc.bdev.set_compress_pmd(args.client, 179 pmd=args.pmd) 180 p = subparsers.add_parser('set_compress_pmd', help='Set pmd option for a compress disk') 181 p.add_argument('-p', '--pmd', type=int, help='0 = auto-select, 1= QAT only, 2 = ISAL only') 182 p.set_defaults(func=set_compress_pmd) 183 184 def bdev_compress_get_orphans(args): 185 print_dict(rpc.bdev.bdev_compress_get_orphans(args.client, 186 name=args.name)) 187 p = subparsers.add_parser( 188 'bdev_compress_get_orphans', help='Display list of orphaned compress bdevs.') 189 p.add_argument('-b', '--name', help="Name of a comp bdev. Example: COMP_Nvme0n1", required=False) 190 p.set_defaults(func=bdev_compress_get_orphans) 191 192 def bdev_crypto_create(args): 193 print_json(rpc.bdev.bdev_crypto_create(args.client, 194 base_bdev_name=args.base_bdev_name, 195 name=args.name, 196 crypto_pmd=args.crypto_pmd, 197 key=args.key)) 198 p = subparsers.add_parser('bdev_crypto_create', aliases=['construct_crypto_bdev'], 199 help='Add a crypto vbdev') 200 p.add_argument('base_bdev_name', help="Name of the base bdev") 201 p.add_argument('name', help="Name of the crypto vbdev") 202 p.add_argument('crypto_pmd', help="Name of the crypto device driver") 203 p.add_argument('key', help="Key") 204 p.set_defaults(func=bdev_crypto_create) 205 206 def bdev_crypto_delete(args): 207 rpc.bdev.bdev_crypto_delete(args.client, 208 name=args.name) 209 210 p = subparsers.add_parser('bdev_crypto_delete', aliases=['delete_crypto_bdev'], 211 help='Delete a crypto disk') 212 p.add_argument('name', help='crypto bdev name') 213 p.set_defaults(func=bdev_crypto_delete) 214 215 def bdev_ocf_create(args): 216 print_json(rpc.bdev.bdev_ocf_create(args.client, 217 name=args.name, 218 mode=args.mode, 219 cache_bdev_name=args.cache_bdev_name, 220 core_bdev_name=args.core_bdev_name)) 221 p = subparsers.add_parser('bdev_ocf_create', aliases=['construct_ocf_bdev'], 222 help='Add an OCF block device') 223 p.add_argument('name', help='Name of resulting OCF bdev') 224 p.add_argument('mode', help='OCF cache mode', choices=['wb', 'wt', 'pt', 'wa', 'wi', 'wo']) 225 p.add_argument('cache_bdev_name', help='Name of underlying cache bdev') 226 p.add_argument('core_bdev_name', help='Name of unerlying core bdev') 227 p.set_defaults(func=bdev_ocf_create) 228 229 def bdev_ocf_delete(args): 230 rpc.bdev.bdev_ocf_delete(args.client, 231 name=args.name) 232 233 p = subparsers.add_parser('bdev_ocf_delete', aliases=['delete_ocf_bdev'], 234 help='Delete an OCF block device') 235 p.add_argument('name', help='Name of OCF bdev') 236 p.set_defaults(func=bdev_ocf_delete) 237 238 def bdev_ocf_get_stats(args): 239 print_dict(rpc.bdev.bdev_ocf_get_stats(args.client, 240 name=args.name)) 241 p = subparsers.add_parser('bdev_ocf_get_stats', aliases=['get_ocf_stats'], 242 help='Get statistics of chosen OCF block device') 243 p.add_argument('name', help='Name of OCF bdev') 244 p.set_defaults(func=bdev_ocf_get_stats) 245 246 def bdev_ocf_get_bdevs(args): 247 print_dict(rpc.bdev.bdev_ocf_get_bdevs(args.client, 248 name=args.name)) 249 p = subparsers.add_parser('bdev_ocf_get_bdevs', aliases=['get_ocf_bdevs'], 250 help='Get list of OCF devices including unregistered ones') 251 p.add_argument('name', nargs='?', default=None, help='name of OCF vbdev or name of cache device or name of core device (optional)') 252 p.set_defaults(func=bdev_ocf_get_bdevs) 253 254 def bdev_malloc_create(args): 255 num_blocks = (args.total_size * 1024 * 1024) // args.block_size 256 print_json(rpc.bdev.bdev_malloc_create(args.client, 257 num_blocks=int(num_blocks), 258 block_size=args.block_size, 259 name=args.name, 260 uuid=args.uuid)) 261 p = subparsers.add_parser('bdev_malloc_create', aliases=['construct_malloc_bdev'], 262 help='Create a bdev with malloc backend') 263 p.add_argument('-b', '--name', help="Name of the bdev") 264 p.add_argument('-u', '--uuid', help="UUID of the bdev") 265 p.add_argument( 266 'total_size', help='Size of malloc bdev in MB (float > 0)', type=float) 267 p.add_argument('block_size', help='Block size for this bdev', type=int) 268 p.set_defaults(func=bdev_malloc_create) 269 270 def bdev_malloc_delete(args): 271 rpc.bdev.bdev_malloc_delete(args.client, 272 name=args.name) 273 274 p = subparsers.add_parser('bdev_malloc_delete', aliases=['delete_malloc_bdev'], 275 help='Delete a malloc disk') 276 p.add_argument('name', help='malloc bdev name') 277 p.set_defaults(func=bdev_malloc_delete) 278 279 def bdev_null_create(args): 280 num_blocks = (args.total_size * 1024 * 1024) // args.block_size 281 print_json(rpc.bdev.bdev_null_create(args.client, 282 num_blocks=num_blocks, 283 block_size=args.block_size, 284 name=args.name, 285 uuid=args.uuid, 286 md_size=args.md_size, 287 dif_type=args.dif_type, 288 dif_is_head_of_md=args.dif_is_head_of_md)) 289 290 p = subparsers.add_parser('bdev_null_create', aliases=['construct_null_bdev'], 291 help='Add a bdev with null backend') 292 p.add_argument('name', help='Block device name') 293 p.add_argument('-u', '--uuid', help='UUID of the bdev') 294 p.add_argument( 295 'total_size', help='Size of null bdev in MB (int > 0)', type=int) 296 p.add_argument('block_size', help='Block size for this bdev', type=int) 297 p.add_argument('-m', '--md-size', type=int, 298 help='Metadata size for this bdev. Default 0') 299 p.add_argument('-t', '--dif-type', type=int, choices=[0, 1, 2, 3], 300 help='Protection information type. Default: 0 - no protection') 301 p.add_argument('-d', '--dif-is-head-of-md', action='store_true', 302 help='Protection information is in the first 8 bytes of metadata. Default: in the last 8 bytes') 303 p.set_defaults(func=bdev_null_create) 304 305 def bdev_null_delete(args): 306 rpc.bdev.bdev_null_delete(args.client, 307 name=args.name) 308 309 p = subparsers.add_parser('bdev_null_delete', aliases=['delete_null_bdev'], 310 help='Delete a null bdev') 311 p.add_argument('name', help='null bdev name') 312 p.set_defaults(func=bdev_null_delete) 313 314 def bdev_aio_create(args): 315 print_json(rpc.bdev.bdev_aio_create(args.client, 316 filename=args.filename, 317 name=args.name, 318 block_size=args.block_size)) 319 320 p = subparsers.add_parser('bdev_aio_create', aliases=['construct_aio_bdev'], 321 help='Add a bdev with aio backend') 322 p.add_argument('filename', help='Path to device or file (ex: /dev/sda)') 323 p.add_argument('name', help='Block device name') 324 p.add_argument('block_size', help='Block size for this bdev', type=int, nargs='?', default=0) 325 p.set_defaults(func=bdev_aio_create) 326 327 def bdev_aio_delete(args): 328 rpc.bdev.bdev_aio_delete(args.client, 329 name=args.name) 330 331 p = subparsers.add_parser('bdev_aio_delete', aliases=['delete_aio_bdev'], 332 help='Delete an aio disk') 333 p.add_argument('name', help='aio bdev name') 334 p.set_defaults(func=bdev_aio_delete) 335 336 def bdev_uring_create(args): 337 print_json(rpc.bdev.bdev_uring_create(args.client, 338 filename=args.filename, 339 name=args.name, 340 block_size=args.block_size)) 341 342 p = subparsers.add_parser('bdev_uring_create', help='Create a bdev with io_uring backend') 343 p.add_argument('filename', help='Path to device or file (ex: /dev/nvme0n1)') 344 p.add_argument('name', help='bdev name') 345 p.add_argument('block_size', help='Block size for this bdev', type=int, nargs='?', default=0) 346 p.set_defaults(func=bdev_uring_create) 347 348 def bdev_uring_delete(args): 349 rpc.bdev.bdev_uring_delete(args.client, 350 name=args.name) 351 352 p = subparsers.add_parser('bdev_uring_delete', help='Delete a uring bdev') 353 p.add_argument('name', help='uring bdev name') 354 p.set_defaults(func=bdev_uring_delete) 355 356 def bdev_nvme_set_options(args): 357 rpc.bdev.bdev_nvme_set_options(args.client, 358 action_on_timeout=args.action_on_timeout, 359 timeout_us=args.timeout_us, 360 retry_count=args.retry_count, 361 arbitration_burst=args.arbitration_burst, 362 low_priority_weight=args.low_priority_weight, 363 medium_priority_weight=args.medium_priority_weight, 364 high_priority_weight=args.high_priority_weight, 365 nvme_adminq_poll_period_us=args.nvme_adminq_poll_period_us, 366 nvme_ioq_poll_period_us=args.nvme_ioq_poll_period_us, 367 io_queue_requests=args.io_queue_requests, 368 delay_cmd_submit=args.delay_cmd_submit) 369 370 p = subparsers.add_parser('bdev_nvme_set_options', aliases=['set_bdev_nvme_options'], 371 help='Set options for the bdev nvme type. This is startup command.') 372 p.add_argument('-a', '--action-on-timeout', 373 help="Action to take on command time out. Valid valies are: none, reset, abort") 374 p.add_argument('-t', '--timeout-us', 375 help="Timeout for each command, in microseconds. If 0, don't track timeouts.", type=int) 376 p.add_argument('-n', '--retry-count', 377 help='the number of attempts per I/O when an I/O fails', type=int) 378 p.add_argument('--arbitration-burst', 379 help='the value is expressed as a power of two', type=int) 380 p.add_argument('--low-priority-weight', 381 help='the maximum number of commands that the controller may launch at one time from a low priority queue', type=int) 382 p.add_argument('--medium-priority-weight', 383 help='the maximum number of commands that the controller may launch at one time from a medium priority queue', type=int) 384 p.add_argument('--high-priority-weight', 385 help='the maximum number of commands that the controller may launch at one time from a high priority queue', type=int) 386 p.add_argument('-p', '--nvme-adminq-poll-period-us', 387 help='How often the admin queue is polled for asynchronous events', type=int) 388 p.add_argument('-i', '--nvme-ioq-poll-period-us', 389 help='How often to poll I/O queues for completions', type=int) 390 p.add_argument('-s', '--io-queue-requests', 391 help='The number of requests allocated for each NVMe I/O queue. Default: 512', type=int) 392 p.add_argument('-d', '--disable-delay-cmd-submit', 393 help='Disable delaying NVMe command submission, i.e. no batching of multiple commands', 394 action='store_false', dest='delay_cmd_submit', default=True) 395 p.set_defaults(func=bdev_nvme_set_options) 396 397 def bdev_nvme_set_hotplug(args): 398 rpc.bdev.bdev_nvme_set_hotplug(args.client, enable=args.enable, period_us=args.period_us) 399 400 p = subparsers.add_parser('bdev_nvme_set_hotplug', aliases=['set_bdev_nvme_hotplug'], 401 help='Set hotplug options for bdev nvme type.') 402 p.add_argument('-d', '--disable', dest='enable', default=False, action='store_false', help="Disable hotplug (default)") 403 p.add_argument('-e', '--enable', dest='enable', action='store_true', help="Enable hotplug") 404 p.add_argument('-r', '--period-us', 405 help='How often the hotplug is processed for insert and remove events', type=int) 406 p.set_defaults(func=bdev_nvme_set_hotplug) 407 408 def bdev_nvme_attach_controller(args): 409 print_array(rpc.bdev.bdev_nvme_attach_controller(args.client, 410 name=args.name, 411 trtype=args.trtype, 412 traddr=args.traddr, 413 adrfam=args.adrfam, 414 trsvcid=args.trsvcid, 415 subnqn=args.subnqn, 416 hostnqn=args.hostnqn, 417 hostaddr=args.hostaddr, 418 hostsvcid=args.hostsvcid, 419 prchk_reftag=args.prchk_reftag, 420 prchk_guard=args.prchk_guard)) 421 422 p = subparsers.add_parser('bdev_nvme_attach_controller', aliases=['construct_nvme_bdev'], 423 help='Add bdevs with nvme backend') 424 p.add_argument('-b', '--name', help="Name of the NVMe controller, prefix for each bdev name", required=True) 425 p.add_argument('-t', '--trtype', 426 help='NVMe-oF target trtype: e.g., rdma, pcie', required=True) 427 p.add_argument('-a', '--traddr', 428 help='NVMe-oF target address: e.g., an ip address or BDF', required=True) 429 p.add_argument('-f', '--adrfam', 430 help='NVMe-oF target adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 431 p.add_argument('-s', '--trsvcid', 432 help='NVMe-oF target trsvcid: e.g., a port number') 433 p.add_argument('-n', '--subnqn', help='NVMe-oF target subnqn') 434 p.add_argument('-q', '--hostnqn', help='NVMe-oF host subnqn') 435 p.add_argument('-i', '--hostaddr', 436 help='NVMe-oF host address: e.g., an ip address') 437 p.add_argument('-c', '--hostsvcid', 438 help='NVMe-oF host svcid: e.g., a port number') 439 p.add_argument('-r', '--prchk-reftag', 440 help='Enable checking of PI reference tag for I/O processing.', action='store_true') 441 p.add_argument('-g', '--prchk-guard', 442 help='Enable checking of PI guard for I/O processing.', action='store_true') 443 p.set_defaults(func=bdev_nvme_attach_controller) 444 445 def bdev_nvme_get_controllers(args): 446 print_dict(rpc.nvme.bdev_nvme_get_controllers(args.client, 447 name=args.name)) 448 449 p = subparsers.add_parser( 450 'bdev_nvme_get_controllers', aliases=['get_nvme_controllers'], 451 help='Display current NVMe controllers list or required NVMe controller') 452 p.add_argument('-n', '--name', help="Name of the NVMe controller. Example: Nvme0", required=False) 453 p.set_defaults(func=bdev_nvme_get_controllers) 454 455 def bdev_nvme_detach_controller(args): 456 rpc.bdev.bdev_nvme_detach_controller(args.client, 457 name=args.name) 458 459 p = subparsers.add_parser('bdev_nvme_detach_controller', aliases=['delete_nvme_controller'], 460 help='Detach an NVMe controller and delete any associated bdevs') 461 p.add_argument('name', help="Name of the controller") 462 p.set_defaults(func=bdev_nvme_detach_controller) 463 464 def bdev_nvme_cuse_register(args): 465 rpc.bdev.bdev_nvme_cuse_register(args.client, 466 name=args.name) 467 468 p = subparsers.add_parser('bdev_nvme_cuse_register', 469 help='Register CUSE devices on NVMe controller') 470 p.add_argument('-n', '--name', 471 help='Name of the NVMe controller. Example: Nvme0', required=True) 472 p.set_defaults(func=bdev_nvme_cuse_register) 473 474 def bdev_nvme_cuse_unregister(args): 475 rpc.bdev.bdev_nvme_cuse_unregister(args.client, 476 name=args.name) 477 478 p = subparsers.add_parser('bdev_nvme_cuse_unregister', 479 help='Unregister CUSE devices on NVMe controller') 480 p.add_argument('-n', '--name', 481 help='Name of the NVMe controller. Example: Nvme0', required=True) 482 p.set_defaults(func=bdev_nvme_cuse_unregister) 483 484 def bdev_zone_block_create(args): 485 print_json(rpc.bdev.bdev_zone_block_create(args.client, 486 name=args.name, 487 base_bdev=args.base_bdev, 488 zone_capacity=args.zone_capacity, 489 optimal_open_zones=args.optimal_open_zones)) 490 491 p = subparsers.add_parser('bdev_zone_block_create', 492 help='Create virtual zone namespace device with block device backend') 493 p.add_argument('-b', '--name', help="Name of the zone device", required=True) 494 p.add_argument('-n', '--base-bdev', help='Name of underlying, non-zoned bdev', required=True) 495 p.add_argument('-z', '--zone-capacity', help='Surfaced zone capacity in blocks', type=int, required=True) 496 p.add_argument('-o', '--optimal-open-zones', help='Number of zones required to reach optimal write speed', type=int, required=True) 497 p.set_defaults(func=bdev_zone_block_create) 498 499 def bdev_zone_block_delete(args): 500 rpc.bdev.bdev_zone_block_delete(args.client, 501 name=args.name) 502 503 p = subparsers.add_parser('bdev_zone_block_delete', help='Delete a virtual zone namespace device') 504 p.add_argument('name', help='Virtual zone bdev name') 505 p.set_defaults(func=bdev_zone_block_delete) 506 507 def bdev_rbd_create(args): 508 config = None 509 if args.config: 510 config = {} 511 for entry in args.config: 512 parts = entry.split('=', 1) 513 if len(parts) != 2: 514 raise Exception('--config %s not in key=value form' % entry) 515 config[parts[0]] = parts[1] 516 print_json(rpc.bdev.bdev_rbd_create(args.client, 517 name=args.name, 518 user=args.user, 519 config=config, 520 pool_name=args.pool_name, 521 rbd_name=args.rbd_name, 522 block_size=args.block_size)) 523 524 p = subparsers.add_parser('bdev_rbd_create', aliases=['construct_rbd_bdev'], 525 help='Add a bdev with ceph rbd backend') 526 p.add_argument('-b', '--name', help="Name of the bdev", required=False) 527 p.add_argument('--user', help="Ceph user name (i.e. admin, not client.admin)", required=False) 528 p.add_argument('--config', action='append', metavar='key=value', 529 help="adds a key=value configuration option for rados_conf_set (default: rely on config file)") 530 p.add_argument('pool_name', help='rbd pool name') 531 p.add_argument('rbd_name', help='rbd image name') 532 p.add_argument('block_size', help='rbd block size', type=int) 533 p.set_defaults(func=bdev_rbd_create) 534 535 def bdev_rbd_delete(args): 536 rpc.bdev.bdev_rbd_delete(args.client, 537 name=args.name) 538 539 p = subparsers.add_parser('bdev_rbd_delete', aliases=['delete_rbd_bdev'], 540 help='Delete a rbd bdev') 541 p.add_argument('name', help='rbd bdev name') 542 p.set_defaults(func=bdev_rbd_delete) 543 544 def bdev_delay_create(args): 545 print_json(rpc.bdev.bdev_delay_create(args.client, 546 base_bdev_name=args.base_bdev_name, 547 name=args.name, 548 avg_read_latency=args.avg_read_latency, 549 p99_read_latency=args.nine_nine_read_latency, 550 avg_write_latency=args.avg_write_latency, 551 p99_write_latency=args.nine_nine_write_latency)) 552 553 p = subparsers.add_parser('bdev_delay_create', 554 help='Add a delay bdev on existing bdev') 555 p.add_argument('-b', '--base-bdev-name', help="Name of the existing bdev", required=True) 556 p.add_argument('-d', '--name', help="Name of the delay bdev", required=True) 557 p.add_argument('-r', '--avg-read-latency', 558 help="Average latency to apply before completing read ops (in microseconds)", required=True, type=int) 559 p.add_argument('-t', '--nine-nine-read-latency', 560 help="latency to apply to 1 in 100 read ops (in microseconds)", required=True, type=int) 561 p.add_argument('-w', '--avg-write-latency', 562 help="Average latency to apply before completing write ops (in microseconds)", required=True, type=int) 563 p.add_argument('-n', '--nine-nine-write-latency', 564 help="latency to apply to 1 in 100 write ops (in microseconds)", required=True, type=int) 565 p.set_defaults(func=bdev_delay_create) 566 567 def bdev_delay_delete(args): 568 rpc.bdev.bdev_delay_delete(args.client, 569 name=args.name) 570 571 p = subparsers.add_parser('bdev_delay_delete', help='Delete a delay bdev') 572 p.add_argument('name', help='delay bdev name') 573 p.set_defaults(func=bdev_delay_delete) 574 575 def bdev_delay_update_latency(args): 576 print_json(rpc.bdev.bdev_delay_update_latency(args.client, 577 delay_bdev_name=args.delay_bdev_name, 578 latency_type=args.latency_type, 579 latency_us=args.latency_us)) 580 p = subparsers.add_parser('bdev_delay_update_latency', 581 help='Update one of the latency values for a given delay bdev') 582 p.add_argument('delay_bdev_name', help='The name of the given delay bdev') 583 p.add_argument('latency_type', help='one of: avg_read, avg_write, p99_read, p99_write. No other values accepted.') 584 p.add_argument('latency_us', help='new latency value in microseconds.', type=int) 585 p.set_defaults(func=bdev_delay_update_latency) 586 587 def bdev_error_create(args): 588 print_json(rpc.bdev.bdev_error_create(args.client, 589 base_name=args.base_name)) 590 591 p = subparsers.add_parser('bdev_error_create', aliases=['construct_error_bdev'], 592 help='Add bdev with error injection backend') 593 p.add_argument('base_name', help='base bdev name') 594 p.set_defaults(func=bdev_error_create) 595 596 def bdev_error_delete(args): 597 rpc.bdev.bdev_error_delete(args.client, 598 name=args.name) 599 600 p = subparsers.add_parser('bdev_error_delete', aliases=['delete_error_bdev'], 601 help='Delete an error bdev') 602 p.add_argument('name', help='error bdev name') 603 p.set_defaults(func=bdev_error_delete) 604 605 def bdev_iscsi_create(args): 606 print_json(rpc.bdev.bdev_iscsi_create(args.client, 607 name=args.name, 608 url=args.url, 609 initiator_iqn=args.initiator_iqn)) 610 611 p = subparsers.add_parser('bdev_iscsi_create', aliases=['construct_iscsi_bdev'], 612 help='Add bdev with iSCSI initiator backend') 613 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 614 p.add_argument('-i', '--initiator-iqn', help="Initiator IQN", required=True) 615 p.add_argument('--url', help="iSCSI Lun URL", required=True) 616 p.set_defaults(func=bdev_iscsi_create) 617 618 def bdev_iscsi_delete(args): 619 rpc.bdev.bdev_iscsi_delete(args.client, 620 name=args.name) 621 622 p = subparsers.add_parser('bdev_iscsi_delete', aliases=['delete_iscsi_bdev'], 623 help='Delete an iSCSI bdev') 624 p.add_argument('name', help='iSCSI bdev name') 625 p.set_defaults(func=bdev_iscsi_delete) 626 627 def bdev_pmem_create(args): 628 print_json(rpc.bdev.bdev_pmem_create(args.client, 629 pmem_file=args.pmem_file, 630 name=args.name)) 631 632 p = subparsers.add_parser('bdev_pmem_create', aliases=['construct_pmem_bdev'], 633 help='Add a bdev with pmem backend') 634 p.add_argument('pmem_file', help='Path to pmemblk pool file') 635 p.add_argument('-n', '--name', help='Block device name', required=True) 636 p.set_defaults(func=bdev_pmem_create) 637 638 def bdev_pmem_delete(args): 639 rpc.bdev.bdev_pmem_delete(args.client, 640 name=args.name) 641 642 p = subparsers.add_parser('bdev_pmem_delete', aliases=['delete_pmem_bdev'], 643 help='Delete a pmem bdev') 644 p.add_argument('name', help='pmem bdev name') 645 p.set_defaults(func=bdev_pmem_delete) 646 647 def bdev_passthru_create(args): 648 print_json(rpc.bdev.bdev_passthru_create(args.client, 649 base_bdev_name=args.base_bdev_name, 650 name=args.name)) 651 652 p = subparsers.add_parser('bdev_passthru_create', aliases=['construct_passthru_bdev'], 653 help='Add a pass through bdev on existing bdev') 654 p.add_argument('-b', '--base-bdev-name', help="Name of the existing bdev", required=True) 655 p.add_argument('-p', '--name', help="Name of the pass through bdev", required=True) 656 p.set_defaults(func=bdev_passthru_create) 657 658 def bdev_passthru_delete(args): 659 rpc.bdev.bdev_passthru_delete(args.client, 660 name=args.name) 661 662 p = subparsers.add_parser('bdev_passthru_delete', aliases=['delete_passthru_bdev'], 663 help='Delete a pass through bdev') 664 p.add_argument('name', help='pass through bdev name') 665 p.set_defaults(func=bdev_passthru_delete) 666 667 def bdev_get_bdevs(args): 668 print_dict(rpc.bdev.bdev_get_bdevs(args.client, 669 name=args.name)) 670 671 p = subparsers.add_parser('bdev_get_bdevs', aliases=['get_bdevs'], 672 help='Display current blockdev list or required blockdev') 673 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 674 p.set_defaults(func=bdev_get_bdevs) 675 676 def bdev_get_iostat(args): 677 print_dict(rpc.bdev.bdev_get_iostat(args.client, 678 name=args.name)) 679 680 p = subparsers.add_parser('bdev_get_iostat', aliases=['get_bdevs_iostat'], 681 help='Display current I/O statistics of all the blockdevs or required blockdev.') 682 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 683 p.set_defaults(func=bdev_get_iostat) 684 685 def bdev_enable_histogram(args): 686 rpc.bdev.bdev_enable_histogram(args.client, name=args.name, enable=args.enable) 687 688 p = subparsers.add_parser('bdev_enable_histogram', aliases=['enable_bdev_histogram'], 689 help='Enable or disable histogram for specified bdev') 690 p.add_argument('-e', '--enable', default=True, dest='enable', action='store_true', help='Enable histograms on specified device') 691 p.add_argument('-d', '--disable', dest='enable', action='store_false', help='Disable histograms on specified device') 692 p.add_argument('name', help='bdev name') 693 p.set_defaults(func=bdev_enable_histogram) 694 695 def bdev_get_histogram(args): 696 print_dict(rpc.bdev.bdev_get_histogram(args.client, name=args.name)) 697 698 p = subparsers.add_parser('bdev_get_histogram', aliases=['get_bdev_histogram'], 699 help='Get histogram for specified bdev') 700 p.add_argument('name', help='bdev name') 701 p.set_defaults(func=bdev_get_histogram) 702 703 def bdev_set_qd_sampling_period(args): 704 rpc.bdev.bdev_set_qd_sampling_period(args.client, 705 name=args.name, 706 period=args.period) 707 708 p = subparsers.add_parser('bdev_set_qd_sampling_period', aliases=['set_bdev_qd_sampling_period'], 709 help="Enable or disable tracking of a bdev's queue depth.") 710 p.add_argument('name', help='Blockdev name. Example: Malloc0') 711 p.add_argument('period', help='Period with which to poll the block device queue depth in microseconds.' 712 ' If set to 0, polling will be disabled.', 713 type=int) 714 p.set_defaults(func=bdev_set_qd_sampling_period) 715 716 def bdev_set_qos_limit(args): 717 rpc.bdev.bdev_set_qos_limit(args.client, 718 name=args.name, 719 rw_ios_per_sec=args.rw_ios_per_sec, 720 rw_mbytes_per_sec=args.rw_mbytes_per_sec, 721 r_mbytes_per_sec=args.r_mbytes_per_sec, 722 w_mbytes_per_sec=args.w_mbytes_per_sec) 723 724 p = subparsers.add_parser('bdev_set_qos_limit', aliases=['set_bdev_qos_limit'], 725 help='Set QoS rate limit on a blockdev') 726 p.add_argument('name', help='Blockdev name to set QoS. Example: Malloc0') 727 p.add_argument('--rw_ios_per_sec', 728 help='R/W IOs per second limit (>=10000, example: 20000). 0 means unlimited.', 729 type=int, required=False) 730 p.add_argument('--rw_mbytes_per_sec', 731 help="R/W megabytes per second limit (>=10, example: 100). 0 means unlimited.", 732 type=int, required=False) 733 p.add_argument('--r_mbytes_per_sec', 734 help="Read megabytes per second limit (>=10, example: 100). 0 means unlimited.", 735 type=int, required=False) 736 p.add_argument('--w_mbytes_per_sec', 737 help="Write megabytes per second limit (>=10, example: 100). 0 means unlimited.", 738 type=int, required=False) 739 p.set_defaults(func=bdev_set_qos_limit) 740 741 def bdev_error_inject_error(args): 742 rpc.bdev.bdev_error_inject_error(args.client, 743 name=args.name, 744 io_type=args.io_type, 745 error_type=args.error_type, 746 num=args.num) 747 748 p = subparsers.add_parser('bdev_error_inject_error', aliases=['bdev_inject_error'], 749 help='bdev inject error') 750 p.add_argument('name', help="""the name of the error injection bdev""") 751 p.add_argument('io_type', help="""io_type: 'clear' 'read' 'write' 'unmap' 'flush' 'all'""") 752 p.add_argument('error_type', help="""error_type: 'failure' 'pending'""") 753 p.add_argument( 754 '-n', '--num', help='the number of commands you want to fail', type=int, default=1) 755 p.set_defaults(func=bdev_error_inject_error) 756 757 def bdev_nvme_apply_firmware(args): 758 print_dict(rpc.bdev.bdev_nvme_apply_firmware(args.client, 759 bdev_name=args.bdev_name, 760 filename=args.filename)) 761 762 p = subparsers.add_parser('apply_firmware', aliases=['apply_firmware'], 763 help='Download and commit firmware to NVMe device') 764 p.add_argument('filename', help='filename of the firmware to download') 765 p.add_argument('bdev_name', help='name of the NVMe device') 766 p.set_defaults(func=bdev_nvme_apply_firmware) 767 768 # iSCSI 769 def iscsi_set_options(args): 770 rpc.iscsi.iscsi_set_options( 771 args.client, 772 auth_file=args.auth_file, 773 node_base=args.node_base, 774 nop_timeout=args.nop_timeout, 775 nop_in_interval=args.nop_in_interval, 776 disable_chap=args.disable_chap, 777 require_chap=args.require_chap, 778 mutual_chap=args.mutual_chap, 779 chap_group=args.chap_group, 780 max_sessions=args.max_sessions, 781 max_queue_depth=args.max_queue_depth, 782 max_connections_per_session=args.max_connections_per_session, 783 default_time2wait=args.default_time2wait, 784 default_time2retain=args.default_time2retain, 785 first_burst_length=args.first_burst_length, 786 immediate_data=args.immediate_data, 787 error_recovery_level=args.error_recovery_level, 788 allow_duplicated_isid=args.allow_duplicated_isid) 789 790 p = subparsers.add_parser('iscsi_set_options', aliases=['set_iscsi_options'], 791 help="""Set options of iSCSI subsystem""") 792 p.add_argument('-f', '--auth-file', help='Path to CHAP shared secret file') 793 p.add_argument('-b', '--node-base', help='Prefix of the name of iSCSI target node') 794 p.add_argument('-o', '--nop-timeout', help='Timeout in seconds to nop-in request to the initiator', type=int) 795 p.add_argument('-n', '--nop-in-interval', help='Time interval in secs between nop-in requests by the target', type=int) 796 p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled. 797 *** Mutually exclusive with --require-chap""", action='store_true') 798 p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required. 799 *** Mutually exclusive with --disable-chap""", action='store_true') 800 p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true') 801 p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session. 802 *** Authentication group must be precreated ***""", type=int) 803 p.add_argument('-a', '--max-sessions', help='Maximum number of sessions in the host.', type=int) 804 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/Os per queue.', type=int) 805 p.add_argument('-c', '--max-connections-per-session', help='Negotiated parameter, MaxConnections.', type=int) 806 p.add_argument('-w', '--default-time2wait', help='Negotiated parameter, DefaultTime2Wait.', type=int) 807 p.add_argument('-v', '--default-time2retain', help='Negotiated parameter, DefaultTime2Retain.', type=int) 808 p.add_argument('-s', '--first-burst-length', help='Negotiated parameter, FirstBurstLength.', type=int) 809 p.add_argument('-i', '--immediate-data', help='Negotiated parameter, ImmediateData.', action='store_true') 810 p.add_argument('-l', '--error-recovery-level', help='Negotiated parameter, ErrorRecoveryLevel', type=int) 811 p.add_argument('-p', '--allow-duplicated-isid', help='Allow duplicated initiator session ID.', action='store_true') 812 p.set_defaults(func=iscsi_set_options) 813 814 def iscsi_set_discovery_auth(args): 815 rpc.iscsi.iscsi_set_discovery_auth( 816 args.client, 817 disable_chap=args.disable_chap, 818 require_chap=args.require_chap, 819 mutual_chap=args.mutual_chap, 820 chap_group=args.chap_group) 821 822 p = subparsers.add_parser('iscsi_set_discovery_auth', aliases=['set_iscsi_discovery_auth'], 823 help="""Set CHAP authentication for discovery session.""") 824 p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled. 825 *** Mutually exclusive with --require-chap""", action='store_true') 826 p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required. 827 *** Mutually exclusive with --disable-chap""", action='store_true') 828 p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true') 829 p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session. 830 *** Authentication group must be precreated ***""", type=int) 831 p.set_defaults(func=iscsi_set_discovery_auth) 832 833 def iscsi_create_auth_group(args): 834 secrets = None 835 if args.secrets: 836 secrets = [dict(u.split(":") for u in a.split(" ")) for a in args.secrets.split(",")] 837 838 rpc.iscsi.iscsi_create_auth_group(args.client, tag=args.tag, secrets=secrets) 839 840 p = subparsers.add_parser('iscsi_create_auth_group', aliases=['add_iscsi_auth_group'], 841 help='Create authentication group for CHAP authentication.') 842 p.add_argument('tag', help='Authentication group tag (unique, integer > 0).', type=int) 843 p.add_argument('-c', '--secrets', help="""Comma-separated list of CHAP secrets 844<user:user_name secret:chap_secret muser:mutual_user_name msecret:mutual_chap_secret> enclosed in quotes. 845Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 msecret:ms2'""", required=False) 846 p.set_defaults(func=iscsi_create_auth_group) 847 848 def iscsi_delete_auth_group(args): 849 rpc.iscsi.iscsi_delete_auth_group(args.client, tag=args.tag) 850 851 p = subparsers.add_parser('iscsi_delete_auth_group', aliases=['delete_iscsi_auth_group'], 852 help='Delete an authentication group.') 853 p.add_argument('tag', help='Authentication group tag', type=int) 854 p.set_defaults(func=iscsi_delete_auth_group) 855 856 def iscsi_auth_group_add_secret(args): 857 rpc.iscsi.iscsi_auth_group_add_secret( 858 args.client, 859 tag=args.tag, 860 user=args.user, 861 secret=args.secret, 862 muser=args.muser, 863 msecret=args.msecret) 864 865 p = subparsers.add_parser('iscsi_auth_group_add_secret', aliases=['add_secret_to_iscsi_auth_group'], 866 help='Add a secret to an authentication group.') 867 p.add_argument('tag', help='Authentication group tag', type=int) 868 p.add_argument('-u', '--user', help='User name for one-way CHAP authentication', required=True) 869 p.add_argument('-s', '--secret', help='Secret for one-way CHAP authentication', required=True) 870 p.add_argument('-m', '--muser', help='User name for mutual CHAP authentication') 871 p.add_argument('-r', '--msecret', help='Secret for mutual CHAP authentication') 872 p.set_defaults(func=iscsi_auth_group_add_secret) 873 874 def iscsi_auth_group_remove_secret(args): 875 rpc.iscsi.iscsi_auth_group_remove_secret(args.client, tag=args.tag, user=args.user) 876 877 p = subparsers.add_parser('iscsi_auth_group_remove_secret', aliases=['delete_secret_from_iscsi_auth_group'], 878 help='Remove a secret from an authentication group.') 879 p.add_argument('tag', help='Authentication group tag', type=int) 880 p.add_argument('-u', '--user', help='User name for one-way CHAP authentication', required=True) 881 p.set_defaults(func=iscsi_auth_group_remove_secret) 882 883 def iscsi_get_auth_groups(args): 884 print_dict(rpc.iscsi.iscsi_get_auth_groups(args.client)) 885 886 p = subparsers.add_parser('iscsi_get_auth_groups', aliases=['get_iscsi_auth_groups'], 887 help='Display current authentication group configuration') 888 p.set_defaults(func=iscsi_get_auth_groups) 889 890 def iscsi_get_portal_groups(args): 891 print_dict(rpc.iscsi.iscsi_get_portal_groups(args.client)) 892 893 p = subparsers.add_parser( 894 'iscsi_get_portal_groups', aliases=['get_portal_groups'], 895 help='Display current portal group configuration') 896 p.set_defaults(func=iscsi_get_portal_groups) 897 898 def iscsi_get_initiator_groups(args): 899 print_dict(rpc.iscsi.iscsi_get_initiator_groups(args.client)) 900 901 p = subparsers.add_parser('iscsi_get_initiator_groups', 902 aliases=['get_initiator_groups'], 903 help='Display current initiator group configuration') 904 p.set_defaults(func=iscsi_get_initiator_groups) 905 906 def iscsi_get_target_nodes(args): 907 print_dict(rpc.iscsi.iscsi_get_target_nodes(args.client)) 908 909 p = subparsers.add_parser('iscsi_get_target_nodes', aliases=['get_target_nodes'], 910 help='Display target nodes') 911 p.set_defaults(func=iscsi_get_target_nodes) 912 913 def iscsi_create_target_node(args): 914 luns = [] 915 for u in args.bdev_name_id_pairs.strip().split(" "): 916 bdev_name, lun_id = u.split(":") 917 luns.append({"bdev_name": bdev_name, "lun_id": int(lun_id)}) 918 919 pg_ig_maps = [] 920 for u in args.pg_ig_mappings.strip().split(" "): 921 pg, ig = u.split(":") 922 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 923 924 rpc.iscsi.iscsi_create_target_node( 925 args.client, 926 luns=luns, 927 pg_ig_maps=pg_ig_maps, 928 name=args.name, 929 alias_name=args.alias_name, 930 queue_depth=args.queue_depth, 931 chap_group=args.chap_group, 932 disable_chap=args.disable_chap, 933 require_chap=args.require_chap, 934 mutual_chap=args.mutual_chap, 935 header_digest=args.header_digest, 936 data_digest=args.data_digest) 937 938 p = subparsers.add_parser('iscsi_create_target_node', aliases=['construct_target_node'], 939 help='Add a target node') 940 p.add_argument('name', help='Target node name (ASCII)') 941 p.add_argument('alias_name', help='Target node alias name (ASCII)') 942 p.add_argument('bdev_name_id_pairs', help="""Whitespace-separated list of <bdev name:LUN ID> pairs enclosed 943 in quotes. Format: 'bdev_name0:id0 bdev_name1:id1' etc 944 Example: 'Malloc0:0 Malloc1:1 Malloc5:2' 945 *** The bdevs must pre-exist *** 946 *** LUN0 (id = 0) is required *** 947 *** bdevs names cannot contain space or colon characters ***""") 948 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 949 Whitespace separated, quoted, mapping defined with colon 950 separated list of "tags" (int > 0) 951 Example: '1:1 2:2 2:1' 952 *** The Portal/Initiator Groups must be precreated ***""") 953 p.add_argument('queue_depth', help='Desired target queue depth', type=int) 954 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 955 *** Authentication group must be precreated ***""", type=int, default=0) 956 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 957 *** Mutually exclusive with --require-chap ***""", action='store_true') 958 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 959 *** Mutually exclusive with --disable-chap ***""", action='store_true') 960 p.add_argument( 961 '-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', action='store_true') 962 p.add_argument('-H', '--header-digest', 963 help='Header Digest should be required for this target node.', action='store_true') 964 p.add_argument('-D', '--data-digest', 965 help='Data Digest should be required for this target node.', action='store_true') 966 p.set_defaults(func=iscsi_create_target_node) 967 968 def iscsi_target_node_add_lun(args): 969 rpc.iscsi.iscsi_target_node_add_lun( 970 args.client, 971 name=args.name, 972 bdev_name=args.bdev_name, 973 lun_id=args.lun_id) 974 975 p = subparsers.add_parser('iscsi_target_node_add_lun', aliases=['target_node_add_lun'], 976 help='Add LUN to the target node') 977 p.add_argument('name', help='Target node name (ASCII)') 978 p.add_argument('bdev_name', help="""bdev name enclosed in quotes. 979 *** bdev name cannot contain space or colon characters ***""") 980 p.add_argument('-i', dest='lun_id', help="""LUN ID (integer >= 0) 981 *** If LUN ID is omitted or -1, the lowest free one is assigned ***""", type=int, required=False) 982 p.set_defaults(func=iscsi_target_node_add_lun) 983 984 def iscsi_target_node_set_auth(args): 985 rpc.iscsi.iscsi_target_node_set_auth( 986 args.client, 987 name=args.name, 988 chap_group=args.chap_group, 989 disable_chap=args.disable_chap, 990 require_chap=args.require_chap, 991 mutual_chap=args.mutual_chap) 992 993 p = subparsers.add_parser('iscsi_target_node_set_auth', aliases=['set_iscsi_target_node_auth'], 994 help='Set CHAP authentication for the target node') 995 p.add_argument('name', help='Target node name (ASCII)') 996 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 997 *** Authentication group must be precreated ***""", type=int, default=0) 998 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 999 *** Mutually exclusive with --require-chap ***""", action='store_true') 1000 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 1001 *** Mutually exclusive with --disable-chap ***""", action='store_true') 1002 p.add_argument('-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', 1003 action='store_true') 1004 p.set_defaults(func=iscsi_target_node_set_auth) 1005 1006 def iscsi_target_node_add_pg_ig_maps(args): 1007 pg_ig_maps = [] 1008 for u in args.pg_ig_mappings.strip().split(" "): 1009 pg, ig = u.split(":") 1010 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 1011 rpc.iscsi.iscsi_target_node_add_pg_ig_maps( 1012 args.client, 1013 pg_ig_maps=pg_ig_maps, 1014 name=args.name) 1015 1016 p = subparsers.add_parser('iscsi_target_node_add_pg_ig_maps', 1017 aliases=['add_pg_ig_maps'], 1018 help='Add PG-IG maps to the target node') 1019 p.add_argument('name', help='Target node name (ASCII)') 1020 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 1021 Whitespace separated, quoted, mapping defined with colon 1022 separated list of "tags" (int > 0) 1023 Example: '1:1 2:2 2:1' 1024 *** The Portal/Initiator Groups must be precreated ***""") 1025 p.set_defaults(func=iscsi_target_node_add_pg_ig_maps) 1026 1027 def iscsi_target_node_remove_pg_ig_maps(args): 1028 pg_ig_maps = [] 1029 for u in args.pg_ig_mappings.strip().split(" "): 1030 pg, ig = u.split(":") 1031 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 1032 rpc.iscsi.iscsi_target_node_remove_pg_ig_maps( 1033 args.client, pg_ig_maps=pg_ig_maps, name=args.name) 1034 1035 p = subparsers.add_parser('iscsi_target_node_remove_pg_ig_maps', 1036 aliases=['delete_pg_ig_maps'], 1037 help='Delete PG-IG maps from the target node') 1038 p.add_argument('name', help='Target node name (ASCII)') 1039 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 1040 Whitespace separated, quoted, mapping defined with colon 1041 separated list of "tags" (int > 0) 1042 Example: '1:1 2:2 2:1' 1043 *** The Portal/Initiator Groups must be precreated ***""") 1044 p.set_defaults(func=iscsi_target_node_remove_pg_ig_maps) 1045 1046 def iscsi_create_portal_group(args): 1047 portals = [] 1048 for p in args.portal_list.strip().split(' '): 1049 ip, separator, port_cpumask = p.rpartition(':') 1050 split_port_cpumask = port_cpumask.split('@') 1051 if len(split_port_cpumask) == 1: 1052 port = port_cpumask 1053 portals.append({'host': ip, 'port': port}) 1054 else: 1055 port = split_port_cpumask[0] 1056 cpumask = split_port_cpumask[1] 1057 portals.append({'host': ip, 'port': port}) 1058 print("WARNING: Specifying a portal group with a CPU mask is no longer supported. Ignoring it.") 1059 rpc.iscsi.iscsi_create_portal_group( 1060 args.client, 1061 portals=portals, 1062 tag=args.tag) 1063 1064 p = subparsers.add_parser('iscsi_create_portal_group', aliases=['add_portal_group'], 1065 help='Add a portal group') 1066 p.add_argument( 1067 'tag', help='Portal group tag (unique, integer > 0)', type=int) 1068 p.add_argument('portal_list', help="""List of portals in host:port format, separated by whitespace 1069 Example: '192.168.100.100:3260 192.168.100.100:3261 192.168.100.100:3262""") 1070 p.set_defaults(func=iscsi_create_portal_group) 1071 1072 def iscsi_create_initiator_group(args): 1073 initiators = [] 1074 netmasks = [] 1075 for i in args.initiator_list.strip().split(' '): 1076 initiators.append(i) 1077 for n in args.netmask_list.strip().split(' '): 1078 netmasks.append(n) 1079 rpc.iscsi.iscsi_create_initiator_group( 1080 args.client, 1081 tag=args.tag, 1082 initiators=initiators, 1083 netmasks=netmasks) 1084 1085 p = subparsers.add_parser('iscsi_create_initiator_group', aliases=['add_initiator_group'], 1086 help='Add an initiator group') 1087 p.add_argument( 1088 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1089 p.add_argument('initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 1090 enclosed in quotes. Example: 'ANY' or '127.0.0.1 192.168.200.100'""") 1091 p.add_argument('netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 1092 Example: '255.255.0.0 255.248.0.0' etc""") 1093 p.set_defaults(func=iscsi_create_initiator_group) 1094 1095 def iscsi_initiator_group_add_initiators(args): 1096 initiators = None 1097 netmasks = None 1098 if args.initiator_list: 1099 initiators = [] 1100 for i in args.initiator_list.strip().split(' '): 1101 initiators.append(i) 1102 if args.netmask_list: 1103 netmasks = [] 1104 for n in args.netmask_list.strip().split(' '): 1105 netmasks.append(n) 1106 rpc.iscsi.iscsi_initiator_group_add_initiators( 1107 args.client, 1108 tag=args.tag, 1109 initiators=initiators, 1110 netmasks=netmasks) 1111 1112 p = subparsers.add_parser('iscsi_initiator_group_add_initiators', 1113 aliases=['add_initiators_to_initiator_group'], 1114 help='Add initiators to an existing initiator group') 1115 p.add_argument( 1116 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1117 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 1118 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 1119 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 1120 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 1121 p.set_defaults(func=iscsi_initiator_group_add_initiators) 1122 1123 def iscsi_initiator_group_remove_initiators(args): 1124 initiators = None 1125 netmasks = None 1126 if args.initiator_list: 1127 initiators = [] 1128 for i in args.initiator_list.strip().split(' '): 1129 initiators.append(i) 1130 if args.netmask_list: 1131 netmasks = [] 1132 for n in args.netmask_list.strip().split(' '): 1133 netmasks.append(n) 1134 rpc.iscsi.iscsi_initiator_group_remove_initiators( 1135 args.client, 1136 tag=args.tag, 1137 initiators=initiators, 1138 netmasks=netmasks) 1139 1140 p = subparsers.add_parser('iscsi_initiator_group_remove_initiators', 1141 aliases=['delete_initiators_from_initiator_group'], 1142 help='Delete initiators from an existing initiator group') 1143 p.add_argument( 1144 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1145 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 1146 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 1147 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 1148 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 1149 p.set_defaults(func=iscsi_initiator_group_remove_initiators) 1150 1151 def iscsi_delete_target_node(args): 1152 rpc.iscsi.iscsi_delete_target_node( 1153 args.client, target_node_name=args.target_node_name) 1154 1155 p = subparsers.add_parser('iscsi_delete_target_node', aliases=['delete_target_node'], 1156 help='Delete a target node') 1157 p.add_argument('target_node_name', 1158 help='Target node name to be deleted. Example: iqn.2016-06.io.spdk:disk1.') 1159 p.set_defaults(func=iscsi_delete_target_node) 1160 1161 def iscsi_delete_portal_group(args): 1162 rpc.iscsi.iscsi_delete_portal_group(args.client, tag=args.tag) 1163 1164 p = subparsers.add_parser('iscsi_delete_portal_group', 1165 aliases=['delete_portal_group'], 1166 help='Delete a portal group') 1167 p.add_argument( 1168 'tag', help='Portal group tag (unique, integer > 0)', type=int) 1169 p.set_defaults(func=iscsi_delete_portal_group) 1170 1171 def iscsi_delete_initiator_group(args): 1172 rpc.iscsi.iscsi_delete_initiator_group(args.client, tag=args.tag) 1173 1174 p = subparsers.add_parser('iscsi_delete_initiator_group', 1175 aliases=['delete_initiator_group'], 1176 help='Delete an initiator group') 1177 p.add_argument( 1178 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1179 p.set_defaults(func=iscsi_delete_initiator_group) 1180 1181 def iscsi_portal_group_set_auth(args): 1182 rpc.iscsi.iscsi_portal_group_set_auth( 1183 args.client, 1184 tag=args.tag, 1185 chap_group=args.chap_group, 1186 disable_chap=args.disable_chap, 1187 require_chap=args.require_chap, 1188 mutual_chap=args.mutual_chap) 1189 1190 p = subparsers.add_parser('iscsi_portal_group_set_auth', 1191 help='Set CHAP authentication for discovery sessions specific for the portal group') 1192 p.add_argument('tag', help='Portal group tag (unique, integer > 0)', type=int) 1193 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this portal group. 1194 *** Authentication group must be precreated ***""", type=int, default=0) 1195 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this portal group. 1196 *** Mutually exclusive with --require-chap ***""", action='store_true') 1197 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this portal group. 1198 *** Mutually exclusive with --disable-chap ***""", action='store_true') 1199 p.add_argument('-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', 1200 action='store_true') 1201 p.set_defaults(func=iscsi_portal_group_set_auth) 1202 1203 def iscsi_get_connections(args): 1204 print_dict(rpc.iscsi.iscsi_get_connections(args.client)) 1205 1206 p = subparsers.add_parser('iscsi_get_connections', aliases=['get_iscsi_connections'], 1207 help='Display iSCSI connections') 1208 p.set_defaults(func=iscsi_get_connections) 1209 1210 def iscsi_get_options(args): 1211 print_dict(rpc.iscsi.iscsi_get_options(args.client)) 1212 1213 p = subparsers.add_parser('iscsi_get_options', aliases=['get_iscsi_global_params'], 1214 help='Display iSCSI global parameters') 1215 p.set_defaults(func=iscsi_get_options) 1216 1217 def scsi_get_devices(args): 1218 print_dict(rpc.iscsi.scsi_get_devices(args.client)) 1219 1220 p = subparsers.add_parser('scsi_get_devices', aliases=['get_scsi_devices'], 1221 help='Display SCSI devices') 1222 p.set_defaults(func=scsi_get_devices) 1223 1224 # trace 1225 def trace_enable_tpoint_group(args): 1226 rpc.trace.trace_enable_tpoint_group(args.client, name=args.name) 1227 1228 p = subparsers.add_parser('trace_enable_tpoint_group', aliases=['enable_tpoint_group'], 1229 help='enable trace on a specific tpoint group') 1230 p.add_argument( 1231 'name', help="""trace group name we want to enable in tpoint_group_mask. 1232 (for example "bdev" for bdev trace group, "all" for all trace groups).""") 1233 p.set_defaults(func=trace_enable_tpoint_group) 1234 1235 def trace_disable_tpoint_group(args): 1236 rpc.trace.trace_disable_tpoint_group(args.client, name=args.name) 1237 1238 p = subparsers.add_parser('trace_disable_tpoint_group', aliases=['disable_tpoint_group'], 1239 help='disable trace on a specific tpoint group') 1240 p.add_argument( 1241 'name', help="""trace group name we want to disable in tpoint_group_mask. 1242 (for example "bdev" for bdev trace group, "all" for all trace groups).""") 1243 p.set_defaults(func=trace_disable_tpoint_group) 1244 1245 def trace_get_tpoint_group_mask(args): 1246 print_dict(rpc.trace.trace_get_tpoint_group_mask(args.client)) 1247 1248 p = subparsers.add_parser('trace_get_tpoint_group_mask', aliases=['get_tpoint_group_mask'], 1249 help='get trace point group mask') 1250 p.set_defaults(func=trace_get_tpoint_group_mask) 1251 1252 # log 1253 def log_set_flag(args): 1254 rpc.log.log_set_flag(args.client, flag=args.flag) 1255 1256 p = subparsers.add_parser('log_set_flag', help='set log flag', aliases=['set_log_flag']) 1257 p.add_argument( 1258 'flag', help='log flag we want to set. (for example "nvme").') 1259 p.set_defaults(func=log_set_flag) 1260 1261 def log_clear_flag(args): 1262 rpc.log.log_clear_flag(args.client, flag=args.flag) 1263 1264 p = subparsers.add_parser('log_clear_flag', help='clear log flag', aliases=['clear_log_flag']) 1265 p.add_argument( 1266 'flag', help='log flag we want to clear. (for example "nvme").') 1267 p.set_defaults(func=log_clear_flag) 1268 1269 def log_get_flags(args): 1270 print_dict(rpc.log.log_get_flags(args.client)) 1271 1272 p = subparsers.add_parser('log_get_flags', help='get log flags', aliases=['get_log_flags']) 1273 p.set_defaults(func=log_get_flags) 1274 1275 def log_set_level(args): 1276 rpc.log.log_set_level(args.client, level=args.level) 1277 1278 p = subparsers.add_parser('log_set_level', aliases=['set_log_level'], 1279 help='set log level') 1280 p.add_argument('level', help='log level we want to set. (for example "DEBUG").') 1281 p.set_defaults(func=log_set_level) 1282 1283 def log_get_level(args): 1284 print_dict(rpc.log.log_get_level(args.client)) 1285 1286 p = subparsers.add_parser('log_get_level', aliases=['get_log_level'], 1287 help='get log level') 1288 p.set_defaults(func=log_get_level) 1289 1290 def log_set_print_level(args): 1291 rpc.log.log_set_print_level(args.client, level=args.level) 1292 1293 p = subparsers.add_parser('log_set_print_level', aliases=['set_log_print_level'], 1294 help='set log print level') 1295 p.add_argument('level', help='log print level we want to set. (for example "DEBUG").') 1296 p.set_defaults(func=log_set_print_level) 1297 1298 def log_get_print_level(args): 1299 print_dict(rpc.log.log_get_print_level(args.client)) 1300 1301 p = subparsers.add_parser('log_get_print_level', aliases=['get_log_print_level'], 1302 help='get log print level') 1303 p.set_defaults(func=log_get_print_level) 1304 1305 # lvol 1306 def bdev_lvol_create_lvstore(args): 1307 print_json(rpc.lvol.bdev_lvol_create_lvstore(args.client, 1308 bdev_name=args.bdev_name, 1309 lvs_name=args.lvs_name, 1310 cluster_sz=args.cluster_sz, 1311 clear_method=args.clear_method)) 1312 1313 p = subparsers.add_parser('bdev_lvol_create_lvstore', aliases=['construct_lvol_store'], 1314 help='Add logical volume store on base bdev') 1315 p.add_argument('bdev_name', help='base bdev name') 1316 p.add_argument('lvs_name', help='name for lvol store') 1317 p.add_argument('-c', '--cluster-sz', help='size of cluster (in bytes)', type=int, required=False) 1318 p.add_argument('--clear-method', help="""Change clear method for data region. 1319 Available: none, unmap, write_zeroes""", required=False) 1320 p.set_defaults(func=bdev_lvol_create_lvstore) 1321 1322 def bdev_lvol_rename_lvstore(args): 1323 rpc.lvol.bdev_lvol_rename_lvstore(args.client, 1324 old_name=args.old_name, 1325 new_name=args.new_name) 1326 1327 p = subparsers.add_parser('bdev_lvol_rename_lvstore', aliases=['rename_lvol_store'], 1328 help='Change logical volume store name') 1329 p.add_argument('old_name', help='old name') 1330 p.add_argument('new_name', help='new name') 1331 p.set_defaults(func=bdev_lvol_rename_lvstore) 1332 1333 def bdev_lvol_create(args): 1334 print_json(rpc.lvol.bdev_lvol_create(args.client, 1335 lvol_name=args.lvol_name, 1336 size=args.size * 1024 * 1024, 1337 thin_provision=args.thin_provision, 1338 clear_method=args.clear_method, 1339 uuid=args.uuid, 1340 lvs_name=args.lvs_name)) 1341 1342 p = subparsers.add_parser('bdev_lvol_create', aliases=['construct_lvol_bdev'], 1343 help='Add a bdev with an logical volume backend') 1344 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1345 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1346 p.add_argument('-t', '--thin-provision', action='store_true', help='create lvol bdev as thin provisioned') 1347 p.add_argument('-c', '--clear-method', help="""Change default data clusters clear method. 1348 Available: none, unmap, write_zeroes""", required=False) 1349 p.add_argument('lvol_name', help='name for this lvol') 1350 p.add_argument('size', help='size in MiB for this bdev', type=int) 1351 p.set_defaults(func=bdev_lvol_create) 1352 1353 def bdev_lvol_snapshot(args): 1354 print_json(rpc.lvol.bdev_lvol_snapshot(args.client, 1355 lvol_name=args.lvol_name, 1356 snapshot_name=args.snapshot_name)) 1357 1358 p = subparsers.add_parser('bdev_lvol_snapshot', aliases=['snapshot_lvol_bdev'], 1359 help='Create a snapshot of an lvol bdev') 1360 p.add_argument('lvol_name', help='lvol bdev name') 1361 p.add_argument('snapshot_name', help='lvol snapshot name') 1362 p.set_defaults(func=bdev_lvol_snapshot) 1363 1364 def bdev_lvol_clone(args): 1365 print_json(rpc.lvol.bdev_lvol_clone(args.client, 1366 snapshot_name=args.snapshot_name, 1367 clone_name=args.clone_name)) 1368 1369 p = subparsers.add_parser('bdev_lvol_clone', aliases=['clone_lvol_bdev'], 1370 help='Create a clone of an lvol snapshot') 1371 p.add_argument('snapshot_name', help='lvol snapshot name') 1372 p.add_argument('clone_name', help='lvol clone name') 1373 p.set_defaults(func=bdev_lvol_clone) 1374 1375 def bdev_lvol_rename(args): 1376 rpc.lvol.bdev_lvol_rename(args.client, 1377 old_name=args.old_name, 1378 new_name=args.new_name) 1379 1380 p = subparsers.add_parser('bdev_lvol_rename', aliases=['rename_lvol_bdev'], 1381 help='Change lvol bdev name') 1382 p.add_argument('old_name', help='lvol bdev name') 1383 p.add_argument('new_name', help='new lvol name') 1384 p.set_defaults(func=bdev_lvol_rename) 1385 1386 def bdev_lvol_inflate(args): 1387 rpc.lvol.bdev_lvol_inflate(args.client, 1388 name=args.name) 1389 1390 p = subparsers.add_parser('bdev_lvol_inflate', aliases=['inflate_lvol_bdev'], 1391 help='Make thin provisioned lvol a thick provisioned lvol') 1392 p.add_argument('name', help='lvol bdev name') 1393 p.set_defaults(func=bdev_lvol_inflate) 1394 1395 def bdev_lvol_decouple_parent(args): 1396 rpc.lvol.bdev_lvol_decouple_parent(args.client, 1397 name=args.name) 1398 1399 p = subparsers.add_parser('bdev_lvol_decouple_parent', aliases=['decouple_parent_lvol_bdev'], 1400 help='Decouple parent of lvol') 1401 p.add_argument('name', help='lvol bdev name') 1402 p.set_defaults(func=bdev_lvol_decouple_parent) 1403 1404 def bdev_lvol_resize(args): 1405 rpc.lvol.bdev_lvol_resize(args.client, 1406 name=args.name, 1407 size=args.size * 1024 * 1024) 1408 1409 p = subparsers.add_parser('bdev_lvol_resize', aliases=['resize_lvol_bdev'], 1410 help='Resize existing lvol bdev') 1411 p.add_argument('name', help='lvol bdev name') 1412 p.add_argument('size', help='new size in MiB for this bdev', type=int) 1413 p.set_defaults(func=bdev_lvol_resize) 1414 1415 def bdev_lvol_set_read_only(args): 1416 rpc.lvol.bdev_lvol_set_read_only(args.client, 1417 name=args.name) 1418 1419 p = subparsers.add_parser('bdev_lvol_set_read_only', aliases=['set_read_only_lvol_bdev'], 1420 help='Mark lvol bdev as read only') 1421 p.add_argument('name', help='lvol bdev name') 1422 p.set_defaults(func=bdev_lvol_set_read_only) 1423 1424 def bdev_lvol_delete(args): 1425 rpc.lvol.bdev_lvol_delete(args.client, 1426 name=args.name) 1427 1428 p = subparsers.add_parser('bdev_lvol_delete', aliases=['destroy_lvol_bdev'], 1429 help='Destroy a logical volume') 1430 p.add_argument('name', help='lvol bdev name') 1431 p.set_defaults(func=bdev_lvol_delete) 1432 1433 def bdev_lvol_delete_lvstore(args): 1434 rpc.lvol.bdev_lvol_delete_lvstore(args.client, 1435 uuid=args.uuid, 1436 lvs_name=args.lvs_name) 1437 1438 p = subparsers.add_parser('bdev_lvol_delete_lvstore', aliases=['destroy_lvol_store'], 1439 help='Destroy an logical volume store') 1440 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1441 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1442 p.set_defaults(func=bdev_lvol_delete_lvstore) 1443 1444 def bdev_lvol_get_lvstores(args): 1445 print_dict(rpc.lvol.bdev_lvol_get_lvstores(args.client, 1446 uuid=args.uuid, 1447 lvs_name=args.lvs_name)) 1448 1449 p = subparsers.add_parser('bdev_lvol_get_lvstores', aliases=['get_lvol_stores'], 1450 help='Display current logical volume store list') 1451 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1452 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1453 p.set_defaults(func=bdev_lvol_get_lvstores) 1454 1455 def bdev_raid_get_bdevs(args): 1456 print_array(rpc.bdev.bdev_raid_get_bdevs(args.client, 1457 category=args.category)) 1458 1459 p = subparsers.add_parser('bdev_raid_get_bdevs', aliases=['get_raid_bdevs'], 1460 help="""This is used to list all the raid bdev names based on the input category 1461 requested. Category should be one of 'all', 'online', 'configuring' or 'offline'. 'all' means all the raid bdevs whether 1462 they are online or configuring or offline. 'online' is the raid bdev which is registered with bdev layer. 'configuring' 1463 is the raid bdev which does not have full configuration discovered yet. 'offline' is the raid bdev which is not registered 1464 with bdev as of now and it has encountered any error or user has requested to offline the raid bdev""") 1465 p.add_argument('category', help='all or online or configuring or offline') 1466 p.set_defaults(func=bdev_raid_get_bdevs) 1467 1468 def bdev_raid_create(args): 1469 base_bdevs = [] 1470 for u in args.base_bdevs.strip().split(" "): 1471 base_bdevs.append(u) 1472 1473 rpc.bdev.bdev_raid_create(args.client, 1474 name=args.name, 1475 strip_size=args.strip_size, 1476 strip_size_kb=args.strip_size_kb, 1477 raid_level=args.raid_level, 1478 base_bdevs=base_bdevs) 1479 p = subparsers.add_parser('bdev_raid_create', aliases=['construct_raid_bdev'], 1480 help='Create new raid bdev') 1481 p.add_argument('-n', '--name', help='raid bdev name', required=True) 1482 p.add_argument('-s', '--strip-size', help='strip size in KB (deprecated)', type=int) 1483 p.add_argument('-z', '--strip-size_kb', help='strip size in KB', type=int) 1484 p.add_argument('-r', '--raid-level', help='raid level, only raid level 0 is supported', required=True) 1485 p.add_argument('-b', '--base-bdevs', help='base bdevs name, whitespace separated list in quotes', required=True) 1486 p.set_defaults(func=bdev_raid_create) 1487 1488 def bdev_raid_delete(args): 1489 rpc.bdev.bdev_raid_delete(args.client, 1490 name=args.name) 1491 p = subparsers.add_parser('bdev_raid_delete', aliases=['destroy_raid_bdev'], 1492 help='Delete existing raid bdev') 1493 p.add_argument('name', help='raid bdev name') 1494 p.set_defaults(func=bdev_raid_delete) 1495 1496 # split 1497 def bdev_split_create(args): 1498 print_array(rpc.bdev.bdev_split_create(args.client, 1499 base_bdev=args.base_bdev, 1500 split_count=args.split_count, 1501 split_size_mb=args.split_size_mb)) 1502 1503 p = subparsers.add_parser('bdev_split_create', aliases=['construct_split_vbdev'], 1504 help="""Add given disk name to split config. If bdev with base_name 1505 name exist the split bdevs will be created right away, if not split bdevs will be created when base bdev became 1506 available (during examination process).""") 1507 p.add_argument('base_bdev', help='base bdev name') 1508 p.add_argument('-s', '--split-size-mb', help='size in MiB for each bdev', type=int, default=0) 1509 p.add_argument('split_count', help="""Optional - number of split bdevs to create. Total size * split_count must not 1510 exceed the base bdev size.""", type=int) 1511 p.set_defaults(func=bdev_split_create) 1512 1513 def bdev_split_delete(args): 1514 rpc.bdev.bdev_split_delete(args.client, 1515 base_bdev=args.base_bdev) 1516 1517 p = subparsers.add_parser('bdev_split_delete', aliases=['destruct_split_vbdev'], 1518 help="""Delete split config with all created splits.""") 1519 p.add_argument('base_bdev', help='base bdev name') 1520 p.set_defaults(func=bdev_split_delete) 1521 1522 # ftl 1523 ftl_valid_limits = ('crit', 'high', 'low', 'start') 1524 1525 def bdev_ftl_create(args): 1526 def parse_limits(limits, arg_dict, key_suffix=''): 1527 for limit in limits.split(','): 1528 key, value = limit.split(':', 1) 1529 if key in ftl_valid_limits: 1530 arg_dict['limit_' + key + key_suffix] = int(value) 1531 else: 1532 raise ValueError('Limit {} is not supported'.format(key)) 1533 1534 arg_limits = {} 1535 if args.limit_threshold: 1536 parse_limits(args.limit_threshold, arg_limits, '_threshold') 1537 1538 if args.limit: 1539 parse_limits(args.limit, arg_limits) 1540 1541 print_dict(rpc.bdev.bdev_ftl_create(args.client, 1542 name=args.name, 1543 trtype=args.trtype, 1544 traddr=args.traddr, 1545 punits=args.punits, 1546 uuid=args.uuid, 1547 cache=args.cache, 1548 allow_open_bands=args.allow_open_bands, 1549 overprovisioning=args.overprovisioning, 1550 **arg_limits)) 1551 1552 p = subparsers.add_parser('bdev_ftl_create', aliases=['construct_ftl_bdev'], 1553 help='Add FTL bdev') 1554 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 1555 p.add_argument('-t', '--trtype', 1556 help='NVMe target trtype: e.g., pcie', default='pcie') 1557 p.add_argument('-a', '--traddr', 1558 help='NVMe target address: e.g., an ip address or BDF', required=True) 1559 p.add_argument('-l', '--punits', help='Parallel unit range in the form of start-end: e.g. 4-8', 1560 required=True) 1561 p.add_argument('-u', '--uuid', help='UUID of restored bdev (not applicable when creating new ' 1562 'instance): e.g. b286d19a-0059-4709-abcd-9f7732b1567d (optional)') 1563 p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache (optional)') 1564 p.add_argument('-o', '--allow_open_bands', help='Restoring after dirty shutdown without cache will' 1565 ' result in partial data recovery, instead of error', action='store_true') 1566 p.add_argument('--overprovisioning', help='Percentage of device used for relocation, not exposed' 1567 ' to user (optional)', type=int) 1568 1569 limits = p.add_argument_group('Defrag limits', 'Configures defrag limits and thresholds for' 1570 ' levels ' + str(ftl_valid_limits)[1:-1]) 1571 limits.add_argument('--limit', help='Percentage of allowed user versus internal writes at given' 1572 ' levels, e.g. crit:0,high:20,low:80') 1573 limits.add_argument('--limit-threshold', help='Number of free bands triggering a given level of' 1574 ' write limiting e.g. crit:1,high:2,low:3,start:4') 1575 p.set_defaults(func=bdev_ftl_create) 1576 1577 def bdev_ftl_delete(args): 1578 print_dict(rpc.bdev.bdev_ftl_delete(args.client, name=args.name)) 1579 1580 p = subparsers.add_parser('bdev_ftl_delete', aliases=['delete_ftl_bdev'], 1581 help='Delete FTL bdev') 1582 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 1583 p.set_defaults(func=bdev_ftl_delete) 1584 1585 # vmd 1586 def enable_vmd(args): 1587 print_dict(rpc.vmd.enable_vmd(args.client)) 1588 1589 p = subparsers.add_parser('enable_vmd', help='Enable VMD enumeration') 1590 p.set_defaults(func=enable_vmd) 1591 1592 # nbd 1593 def nbd_start_disk(args): 1594 print(rpc.nbd.nbd_start_disk(args.client, 1595 bdev_name=args.bdev_name, 1596 nbd_device=args.nbd_device)) 1597 1598 p = subparsers.add_parser('nbd_start_disk', aliases=['start_nbd_disk'], 1599 help='Export a bdev as an nbd disk') 1600 p.add_argument('bdev_name', help='Blockdev name to be exported. Example: Malloc0.') 1601 p.add_argument('nbd_device', help='Nbd device name to be assigned. Example: /dev/nbd0.', nargs='?') 1602 p.set_defaults(func=nbd_start_disk) 1603 1604 def nbd_stop_disk(args): 1605 rpc.nbd.nbd_stop_disk(args.client, 1606 nbd_device=args.nbd_device) 1607 1608 p = subparsers.add_parser('nbd_stop_disk', aliases=['stop_nbd_disk'], 1609 help='Stop an nbd disk') 1610 p.add_argument('nbd_device', help='Nbd device name to be stopped. Example: /dev/nbd0.') 1611 p.set_defaults(func=nbd_stop_disk) 1612 1613 def nbd_get_disks(args): 1614 print_dict(rpc.nbd.nbd_get_disks(args.client, 1615 nbd_device=args.nbd_device)) 1616 1617 p = subparsers.add_parser('nbd_get_disks', aliases=['get_nbd_disks'], 1618 help='Display full or specified nbd device list') 1619 p.add_argument('-n', '--nbd-device', help="Path of the nbd device. Example: /dev/nbd0", required=False) 1620 p.set_defaults(func=nbd_get_disks) 1621 1622 # net 1623 def net_interface_add_ip_address(args): 1624 rpc.net.net_interface_add_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1625 1626 p = subparsers.add_parser('net_interface_add_ip_address', aliases=['add_ip_address'], 1627 help='Add IP address') 1628 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1629 p.add_argument('ip_addr', help='ip address will be added.') 1630 p.set_defaults(func=net_interface_add_ip_address) 1631 1632 def net_interface_delete_ip_address(args): 1633 rpc.net.net_interface_delete_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1634 1635 p = subparsers.add_parser('net_interface_delete_ip_address', aliases=['delete_ip_address'], 1636 help='Delete IP address') 1637 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1638 p.add_argument('ip_addr', help='ip address will be deleted.') 1639 p.set_defaults(func=net_interface_delete_ip_address) 1640 1641 def net_get_interfaces(args): 1642 print_dict(rpc.net.net_get_interfaces(args.client)) 1643 1644 p = subparsers.add_parser( 1645 'net_get_interfaces', aliases=['get_interfaces'], help='Display current interface list') 1646 p.set_defaults(func=net_get_interfaces) 1647 1648 # NVMe-oF 1649 def nvmf_set_max_subsystems(args): 1650 rpc.nvmf.nvmf_set_max_subsystems(args.client, 1651 max_subsystems=args.max_subsystems) 1652 1653 p = subparsers.add_parser('nvmf_set_max_subsystems', aliases=['set_nvmf_target_max_subsystems'], 1654 help='Set the maximum number of NVMf target subsystems') 1655 p.add_argument('-x', '--max-subsystems', help='Max number of NVMf subsystems', type=int, required=True) 1656 p.set_defaults(func=nvmf_set_max_subsystems) 1657 1658 def nvmf_set_config(args): 1659 rpc.nvmf.nvmf_set_config(args.client, 1660 acceptor_poll_rate=args.acceptor_poll_rate, 1661 conn_sched=args.conn_sched) 1662 1663 p = subparsers.add_parser('nvmf_set_config', aliases=['set_nvmf_target_config'], 1664 help='Set NVMf target config') 1665 p.add_argument('-r', '--acceptor-poll-rate', help='Polling interval of the acceptor for incoming connections (usec)', type=int) 1666 p.add_argument('-s', '--conn-sched', help="""'roundrobin' - Schedule the incoming connections from any host 1667 on the cores in a round robin manner (Default). 'hostip' - Schedule all the incoming connections from a 1668 specific host IP on to the same core. Connections from different IP will be assigned to cores in a round 1669 robin manner. 'transport' - Schedule the connection according to the transport characteristics.""") 1670 p.set_defaults(func=nvmf_set_config) 1671 1672 def nvmf_create_transport(args): 1673 rpc.nvmf.nvmf_create_transport(args.client, 1674 trtype=args.trtype, 1675 tgt_name=args.tgt_name, 1676 max_queue_depth=args.max_queue_depth, 1677 max_qpairs_per_ctrlr=args.max_qpairs_per_ctrlr, 1678 in_capsule_data_size=args.in_capsule_data_size, 1679 max_io_size=args.max_io_size, 1680 io_unit_size=args.io_unit_size, 1681 max_aq_depth=args.max_aq_depth, 1682 num_shared_buffers=args.num_shared_buffers, 1683 buf_cache_size=args.buf_cache_size, 1684 max_srq_depth=args.max_srq_depth, 1685 no_srq=args.no_srq, 1686 c2h_success=args.c2h_success, 1687 dif_insert_or_strip=args.dif_insert_or_strip, 1688 sock_priority=args.sock_priority) 1689 1690 p = subparsers.add_parser('nvmf_create_transport', help='Create NVMf transport') 1691 p.add_argument('-t', '--trtype', help='Transport type (ex. RDMA)', type=str, required=True) 1692 p.add_argument('-g', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1693 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int) 1694 p.add_argument('-p', '--max-qpairs-per-ctrlr', help='Max number of SQ and CQ per controller', type=int) 1695 p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int) 1696 p.add_argument('-i', '--max-io-size', help='Max I/O size (bytes)', type=int) 1697 p.add_argument('-u', '--io-unit-size', help='I/O unit size (bytes)', type=int) 1698 p.add_argument('-a', '--max-aq-depth', help='Max number of admin cmds per AQ', type=int) 1699 p.add_argument('-n', '--num-shared-buffers', help='The number of pooled data buffers available to the transport', type=int) 1700 p.add_argument('-b', '--buf-cache-size', help='The number of shared buffers to reserve for each poll group', type=int) 1701 p.add_argument('-s', '--max-srq-depth', help='Max number of outstanding I/O per SRQ. Relevant only for RDMA transport', type=int) 1702 p.add_argument('-r', '--no-srq', action='store_true', help='Disable per-thread shared receive queue. Relevant only for RDMA transport') 1703 p.add_argument('-o', '--c2h-success', action='store_false', help='Disable C2H success optimization. Relevant only for TCP transport') 1704 p.add_argument('-f', '--dif-insert-or-strip', action='store_true', help='Enable DIF insert/strip. Relevant only for TCP transport') 1705 p.add_argument('-y', '--sock-priority', help='The sock priority of the tcp connection. Relevant only for TCP transport', type=int) 1706 p.set_defaults(func=nvmf_create_transport) 1707 1708 def nvmf_get_transports(args): 1709 print_dict(rpc.nvmf.nvmf_get_transports(args.client, tgt_name=args.tgt_name)) 1710 1711 p = subparsers.add_parser('nvmf_get_transports', aliases=['get_nvmf_transports'], 1712 help='Display nvmf transports') 1713 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1714 p.set_defaults(func=nvmf_get_transports) 1715 1716 def nvmf_get_subsystems(args): 1717 print_dict(rpc.nvmf.nvmf_get_subsystems(args.client, tgt_name=args.tgt_name)) 1718 1719 p = subparsers.add_parser('nvmf_get_subsystems', aliases=['get_nvmf_subsystems'], 1720 help='Display nvmf subsystems') 1721 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1722 p.set_defaults(func=nvmf_get_subsystems) 1723 1724 def nvmf_create_subsystem(args): 1725 rpc.nvmf.nvmf_create_subsystem(args.client, 1726 nqn=args.nqn, 1727 tgt_name=args.tgt_name, 1728 serial_number=args.serial_number, 1729 model_number=args.model_number, 1730 allow_any_host=args.allow_any_host, 1731 max_namespaces=args.max_namespaces) 1732 1733 p = subparsers.add_parser('nvmf_create_subsystem', aliases=['nvmf_subsystem_create'], 1734 help='Create an NVMe-oF subsystem') 1735 p.add_argument('nqn', help='Subsystem NQN (ASCII)') 1736 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1737 p.add_argument("-s", "--serial-number", help=""" 1738 Format: 'sn' etc 1739 Example: 'SPDK00000000000001'""", default='00000000000000000000') 1740 p.add_argument("-d", "--model-number", help=""" 1741 Format: 'mn' etc 1742 Example: 'SPDK Controller'""", default='SPDK bdev Controller') 1743 p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce host NQN whitelist)") 1744 p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed", 1745 type=int, default=0) 1746 p.set_defaults(func=nvmf_create_subsystem) 1747 1748 def nvmf_delete_subsystem(args): 1749 rpc.nvmf.nvmf_delete_subsystem(args.client, 1750 nqn=args.subsystem_nqn, 1751 tgt_name=args.tgt_name) 1752 1753 p = subparsers.add_parser('nvmf_delete_subsystem', aliases=['delete_nvmf_subsystem'], 1754 help='Delete a nvmf subsystem') 1755 p.add_argument('subsystem_nqn', 1756 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 1757 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1758 p.set_defaults(func=nvmf_delete_subsystem) 1759 1760 def nvmf_subsystem_add_listener(args): 1761 rpc.nvmf.nvmf_subsystem_add_listener(args.client, 1762 nqn=args.nqn, 1763 trtype=args.trtype, 1764 traddr=args.traddr, 1765 tgt_name=args.tgt_name, 1766 adrfam=args.adrfam, 1767 trsvcid=args.trsvcid) 1768 1769 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 1770 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1771 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1772 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1773 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1774 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1775 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1776 p.set_defaults(func=nvmf_subsystem_add_listener) 1777 1778 def nvmf_subsystem_remove_listener(args): 1779 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, 1780 nqn=args.nqn, 1781 trtype=args.trtype, 1782 traddr=args.traddr, 1783 tgt_name=args.tgt_name, 1784 adrfam=args.adrfam, 1785 trsvcid=args.trsvcid) 1786 1787 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 1788 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1789 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1790 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1791 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1792 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1793 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1794 p.set_defaults(func=nvmf_subsystem_remove_listener) 1795 1796 def nvmf_subsystem_add_ns(args): 1797 rpc.nvmf.nvmf_subsystem_add_ns(args.client, 1798 nqn=args.nqn, 1799 bdev_name=args.bdev_name, 1800 tgt_name=args.tgt_name, 1801 ptpl_file=args.ptpl_file, 1802 nsid=args.nsid, 1803 nguid=args.nguid, 1804 eui64=args.eui64, 1805 uuid=args.uuid) 1806 1807 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 1808 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1809 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 1810 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1811 p.add_argument('-p', '--ptpl-file', help='The persistent reservation storage location (optional)', type=str) 1812 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 1813 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 1814 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 1815 p.add_argument('-u', '--uuid', help='Namespace UUID (optional)') 1816 p.set_defaults(func=nvmf_subsystem_add_ns) 1817 1818 def nvmf_subsystem_remove_ns(args): 1819 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, 1820 nqn=args.nqn, 1821 nsid=args.nsid, 1822 tgt_name=args.tgt_name) 1823 1824 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 1825 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1826 p.add_argument('nsid', help='The requested NSID', type=int) 1827 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1828 p.set_defaults(func=nvmf_subsystem_remove_ns) 1829 1830 def nvmf_subsystem_add_host(args): 1831 rpc.nvmf.nvmf_subsystem_add_host(args.client, 1832 nqn=args.nqn, 1833 host=args.host, 1834 tgt_name=args.tgt_name) 1835 1836 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 1837 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1838 p.add_argument('host', help='Host NQN to allow') 1839 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1840 p.set_defaults(func=nvmf_subsystem_add_host) 1841 1842 def nvmf_subsystem_remove_host(args): 1843 rpc.nvmf.nvmf_subsystem_remove_host(args.client, 1844 nqn=args.nqn, 1845 host=args.host, 1846 tgt_name=args.tgt_name) 1847 1848 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 1849 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1850 p.add_argument('host', help='Host NQN to remove') 1851 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1852 p.set_defaults(func=nvmf_subsystem_remove_host) 1853 1854 def nvmf_subsystem_allow_any_host(args): 1855 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, 1856 nqn=args.nqn, 1857 disable=args.disable, 1858 tgt_name=args.tgt_name) 1859 1860 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 1861 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1862 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 1863 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 1864 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1865 p.set_defaults(func=nvmf_subsystem_allow_any_host) 1866 1867 def nvmf_get_stats(args): 1868 print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name)) 1869 1870 p = subparsers.add_parser( 1871 'nvmf_get_stats', help='Display current statistics for NVMf subsystem') 1872 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1873 p.set_defaults(func=nvmf_get_stats) 1874 1875 # pmem 1876 def bdev_pmem_create_pool(args): 1877 num_blocks = int((args.total_size * 1024 * 1024) / args.block_size) 1878 rpc.pmem.bdev_pmem_create_pool(args.client, 1879 pmem_file=args.pmem_file, 1880 num_blocks=num_blocks, 1881 block_size=args.block_size) 1882 1883 p = subparsers.add_parser('bdev_pmem_create_pool', aliases=['create_pmem_pool'], 1884 help='Create pmem pool') 1885 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1886 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 1887 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 1888 p.set_defaults(func=bdev_pmem_create_pool) 1889 1890 def bdev_pmem_get_pool_info(args): 1891 print_dict(rpc.pmem.bdev_pmem_get_pool_info(args.client, 1892 pmem_file=args.pmem_file)) 1893 1894 p = subparsers.add_parser('bdev_pmem_get_pool_info', aliases=['pmem_pool_info'], 1895 help='Display pmem pool info and check consistency') 1896 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1897 p.set_defaults(func=bdev_pmem_get_pool_info) 1898 1899 def bdev_pmem_delete_pool(args): 1900 rpc.pmem.bdev_pmem_delete_pool(args.client, 1901 pmem_file=args.pmem_file) 1902 1903 p = subparsers.add_parser('bdev_pmem_delete_pool', aliases=['delete_pmem_pool'], 1904 help='Delete pmem pool') 1905 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1906 p.set_defaults(func=bdev_pmem_delete_pool) 1907 1908 # subsystem 1909 def framework_get_subsystems(args): 1910 print_dict(rpc.subsystem.framework_get_subsystems(args.client)) 1911 1912 p = subparsers.add_parser('framework_get_subsystems', aliases=['get_subsystems'], 1913 help="""Print subsystems array in initialization order. Each subsystem 1914 entry contain (unsorted) array of subsystems it depends on.""") 1915 p.set_defaults(func=framework_get_subsystems) 1916 1917 def framework_get_config(args): 1918 print_dict(rpc.subsystem.framework_get_config(args.client, args.name)) 1919 1920 p = subparsers.add_parser('framework_get_config', aliases=['get_subsystem_config'], 1921 help="""Print subsystem configuration""") 1922 p.add_argument('name', help='Name of subsystem to query') 1923 p.set_defaults(func=framework_get_config) 1924 1925 # vhost 1926 def vhost_controller_set_coalescing(args): 1927 rpc.vhost.vhost_controller_set_coalescing(args.client, 1928 ctrlr=args.ctrlr, 1929 delay_base_us=args.delay_base_us, 1930 iops_threshold=args.iops_threshold) 1931 1932 p = subparsers.add_parser('vhost_controller_set_coalescing', aliases=['set_vhost_controller_coalescing'], 1933 help='Set vhost controller coalescing') 1934 p.add_argument('ctrlr', help='controller name') 1935 p.add_argument('delay_base_us', help='Base delay time', type=int) 1936 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 1937 p.set_defaults(func=vhost_controller_set_coalescing) 1938 1939 def vhost_create_scsi_controller(args): 1940 rpc.vhost.vhost_create_scsi_controller(args.client, 1941 ctrlr=args.ctrlr, 1942 cpumask=args.cpumask) 1943 1944 p = subparsers.add_parser( 1945 'vhost_create_scsi_controller', aliases=['construct_vhost_scsi_controller'], 1946 help='Add new vhost controller') 1947 p.add_argument('ctrlr', help='controller name') 1948 p.add_argument('--cpumask', help='cpu mask for this controller') 1949 p.set_defaults(func=vhost_create_scsi_controller) 1950 1951 def vhost_scsi_controller_add_target(args): 1952 print_json(rpc.vhost.vhost_scsi_controller_add_target(args.client, 1953 ctrlr=args.ctrlr, 1954 scsi_target_num=args.scsi_target_num, 1955 bdev_name=args.bdev_name)) 1956 1957 p = subparsers.add_parser('vhost_scsi_controller_add_target', 1958 aliases=['add_vhost_scsi_lun'], 1959 help='Add lun to vhost controller') 1960 p.add_argument('ctrlr', help='conntroller name where add lun') 1961 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 1962 p.add_argument('bdev_name', help='bdev name') 1963 p.set_defaults(func=vhost_scsi_controller_add_target) 1964 1965 def vhost_scsi_controller_remove_target(args): 1966 rpc.vhost.vhost_scsi_controller_remove_target(args.client, 1967 ctrlr=args.ctrlr, 1968 scsi_target_num=args.scsi_target_num) 1969 1970 p = subparsers.add_parser('vhost_scsi_controller_remove_target', 1971 aliases=['remove_vhost_scsi_target'], 1972 help='Remove target from vhost controller') 1973 p.add_argument('ctrlr', help='controller name to remove target from') 1974 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 1975 p.set_defaults(func=vhost_scsi_controller_remove_target) 1976 1977 def vhost_create_blk_controller(args): 1978 rpc.vhost.vhost_create_blk_controller(args.client, 1979 ctrlr=args.ctrlr, 1980 dev_name=args.dev_name, 1981 cpumask=args.cpumask, 1982 readonly=args.readonly) 1983 1984 p = subparsers.add_parser('vhost_create_blk_controller', 1985 aliases=['construct_vhost_blk_controller'], 1986 help='Add a new vhost block controller') 1987 p.add_argument('ctrlr', help='controller name') 1988 p.add_argument('dev_name', help='device name') 1989 p.add_argument('--cpumask', help='cpu mask for this controller') 1990 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 1991 p.set_defaults(func=vhost_create_blk_controller) 1992 1993 def vhost_create_nvme_controller(args): 1994 rpc.vhost.vhost_create_nvme_controller(args.client, 1995 ctrlr=args.ctrlr, 1996 io_queues=args.io_queues, 1997 cpumask=args.cpumask) 1998 1999 p = subparsers.add_parser('vhost_create_nvme_controller', aliases=['vhost_create_nvme_controller'], 2000 help='Add new vhost controller') 2001 p.add_argument('ctrlr', help='controller name') 2002 p.add_argument('io_queues', help='number of IO queues for the controller', type=int) 2003 p.add_argument('--cpumask', help='cpu mask for this controller') 2004 p.set_defaults(func=vhost_create_nvme_controller) 2005 2006 def vhost_nvme_controller_add_ns(args): 2007 rpc.vhost.vhost_nvme_controller_add_ns(args.client, 2008 ctrlr=args.ctrlr, 2009 bdev_name=args.bdev_name) 2010 2011 p = subparsers.add_parser('vhost_nvme_controller_add_ns', aliases=['add_vhost_nvme_ns'], 2012 help='Add a Namespace to vhost controller') 2013 p.add_argument('ctrlr', help='conntroller name where add a Namespace') 2014 p.add_argument('bdev_name', help='block device name for a new Namespace') 2015 p.set_defaults(func=vhost_nvme_controller_add_ns) 2016 2017 def vhost_get_controllers(args): 2018 print_dict(rpc.vhost.vhost_get_controllers(args.client, args.name)) 2019 2020 p = subparsers.add_parser('vhost_get_controllers', aliases=['get_vhost_controllers'], 2021 help='List all or specific vhost controller(s)') 2022 p.add_argument('-n', '--name', help="Name of vhost controller", required=False) 2023 p.set_defaults(func=vhost_get_controllers) 2024 2025 def vhost_delete_controller(args): 2026 rpc.vhost.vhost_delete_controller(args.client, 2027 ctrlr=args.ctrlr) 2028 2029 p = subparsers.add_parser('vhost_delete_controller', aliases=['remove_vhost_controller'], 2030 help='Delete a vhost controller') 2031 p.add_argument('ctrlr', help='controller name') 2032 p.set_defaults(func=vhost_delete_controller) 2033 2034 def bdev_virtio_attach_controller(args): 2035 print_array(rpc.vhost.bdev_virtio_attach_controller(args.client, 2036 name=args.name, 2037 trtype=args.trtype, 2038 traddr=args.traddr, 2039 dev_type=args.dev_type, 2040 vq_count=args.vq_count, 2041 vq_size=args.vq_size)) 2042 2043 p = subparsers.add_parser('bdev_virtio_attach_controller', aliases=['construct_virtio_dev'], 2044 help="""Attach virtio controller using provided 2045 transport type and device type. This will also create bdevs for any block devices connected to the 2046 controller (for example, SCSI devices for a virtio-scsi controller). 2047 Result is array of added bdevs.""") 2048 p.add_argument('name', help="Use this name as base for new created bdevs") 2049 p.add_argument('-t', '--trtype', 2050 help='Virtio target transport type: pci or user', required=True) 2051 p.add_argument('-a', '--traddr', 2052 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 2053 p.add_argument('-d', '--dev-type', 2054 help='Device type: blk or scsi', required=True) 2055 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 2056 p.add_argument('--vq-size', help='Size of each queue', type=int) 2057 p.set_defaults(func=bdev_virtio_attach_controller) 2058 2059 def bdev_virtio_scsi_get_devices(args): 2060 print_dict(rpc.vhost.bdev_virtio_scsi_get_devices(args.client)) 2061 2062 p = subparsers.add_parser('bdev_virtio_scsi_get_devices', aliases=['get_virtio_scsi_devs'], 2063 help='List all Virtio-SCSI devices.') 2064 p.set_defaults(func=bdev_virtio_scsi_get_devices) 2065 2066 def bdev_virtio_detach_controller(args): 2067 rpc.vhost.bdev_virtio_detach_controller(args.client, 2068 name=args.name) 2069 2070 p = subparsers.add_parser('bdev_virtio_detach_controller', aliases=['remove_virtio_bdev'], 2071 help="""Remove a Virtio device 2072 This will delete all bdevs exposed by this device""") 2073 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 2074 p.set_defaults(func=bdev_virtio_detach_controller) 2075 2076 # OCSSD 2077 def bdev_ocssd_create(args): 2078 nsid = int(args.nsid) if args.nsid is not None else None 2079 print_json(rpc.bdev.bdev_ocssd_create(args.client, 2080 ctrlr_name=args.ctrlr_name, 2081 bdev_name=args.name, 2082 nsid=nsid, 2083 range=args.range)) 2084 2085 p = subparsers.add_parser('bdev_ocssd_create', 2086 help='Creates zoned bdev on specified Open Channel controller') 2087 p.add_argument('-c', '--ctrlr_name', help='Name of the OC NVMe controller', required=True) 2088 p.add_argument('-b', '--name', help='Name of the bdev to create', required=True) 2089 p.add_argument('-n', '--nsid', help='Namespace ID', required=False) 2090 p.add_argument('-r', '--range', help='Parallel unit range (in the form of BEGIN-END (inclusive))', 2091 required=False) 2092 p.set_defaults(func=bdev_ocssd_create) 2093 2094 def bdev_ocssd_delete(args): 2095 print_json(rpc.bdev.bdev_ocssd_delete(args.client, 2096 name=args.name)) 2097 2098 p = subparsers.add_parser('bdev_ocssd_delete', 2099 help='Deletes Open Channel bdev') 2100 p.add_argument('name', help='Name of the Open Channel bdev') 2101 p.set_defaults(func=bdev_ocssd_delete) 2102 2103 # ioat 2104 def ioat_scan_copy_engine(args): 2105 pci_whitelist = [] 2106 if args.pci_whitelist: 2107 for w in args.pci_whitelist.strip().split(" "): 2108 pci_whitelist.append(w) 2109 rpc.ioat.ioat_scan_copy_engine(args.client, pci_whitelist) 2110 2111 p = subparsers.add_parser('ioat_scan_copy_engine', aliases=['scan_ioat_copy_engine'], 2112 help='Set scan and enable IOAT copy engine offload.') 2113 p.add_argument('-w', '--pci-whitelist', help="""Whitespace-separated list of PCI addresses in 2114 domain:bus:device.function format or domain.bus.device.function format""") 2115 p.set_defaults(func=ioat_scan_copy_engine) 2116 2117 # opal 2118 def bdev_nvme_opal_init(args): 2119 rpc.nvme.bdev_nvme_opal_init(args.client, 2120 nvme_ctrlr_name=args.nvme_ctrlr_name, 2121 password=args.password) 2122 2123 p = subparsers.add_parser('bdev_nvme_opal_init', help='take ownership and activate') 2124 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2125 p.add_argument('-p', '--password', help='password for admin') 2126 p.set_defaults(func=bdev_nvme_opal_init) 2127 2128 def bdev_nvme_opal_revert(args): 2129 rpc.nvme.bdev_nvme_opal_revert(args.client, 2130 nvme_ctrlr_name=args.nvme_ctrlr_name, 2131 password=args.password) 2132 p = subparsers.add_parser('bdev_nvme_opal_revert', help='Revert to default factory settings') 2133 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2134 p.add_argument('-p', '--password', help='password') 2135 p.set_defaults(func=bdev_nvme_opal_revert) 2136 2137 def bdev_opal_create(args): 2138 print_json(rpc.bdev.bdev_opal_create(args.client, 2139 nvme_ctrlr_name=args.nvme_ctrlr_name, 2140 nsid=args.nsid, 2141 locking_range_id=args.locking_range_id, 2142 range_start=args.range_start, 2143 range_length=args.range_length, 2144 password=args.password)) 2145 2146 p = subparsers.add_parser('bdev_opal_create', help="""Create opal bdev on specified NVMe controller""") 2147 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name', required=True) 2148 p.add_argument('-n', '--nsid', help='namespace ID (only support nsid=1 for now)', type=int, required=True) 2149 p.add_argument('-i', '--locking-range-id', help='locking range id', type=int, required=True) 2150 p.add_argument('-s', '--range-start', help='locking range start LBA', type=int, required=True) 2151 p.add_argument('-l', '--range-length', help='locking range length (in blocks)', type=int, required=True) 2152 p.add_argument('-p', '--password', help='admin password', required=True) 2153 p.set_defaults(func=bdev_opal_create) 2154 2155 def bdev_opal_get_info(args): 2156 print_dict(rpc.bdev.bdev_opal_get_info(args.client, 2157 bdev_name=args.bdev_name, 2158 password=args.password)) 2159 2160 p = subparsers.add_parser('bdev_opal_get_info', help='get opal locking range info for this bdev') 2161 p.add_argument('-b', '--bdev-name', help='opal bdev') 2162 p.add_argument('-p', '--password', help='password') 2163 p.set_defaults(func=bdev_opal_get_info) 2164 2165 def bdev_opal_delete(args): 2166 rpc.bdev.bdev_opal_delete(args.client, 2167 bdev_name=args.bdev_name, 2168 password=args.password) 2169 2170 p = subparsers.add_parser('bdev_opal_delete', help="""delete a virtual opal bdev""") 2171 p.add_argument('-b', '--bdev-name', help='opal virtual bdev', required=True) 2172 p.add_argument('-p', '--password', help='admin password', required=True) 2173 p.set_defaults(func=bdev_opal_delete) 2174 2175 def bdev_opal_new_user(args): 2176 rpc.bdev.bdev_opal_new_user(args.client, 2177 bdev_name=args.bdev_name, 2178 admin_password=args.admin_password, 2179 user_id=args.user_id, 2180 user_password=args.user_password) 2181 2182 p = subparsers.add_parser('bdev_opal_new_user', help="""Add a user to opal bdev who can set lock state for this bdev""") 2183 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2184 p.add_argument('-p', '--admin-password', help='admin password', required=True) 2185 p.add_argument('-i', '--user-id', help='ID for new user', type=int, required=True) 2186 p.add_argument('-u', '--user-password', help='password set for this user', required=True) 2187 p.set_defaults(func=bdev_opal_new_user) 2188 2189 def bdev_opal_set_lock_state(args): 2190 rpc.bdev.bdev_opal_set_lock_state(args.client, 2191 bdev_name=args.bdev_name, 2192 user_id=args.user_id, 2193 password=args.password, 2194 lock_state=args.lock_state) 2195 2196 p = subparsers.add_parser('bdev_opal_set_lock_state', help="""set lock state for an opal bdev""") 2197 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2198 p.add_argument('-i', '--user-id', help='ID of the user who want to set lock state, either admin or a user assigned to this bdev', 2199 type=int, required=True) 2200 p.add_argument('-p', '--password', help='password of this user', required=True) 2201 p.add_argument('-l', '--lock-state', help='lock state to set, choose from {readwrite, readonly, rwlock}', required=True) 2202 p.set_defaults(func=bdev_opal_set_lock_state) 2203 2204 # bdev_nvme_send_cmd 2205 def bdev_nvme_send_cmd(args): 2206 print_dict(rpc.nvme.bdev_nvme_send_cmd(args.client, 2207 name=args.nvme_name, 2208 cmd_type=args.cmd_type, 2209 data_direction=args.data_direction, 2210 cmdbuf=args.cmdbuf, 2211 data=args.data, 2212 metadata=args.metadata, 2213 data_len=args.data_length, 2214 metadata_len=args.metadata_length, 2215 timeout_ms=args.timeout_ms)) 2216 2217 p = subparsers.add_parser('bdev_nvme_send_cmd', aliases=['send_nvme_cmd'], 2218 help='NVMe passthrough cmd.') 2219 p.add_argument('-n', '--nvme-name', help="""Name of the operating NVMe controller""") 2220 p.add_argument('-t', '--cmd-type', help="""Type of nvme cmd. Valid values are: admin, io""") 2221 p.add_argument('-r', '--data-direction', help="""Direction of data transfer. Valid values are: c2h, h2c""") 2222 p.add_argument('-c', '--cmdbuf', help="""NVMe command encoded by base64 urlsafe""") 2223 p.add_argument('-d', '--data', help="""Data transferring to controller from host, encoded by base64 urlsafe""") 2224 p.add_argument('-m', '--metadata', help="""Metadata transferring to controller from host, encoded by base64 urlsafe""") 2225 p.add_argument('-D', '--data-length', help="""Data length required to transfer from controller to host""", type=int) 2226 p.add_argument('-M', '--metadata-length', help="""Metadata length required to transfer from controller to host""", type=int) 2227 p.add_argument('-T', '--timeout-ms', 2228 help="""Command execution timeout value, in milliseconds, if 0, don't track timeout""", type=int, default=0) 2229 p.set_defaults(func=bdev_nvme_send_cmd) 2230 2231 # Notifications 2232 def notify_get_types(args): 2233 print_dict(rpc.notify.notify_get_types(args.client)) 2234 2235 p = subparsers.add_parser('notify_get_types', aliases=['get_notification_types'], 2236 help='List available notifications that user can subscribe to.') 2237 p.set_defaults(func=notify_get_types) 2238 2239 def notify_get_notifications(args): 2240 ret = rpc.notify.notify_get_notifications(args.client, 2241 id=args.id, 2242 max=args.max) 2243 print_dict(ret) 2244 2245 p = subparsers.add_parser('notify_get_notifications', aliases=['get_notifications'], 2246 help='Get notifications') 2247 p.add_argument('-i', '--id', help="""First ID to start fetching from""", type=int) 2248 p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int) 2249 p.set_defaults(func=notify_get_notifications) 2250 2251 def thread_get_stats(args): 2252 print_dict(rpc.app.thread_get_stats(args.client)) 2253 2254 p = subparsers.add_parser( 2255 'thread_get_stats', help='Display current statistics of all the threads') 2256 p.set_defaults(func=thread_get_stats) 2257 2258 def env_dpdk_get_mem_stats(args): 2259 print_dict(rpc.env_dpdk.env_dpdk_get_mem_stats(args.client)) 2260 2261 p = subparsers.add_parser( 2262 'env_dpdk_get_mem_stats', help='write the dpdk memory stats to a file.') 2263 p.set_defaults(func=env_dpdk_get_mem_stats) 2264 2265 # blobfs 2266 def blobfs_detect(args): 2267 print(rpc.blobfs.blobfs_detect(args.client, 2268 bdev_name=args.bdev_name)) 2269 2270 p = subparsers.add_parser('blobfs_detect', help='Detect whether a blobfs exists on bdev') 2271 p.add_argument('bdev_name', help='Blockdev name to detect blobfs. Example: Malloc0.') 2272 p.set_defaults(func=blobfs_detect) 2273 2274 def blobfs_create(args): 2275 print(rpc.blobfs.blobfs_create(args.client, 2276 bdev_name=args.bdev_name, 2277 cluster_sz=args.cluster_sz)) 2278 2279 p = subparsers.add_parser('blobfs_create', help='Build a blobfs on bdev') 2280 p.add_argument('bdev_name', help='Blockdev name to build blobfs. Example: Malloc0.') 2281 p.add_argument('-c', '--cluster_sz', 2282 help="""Size of cluster in bytes (Optional). Must be multiple of 4KB page size. Default and minimal value is 1M.""") 2283 p.set_defaults(func=blobfs_create) 2284 2285 def blobfs_mount(args): 2286 print(rpc.blobfs.blobfs_mount(args.client, 2287 bdev_name=args.bdev_name, 2288 mountpoint=args.mountpoint)) 2289 2290 p = subparsers.add_parser('blobfs_mount', help='Mount a blobfs on bdev to host path by FUSE') 2291 p.add_argument('bdev_name', help='Blockdev name where the blobfs is. Example: Malloc0.') 2292 p.add_argument('mountpoint', help='Mountpoint path in host to mount blobfs. Example: /mnt/.') 2293 p.set_defaults(func=blobfs_mount) 2294 2295 def blobfs_set_cache_size(args): 2296 print(rpc.blobfs.blobfs_set_cache_size(args.client, 2297 size_in_mb=args.size_in_mb)) 2298 2299 p = subparsers.add_parser('blobfs_set_cache_size', help='Set cache size for blobfs') 2300 p.add_argument('size_in_mb', help='Cache size for blobfs in megabytes.', type=int) 2301 p.set_defaults(func=blobfs_set_cache_size) 2302 2303 def check_called_name(name): 2304 if name in deprecated_aliases: 2305 print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr) 2306 2307 class dry_run_client: 2308 def call(self, method, params=None): 2309 print("Request:\n" + json.dumps({"method": method, "params": params}, indent=2)) 2310 2311 def null_print(arg): 2312 pass 2313 2314 def call_rpc_func(args): 2315 args.func(args) 2316 check_called_name(args.called_rpc_name) 2317 2318 def execute_script(parser, client, fd): 2319 executed_rpc = "" 2320 for rpc_call in map(str.rstrip, fd): 2321 if not rpc_call.strip(): 2322 continue 2323 executed_rpc = "\n".join([executed_rpc, rpc_call]) 2324 args = parser.parse_args(shlex.split(rpc_call)) 2325 args.client = client 2326 try: 2327 call_rpc_func(args) 2328 except JSONRPCException as ex: 2329 print("Exception:") 2330 print(executed_rpc.strip() + " <<<") 2331 print(ex.message) 2332 exit(1) 2333 2334 args = parser.parse_args() 2335 if args.dry_run: 2336 args.client = dry_run_client() 2337 print_dict = null_print 2338 print_json = null_print 2339 print_array = null_print 2340 else: 2341 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, log_level=getattr(logging, args.verbose.upper())) 2342 if hasattr(args, 'func'): 2343 try: 2344 call_rpc_func(args) 2345 except JSONRPCException as ex: 2346 print(ex.message) 2347 exit(1) 2348 elif sys.stdin.isatty(): 2349 # No arguments and no data piped through stdin 2350 parser.print_help() 2351 exit(1) 2352 else: 2353 execute_script(parser, args.client, sys.stdin) 2354