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