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