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