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