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