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