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