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