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 # iSCSI 908 def iscsi_set_options(args): 909 rpc.iscsi.iscsi_set_options( 910 args.client, 911 auth_file=args.auth_file, 912 node_base=args.node_base, 913 nop_timeout=args.nop_timeout, 914 nop_in_interval=args.nop_in_interval, 915 disable_chap=args.disable_chap, 916 require_chap=args.require_chap, 917 mutual_chap=args.mutual_chap, 918 chap_group=args.chap_group, 919 max_sessions=args.max_sessions, 920 max_queue_depth=args.max_queue_depth, 921 max_connections_per_session=args.max_connections_per_session, 922 default_time2wait=args.default_time2wait, 923 default_time2retain=args.default_time2retain, 924 first_burst_length=args.first_burst_length, 925 immediate_data=args.immediate_data, 926 error_recovery_level=args.error_recovery_level, 927 allow_duplicated_isid=args.allow_duplicated_isid, 928 max_large_datain_per_connection=args.max_large_datain_per_connection, 929 max_r2t_per_connection=args.max_r2t_per_connection) 930 931 p = subparsers.add_parser('iscsi_set_options', aliases=['set_iscsi_options'], 932 help="""Set options of iSCSI subsystem""") 933 p.add_argument('-f', '--auth-file', help='Path to CHAP shared secret file') 934 p.add_argument('-b', '--node-base', help='Prefix of the name of iSCSI target node') 935 p.add_argument('-o', '--nop-timeout', help='Timeout in seconds to nop-in request to the initiator', type=int) 936 p.add_argument('-n', '--nop-in-interval', help='Time interval in secs between nop-in requests by the target', type=int) 937 p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled. 938 *** Mutually exclusive with --require-chap""", action='store_true') 939 p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required. 940 *** Mutually exclusive with --disable-chap""", action='store_true') 941 p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true') 942 p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session. 943 *** Authentication group must be precreated ***""", type=int) 944 p.add_argument('-a', '--max-sessions', help='Maximum number of sessions in the host.', type=int) 945 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/Os per queue.', type=int) 946 p.add_argument('-c', '--max-connections-per-session', help='Negotiated parameter, MaxConnections.', type=int) 947 p.add_argument('-w', '--default-time2wait', help='Negotiated parameter, DefaultTime2Wait.', type=int) 948 p.add_argument('-v', '--default-time2retain', help='Negotiated parameter, DefaultTime2Retain.', type=int) 949 p.add_argument('-s', '--first-burst-length', help='Negotiated parameter, FirstBurstLength.', type=int) 950 p.add_argument('-i', '--immediate-data', help='Negotiated parameter, ImmediateData.', action='store_true') 951 p.add_argument('-l', '--error-recovery-level', help='Negotiated parameter, ErrorRecoveryLevel', type=int) 952 p.add_argument('-p', '--allow-duplicated-isid', help='Allow duplicated initiator session ID.', action='store_true') 953 p.add_argument('-x', '--max-large-datain-per-connection', help='Max number of outstanding split read I/Os per connection', type=int) 954 p.add_argument('-k', '--max-r2t-per-connection', help='Max number of outstanding R2Ts per connection', type=int) 955 p.set_defaults(func=iscsi_set_options) 956 957 def iscsi_set_discovery_auth(args): 958 rpc.iscsi.iscsi_set_discovery_auth( 959 args.client, 960 disable_chap=args.disable_chap, 961 require_chap=args.require_chap, 962 mutual_chap=args.mutual_chap, 963 chap_group=args.chap_group) 964 965 p = subparsers.add_parser('iscsi_set_discovery_auth', aliases=['set_iscsi_discovery_auth'], 966 help="""Set CHAP authentication for discovery session.""") 967 p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled. 968 *** Mutually exclusive with --require-chap""", action='store_true') 969 p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required. 970 *** Mutually exclusive with --disable-chap""", action='store_true') 971 p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true') 972 p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session. 973 *** Authentication group must be precreated ***""", type=int) 974 p.set_defaults(func=iscsi_set_discovery_auth) 975 976 def iscsi_create_auth_group(args): 977 secrets = None 978 if args.secrets: 979 secrets = [dict(u.split(":") for u in a.split(" ")) for a in args.secrets.split(",")] 980 981 rpc.iscsi.iscsi_create_auth_group(args.client, tag=args.tag, secrets=secrets) 982 983 p = subparsers.add_parser('iscsi_create_auth_group', aliases=['add_iscsi_auth_group'], 984 help='Create authentication group for CHAP authentication.') 985 p.add_argument('tag', help='Authentication group tag (unique, integer > 0).', type=int) 986 p.add_argument('-c', '--secrets', help="""Comma-separated list of CHAP secrets 987<user:user_name secret:chap_secret muser:mutual_user_name msecret:mutual_chap_secret> enclosed in quotes. 988Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 msecret:ms2'""", required=False) 989 p.set_defaults(func=iscsi_create_auth_group) 990 991 def iscsi_delete_auth_group(args): 992 rpc.iscsi.iscsi_delete_auth_group(args.client, tag=args.tag) 993 994 p = subparsers.add_parser('iscsi_delete_auth_group', aliases=['delete_iscsi_auth_group'], 995 help='Delete an authentication group.') 996 p.add_argument('tag', help='Authentication group tag', type=int) 997 p.set_defaults(func=iscsi_delete_auth_group) 998 999 def iscsi_auth_group_add_secret(args): 1000 rpc.iscsi.iscsi_auth_group_add_secret( 1001 args.client, 1002 tag=args.tag, 1003 user=args.user, 1004 secret=args.secret, 1005 muser=args.muser, 1006 msecret=args.msecret) 1007 1008 p = subparsers.add_parser('iscsi_auth_group_add_secret', aliases=['add_secret_to_iscsi_auth_group'], 1009 help='Add a secret to an authentication group.') 1010 p.add_argument('tag', help='Authentication group tag', type=int) 1011 p.add_argument('-u', '--user', help='User name for one-way CHAP authentication', required=True) 1012 p.add_argument('-s', '--secret', help='Secret for one-way CHAP authentication', required=True) 1013 p.add_argument('-m', '--muser', help='User name for mutual CHAP authentication') 1014 p.add_argument('-r', '--msecret', help='Secret for mutual CHAP authentication') 1015 p.set_defaults(func=iscsi_auth_group_add_secret) 1016 1017 def iscsi_auth_group_remove_secret(args): 1018 rpc.iscsi.iscsi_auth_group_remove_secret(args.client, tag=args.tag, user=args.user) 1019 1020 p = subparsers.add_parser('iscsi_auth_group_remove_secret', aliases=['delete_secret_from_iscsi_auth_group'], 1021 help='Remove a secret from an authentication group.') 1022 p.add_argument('tag', help='Authentication group tag', type=int) 1023 p.add_argument('-u', '--user', help='User name for one-way CHAP authentication', required=True) 1024 p.set_defaults(func=iscsi_auth_group_remove_secret) 1025 1026 def iscsi_get_auth_groups(args): 1027 print_dict(rpc.iscsi.iscsi_get_auth_groups(args.client)) 1028 1029 p = subparsers.add_parser('iscsi_get_auth_groups', aliases=['get_iscsi_auth_groups'], 1030 help='Display current authentication group configuration') 1031 p.set_defaults(func=iscsi_get_auth_groups) 1032 1033 def iscsi_get_portal_groups(args): 1034 print_dict(rpc.iscsi.iscsi_get_portal_groups(args.client)) 1035 1036 p = subparsers.add_parser( 1037 'iscsi_get_portal_groups', aliases=['get_portal_groups'], 1038 help='Display current portal group configuration') 1039 p.set_defaults(func=iscsi_get_portal_groups) 1040 1041 def iscsi_get_initiator_groups(args): 1042 print_dict(rpc.iscsi.iscsi_get_initiator_groups(args.client)) 1043 1044 p = subparsers.add_parser('iscsi_get_initiator_groups', 1045 aliases=['get_initiator_groups'], 1046 help='Display current initiator group configuration') 1047 p.set_defaults(func=iscsi_get_initiator_groups) 1048 1049 def iscsi_get_target_nodes(args): 1050 print_dict(rpc.iscsi.iscsi_get_target_nodes(args.client)) 1051 1052 p = subparsers.add_parser('iscsi_get_target_nodes', aliases=['get_target_nodes'], 1053 help='Display target nodes') 1054 p.set_defaults(func=iscsi_get_target_nodes) 1055 1056 def iscsi_create_target_node(args): 1057 luns = [] 1058 for u in args.bdev_name_id_pairs.strip().split(" "): 1059 bdev_name, lun_id = u.split(":") 1060 luns.append({"bdev_name": bdev_name, "lun_id": int(lun_id)}) 1061 1062 pg_ig_maps = [] 1063 for u in args.pg_ig_mappings.strip().split(" "): 1064 pg, ig = u.split(":") 1065 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 1066 1067 rpc.iscsi.iscsi_create_target_node( 1068 args.client, 1069 luns=luns, 1070 pg_ig_maps=pg_ig_maps, 1071 name=args.name, 1072 alias_name=args.alias_name, 1073 queue_depth=args.queue_depth, 1074 chap_group=args.chap_group, 1075 disable_chap=args.disable_chap, 1076 require_chap=args.require_chap, 1077 mutual_chap=args.mutual_chap, 1078 header_digest=args.header_digest, 1079 data_digest=args.data_digest) 1080 1081 p = subparsers.add_parser('iscsi_create_target_node', aliases=['construct_target_node'], 1082 help='Add a target node') 1083 p.add_argument('name', help='Target node name (ASCII)') 1084 p.add_argument('alias_name', help='Target node alias name (ASCII)') 1085 p.add_argument('bdev_name_id_pairs', help="""Whitespace-separated list of <bdev name:LUN ID> pairs enclosed 1086 in quotes. Format: 'bdev_name0:id0 bdev_name1:id1' etc 1087 Example: 'Malloc0:0 Malloc1:1 Malloc5:2' 1088 *** The bdevs must pre-exist *** 1089 *** LUN0 (id = 0) is required *** 1090 *** bdevs names cannot contain space or colon characters ***""") 1091 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 1092 Whitespace separated, quoted, mapping defined with colon 1093 separated list of "tags" (int > 0) 1094 Example: '1:1 2:2 2:1' 1095 *** The Portal/Initiator Groups must be precreated ***""") 1096 p.add_argument('queue_depth', help='Desired target queue depth', type=int) 1097 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 1098 *** Authentication group must be precreated ***""", type=int, default=0) 1099 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 1100 *** Mutually exclusive with --require-chap ***""", action='store_true') 1101 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 1102 *** Mutually exclusive with --disable-chap ***""", action='store_true') 1103 p.add_argument( 1104 '-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', action='store_true') 1105 p.add_argument('-H', '--header-digest', 1106 help='Header Digest should be required for this target node.', action='store_true') 1107 p.add_argument('-D', '--data-digest', 1108 help='Data Digest should be required for this target node.', action='store_true') 1109 p.set_defaults(func=iscsi_create_target_node) 1110 1111 def iscsi_target_node_add_lun(args): 1112 rpc.iscsi.iscsi_target_node_add_lun( 1113 args.client, 1114 name=args.name, 1115 bdev_name=args.bdev_name, 1116 lun_id=args.lun_id) 1117 1118 p = subparsers.add_parser('iscsi_target_node_add_lun', aliases=['target_node_add_lun'], 1119 help='Add LUN to the target node') 1120 p.add_argument('name', help='Target node name (ASCII)') 1121 p.add_argument('bdev_name', help="""bdev name enclosed in quotes. 1122 *** bdev name cannot contain space or colon characters ***""") 1123 p.add_argument('-i', dest='lun_id', help="""LUN ID (integer >= 0) 1124 *** If LUN ID is omitted or -1, the lowest free one is assigned ***""", type=int, required=False) 1125 p.set_defaults(func=iscsi_target_node_add_lun) 1126 1127 def iscsi_target_node_set_auth(args): 1128 rpc.iscsi.iscsi_target_node_set_auth( 1129 args.client, 1130 name=args.name, 1131 chap_group=args.chap_group, 1132 disable_chap=args.disable_chap, 1133 require_chap=args.require_chap, 1134 mutual_chap=args.mutual_chap) 1135 1136 p = subparsers.add_parser('iscsi_target_node_set_auth', aliases=['set_iscsi_target_node_auth'], 1137 help='Set CHAP authentication for the target node') 1138 p.add_argument('name', help='Target node name (ASCII)') 1139 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 1140 *** Authentication group must be precreated ***""", type=int, default=0) 1141 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 1142 *** Mutually exclusive with --require-chap ***""", action='store_true') 1143 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 1144 *** Mutually exclusive with --disable-chap ***""", action='store_true') 1145 p.add_argument('-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', 1146 action='store_true') 1147 p.set_defaults(func=iscsi_target_node_set_auth) 1148 1149 def iscsi_target_node_add_pg_ig_maps(args): 1150 pg_ig_maps = [] 1151 for u in args.pg_ig_mappings.strip().split(" "): 1152 pg, ig = u.split(":") 1153 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 1154 rpc.iscsi.iscsi_target_node_add_pg_ig_maps( 1155 args.client, 1156 pg_ig_maps=pg_ig_maps, 1157 name=args.name) 1158 1159 p = subparsers.add_parser('iscsi_target_node_add_pg_ig_maps', 1160 aliases=['add_pg_ig_maps'], 1161 help='Add PG-IG maps to the target node') 1162 p.add_argument('name', help='Target node name (ASCII)') 1163 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 1164 Whitespace separated, quoted, mapping defined with colon 1165 separated list of "tags" (int > 0) 1166 Example: '1:1 2:2 2:1' 1167 *** The Portal/Initiator Groups must be precreated ***""") 1168 p.set_defaults(func=iscsi_target_node_add_pg_ig_maps) 1169 1170 def iscsi_target_node_remove_pg_ig_maps(args): 1171 pg_ig_maps = [] 1172 for u in args.pg_ig_mappings.strip().split(" "): 1173 pg, ig = u.split(":") 1174 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 1175 rpc.iscsi.iscsi_target_node_remove_pg_ig_maps( 1176 args.client, pg_ig_maps=pg_ig_maps, name=args.name) 1177 1178 p = subparsers.add_parser('iscsi_target_node_remove_pg_ig_maps', 1179 aliases=['delete_pg_ig_maps'], 1180 help='Delete PG-IG maps from the target node') 1181 p.add_argument('name', help='Target node name (ASCII)') 1182 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 1183 Whitespace separated, quoted, mapping defined with colon 1184 separated list of "tags" (int > 0) 1185 Example: '1:1 2:2 2:1' 1186 *** The Portal/Initiator Groups must be precreated ***""") 1187 p.set_defaults(func=iscsi_target_node_remove_pg_ig_maps) 1188 1189 def iscsi_target_node_set_redirect(args): 1190 rpc.iscsi.iscsi_target_node_set_redirect( 1191 args.client, 1192 name=args.name, 1193 pg_tag=args.pg_tag, 1194 redirect_host=args.redirect_host, 1195 redirect_port=args.redirect_port) 1196 1197 p = subparsers.add_parser('iscsi_target_node_set_redirect', 1198 help="""Update redirect portal of the public portal group for the target node. 1199 Omit redirect host and port to clear previously set redirect settings.""") 1200 p.add_argument('name', help='Target node name (ASCII)') 1201 p.add_argument('pg_tag', help='Portal group tag (unique, integer > 0)', type=int) 1202 p.add_argument('-a', '--redirect_host', help='Numeric IP address for redirect portal', required=False) 1203 p.add_argument('-p', '--redirect_port', help='Numeric TCP port for redirect portal', required=False) 1204 p.set_defaults(func=iscsi_target_node_set_redirect) 1205 1206 def iscsi_target_node_request_logout(args): 1207 rpc.iscsi.iscsi_target_node_request_logout( 1208 args.client, 1209 name=args.name, 1210 pg_tag=args.pg_tag) 1211 1212 p = subparsers.add_parser('iscsi_target_node_request_logout', 1213 help="""For the target node, request connections whose portal group tag 1214 match to logout, or request all connections if portal group tag is omitted.""") 1215 p.add_argument('name', help='Target node name (ASCII)') 1216 p.add_argument('-t', '--pg-tag', help='Portal group tag (unique, integer > 0)', type=int, required=False) 1217 p.set_defaults(func=iscsi_target_node_request_logout) 1218 1219 def iscsi_create_portal_group(args): 1220 portals = [] 1221 for p in args.portal_list.strip().split(' '): 1222 ip, separator, port_cpumask = p.rpartition(':') 1223 split_port_cpumask = port_cpumask.split('@') 1224 if len(split_port_cpumask) == 1: 1225 port = port_cpumask 1226 portals.append({'host': ip, 'port': port}) 1227 else: 1228 port = split_port_cpumask[0] 1229 cpumask = split_port_cpumask[1] 1230 portals.append({'host': ip, 'port': port}) 1231 print("WARNING: Specifying a portal group with a CPU mask is no longer supported. Ignoring it.") 1232 rpc.iscsi.iscsi_create_portal_group( 1233 args.client, 1234 portals=portals, 1235 tag=args.tag, 1236 private=args.private, 1237 wait=args.wait) 1238 1239 p = subparsers.add_parser('iscsi_create_portal_group', aliases=['add_portal_group'], 1240 help='Add a portal group') 1241 p.add_argument( 1242 'tag', help='Portal group tag (unique, integer > 0)', type=int) 1243 p.add_argument('portal_list', help="""List of portals in host:port format, separated by whitespace 1244 Example: '192.168.100.100:3260 192.168.100.100:3261 192.168.100.100:3262""") 1245 p.add_argument('-p', '--private', help="""Public (false) or private (true) portal group. 1246 Private portal groups do not have their portals returned by a discovery session. A public 1247 portal group may optionally specify a redirect portal for non-discovery logins. This redirect 1248 portal must be from a private portal group.""", action='store_true') 1249 p.add_argument('-w', '--wait', help="""Do not listening on portals until it is started explicitly. 1250 One major iSCSI initiator may not retry login once it failed. Hence for such initiator, listening 1251 on portals should be allowed after all associated target nodes are created.""", action='store_true') 1252 p.set_defaults(func=iscsi_create_portal_group) 1253 1254 def iscsi_start_portal_group(args): 1255 rpc.iscsi.iscsi_start_portal_group(args.client, tag=args.tag) 1256 1257 p = subparsers.add_parser('iscsi_start_portal_group', 1258 help='Start listening on portals if it is not started yet.') 1259 p.add_argument( 1260 'tag', help='Portal group tag (unique, integer > 0)', type=int) 1261 p.set_defaults(func=iscsi_start_portal_group) 1262 1263 def iscsi_create_initiator_group(args): 1264 initiators = [] 1265 netmasks = [] 1266 for i in args.initiator_list.strip().split(' '): 1267 initiators.append(i) 1268 for n in args.netmask_list.strip().split(' '): 1269 netmasks.append(n) 1270 rpc.iscsi.iscsi_create_initiator_group( 1271 args.client, 1272 tag=args.tag, 1273 initiators=initiators, 1274 netmasks=netmasks) 1275 1276 p = subparsers.add_parser('iscsi_create_initiator_group', aliases=['add_initiator_group'], 1277 help='Add an initiator group') 1278 p.add_argument( 1279 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1280 p.add_argument('initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 1281 enclosed in quotes. Example: 'ANY' or '127.0.0.1 192.168.200.100'""") 1282 p.add_argument('netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 1283 Example: '255.255.0.0 255.248.0.0' etc""") 1284 p.set_defaults(func=iscsi_create_initiator_group) 1285 1286 def iscsi_initiator_group_add_initiators(args): 1287 initiators = None 1288 netmasks = None 1289 if args.initiator_list: 1290 initiators = [] 1291 for i in args.initiator_list.strip().split(' '): 1292 initiators.append(i) 1293 if args.netmask_list: 1294 netmasks = [] 1295 for n in args.netmask_list.strip().split(' '): 1296 netmasks.append(n) 1297 rpc.iscsi.iscsi_initiator_group_add_initiators( 1298 args.client, 1299 tag=args.tag, 1300 initiators=initiators, 1301 netmasks=netmasks) 1302 1303 p = subparsers.add_parser('iscsi_initiator_group_add_initiators', 1304 aliases=['add_initiators_to_initiator_group'], 1305 help='Add initiators to an existing initiator group') 1306 p.add_argument( 1307 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1308 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 1309 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 1310 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 1311 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 1312 p.set_defaults(func=iscsi_initiator_group_add_initiators) 1313 1314 def iscsi_initiator_group_remove_initiators(args): 1315 initiators = None 1316 netmasks = None 1317 if args.initiator_list: 1318 initiators = [] 1319 for i in args.initiator_list.strip().split(' '): 1320 initiators.append(i) 1321 if args.netmask_list: 1322 netmasks = [] 1323 for n in args.netmask_list.strip().split(' '): 1324 netmasks.append(n) 1325 rpc.iscsi.iscsi_initiator_group_remove_initiators( 1326 args.client, 1327 tag=args.tag, 1328 initiators=initiators, 1329 netmasks=netmasks) 1330 1331 p = subparsers.add_parser('iscsi_initiator_group_remove_initiators', 1332 aliases=['delete_initiators_from_initiator_group'], 1333 help='Delete initiators from an existing initiator group') 1334 p.add_argument( 1335 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1336 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 1337 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 1338 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 1339 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 1340 p.set_defaults(func=iscsi_initiator_group_remove_initiators) 1341 1342 def iscsi_delete_target_node(args): 1343 rpc.iscsi.iscsi_delete_target_node( 1344 args.client, target_node_name=args.target_node_name) 1345 1346 p = subparsers.add_parser('iscsi_delete_target_node', aliases=['delete_target_node'], 1347 help='Delete a target node') 1348 p.add_argument('target_node_name', 1349 help='Target node name to be deleted. Example: iqn.2016-06.io.spdk:disk1.') 1350 p.set_defaults(func=iscsi_delete_target_node) 1351 1352 def iscsi_delete_portal_group(args): 1353 rpc.iscsi.iscsi_delete_portal_group(args.client, tag=args.tag) 1354 1355 p = subparsers.add_parser('iscsi_delete_portal_group', 1356 aliases=['delete_portal_group'], 1357 help='Delete a portal group') 1358 p.add_argument( 1359 'tag', help='Portal group tag (unique, integer > 0)', type=int) 1360 p.set_defaults(func=iscsi_delete_portal_group) 1361 1362 def iscsi_delete_initiator_group(args): 1363 rpc.iscsi.iscsi_delete_initiator_group(args.client, tag=args.tag) 1364 1365 p = subparsers.add_parser('iscsi_delete_initiator_group', 1366 aliases=['delete_initiator_group'], 1367 help='Delete an initiator group') 1368 p.add_argument( 1369 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1370 p.set_defaults(func=iscsi_delete_initiator_group) 1371 1372 def iscsi_portal_group_set_auth(args): 1373 rpc.iscsi.iscsi_portal_group_set_auth( 1374 args.client, 1375 tag=args.tag, 1376 chap_group=args.chap_group, 1377 disable_chap=args.disable_chap, 1378 require_chap=args.require_chap, 1379 mutual_chap=args.mutual_chap) 1380 1381 p = subparsers.add_parser('iscsi_portal_group_set_auth', 1382 help='Set CHAP authentication for discovery sessions specific for the portal group') 1383 p.add_argument('tag', help='Portal group tag (unique, integer > 0)', type=int) 1384 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this portal group. 1385 *** Authentication group must be precreated ***""", type=int, default=0) 1386 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this portal group. 1387 *** Mutually exclusive with --require-chap ***""", action='store_true') 1388 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this portal group. 1389 *** Mutually exclusive with --disable-chap ***""", action='store_true') 1390 p.add_argument('-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', 1391 action='store_true') 1392 p.set_defaults(func=iscsi_portal_group_set_auth) 1393 1394 def iscsi_get_connections(args): 1395 print_dict(rpc.iscsi.iscsi_get_connections(args.client)) 1396 1397 p = subparsers.add_parser('iscsi_get_connections', aliases=['get_iscsi_connections'], 1398 help='Display iSCSI connections') 1399 p.set_defaults(func=iscsi_get_connections) 1400 1401 def iscsi_get_options(args): 1402 print_dict(rpc.iscsi.iscsi_get_options(args.client)) 1403 1404 p = subparsers.add_parser('iscsi_get_options', aliases=['get_iscsi_global_params'], 1405 help='Display iSCSI global parameters') 1406 p.set_defaults(func=iscsi_get_options) 1407 1408 def scsi_get_devices(args): 1409 print_dict(rpc.iscsi.scsi_get_devices(args.client)) 1410 1411 p = subparsers.add_parser('scsi_get_devices', aliases=['get_scsi_devices'], 1412 help='Display SCSI devices') 1413 p.set_defaults(func=scsi_get_devices) 1414 1415 # trace 1416 def trace_enable_tpoint_group(args): 1417 rpc.trace.trace_enable_tpoint_group(args.client, name=args.name) 1418 1419 p = subparsers.add_parser('trace_enable_tpoint_group', aliases=['enable_tpoint_group'], 1420 help='enable trace on a specific tpoint group') 1421 p.add_argument( 1422 'name', help="""trace group name we want to enable in tpoint_group_mask. 1423 (for example "bdev" for bdev trace group, "all" for all trace groups).""") 1424 p.set_defaults(func=trace_enable_tpoint_group) 1425 1426 def trace_disable_tpoint_group(args): 1427 rpc.trace.trace_disable_tpoint_group(args.client, name=args.name) 1428 1429 p = subparsers.add_parser('trace_disable_tpoint_group', aliases=['disable_tpoint_group'], 1430 help='disable trace on a specific tpoint group') 1431 p.add_argument( 1432 'name', help="""trace group name we want to disable in tpoint_group_mask. 1433 (for example "bdev" for bdev trace group, "all" for all trace groups).""") 1434 p.set_defaults(func=trace_disable_tpoint_group) 1435 1436 def trace_get_tpoint_group_mask(args): 1437 print_dict(rpc.trace.trace_get_tpoint_group_mask(args.client)) 1438 1439 p = subparsers.add_parser('trace_get_tpoint_group_mask', aliases=['get_tpoint_group_mask'], 1440 help='get trace point group mask') 1441 p.set_defaults(func=trace_get_tpoint_group_mask) 1442 1443 # log 1444 def log_set_flag(args): 1445 rpc.log.log_set_flag(args.client, flag=args.flag) 1446 1447 p = subparsers.add_parser('log_set_flag', help='set log flag', aliases=['set_log_flag']) 1448 p.add_argument( 1449 'flag', help='log flag we want to set. (for example "nvme").') 1450 p.set_defaults(func=log_set_flag) 1451 1452 def log_clear_flag(args): 1453 rpc.log.log_clear_flag(args.client, flag=args.flag) 1454 1455 p = subparsers.add_parser('log_clear_flag', help='clear log flag', aliases=['clear_log_flag']) 1456 p.add_argument( 1457 'flag', help='log flag we want to clear. (for example "nvme").') 1458 p.set_defaults(func=log_clear_flag) 1459 1460 def log_get_flags(args): 1461 print_dict(rpc.log.log_get_flags(args.client)) 1462 1463 p = subparsers.add_parser('log_get_flags', help='get log flags', aliases=['get_log_flags']) 1464 p.set_defaults(func=log_get_flags) 1465 1466 def log_set_level(args): 1467 rpc.log.log_set_level(args.client, level=args.level) 1468 1469 p = subparsers.add_parser('log_set_level', aliases=['set_log_level'], 1470 help='set log level') 1471 p.add_argument('level', help='log level we want to set. (for example "DEBUG").') 1472 p.set_defaults(func=log_set_level) 1473 1474 def log_get_level(args): 1475 print_dict(rpc.log.log_get_level(args.client)) 1476 1477 p = subparsers.add_parser('log_get_level', aliases=['get_log_level'], 1478 help='get log level') 1479 p.set_defaults(func=log_get_level) 1480 1481 def log_set_print_level(args): 1482 rpc.log.log_set_print_level(args.client, level=args.level) 1483 1484 p = subparsers.add_parser('log_set_print_level', aliases=['set_log_print_level'], 1485 help='set log print level') 1486 p.add_argument('level', help='log print level we want to set. (for example "DEBUG").') 1487 p.set_defaults(func=log_set_print_level) 1488 1489 def log_get_print_level(args): 1490 print_dict(rpc.log.log_get_print_level(args.client)) 1491 1492 p = subparsers.add_parser('log_get_print_level', aliases=['get_log_print_level'], 1493 help='get log print level') 1494 p.set_defaults(func=log_get_print_level) 1495 1496 # lvol 1497 def bdev_lvol_create_lvstore(args): 1498 print_json(rpc.lvol.bdev_lvol_create_lvstore(args.client, 1499 bdev_name=args.bdev_name, 1500 lvs_name=args.lvs_name, 1501 cluster_sz=args.cluster_sz, 1502 clear_method=args.clear_method)) 1503 1504 p = subparsers.add_parser('bdev_lvol_create_lvstore', aliases=['construct_lvol_store'], 1505 help='Add logical volume store on base bdev') 1506 p.add_argument('bdev_name', help='base bdev name') 1507 p.add_argument('lvs_name', help='name for lvol store') 1508 p.add_argument('-c', '--cluster-sz', help='size of cluster (in bytes)', type=int, required=False) 1509 p.add_argument('--clear-method', help="""Change clear method for data region. 1510 Available: none, unmap, write_zeroes""", required=False) 1511 p.set_defaults(func=bdev_lvol_create_lvstore) 1512 1513 def bdev_lvol_rename_lvstore(args): 1514 rpc.lvol.bdev_lvol_rename_lvstore(args.client, 1515 old_name=args.old_name, 1516 new_name=args.new_name) 1517 1518 p = subparsers.add_parser('bdev_lvol_rename_lvstore', aliases=['rename_lvol_store'], 1519 help='Change logical volume store name') 1520 p.add_argument('old_name', help='old name') 1521 p.add_argument('new_name', help='new name') 1522 p.set_defaults(func=bdev_lvol_rename_lvstore) 1523 1524 def bdev_lvol_create(args): 1525 print_json(rpc.lvol.bdev_lvol_create(args.client, 1526 lvol_name=args.lvol_name, 1527 size=args.size * 1024 * 1024, 1528 thin_provision=args.thin_provision, 1529 clear_method=args.clear_method, 1530 uuid=args.uuid, 1531 lvs_name=args.lvs_name)) 1532 1533 p = subparsers.add_parser('bdev_lvol_create', aliases=['construct_lvol_bdev'], 1534 help='Add a bdev with an logical volume backend') 1535 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1536 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1537 p.add_argument('-t', '--thin-provision', action='store_true', help='create lvol bdev as thin provisioned') 1538 p.add_argument('-c', '--clear-method', help="""Change default data clusters clear method. 1539 Available: none, unmap, write_zeroes""", required=False) 1540 p.add_argument('lvol_name', help='name for this lvol') 1541 p.add_argument('size', help='size in MiB for this bdev', type=int) 1542 p.set_defaults(func=bdev_lvol_create) 1543 1544 def bdev_lvol_snapshot(args): 1545 print_json(rpc.lvol.bdev_lvol_snapshot(args.client, 1546 lvol_name=args.lvol_name, 1547 snapshot_name=args.snapshot_name)) 1548 1549 p = subparsers.add_parser('bdev_lvol_snapshot', aliases=['snapshot_lvol_bdev'], 1550 help='Create a snapshot of an lvol bdev') 1551 p.add_argument('lvol_name', help='lvol bdev name') 1552 p.add_argument('snapshot_name', help='lvol snapshot name') 1553 p.set_defaults(func=bdev_lvol_snapshot) 1554 1555 def bdev_lvol_clone(args): 1556 print_json(rpc.lvol.bdev_lvol_clone(args.client, 1557 snapshot_name=args.snapshot_name, 1558 clone_name=args.clone_name)) 1559 1560 p = subparsers.add_parser('bdev_lvol_clone', aliases=['clone_lvol_bdev'], 1561 help='Create a clone of an lvol snapshot') 1562 p.add_argument('snapshot_name', help='lvol snapshot name') 1563 p.add_argument('clone_name', help='lvol clone name') 1564 p.set_defaults(func=bdev_lvol_clone) 1565 1566 def bdev_lvol_rename(args): 1567 rpc.lvol.bdev_lvol_rename(args.client, 1568 old_name=args.old_name, 1569 new_name=args.new_name) 1570 1571 p = subparsers.add_parser('bdev_lvol_rename', aliases=['rename_lvol_bdev'], 1572 help='Change lvol bdev name') 1573 p.add_argument('old_name', help='lvol bdev name') 1574 p.add_argument('new_name', help='new lvol name') 1575 p.set_defaults(func=bdev_lvol_rename) 1576 1577 def bdev_lvol_inflate(args): 1578 rpc.lvol.bdev_lvol_inflate(args.client, 1579 name=args.name) 1580 1581 p = subparsers.add_parser('bdev_lvol_inflate', aliases=['inflate_lvol_bdev'], 1582 help='Make thin provisioned lvol a thick provisioned lvol') 1583 p.add_argument('name', help='lvol bdev name') 1584 p.set_defaults(func=bdev_lvol_inflate) 1585 1586 def bdev_lvol_decouple_parent(args): 1587 rpc.lvol.bdev_lvol_decouple_parent(args.client, 1588 name=args.name) 1589 1590 p = subparsers.add_parser('bdev_lvol_decouple_parent', aliases=['decouple_parent_lvol_bdev'], 1591 help='Decouple parent of lvol') 1592 p.add_argument('name', help='lvol bdev name') 1593 p.set_defaults(func=bdev_lvol_decouple_parent) 1594 1595 def bdev_lvol_resize(args): 1596 rpc.lvol.bdev_lvol_resize(args.client, 1597 name=args.name, 1598 size=args.size * 1024 * 1024) 1599 1600 p = subparsers.add_parser('bdev_lvol_resize', aliases=['resize_lvol_bdev'], 1601 help='Resize existing lvol bdev') 1602 p.add_argument('name', help='lvol bdev name') 1603 p.add_argument('size', help='new size in MiB for this bdev', type=int) 1604 p.set_defaults(func=bdev_lvol_resize) 1605 1606 def bdev_lvol_set_read_only(args): 1607 rpc.lvol.bdev_lvol_set_read_only(args.client, 1608 name=args.name) 1609 1610 p = subparsers.add_parser('bdev_lvol_set_read_only', aliases=['set_read_only_lvol_bdev'], 1611 help='Mark lvol bdev as read only') 1612 p.add_argument('name', help='lvol bdev name') 1613 p.set_defaults(func=bdev_lvol_set_read_only) 1614 1615 def bdev_lvol_delete(args): 1616 rpc.lvol.bdev_lvol_delete(args.client, 1617 name=args.name) 1618 1619 p = subparsers.add_parser('bdev_lvol_delete', aliases=['destroy_lvol_bdev'], 1620 help='Destroy a logical volume') 1621 p.add_argument('name', help='lvol bdev name') 1622 p.set_defaults(func=bdev_lvol_delete) 1623 1624 def bdev_lvol_delete_lvstore(args): 1625 rpc.lvol.bdev_lvol_delete_lvstore(args.client, 1626 uuid=args.uuid, 1627 lvs_name=args.lvs_name) 1628 1629 p = subparsers.add_parser('bdev_lvol_delete_lvstore', aliases=['destroy_lvol_store'], 1630 help='Destroy an logical volume store') 1631 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1632 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1633 p.set_defaults(func=bdev_lvol_delete_lvstore) 1634 1635 def bdev_lvol_get_lvstores(args): 1636 print_dict(rpc.lvol.bdev_lvol_get_lvstores(args.client, 1637 uuid=args.uuid, 1638 lvs_name=args.lvs_name)) 1639 1640 p = subparsers.add_parser('bdev_lvol_get_lvstores', aliases=['get_lvol_stores'], 1641 help='Display current logical volume store list') 1642 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1643 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1644 p.set_defaults(func=bdev_lvol_get_lvstores) 1645 1646 def bdev_raid_get_bdevs(args): 1647 print_array(rpc.bdev.bdev_raid_get_bdevs(args.client, 1648 category=args.category)) 1649 1650 p = subparsers.add_parser('bdev_raid_get_bdevs', aliases=['get_raid_bdevs'], 1651 help="""This is used to list all the raid bdev names based on the input category 1652 requested. Category should be one of 'all', 'online', 'configuring' or 'offline'. 'all' means all the raid bdevs whether 1653 they are online or configuring or offline. 'online' is the raid bdev which is registered with bdev layer. 'configuring' 1654 is the raid bdev which does not have full configuration discovered yet. 'offline' is the raid bdev which is not registered 1655 with bdev as of now and it has encountered any error or user has requested to offline the raid bdev""") 1656 p.add_argument('category', help='all or online or configuring or offline') 1657 p.set_defaults(func=bdev_raid_get_bdevs) 1658 1659 def bdev_raid_create(args): 1660 base_bdevs = [] 1661 for u in args.base_bdevs.strip().split(" "): 1662 base_bdevs.append(u) 1663 1664 rpc.bdev.bdev_raid_create(args.client, 1665 name=args.name, 1666 strip_size=args.strip_size, 1667 strip_size_kb=args.strip_size_kb, 1668 raid_level=args.raid_level, 1669 base_bdevs=base_bdevs) 1670 p = subparsers.add_parser('bdev_raid_create', aliases=['construct_raid_bdev'], 1671 help='Create new raid bdev') 1672 p.add_argument('-n', '--name', help='raid bdev name', required=True) 1673 p.add_argument('-s', '--strip-size', help='strip size in KB (deprecated)', type=int) 1674 p.add_argument('-z', '--strip-size_kb', help='strip size in KB', type=int) 1675 p.add_argument('-r', '--raid-level', help='raid level, only raid level 0 is supported', required=True) 1676 p.add_argument('-b', '--base-bdevs', help='base bdevs name, whitespace separated list in quotes', required=True) 1677 p.set_defaults(func=bdev_raid_create) 1678 1679 def bdev_raid_delete(args): 1680 rpc.bdev.bdev_raid_delete(args.client, 1681 name=args.name) 1682 p = subparsers.add_parser('bdev_raid_delete', aliases=['destroy_raid_bdev'], 1683 help='Delete existing raid bdev') 1684 p.add_argument('name', help='raid bdev name') 1685 p.set_defaults(func=bdev_raid_delete) 1686 1687 # split 1688 def bdev_split_create(args): 1689 print_array(rpc.bdev.bdev_split_create(args.client, 1690 base_bdev=args.base_bdev, 1691 split_count=args.split_count, 1692 split_size_mb=args.split_size_mb)) 1693 1694 p = subparsers.add_parser('bdev_split_create', aliases=['construct_split_vbdev'], 1695 help="""Add given disk name to split config. If bdev with base_name 1696 name exist the split bdevs will be created right away, if not split bdevs will be created when base bdev became 1697 available (during examination process).""") 1698 p.add_argument('base_bdev', help='base bdev name') 1699 p.add_argument('-s', '--split-size-mb', help='size in MiB for each bdev', type=int, default=0) 1700 p.add_argument('split_count', help="""Optional - number of split bdevs to create. Total size * split_count must not 1701 exceed the base bdev size.""", type=int) 1702 p.set_defaults(func=bdev_split_create) 1703 1704 def bdev_split_delete(args): 1705 rpc.bdev.bdev_split_delete(args.client, 1706 base_bdev=args.base_bdev) 1707 1708 p = subparsers.add_parser('bdev_split_delete', aliases=['destruct_split_vbdev'], 1709 help="""Delete split config with all created splits.""") 1710 p.add_argument('base_bdev', help='base bdev name') 1711 p.set_defaults(func=bdev_split_delete) 1712 1713 # ftl 1714 ftl_valid_limits = ('crit', 'high', 'low', 'start') 1715 1716 def bdev_ftl_create(args): 1717 def parse_limits(limits, arg_dict, key_suffix=''): 1718 for limit in limits.split(','): 1719 key, value = limit.split(':', 1) 1720 if key in ftl_valid_limits: 1721 arg_dict['limit_' + key + key_suffix] = int(value) 1722 else: 1723 raise ValueError('Limit {} is not supported'.format(key)) 1724 1725 arg_limits = {} 1726 if args.limit_threshold: 1727 parse_limits(args.limit_threshold, arg_limits, '_threshold') 1728 1729 if args.limit: 1730 parse_limits(args.limit, arg_limits) 1731 1732 print_dict(rpc.bdev.bdev_ftl_create(args.client, 1733 name=args.name, 1734 base_bdev=args.base_bdev, 1735 uuid=args.uuid, 1736 cache=args.cache, 1737 allow_open_bands=args.allow_open_bands, 1738 overprovisioning=args.overprovisioning, 1739 l2p_path=args.l2p_path, 1740 use_append=args.use_append, 1741 **arg_limits)) 1742 1743 p = subparsers.add_parser('bdev_ftl_create', aliases=['construct_ftl_bdev'], help='Add FTL bdev') 1744 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 1745 p.add_argument('-d', '--base_bdev', help='Name of zoned bdev used as underlying device', 1746 required=True) 1747 p.add_argument('-u', '--uuid', help='UUID of restored bdev (not applicable when creating new ' 1748 'instance): e.g. b286d19a-0059-4709-abcd-9f7732b1567d (optional)') 1749 p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache (optional)') 1750 p.add_argument('-o', '--allow_open_bands', help='Restoring after dirty shutdown without cache will' 1751 ' result in partial data recovery, instead of error', action='store_true') 1752 p.add_argument('--overprovisioning', help='Percentage of device used for relocation, not exposed' 1753 ' to user (optional)', type=int) 1754 p.add_argument('--l2p_path', help='Path to persistent memory file or device to store l2p onto, ' 1755 'by default l2p is kept in DRAM and is volatile (optional)') 1756 p.add_argument('--use_append', help='Use appends instead of writes', action='store_true') 1757 1758 limits = p.add_argument_group('Defrag limits', 'Configures defrag limits and thresholds for' 1759 ' levels ' + str(ftl_valid_limits)[1:-1]) 1760 limits.add_argument('--limit', help='Percentage of allowed user versus internal writes at given' 1761 ' levels, e.g. crit:0,high:20,low:80') 1762 limits.add_argument('--limit-threshold', help='Number of free bands triggering a given level of' 1763 ' write limiting e.g. crit:1,high:2,low:3,start:4') 1764 p.set_defaults(func=bdev_ftl_create) 1765 1766 def bdev_ftl_delete(args): 1767 print_dict(rpc.bdev.bdev_ftl_delete(args.client, name=args.name)) 1768 1769 p = subparsers.add_parser('bdev_ftl_delete', aliases=['delete_ftl_bdev'], 1770 help='Delete FTL bdev') 1771 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 1772 p.set_defaults(func=bdev_ftl_delete) 1773 1774 # vmd 1775 def enable_vmd(args): 1776 print_dict(rpc.vmd.enable_vmd(args.client)) 1777 1778 p = subparsers.add_parser('enable_vmd', help='Enable VMD enumeration') 1779 p.set_defaults(func=enable_vmd) 1780 1781 # nbd 1782 def nbd_start_disk(args): 1783 print(rpc.nbd.nbd_start_disk(args.client, 1784 bdev_name=args.bdev_name, 1785 nbd_device=args.nbd_device)) 1786 1787 p = subparsers.add_parser('nbd_start_disk', aliases=['start_nbd_disk'], 1788 help='Export a bdev as an nbd disk') 1789 p.add_argument('bdev_name', help='Blockdev name to be exported. Example: Malloc0.') 1790 p.add_argument('nbd_device', help='Nbd device name to be assigned. Example: /dev/nbd0.', nargs='?') 1791 p.set_defaults(func=nbd_start_disk) 1792 1793 def nbd_stop_disk(args): 1794 rpc.nbd.nbd_stop_disk(args.client, 1795 nbd_device=args.nbd_device) 1796 1797 p = subparsers.add_parser('nbd_stop_disk', aliases=['stop_nbd_disk'], 1798 help='Stop an nbd disk') 1799 p.add_argument('nbd_device', help='Nbd device name to be stopped. Example: /dev/nbd0.') 1800 p.set_defaults(func=nbd_stop_disk) 1801 1802 def nbd_get_disks(args): 1803 print_dict(rpc.nbd.nbd_get_disks(args.client, 1804 nbd_device=args.nbd_device)) 1805 1806 p = subparsers.add_parser('nbd_get_disks', aliases=['get_nbd_disks'], 1807 help='Display full or specified nbd device list') 1808 p.add_argument('-n', '--nbd-device', help="Path of the nbd device. Example: /dev/nbd0", required=False) 1809 p.set_defaults(func=nbd_get_disks) 1810 1811 # net 1812 def net_interface_add_ip_address(args): 1813 rpc.net.net_interface_add_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1814 1815 p = subparsers.add_parser('net_interface_add_ip_address', aliases=['add_ip_address'], 1816 help='Add IP address') 1817 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1818 p.add_argument('ip_addr', help='ip address will be added.') 1819 p.set_defaults(func=net_interface_add_ip_address) 1820 1821 def net_interface_delete_ip_address(args): 1822 rpc.net.net_interface_delete_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1823 1824 p = subparsers.add_parser('net_interface_delete_ip_address', aliases=['delete_ip_address'], 1825 help='Delete IP address') 1826 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1827 p.add_argument('ip_addr', help='ip address will be deleted.') 1828 p.set_defaults(func=net_interface_delete_ip_address) 1829 1830 def net_get_interfaces(args): 1831 print_dict(rpc.net.net_get_interfaces(args.client)) 1832 1833 p = subparsers.add_parser( 1834 'net_get_interfaces', aliases=['get_interfaces'], help='Display current interface list') 1835 p.set_defaults(func=net_get_interfaces) 1836 1837 # NVMe-oF 1838 def nvmf_set_max_subsystems(args): 1839 rpc.nvmf.nvmf_set_max_subsystems(args.client, 1840 max_subsystems=args.max_subsystems) 1841 1842 p = subparsers.add_parser('nvmf_set_max_subsystems', aliases=['set_nvmf_target_max_subsystems'], 1843 help='Set the maximum number of NVMf target subsystems') 1844 p.add_argument('-x', '--max-subsystems', help='Max number of NVMf subsystems', type=int, required=True) 1845 p.set_defaults(func=nvmf_set_max_subsystems) 1846 1847 def nvmf_set_config(args): 1848 rpc.nvmf.nvmf_set_config(args.client, 1849 acceptor_poll_rate=args.acceptor_poll_rate, 1850 conn_sched=args.conn_sched, 1851 passthru_identify_ctrlr=args.passthru_identify_ctrlr) 1852 1853 p = subparsers.add_parser('nvmf_set_config', aliases=['set_nvmf_target_config'], 1854 help='Set NVMf target config') 1855 p.add_argument('-r', '--acceptor-poll-rate', help='Polling interval of the acceptor for incoming connections (usec)', type=int) 1856 p.add_argument('-s', '--conn-sched', help='(Deprecated). Ignored.') 1857 p.add_argument('-i', '--passthru-identify-ctrlr', help="""Passthrough fields like serial number and model number 1858 when the controller has a single namespace that is an NVMe bdev""", action='store_true') 1859 p.set_defaults(func=nvmf_set_config) 1860 1861 def nvmf_create_transport(args): 1862 rpc.nvmf.nvmf_create_transport(args.client, 1863 trtype=args.trtype, 1864 tgt_name=args.tgt_name, 1865 max_queue_depth=args.max_queue_depth, 1866 max_qpairs_per_ctrlr=args.max_qpairs_per_ctrlr, 1867 max_io_qpairs_per_ctrlr=args.max_io_qpairs_per_ctrlr, 1868 in_capsule_data_size=args.in_capsule_data_size, 1869 max_io_size=args.max_io_size, 1870 io_unit_size=args.io_unit_size, 1871 max_aq_depth=args.max_aq_depth, 1872 num_shared_buffers=args.num_shared_buffers, 1873 buf_cache_size=args.buf_cache_size, 1874 num_cqe=args.num_cqe, 1875 max_srq_depth=args.max_srq_depth, 1876 no_srq=args.no_srq, 1877 c2h_success=args.c2h_success, 1878 dif_insert_or_strip=args.dif_insert_or_strip, 1879 sock_priority=args.sock_priority, 1880 acceptor_backlog=args.acceptor_backlog, 1881 abort_timeout_sec=args.abort_timeout_sec, 1882 no_wr_batching=args.no_wr_batching, 1883 control_msg_num=args.control_msg_num) 1884 1885 p = subparsers.add_parser('nvmf_create_transport', help='Create NVMf transport') 1886 p.add_argument('-t', '--trtype', help='Transport type (ex. RDMA)', type=str, required=True) 1887 p.add_argument('-g', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1888 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int) 1889 p.add_argument('-p', '--max-qpairs-per-ctrlr', help="""Max number of SQ and CQ per controller. 1890 Deprecated, use max-io-qpairs-per-ctrlr""", type=int) 1891 p.add_argument('-m', '--max-io-qpairs-per-ctrlr', help='Max number of IO qpairs per controller', type=int) 1892 p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int) 1893 p.add_argument('-i', '--max-io-size', help='Max I/O size (bytes)', type=int) 1894 p.add_argument('-u', '--io-unit-size', help='I/O unit size (bytes)', type=int) 1895 p.add_argument('-a', '--max-aq-depth', help='Max number of admin cmds per AQ', type=int) 1896 p.add_argument('-n', '--num-shared-buffers', help='The number of pooled data buffers available to the transport', type=int) 1897 p.add_argument('-b', '--buf-cache-size', help='The number of shared buffers to reserve for each poll group', type=int) 1898 p.add_argument('-d', '--num_cqe', help="""The number of CQ entires. Only used when no_srq=true. 1899 Relevant only for RDMA transport""", type=int) 1900 p.add_argument('-s', '--max-srq-depth', help='Max number of outstanding I/O per SRQ. Relevant only for RDMA transport', type=int) 1901 p.add_argument('-r', '--no-srq', action='store_true', help='Disable per-thread shared receive queue. Relevant only for RDMA transport') 1902 p.add_argument('-o', '--c2h-success', action='store_false', help='Disable C2H success optimization. Relevant only for TCP transport') 1903 p.add_argument('-f', '--dif-insert-or-strip', action='store_true', help='Enable DIF insert/strip. Relevant only for TCP transport') 1904 p.add_argument('-y', '--sock-priority', help='The sock priority of the tcp connection. Relevant only for TCP transport', type=int) 1905 p.add_argument('-l', '--acceptor_backlog', help='Pending connections allowed at one time. Relevant only for RDMA transport', type=int) 1906 p.add_argument('-x', '--abort-timeout-sec', help='Abort execution timeout value, in seconds', type=int) 1907 p.add_argument('-w', '--no-wr-batching', action='store_true', help='Disable work requests batching. Relevant only for RDMA transport') 1908 p.add_argument('-e', '--control_msg_num', help="""The number of control messages per poll group. 1909 Relevant only for TCP transport""", type=int) 1910 p.set_defaults(func=nvmf_create_transport) 1911 1912 def nvmf_get_transports(args): 1913 print_dict(rpc.nvmf.nvmf_get_transports(args.client, tgt_name=args.tgt_name)) 1914 1915 p = subparsers.add_parser('nvmf_get_transports', aliases=['get_nvmf_transports'], 1916 help='Display nvmf transports') 1917 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1918 p.set_defaults(func=nvmf_get_transports) 1919 1920 def nvmf_get_subsystems(args): 1921 print_dict(rpc.nvmf.nvmf_get_subsystems(args.client, tgt_name=args.tgt_name)) 1922 1923 p = subparsers.add_parser('nvmf_get_subsystems', aliases=['get_nvmf_subsystems'], 1924 help='Display nvmf subsystems') 1925 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1926 p.set_defaults(func=nvmf_get_subsystems) 1927 1928 def nvmf_create_subsystem(args): 1929 rpc.nvmf.nvmf_create_subsystem(args.client, 1930 nqn=args.nqn, 1931 tgt_name=args.tgt_name, 1932 serial_number=args.serial_number, 1933 model_number=args.model_number, 1934 allow_any_host=args.allow_any_host, 1935 max_namespaces=args.max_namespaces, 1936 ana_reporting=args.ana_reporting) 1937 1938 p = subparsers.add_parser('nvmf_create_subsystem', aliases=['nvmf_subsystem_create'], 1939 help='Create an NVMe-oF subsystem') 1940 p.add_argument('nqn', help='Subsystem NQN (ASCII)') 1941 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1942 p.add_argument("-s", "--serial-number", help=""" 1943 Format: 'sn' etc 1944 Example: 'SPDK00000000000001'""", default='00000000000000000000') 1945 p.add_argument("-d", "--model-number", help=""" 1946 Format: 'mn' etc 1947 Example: 'SPDK Controller'""", default='SPDK bdev Controller') 1948 p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce allowed host NQN list)") 1949 p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed", 1950 type=int, default=0) 1951 p.add_argument("-r", "--ana-reporting", action='store_true', help="Enable ANA reporting feature") 1952 p.set_defaults(func=nvmf_create_subsystem) 1953 1954 def nvmf_delete_subsystem(args): 1955 rpc.nvmf.nvmf_delete_subsystem(args.client, 1956 nqn=args.subsystem_nqn, 1957 tgt_name=args.tgt_name) 1958 1959 p = subparsers.add_parser('nvmf_delete_subsystem', aliases=['delete_nvmf_subsystem'], 1960 help='Delete a nvmf subsystem') 1961 p.add_argument('subsystem_nqn', 1962 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 1963 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1964 p.set_defaults(func=nvmf_delete_subsystem) 1965 1966 def nvmf_subsystem_add_listener(args): 1967 rpc.nvmf.nvmf_subsystem_add_listener(args.client, 1968 nqn=args.nqn, 1969 trtype=args.trtype, 1970 traddr=args.traddr, 1971 tgt_name=args.tgt_name, 1972 adrfam=args.adrfam, 1973 trsvcid=args.trsvcid) 1974 1975 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 1976 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1977 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1978 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1979 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1980 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1981 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number (required for RDMA or TCP)') 1982 p.set_defaults(func=nvmf_subsystem_add_listener) 1983 1984 def nvmf_subsystem_remove_listener(args): 1985 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, 1986 nqn=args.nqn, 1987 trtype=args.trtype, 1988 traddr=args.traddr, 1989 tgt_name=args.tgt_name, 1990 adrfam=args.adrfam, 1991 trsvcid=args.trsvcid) 1992 1993 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 1994 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1995 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1996 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1997 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1998 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1999 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 2000 p.set_defaults(func=nvmf_subsystem_remove_listener) 2001 2002 def nvmf_subsystem_listener_set_ana_state(args): 2003 rpc.nvmf.nvmf_subsystem_listener_set_ana_state(args.client, 2004 nqn=args.nqn, 2005 ana_state=args.ana_state, 2006 trtype=args.trtype, 2007 traddr=args.traddr, 2008 tgt_name=args.tgt_name, 2009 adrfam=args.adrfam, 2010 trsvcid=args.trsvcid) 2011 2012 p = subparsers.add_parser('nvmf_subsystem_listener_set_ana_state', help='Set ANA state of a listener for an NVMe-oF subsystem') 2013 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2014 p.add_argument('-n', '--ana-state', help='ANA state to set: optimized, non-optimized, or inaccessible', required=True) 2015 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 2016 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 2017 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2018 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 2019 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 2020 p.set_defaults(func=nvmf_subsystem_listener_set_ana_state) 2021 2022 def nvmf_subsystem_add_ns(args): 2023 rpc.nvmf.nvmf_subsystem_add_ns(args.client, 2024 nqn=args.nqn, 2025 bdev_name=args.bdev_name, 2026 tgt_name=args.tgt_name, 2027 ptpl_file=args.ptpl_file, 2028 nsid=args.nsid, 2029 nguid=args.nguid, 2030 eui64=args.eui64, 2031 uuid=args.uuid) 2032 2033 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 2034 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2035 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 2036 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2037 p.add_argument('-p', '--ptpl-file', help='The persistent reservation storage location (optional)', type=str) 2038 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 2039 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 2040 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 2041 p.add_argument('-u', '--uuid', help='Namespace UUID (optional)') 2042 p.set_defaults(func=nvmf_subsystem_add_ns) 2043 2044 def nvmf_subsystem_remove_ns(args): 2045 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, 2046 nqn=args.nqn, 2047 nsid=args.nsid, 2048 tgt_name=args.tgt_name) 2049 2050 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 2051 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2052 p.add_argument('nsid', help='The requested NSID', type=int) 2053 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2054 p.set_defaults(func=nvmf_subsystem_remove_ns) 2055 2056 def nvmf_subsystem_add_host(args): 2057 rpc.nvmf.nvmf_subsystem_add_host(args.client, 2058 nqn=args.nqn, 2059 host=args.host, 2060 tgt_name=args.tgt_name) 2061 2062 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 2063 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2064 p.add_argument('host', help='Host NQN to allow') 2065 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2066 p.set_defaults(func=nvmf_subsystem_add_host) 2067 2068 def nvmf_subsystem_remove_host(args): 2069 rpc.nvmf.nvmf_subsystem_remove_host(args.client, 2070 nqn=args.nqn, 2071 host=args.host, 2072 tgt_name=args.tgt_name) 2073 2074 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 2075 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2076 p.add_argument('host', help='Host NQN to remove') 2077 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2078 p.set_defaults(func=nvmf_subsystem_remove_host) 2079 2080 def nvmf_subsystem_allow_any_host(args): 2081 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, 2082 nqn=args.nqn, 2083 disable=args.disable, 2084 tgt_name=args.tgt_name) 2085 2086 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 2087 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2088 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 2089 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 2090 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2091 p.set_defaults(func=nvmf_subsystem_allow_any_host) 2092 2093 def nvmf_subsystem_get_controllers(args): 2094 print_dict(rpc.nvmf.nvmf_subsystem_get_controllers(args.client, 2095 nqn=args.nqn, 2096 tgt_name=args.tgt_name)) 2097 2098 p = subparsers.add_parser('nvmf_subsystem_get_controllers', 2099 help='Display controllers of an NVMe-oF subsystem.') 2100 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2101 p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str) 2102 p.set_defaults(func=nvmf_subsystem_get_controllers) 2103 2104 def nvmf_subsystem_get_qpairs(args): 2105 print_dict(rpc.nvmf.nvmf_subsystem_get_qpairs(args.client, 2106 nqn=args.nqn, 2107 tgt_name=args.tgt_name)) 2108 2109 p = subparsers.add_parser('nvmf_subsystem_get_qpairs', 2110 help='Display queue pairs of an NVMe-oF subsystem.') 2111 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2112 p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str) 2113 p.set_defaults(func=nvmf_subsystem_get_qpairs) 2114 2115 def nvmf_subsystem_get_listeners(args): 2116 print_dict(rpc.nvmf.nvmf_subsystem_get_listeners(args.client, 2117 nqn=args.nqn, 2118 tgt_name=args.tgt_name)) 2119 2120 p = subparsers.add_parser('nvmf_subsystem_get_listeners', 2121 help='Display listeners of an NVMe-oF subsystem.') 2122 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2123 p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str) 2124 p.set_defaults(func=nvmf_subsystem_get_listeners) 2125 2126 def nvmf_get_stats(args): 2127 print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name)) 2128 2129 p = subparsers.add_parser( 2130 'nvmf_get_stats', help='Display current statistics for NVMf subsystem') 2131 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2132 p.set_defaults(func=nvmf_get_stats) 2133 2134 # pmem 2135 def bdev_pmem_create_pool(args): 2136 num_blocks = int((args.total_size * 1024 * 1024) / args.block_size) 2137 rpc.pmem.bdev_pmem_create_pool(args.client, 2138 pmem_file=args.pmem_file, 2139 num_blocks=num_blocks, 2140 block_size=args.block_size) 2141 2142 p = subparsers.add_parser('bdev_pmem_create_pool', aliases=['create_pmem_pool'], 2143 help='Create pmem pool') 2144 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2145 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 2146 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 2147 p.set_defaults(func=bdev_pmem_create_pool) 2148 2149 def bdev_pmem_get_pool_info(args): 2150 print_dict(rpc.pmem.bdev_pmem_get_pool_info(args.client, 2151 pmem_file=args.pmem_file)) 2152 2153 p = subparsers.add_parser('bdev_pmem_get_pool_info', aliases=['pmem_pool_info'], 2154 help='Display pmem pool info and check consistency') 2155 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2156 p.set_defaults(func=bdev_pmem_get_pool_info) 2157 2158 def bdev_pmem_delete_pool(args): 2159 rpc.pmem.bdev_pmem_delete_pool(args.client, 2160 pmem_file=args.pmem_file) 2161 2162 p = subparsers.add_parser('bdev_pmem_delete_pool', aliases=['delete_pmem_pool'], 2163 help='Delete pmem pool') 2164 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2165 p.set_defaults(func=bdev_pmem_delete_pool) 2166 2167 # subsystem 2168 def framework_get_subsystems(args): 2169 print_dict(rpc.subsystem.framework_get_subsystems(args.client)) 2170 2171 p = subparsers.add_parser('framework_get_subsystems', aliases=['get_subsystems'], 2172 help="""Print subsystems array in initialization order. Each subsystem 2173 entry contain (unsorted) array of subsystems it depends on.""") 2174 p.set_defaults(func=framework_get_subsystems) 2175 2176 def framework_get_config(args): 2177 print_dict(rpc.subsystem.framework_get_config(args.client, args.name)) 2178 2179 p = subparsers.add_parser('framework_get_config', aliases=['get_subsystem_config'], 2180 help="""Print subsystem configuration""") 2181 p.add_argument('name', help='Name of subsystem to query') 2182 p.set_defaults(func=framework_get_config) 2183 2184 # vhost 2185 def vhost_controller_set_coalescing(args): 2186 rpc.vhost.vhost_controller_set_coalescing(args.client, 2187 ctrlr=args.ctrlr, 2188 delay_base_us=args.delay_base_us, 2189 iops_threshold=args.iops_threshold) 2190 2191 p = subparsers.add_parser('vhost_controller_set_coalescing', aliases=['set_vhost_controller_coalescing'], 2192 help='Set vhost controller coalescing') 2193 p.add_argument('ctrlr', help='controller name') 2194 p.add_argument('delay_base_us', help='Base delay time', type=int) 2195 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 2196 p.set_defaults(func=vhost_controller_set_coalescing) 2197 2198 def vhost_create_scsi_controller(args): 2199 rpc.vhost.vhost_create_scsi_controller(args.client, 2200 ctrlr=args.ctrlr, 2201 cpumask=args.cpumask) 2202 2203 p = subparsers.add_parser( 2204 'vhost_create_scsi_controller', aliases=['construct_vhost_scsi_controller'], 2205 help='Add new vhost controller') 2206 p.add_argument('ctrlr', help='controller name') 2207 p.add_argument('--cpumask', help='cpu mask for this controller') 2208 p.set_defaults(func=vhost_create_scsi_controller) 2209 2210 def vhost_scsi_controller_add_target(args): 2211 print_json(rpc.vhost.vhost_scsi_controller_add_target(args.client, 2212 ctrlr=args.ctrlr, 2213 scsi_target_num=args.scsi_target_num, 2214 bdev_name=args.bdev_name)) 2215 2216 p = subparsers.add_parser('vhost_scsi_controller_add_target', 2217 aliases=['add_vhost_scsi_lun'], 2218 help='Add lun to vhost controller') 2219 p.add_argument('ctrlr', help='conntroller name where add lun') 2220 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 2221 p.add_argument('bdev_name', help='bdev name') 2222 p.set_defaults(func=vhost_scsi_controller_add_target) 2223 2224 def vhost_scsi_controller_remove_target(args): 2225 rpc.vhost.vhost_scsi_controller_remove_target(args.client, 2226 ctrlr=args.ctrlr, 2227 scsi_target_num=args.scsi_target_num) 2228 2229 p = subparsers.add_parser('vhost_scsi_controller_remove_target', 2230 aliases=['remove_vhost_scsi_target'], 2231 help='Remove target from vhost controller') 2232 p.add_argument('ctrlr', help='controller name to remove target from') 2233 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 2234 p.set_defaults(func=vhost_scsi_controller_remove_target) 2235 2236 def vhost_create_blk_controller(args): 2237 rpc.vhost.vhost_create_blk_controller(args.client, 2238 ctrlr=args.ctrlr, 2239 dev_name=args.dev_name, 2240 cpumask=args.cpumask, 2241 readonly=args.readonly, 2242 packed_ring=args.packed_ring, 2243 packed_ring_recovery=args.packed_ring_recovery) 2244 2245 p = subparsers.add_parser('vhost_create_blk_controller', 2246 aliases=['construct_vhost_blk_controller'], 2247 help='Add a new vhost block controller') 2248 p.add_argument('ctrlr', help='controller name') 2249 p.add_argument('dev_name', help='device name') 2250 p.add_argument('--cpumask', help='cpu mask for this controller') 2251 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 2252 p.add_argument("-p", "--packed_ring", action='store_true', help='Set controller as packed ring supported') 2253 p.add_argument("-l", "--packed_ring_recovery", action='store_true', help='Enable packed ring live reocvery') 2254 p.set_defaults(func=vhost_create_blk_controller) 2255 2256 def vhost_get_controllers(args): 2257 print_dict(rpc.vhost.vhost_get_controllers(args.client, args.name)) 2258 2259 p = subparsers.add_parser('vhost_get_controllers', aliases=['get_vhost_controllers'], 2260 help='List all or specific vhost controller(s)') 2261 p.add_argument('-n', '--name', help="Name of vhost controller", required=False) 2262 p.set_defaults(func=vhost_get_controllers) 2263 2264 def vhost_delete_controller(args): 2265 rpc.vhost.vhost_delete_controller(args.client, 2266 ctrlr=args.ctrlr) 2267 2268 p = subparsers.add_parser('vhost_delete_controller', aliases=['remove_vhost_controller'], 2269 help='Delete a vhost controller') 2270 p.add_argument('ctrlr', help='controller name') 2271 p.set_defaults(func=vhost_delete_controller) 2272 2273 def bdev_virtio_attach_controller(args): 2274 print_array(rpc.vhost.bdev_virtio_attach_controller(args.client, 2275 name=args.name, 2276 trtype=args.trtype, 2277 traddr=args.traddr, 2278 dev_type=args.dev_type, 2279 vq_count=args.vq_count, 2280 vq_size=args.vq_size)) 2281 2282 p = subparsers.add_parser('bdev_virtio_attach_controller', aliases=['construct_virtio_dev'], 2283 help="""Attach virtio controller using provided 2284 transport type and device type. This will also create bdevs for any block devices connected to the 2285 controller (for example, SCSI devices for a virtio-scsi controller). 2286 Result is array of added bdevs.""") 2287 p.add_argument('name', help="Use this name as base for new created bdevs") 2288 p.add_argument('-t', '--trtype', 2289 help='Virtio target transport type: pci or user', required=True) 2290 p.add_argument('-a', '--traddr', 2291 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 2292 p.add_argument('-d', '--dev-type', 2293 help='Device type: blk or scsi', required=True) 2294 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 2295 p.add_argument('--vq-size', help='Size of each queue', type=int) 2296 p.set_defaults(func=bdev_virtio_attach_controller) 2297 2298 def bdev_virtio_scsi_get_devices(args): 2299 print_dict(rpc.vhost.bdev_virtio_scsi_get_devices(args.client)) 2300 2301 p = subparsers.add_parser('bdev_virtio_scsi_get_devices', aliases=['get_virtio_scsi_devs'], 2302 help='List all Virtio-SCSI devices.') 2303 p.set_defaults(func=bdev_virtio_scsi_get_devices) 2304 2305 def bdev_virtio_detach_controller(args): 2306 rpc.vhost.bdev_virtio_detach_controller(args.client, 2307 name=args.name) 2308 2309 p = subparsers.add_parser('bdev_virtio_detach_controller', aliases=['remove_virtio_bdev'], 2310 help="""Remove a Virtio device 2311 This will delete all bdevs exposed by this device""") 2312 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 2313 p.set_defaults(func=bdev_virtio_detach_controller) 2314 2315 # OCSSD 2316 def bdev_ocssd_create(args): 2317 nsid = int(args.nsid) if args.nsid is not None else None 2318 print_json(rpc.bdev.bdev_ocssd_create(args.client, 2319 ctrlr_name=args.ctrlr_name, 2320 bdev_name=args.name, 2321 nsid=nsid)) 2322 2323 p = subparsers.add_parser('bdev_ocssd_create', 2324 help='Creates zoned bdev on specified Open Channel controller') 2325 p.add_argument('-c', '--ctrlr_name', help='Name of the OC NVMe controller', required=True) 2326 p.add_argument('-b', '--name', help='Name of the bdev to create', required=True) 2327 p.add_argument('-n', '--nsid', help='Namespace ID', required=False) 2328 p.set_defaults(func=bdev_ocssd_create) 2329 2330 def bdev_ocssd_delete(args): 2331 print_json(rpc.bdev.bdev_ocssd_delete(args.client, 2332 name=args.name)) 2333 2334 p = subparsers.add_parser('bdev_ocssd_delete', 2335 help='Deletes Open Channel bdev') 2336 p.add_argument('name', help='Name of the Open Channel bdev') 2337 p.set_defaults(func=bdev_ocssd_delete) 2338 2339 # ioat 2340 def ioat_scan_accel_engine(args): 2341 rpc.ioat.ioat_scan_accel_engine(args.client) 2342 2343 p = subparsers.add_parser('ioat_scan_accel_engine', 2344 aliases=['ioat_scan_copy_engine', 'scan_ioat_copy_engine'], 2345 help='Enable IOAT accel engine offload.') 2346 p.set_defaults(func=ioat_scan_accel_engine) 2347 2348 # idxd 2349 def idxd_scan_accel_engine(args): 2350 rpc.idxd.idxd_scan_accel_engine(args.client, config_number=args.config_number) 2351 2352 p = subparsers.add_parser('idxd_scan_accel_engine', 2353 help='Set config and enable idxd accel engine offload.') 2354 p.add_argument('-c', '--config-number', help="""Pre-defined configuration number to use. See docs.""", type=int) 2355 p.set_defaults(func=idxd_scan_accel_engine) 2356 2357 # opal 2358 def bdev_nvme_opal_init(args): 2359 rpc.nvme.bdev_nvme_opal_init(args.client, 2360 nvme_ctrlr_name=args.nvme_ctrlr_name, 2361 password=args.password) 2362 2363 p = subparsers.add_parser('bdev_nvme_opal_init', help='take ownership and activate') 2364 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2365 p.add_argument('-p', '--password', help='password for admin') 2366 p.set_defaults(func=bdev_nvme_opal_init) 2367 2368 def bdev_nvme_opal_revert(args): 2369 rpc.nvme.bdev_nvme_opal_revert(args.client, 2370 nvme_ctrlr_name=args.nvme_ctrlr_name, 2371 password=args.password) 2372 p = subparsers.add_parser('bdev_nvme_opal_revert', help='Revert to default factory settings') 2373 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2374 p.add_argument('-p', '--password', help='password') 2375 p.set_defaults(func=bdev_nvme_opal_revert) 2376 2377 def bdev_opal_create(args): 2378 print_json(rpc.bdev.bdev_opal_create(args.client, 2379 nvme_ctrlr_name=args.nvme_ctrlr_name, 2380 nsid=args.nsid, 2381 locking_range_id=args.locking_range_id, 2382 range_start=args.range_start, 2383 range_length=args.range_length, 2384 password=args.password)) 2385 2386 p = subparsers.add_parser('bdev_opal_create', help="""Create opal bdev on specified NVMe controller""") 2387 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name', required=True) 2388 p.add_argument('-n', '--nsid', help='namespace ID (only support nsid=1 for now)', type=int, required=True) 2389 p.add_argument('-i', '--locking-range-id', help='locking range id', type=int, required=True) 2390 p.add_argument('-s', '--range-start', help='locking range start LBA', type=int, required=True) 2391 p.add_argument('-l', '--range-length', help='locking range length (in blocks)', type=int, required=True) 2392 p.add_argument('-p', '--password', help='admin password', required=True) 2393 p.set_defaults(func=bdev_opal_create) 2394 2395 def bdev_opal_get_info(args): 2396 print_dict(rpc.bdev.bdev_opal_get_info(args.client, 2397 bdev_name=args.bdev_name, 2398 password=args.password)) 2399 2400 p = subparsers.add_parser('bdev_opal_get_info', help='get opal locking range info for this bdev') 2401 p.add_argument('-b', '--bdev-name', help='opal bdev') 2402 p.add_argument('-p', '--password', help='password') 2403 p.set_defaults(func=bdev_opal_get_info) 2404 2405 def bdev_opal_delete(args): 2406 rpc.bdev.bdev_opal_delete(args.client, 2407 bdev_name=args.bdev_name, 2408 password=args.password) 2409 2410 p = subparsers.add_parser('bdev_opal_delete', help="""delete a virtual opal bdev""") 2411 p.add_argument('-b', '--bdev-name', help='opal virtual bdev', required=True) 2412 p.add_argument('-p', '--password', help='admin password', required=True) 2413 p.set_defaults(func=bdev_opal_delete) 2414 2415 def bdev_opal_new_user(args): 2416 rpc.bdev.bdev_opal_new_user(args.client, 2417 bdev_name=args.bdev_name, 2418 admin_password=args.admin_password, 2419 user_id=args.user_id, 2420 user_password=args.user_password) 2421 2422 p = subparsers.add_parser('bdev_opal_new_user', help="""Add a user to opal bdev who can set lock state for this bdev""") 2423 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2424 p.add_argument('-p', '--admin-password', help='admin password', required=True) 2425 p.add_argument('-i', '--user-id', help='ID for new user', type=int, required=True) 2426 p.add_argument('-u', '--user-password', help='password set for this user', required=True) 2427 p.set_defaults(func=bdev_opal_new_user) 2428 2429 def bdev_opal_set_lock_state(args): 2430 rpc.bdev.bdev_opal_set_lock_state(args.client, 2431 bdev_name=args.bdev_name, 2432 user_id=args.user_id, 2433 password=args.password, 2434 lock_state=args.lock_state) 2435 2436 p = subparsers.add_parser('bdev_opal_set_lock_state', help="""set lock state for an opal bdev""") 2437 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2438 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', 2439 type=int, required=True) 2440 p.add_argument('-p', '--password', help='password of this user', required=True) 2441 p.add_argument('-l', '--lock-state', help='lock state to set, choose from {readwrite, readonly, rwlock}', required=True) 2442 p.set_defaults(func=bdev_opal_set_lock_state) 2443 2444 # bdev_nvme_send_cmd 2445 def bdev_nvme_send_cmd(args): 2446 print_dict(rpc.nvme.bdev_nvme_send_cmd(args.client, 2447 name=args.nvme_name, 2448 cmd_type=args.cmd_type, 2449 data_direction=args.data_direction, 2450 cmdbuf=args.cmdbuf, 2451 data=args.data, 2452 metadata=args.metadata, 2453 data_len=args.data_length, 2454 metadata_len=args.metadata_length, 2455 timeout_ms=args.timeout_ms)) 2456 2457 p = subparsers.add_parser('bdev_nvme_send_cmd', aliases=['send_nvme_cmd'], 2458 help='NVMe passthrough cmd.') 2459 p.add_argument('-n', '--nvme-name', help="""Name of the operating NVMe controller""") 2460 p.add_argument('-t', '--cmd-type', help="""Type of nvme cmd. Valid values are: admin, io""") 2461 p.add_argument('-r', '--data-direction', help="""Direction of data transfer. Valid values are: c2h, h2c""") 2462 p.add_argument('-c', '--cmdbuf', help="""NVMe command encoded by base64 urlsafe""") 2463 p.add_argument('-d', '--data', help="""Data transferring to controller from host, encoded by base64 urlsafe""") 2464 p.add_argument('-m', '--metadata', help="""Metadata transferring to controller from host, encoded by base64 urlsafe""") 2465 p.add_argument('-D', '--data-length', help="""Data length required to transfer from controller to host""", type=int) 2466 p.add_argument('-M', '--metadata-length', help="""Metadata length required to transfer from controller to host""", type=int) 2467 p.add_argument('-T', '--timeout-ms', 2468 help="""Command execution timeout value, in milliseconds, if 0, don't track timeout""", type=int, default=0) 2469 p.set_defaults(func=bdev_nvme_send_cmd) 2470 2471 # Notifications 2472 def notify_get_types(args): 2473 print_dict(rpc.notify.notify_get_types(args.client)) 2474 2475 p = subparsers.add_parser('notify_get_types', aliases=['get_notification_types'], 2476 help='List available notifications that user can subscribe to.') 2477 p.set_defaults(func=notify_get_types) 2478 2479 def notify_get_notifications(args): 2480 ret = rpc.notify.notify_get_notifications(args.client, 2481 id=args.id, 2482 max=args.max) 2483 print_dict(ret) 2484 2485 p = subparsers.add_parser('notify_get_notifications', aliases=['get_notifications'], 2486 help='Get notifications') 2487 p.add_argument('-i', '--id', help="""First ID to start fetching from""", type=int) 2488 p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int) 2489 p.set_defaults(func=notify_get_notifications) 2490 2491 def thread_get_stats(args): 2492 print_dict(rpc.app.thread_get_stats(args.client)) 2493 2494 p = subparsers.add_parser( 2495 'thread_get_stats', help='Display current statistics of all the threads') 2496 p.set_defaults(func=thread_get_stats) 2497 2498 def thread_set_cpumask(args): 2499 ret = rpc.app.thread_set_cpumask(args.client, 2500 id=args.id, 2501 cpumask=args.cpumask) 2502 p = subparsers.add_parser('thread_set_cpumask', 2503 help="""set the cpumask of the thread whose ID matches to the 2504 specified value. The thread may be migrated to one of the specified CPUs.""") 2505 p.add_argument('-i', '--id', type=int, help='thread ID') 2506 p.add_argument('-m', '--cpumask', help='cpumask for this thread') 2507 p.set_defaults(func=thread_set_cpumask) 2508 2509 def log_enable_timestamps(args): 2510 ret = rpc.app.log_enable_timestamps(args.client, 2511 enabled=args.enabled) 2512 p = subparsers.add_parser('log_enable_timestamps', 2513 help='Enable or disable timestamps.') 2514 p.add_argument('-d', '--disable', dest='enabled', default=False, action='store_false', help="Disable timestamps") 2515 p.add_argument('-e', '--enable', dest='enabled', action='store_true', help="Enable timestamps") 2516 p.set_defaults(func=log_enable_timestamps) 2517 2518 def thread_get_pollers(args): 2519 print_dict(rpc.app.thread_get_pollers(args.client)) 2520 2521 p = subparsers.add_parser( 2522 'thread_get_pollers', help='Display current pollers of all the threads') 2523 p.set_defaults(func=thread_get_pollers) 2524 2525 def thread_get_io_channels(args): 2526 print_dict(rpc.app.thread_get_io_channels(args.client)) 2527 2528 p = subparsers.add_parser( 2529 'thread_get_io_channels', help='Display current IO channels of all the threads') 2530 p.set_defaults(func=thread_get_io_channels) 2531 2532 def env_dpdk_get_mem_stats(args): 2533 print_dict(rpc.env_dpdk.env_dpdk_get_mem_stats(args.client)) 2534 2535 p = subparsers.add_parser( 2536 'env_dpdk_get_mem_stats', help='write the dpdk memory stats to a file.') 2537 p.set_defaults(func=env_dpdk_get_mem_stats) 2538 2539 # blobfs 2540 def blobfs_detect(args): 2541 print(rpc.blobfs.blobfs_detect(args.client, 2542 bdev_name=args.bdev_name)) 2543 2544 p = subparsers.add_parser('blobfs_detect', help='Detect whether a blobfs exists on bdev') 2545 p.add_argument('bdev_name', help='Blockdev name to detect blobfs. Example: Malloc0.') 2546 p.set_defaults(func=blobfs_detect) 2547 2548 def blobfs_create(args): 2549 print(rpc.blobfs.blobfs_create(args.client, 2550 bdev_name=args.bdev_name, 2551 cluster_sz=args.cluster_sz)) 2552 2553 p = subparsers.add_parser('blobfs_create', help='Build a blobfs on bdev') 2554 p.add_argument('bdev_name', help='Blockdev name to build blobfs. Example: Malloc0.') 2555 p.add_argument('-c', '--cluster_sz', 2556 help="""Size of cluster in bytes (Optional). Must be multiple of 4KB page size. Default and minimal value is 1M.""") 2557 p.set_defaults(func=blobfs_create) 2558 2559 def blobfs_mount(args): 2560 print(rpc.blobfs.blobfs_mount(args.client, 2561 bdev_name=args.bdev_name, 2562 mountpoint=args.mountpoint)) 2563 2564 p = subparsers.add_parser('blobfs_mount', help='Mount a blobfs on bdev to host path by FUSE') 2565 p.add_argument('bdev_name', help='Blockdev name where the blobfs is. Example: Malloc0.') 2566 p.add_argument('mountpoint', help='Mountpoint path in host to mount blobfs. Example: /mnt/.') 2567 p.set_defaults(func=blobfs_mount) 2568 2569 def blobfs_set_cache_size(args): 2570 print(rpc.blobfs.blobfs_set_cache_size(args.client, 2571 size_in_mb=args.size_in_mb)) 2572 2573 p = subparsers.add_parser('blobfs_set_cache_size', help='Set cache size for blobfs') 2574 p.add_argument('size_in_mb', help='Cache size for blobfs in megabytes.', type=int) 2575 p.set_defaults(func=blobfs_set_cache_size) 2576 2577 # sock 2578 def sock_impl_get_options(args): 2579 print_json(rpc.sock.sock_impl_get_options(args.client, 2580 impl_name=args.impl)) 2581 2582 p = subparsers.add_parser('sock_impl_get_options', help="""Get options of socket layer implementation""") 2583 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2584 p.set_defaults(func=sock_impl_get_options) 2585 2586 def sock_impl_set_options(args): 2587 rpc.sock.sock_impl_set_options(args.client, 2588 impl_name=args.impl, 2589 recv_buf_size=args.recv_buf_size, 2590 send_buf_size=args.send_buf_size, 2591 enable_recv_pipe=args.enable_recv_pipe, 2592 enable_zerocopy_send=args.enable_zerocopy_send, 2593 enable_quickack=args.enable_quickack, 2594 enable_placement_id=args.enable_placement_id) 2595 2596 p = subparsers.add_parser('sock_impl_set_options', help="""Set options of socket layer implementation""") 2597 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2598 p.add_argument('-r', '--recv-buf-size', help='Size of receive buffer on socket in bytes', type=int) 2599 p.add_argument('-s', '--send-buf-size', help='Size of send buffer on socket in bytes', type=int) 2600 p.add_argument('-p', '--enable-placement-id', help='Option for placement-id. 0:disable,1:incoming_napi,2:incoming_cpu', type=int) 2601 p.add_argument('--enable-recv-pipe', help='Enable receive pipe', 2602 action='store_true', dest='enable_recv_pipe') 2603 p.add_argument('--disable-recv-pipe', help='Disable receive pipe', 2604 action='store_false', dest='enable_recv_pipe') 2605 p.add_argument('--enable-zerocopy-send', help='Enable zerocopy on send', 2606 action='store_true', dest='enable_zerocopy_send') 2607 p.add_argument('--disable-zerocopy-send', help='Disable zerocopy on send', 2608 action='store_false', dest='enable_zerocopy_send') 2609 p.add_argument('--enable-quickack', help='Enable quick ACK', 2610 action='store_true', dest='enable_quickack') 2611 p.add_argument('--disable-quickack', help='Disable quick ACK', 2612 action='store_false', dest='enable_quickack') 2613 p.set_defaults(func=sock_impl_set_options, enable_recv_pipe=None, enable_zerocopy_send=None, 2614 enable_quickack=None, enable_placement_id=None) 2615 2616 def sock_set_default_impl(args): 2617 print_json(rpc.sock.sock_set_default_impl(args.client, 2618 impl_name=args.impl)) 2619 2620 p = subparsers.add_parser('sock_set_default_impl', help="""Set the default sock implementation""") 2621 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2622 p.set_defaults(func=sock_set_default_impl) 2623 2624 def check_called_name(name): 2625 if name in deprecated_aliases: 2626 print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr) 2627 2628 class dry_run_client: 2629 def call(self, method, params=None): 2630 print("Request:\n" + json.dumps({"method": method, "params": params}, indent=2)) 2631 2632 def null_print(arg): 2633 pass 2634 2635 def call_rpc_func(args): 2636 args.func(args) 2637 check_called_name(args.called_rpc_name) 2638 2639 def execute_script(parser, client, fd): 2640 executed_rpc = "" 2641 for rpc_call in map(str.rstrip, fd): 2642 if not rpc_call.strip(): 2643 continue 2644 executed_rpc = "\n".join([executed_rpc, rpc_call]) 2645 args = parser.parse_args(shlex.split(rpc_call)) 2646 args.client = client 2647 try: 2648 call_rpc_func(args) 2649 except JSONRPCException as ex: 2650 print("Exception:") 2651 print(executed_rpc.strip() + " <<<") 2652 print(ex.message) 2653 exit(1) 2654 2655 # Create temporary parser, pull out the plugin parameter, load the module, and then run the real argument parser 2656 plugin_parser = argparse.ArgumentParser(add_help=False) 2657 plugin_parser.add_argument('--plugin', dest='rpc_plugin', help='Module name of plugin with additional RPC commands') 2658 2659 rpc_module = plugin_parser.parse_known_args()[0].rpc_plugin 2660 if rpc_module is not None: 2661 try: 2662 rpc_plugin = importlib.import_module(rpc_module) 2663 try: 2664 rpc_plugin.spdk_rpc_plugin_initialize(subparsers) 2665 except AttributeError: 2666 print("Module %s does not contain 'spdk_rpc_plugin_initialize' function" % rpc_module) 2667 except ModuleNotFoundError: 2668 print("Module %s not found" % rpc_module) 2669 2670 args = parser.parse_args() 2671 2672 if sys.stdin.isatty() and not hasattr(args, 'func'): 2673 # No arguments and no data piped through stdin 2674 parser.print_help() 2675 exit(1) 2676 if args.is_server: 2677 for input in sys.stdin: 2678 cmd = shlex.split(input) 2679 try: 2680 tmp_args = parser.parse_args(cmd) 2681 except SystemExit as ex: 2682 print("**STATUS=1", flush=True) 2683 continue 2684 2685 try: 2686 tmp_args.client = rpc.client.JSONRPCClient( 2687 tmp_args.server_addr, tmp_args.port, tmp_args.timeout, 2688 log_level=getattr(logging, tmp_args.verbose.upper()), conn_retries=tmp_args.conn_retries) 2689 call_rpc_func(tmp_args) 2690 print("**STATUS=0", flush=True) 2691 except JSONRPCException as ex: 2692 print(ex.message) 2693 print("**STATUS=1", flush=True) 2694 exit(0) 2695 elif args.dry_run: 2696 args.client = dry_run_client() 2697 print_dict = null_print 2698 print_json = null_print 2699 print_array = null_print 2700 else: 2701 try: 2702 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, 2703 log_level=getattr(logging, args.verbose.upper()), 2704 conn_retries=args.conn_retries) 2705 except JSONRPCException as ex: 2706 print(ex.message) 2707 exit(1) 2708 2709 if hasattr(args, 'func'): 2710 try: 2711 call_rpc_func(args) 2712 except JSONRPCException as ex: 2713 print(ex.message) 2714 exit(1) 2715 else: 2716 execute_script(parser, args.client, sys.stdin) 2717