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