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