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