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_kb=args.strip_size_kb, 1667 raid_level=args.raid_level, 1668 base_bdevs=base_bdevs) 1669 p = subparsers.add_parser('bdev_raid_create', aliases=['construct_raid_bdev'], 1670 help='Create new raid bdev') 1671 p.add_argument('-n', '--name', help='raid bdev name', required=True) 1672 p.add_argument('-z', '--strip-size_kb', help='strip size in KB', type=int) 1673 p.add_argument('-r', '--raid-level', help='raid level, only raid level 0 is supported', required=True) 1674 p.add_argument('-b', '--base-bdevs', help='base bdevs name, whitespace separated list in quotes', required=True) 1675 p.set_defaults(func=bdev_raid_create) 1676 1677 def bdev_raid_delete(args): 1678 rpc.bdev.bdev_raid_delete(args.client, 1679 name=args.name) 1680 p = subparsers.add_parser('bdev_raid_delete', aliases=['destroy_raid_bdev'], 1681 help='Delete existing raid bdev') 1682 p.add_argument('name', help='raid bdev name') 1683 p.set_defaults(func=bdev_raid_delete) 1684 1685 # split 1686 def bdev_split_create(args): 1687 print_array(rpc.bdev.bdev_split_create(args.client, 1688 base_bdev=args.base_bdev, 1689 split_count=args.split_count, 1690 split_size_mb=args.split_size_mb)) 1691 1692 p = subparsers.add_parser('bdev_split_create', aliases=['construct_split_vbdev'], 1693 help="""Add given disk name to split config. If bdev with base_name 1694 name exist the split bdevs will be created right away, if not split bdevs will be created when base bdev became 1695 available (during examination process).""") 1696 p.add_argument('base_bdev', help='base bdev name') 1697 p.add_argument('-s', '--split-size-mb', help='size in MiB for each bdev', type=int, default=0) 1698 p.add_argument('split_count', help="""Optional - number of split bdevs to create. Total size * split_count must not 1699 exceed the base bdev size.""", type=int) 1700 p.set_defaults(func=bdev_split_create) 1701 1702 def bdev_split_delete(args): 1703 rpc.bdev.bdev_split_delete(args.client, 1704 base_bdev=args.base_bdev) 1705 1706 p = subparsers.add_parser('bdev_split_delete', aliases=['destruct_split_vbdev'], 1707 help="""Delete split config with all created splits.""") 1708 p.add_argument('base_bdev', help='base bdev name') 1709 p.set_defaults(func=bdev_split_delete) 1710 1711 # ftl 1712 ftl_valid_limits = ('crit', 'high', 'low', 'start') 1713 1714 def bdev_ftl_create(args): 1715 def parse_limits(limits, arg_dict, key_suffix=''): 1716 for limit in limits.split(','): 1717 key, value = limit.split(':', 1) 1718 if key in ftl_valid_limits: 1719 arg_dict['limit_' + key + key_suffix] = int(value) 1720 else: 1721 raise ValueError('Limit {} is not supported'.format(key)) 1722 1723 arg_limits = {} 1724 if args.limit_threshold: 1725 parse_limits(args.limit_threshold, arg_limits, '_threshold') 1726 1727 if args.limit: 1728 parse_limits(args.limit, arg_limits) 1729 1730 print_dict(rpc.bdev.bdev_ftl_create(args.client, 1731 name=args.name, 1732 base_bdev=args.base_bdev, 1733 uuid=args.uuid, 1734 cache=args.cache, 1735 allow_open_bands=args.allow_open_bands, 1736 overprovisioning=args.overprovisioning, 1737 l2p_path=args.l2p_path, 1738 use_append=args.use_append, 1739 **arg_limits)) 1740 1741 p = subparsers.add_parser('bdev_ftl_create', aliases=['construct_ftl_bdev'], help='Add FTL bdev') 1742 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 1743 p.add_argument('-d', '--base_bdev', help='Name of zoned bdev used as underlying device', 1744 required=True) 1745 p.add_argument('-u', '--uuid', help='UUID of restored bdev (not applicable when creating new ' 1746 'instance): e.g. b286d19a-0059-4709-abcd-9f7732b1567d (optional)') 1747 p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache (optional)') 1748 p.add_argument('-o', '--allow_open_bands', help='Restoring after dirty shutdown without cache will' 1749 ' result in partial data recovery, instead of error', action='store_true') 1750 p.add_argument('--overprovisioning', help='Percentage of device used for relocation, not exposed' 1751 ' to user (optional)', type=int) 1752 p.add_argument('--l2p_path', help='Path to persistent memory file or device to store l2p onto, ' 1753 'by default l2p is kept in DRAM and is volatile (optional)') 1754 p.add_argument('--use_append', help='Use appends instead of writes', action='store_true') 1755 1756 limits = p.add_argument_group('Defrag limits', 'Configures defrag limits and thresholds for' 1757 ' levels ' + str(ftl_valid_limits)[1:-1]) 1758 limits.add_argument('--limit', help='Percentage of allowed user versus internal writes at given' 1759 ' levels, e.g. crit:0,high:20,low:80') 1760 limits.add_argument('--limit-threshold', help='Number of free bands triggering a given level of' 1761 ' write limiting e.g. crit:1,high:2,low:3,start:4') 1762 p.set_defaults(func=bdev_ftl_create) 1763 1764 def bdev_ftl_delete(args): 1765 print_dict(rpc.bdev.bdev_ftl_delete(args.client, name=args.name)) 1766 1767 p = subparsers.add_parser('bdev_ftl_delete', aliases=['delete_ftl_bdev'], 1768 help='Delete FTL bdev') 1769 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 1770 p.set_defaults(func=bdev_ftl_delete) 1771 1772 # vmd 1773 def enable_vmd(args): 1774 print_dict(rpc.vmd.enable_vmd(args.client)) 1775 1776 p = subparsers.add_parser('enable_vmd', help='Enable VMD enumeration') 1777 p.set_defaults(func=enable_vmd) 1778 1779 # nbd 1780 def nbd_start_disk(args): 1781 print(rpc.nbd.nbd_start_disk(args.client, 1782 bdev_name=args.bdev_name, 1783 nbd_device=args.nbd_device)) 1784 1785 p = subparsers.add_parser('nbd_start_disk', aliases=['start_nbd_disk'], 1786 help='Export a bdev as an nbd disk') 1787 p.add_argument('bdev_name', help='Blockdev name to be exported. Example: Malloc0.') 1788 p.add_argument('nbd_device', help='Nbd device name to be assigned. Example: /dev/nbd0.', nargs='?') 1789 p.set_defaults(func=nbd_start_disk) 1790 1791 def nbd_stop_disk(args): 1792 rpc.nbd.nbd_stop_disk(args.client, 1793 nbd_device=args.nbd_device) 1794 1795 p = subparsers.add_parser('nbd_stop_disk', aliases=['stop_nbd_disk'], 1796 help='Stop an nbd disk') 1797 p.add_argument('nbd_device', help='Nbd device name to be stopped. Example: /dev/nbd0.') 1798 p.set_defaults(func=nbd_stop_disk) 1799 1800 def nbd_get_disks(args): 1801 print_dict(rpc.nbd.nbd_get_disks(args.client, 1802 nbd_device=args.nbd_device)) 1803 1804 p = subparsers.add_parser('nbd_get_disks', aliases=['get_nbd_disks'], 1805 help='Display full or specified nbd device list') 1806 p.add_argument('-n', '--nbd-device', help="Path of the nbd device. Example: /dev/nbd0", required=False) 1807 p.set_defaults(func=nbd_get_disks) 1808 1809 # net 1810 def net_interface_add_ip_address(args): 1811 rpc.net.net_interface_add_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1812 1813 p = subparsers.add_parser('net_interface_add_ip_address', aliases=['add_ip_address'], 1814 help='Add IP address') 1815 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1816 p.add_argument('ip_addr', help='ip address will be added.') 1817 p.set_defaults(func=net_interface_add_ip_address) 1818 1819 def net_interface_delete_ip_address(args): 1820 rpc.net.net_interface_delete_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1821 1822 p = subparsers.add_parser('net_interface_delete_ip_address', aliases=['delete_ip_address'], 1823 help='Delete IP address') 1824 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1825 p.add_argument('ip_addr', help='ip address will be deleted.') 1826 p.set_defaults(func=net_interface_delete_ip_address) 1827 1828 def net_get_interfaces(args): 1829 print_dict(rpc.net.net_get_interfaces(args.client)) 1830 1831 p = subparsers.add_parser( 1832 'net_get_interfaces', aliases=['get_interfaces'], help='Display current interface list') 1833 p.set_defaults(func=net_get_interfaces) 1834 1835 # NVMe-oF 1836 def nvmf_set_max_subsystems(args): 1837 rpc.nvmf.nvmf_set_max_subsystems(args.client, 1838 max_subsystems=args.max_subsystems) 1839 1840 p = subparsers.add_parser('nvmf_set_max_subsystems', aliases=['set_nvmf_target_max_subsystems'], 1841 help='Set the maximum number of NVMf target subsystems') 1842 p.add_argument('-x', '--max-subsystems', help='Max number of NVMf subsystems', type=int, required=True) 1843 p.set_defaults(func=nvmf_set_max_subsystems) 1844 1845 def nvmf_set_config(args): 1846 rpc.nvmf.nvmf_set_config(args.client, 1847 acceptor_poll_rate=args.acceptor_poll_rate, 1848 conn_sched=args.conn_sched, 1849 passthru_identify_ctrlr=args.passthru_identify_ctrlr) 1850 1851 p = subparsers.add_parser('nvmf_set_config', aliases=['set_nvmf_target_config'], 1852 help='Set NVMf target config') 1853 p.add_argument('-r', '--acceptor-poll-rate', help='Polling interval of the acceptor for incoming connections (usec)', type=int) 1854 p.add_argument('-s', '--conn-sched', help='(Deprecated). Ignored.') 1855 p.add_argument('-i', '--passthru-identify-ctrlr', help="""Passthrough fields like serial number and model number 1856 when the controller has a single namespace that is an NVMe bdev""", action='store_true') 1857 p.set_defaults(func=nvmf_set_config) 1858 1859 def nvmf_create_transport(args): 1860 rpc.nvmf.nvmf_create_transport(args.client, 1861 trtype=args.trtype, 1862 tgt_name=args.tgt_name, 1863 max_queue_depth=args.max_queue_depth, 1864 max_qpairs_per_ctrlr=args.max_qpairs_per_ctrlr, 1865 max_io_qpairs_per_ctrlr=args.max_io_qpairs_per_ctrlr, 1866 in_capsule_data_size=args.in_capsule_data_size, 1867 max_io_size=args.max_io_size, 1868 io_unit_size=args.io_unit_size, 1869 max_aq_depth=args.max_aq_depth, 1870 num_shared_buffers=args.num_shared_buffers, 1871 buf_cache_size=args.buf_cache_size, 1872 num_cqe=args.num_cqe, 1873 max_srq_depth=args.max_srq_depth, 1874 no_srq=args.no_srq, 1875 c2h_success=args.c2h_success, 1876 dif_insert_or_strip=args.dif_insert_or_strip, 1877 sock_priority=args.sock_priority, 1878 acceptor_backlog=args.acceptor_backlog, 1879 abort_timeout_sec=args.abort_timeout_sec, 1880 no_wr_batching=args.no_wr_batching, 1881 control_msg_num=args.control_msg_num) 1882 1883 p = subparsers.add_parser('nvmf_create_transport', help='Create NVMf transport') 1884 p.add_argument('-t', '--trtype', help='Transport type (ex. RDMA)', type=str, required=True) 1885 p.add_argument('-g', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1886 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int) 1887 p.add_argument('-p', '--max-qpairs-per-ctrlr', help="""Max number of SQ and CQ per controller. 1888 Deprecated, use max-io-qpairs-per-ctrlr""", type=int) 1889 p.add_argument('-m', '--max-io-qpairs-per-ctrlr', help='Max number of IO qpairs per controller', type=int) 1890 p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int) 1891 p.add_argument('-i', '--max-io-size', help='Max I/O size (bytes)', type=int) 1892 p.add_argument('-u', '--io-unit-size', help='I/O unit size (bytes)', type=int) 1893 p.add_argument('-a', '--max-aq-depth', help='Max number of admin cmds per AQ', type=int) 1894 p.add_argument('-n', '--num-shared-buffers', help='The number of pooled data buffers available to the transport', type=int) 1895 p.add_argument('-b', '--buf-cache-size', help='The number of shared buffers to reserve for each poll group', type=int) 1896 p.add_argument('-d', '--num_cqe', help="""The number of CQ entires. Only used when no_srq=true. 1897 Relevant only for RDMA transport""", type=int) 1898 p.add_argument('-s', '--max-srq-depth', help='Max number of outstanding I/O per SRQ. Relevant only for RDMA transport', type=int) 1899 p.add_argument('-r', '--no-srq', action='store_true', help='Disable per-thread shared receive queue. Relevant only for RDMA transport') 1900 p.add_argument('-o', '--c2h-success', action='store_false', help='Disable C2H success optimization. Relevant only for TCP transport') 1901 p.add_argument('-f', '--dif-insert-or-strip', action='store_true', help='Enable DIF insert/strip. Relevant only for TCP transport') 1902 p.add_argument('-y', '--sock-priority', help='The sock priority of the tcp connection. Relevant only for TCP transport', type=int) 1903 p.add_argument('-l', '--acceptor_backlog', help='Pending connections allowed at one time. Relevant only for RDMA transport', type=int) 1904 p.add_argument('-x', '--abort-timeout-sec', help='Abort execution timeout value, in seconds', type=int) 1905 p.add_argument('-w', '--no-wr-batching', action='store_true', help='Disable work requests batching. Relevant only for RDMA transport') 1906 p.add_argument('-e', '--control_msg_num', help="""The number of control messages per poll group. 1907 Relevant only for TCP transport""", type=int) 1908 p.set_defaults(func=nvmf_create_transport) 1909 1910 def nvmf_get_transports(args): 1911 print_dict(rpc.nvmf.nvmf_get_transports(args.client, tgt_name=args.tgt_name)) 1912 1913 p = subparsers.add_parser('nvmf_get_transports', aliases=['get_nvmf_transports'], 1914 help='Display nvmf transports') 1915 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1916 p.set_defaults(func=nvmf_get_transports) 1917 1918 def nvmf_get_subsystems(args): 1919 print_dict(rpc.nvmf.nvmf_get_subsystems(args.client, tgt_name=args.tgt_name)) 1920 1921 p = subparsers.add_parser('nvmf_get_subsystems', aliases=['get_nvmf_subsystems'], 1922 help='Display nvmf subsystems') 1923 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1924 p.set_defaults(func=nvmf_get_subsystems) 1925 1926 def nvmf_create_subsystem(args): 1927 rpc.nvmf.nvmf_create_subsystem(args.client, 1928 nqn=args.nqn, 1929 tgt_name=args.tgt_name, 1930 serial_number=args.serial_number, 1931 model_number=args.model_number, 1932 allow_any_host=args.allow_any_host, 1933 max_namespaces=args.max_namespaces, 1934 ana_reporting=args.ana_reporting) 1935 1936 p = subparsers.add_parser('nvmf_create_subsystem', aliases=['nvmf_subsystem_create'], 1937 help='Create an NVMe-oF subsystem') 1938 p.add_argument('nqn', help='Subsystem NQN (ASCII)') 1939 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1940 p.add_argument("-s", "--serial-number", help=""" 1941 Format: 'sn' etc 1942 Example: 'SPDK00000000000001'""", default='00000000000000000000') 1943 p.add_argument("-d", "--model-number", help=""" 1944 Format: 'mn' etc 1945 Example: 'SPDK Controller'""", default='SPDK bdev Controller') 1946 p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce allowed host NQN list)") 1947 p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed", 1948 type=int, default=0) 1949 p.add_argument("-r", "--ana-reporting", action='store_true', help="Enable ANA reporting feature") 1950 p.set_defaults(func=nvmf_create_subsystem) 1951 1952 def nvmf_delete_subsystem(args): 1953 rpc.nvmf.nvmf_delete_subsystem(args.client, 1954 nqn=args.subsystem_nqn, 1955 tgt_name=args.tgt_name) 1956 1957 p = subparsers.add_parser('nvmf_delete_subsystem', aliases=['delete_nvmf_subsystem'], 1958 help='Delete a nvmf subsystem') 1959 p.add_argument('subsystem_nqn', 1960 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 1961 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1962 p.set_defaults(func=nvmf_delete_subsystem) 1963 1964 def nvmf_subsystem_add_listener(args): 1965 rpc.nvmf.nvmf_subsystem_add_listener(args.client, 1966 nqn=args.nqn, 1967 trtype=args.trtype, 1968 traddr=args.traddr, 1969 tgt_name=args.tgt_name, 1970 adrfam=args.adrfam, 1971 trsvcid=args.trsvcid) 1972 1973 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 1974 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1975 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1976 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1977 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1978 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1979 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number (required for RDMA or TCP)') 1980 p.set_defaults(func=nvmf_subsystem_add_listener) 1981 1982 def nvmf_subsystem_remove_listener(args): 1983 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, 1984 nqn=args.nqn, 1985 trtype=args.trtype, 1986 traddr=args.traddr, 1987 tgt_name=args.tgt_name, 1988 adrfam=args.adrfam, 1989 trsvcid=args.trsvcid) 1990 1991 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 1992 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1993 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1994 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1995 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1996 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1997 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1998 p.set_defaults(func=nvmf_subsystem_remove_listener) 1999 2000 def nvmf_subsystem_listener_set_ana_state(args): 2001 rpc.nvmf.nvmf_subsystem_listener_set_ana_state(args.client, 2002 nqn=args.nqn, 2003 ana_state=args.ana_state, 2004 trtype=args.trtype, 2005 traddr=args.traddr, 2006 tgt_name=args.tgt_name, 2007 adrfam=args.adrfam, 2008 trsvcid=args.trsvcid) 2009 2010 p = subparsers.add_parser('nvmf_subsystem_listener_set_ana_state', help='Set ANA state of a listener for an NVMe-oF subsystem') 2011 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2012 p.add_argument('-n', '--ana-state', help='ANA state to set: optimized, non-optimized, or inaccessible', required=True) 2013 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 2014 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 2015 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2016 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 2017 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 2018 p.set_defaults(func=nvmf_subsystem_listener_set_ana_state) 2019 2020 def nvmf_subsystem_add_ns(args): 2021 rpc.nvmf.nvmf_subsystem_add_ns(args.client, 2022 nqn=args.nqn, 2023 bdev_name=args.bdev_name, 2024 tgt_name=args.tgt_name, 2025 ptpl_file=args.ptpl_file, 2026 nsid=args.nsid, 2027 nguid=args.nguid, 2028 eui64=args.eui64, 2029 uuid=args.uuid) 2030 2031 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 2032 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2033 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 2034 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2035 p.add_argument('-p', '--ptpl-file', help='The persistent reservation storage location (optional)', type=str) 2036 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 2037 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 2038 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 2039 p.add_argument('-u', '--uuid', help='Namespace UUID (optional)') 2040 p.set_defaults(func=nvmf_subsystem_add_ns) 2041 2042 def nvmf_subsystem_remove_ns(args): 2043 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, 2044 nqn=args.nqn, 2045 nsid=args.nsid, 2046 tgt_name=args.tgt_name) 2047 2048 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 2049 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2050 p.add_argument('nsid', help='The requested NSID', type=int) 2051 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2052 p.set_defaults(func=nvmf_subsystem_remove_ns) 2053 2054 def nvmf_subsystem_add_host(args): 2055 rpc.nvmf.nvmf_subsystem_add_host(args.client, 2056 nqn=args.nqn, 2057 host=args.host, 2058 tgt_name=args.tgt_name) 2059 2060 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 2061 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2062 p.add_argument('host', help='Host NQN to allow') 2063 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2064 p.set_defaults(func=nvmf_subsystem_add_host) 2065 2066 def nvmf_subsystem_remove_host(args): 2067 rpc.nvmf.nvmf_subsystem_remove_host(args.client, 2068 nqn=args.nqn, 2069 host=args.host, 2070 tgt_name=args.tgt_name) 2071 2072 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 2073 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2074 p.add_argument('host', help='Host NQN to remove') 2075 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2076 p.set_defaults(func=nvmf_subsystem_remove_host) 2077 2078 def nvmf_subsystem_allow_any_host(args): 2079 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, 2080 nqn=args.nqn, 2081 disable=args.disable, 2082 tgt_name=args.tgt_name) 2083 2084 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 2085 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2086 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 2087 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 2088 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2089 p.set_defaults(func=nvmf_subsystem_allow_any_host) 2090 2091 def nvmf_subsystem_get_controllers(args): 2092 print_dict(rpc.nvmf.nvmf_subsystem_get_controllers(args.client, 2093 nqn=args.nqn, 2094 tgt_name=args.tgt_name)) 2095 2096 p = subparsers.add_parser('nvmf_subsystem_get_controllers', 2097 help='Display controllers of an NVMe-oF subsystem.') 2098 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2099 p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str) 2100 p.set_defaults(func=nvmf_subsystem_get_controllers) 2101 2102 def nvmf_subsystem_get_qpairs(args): 2103 print_dict(rpc.nvmf.nvmf_subsystem_get_qpairs(args.client, 2104 nqn=args.nqn, 2105 tgt_name=args.tgt_name)) 2106 2107 p = subparsers.add_parser('nvmf_subsystem_get_qpairs', 2108 help='Display queue pairs of an NVMe-oF subsystem.') 2109 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2110 p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str) 2111 p.set_defaults(func=nvmf_subsystem_get_qpairs) 2112 2113 def nvmf_subsystem_get_listeners(args): 2114 print_dict(rpc.nvmf.nvmf_subsystem_get_listeners(args.client, 2115 nqn=args.nqn, 2116 tgt_name=args.tgt_name)) 2117 2118 p = subparsers.add_parser('nvmf_subsystem_get_listeners', 2119 help='Display listeners of an NVMe-oF subsystem.') 2120 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2121 p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str) 2122 p.set_defaults(func=nvmf_subsystem_get_listeners) 2123 2124 def nvmf_get_stats(args): 2125 print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name)) 2126 2127 p = subparsers.add_parser( 2128 'nvmf_get_stats', help='Display current statistics for NVMf subsystem') 2129 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 2130 p.set_defaults(func=nvmf_get_stats) 2131 2132 # pmem 2133 def bdev_pmem_create_pool(args): 2134 num_blocks = int((args.total_size * 1024 * 1024) / args.block_size) 2135 rpc.pmem.bdev_pmem_create_pool(args.client, 2136 pmem_file=args.pmem_file, 2137 num_blocks=num_blocks, 2138 block_size=args.block_size) 2139 2140 p = subparsers.add_parser('bdev_pmem_create_pool', aliases=['create_pmem_pool'], 2141 help='Create pmem pool') 2142 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2143 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 2144 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 2145 p.set_defaults(func=bdev_pmem_create_pool) 2146 2147 def bdev_pmem_get_pool_info(args): 2148 print_dict(rpc.pmem.bdev_pmem_get_pool_info(args.client, 2149 pmem_file=args.pmem_file)) 2150 2151 p = subparsers.add_parser('bdev_pmem_get_pool_info', aliases=['pmem_pool_info'], 2152 help='Display pmem pool info and check consistency') 2153 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2154 p.set_defaults(func=bdev_pmem_get_pool_info) 2155 2156 def bdev_pmem_delete_pool(args): 2157 rpc.pmem.bdev_pmem_delete_pool(args.client, 2158 pmem_file=args.pmem_file) 2159 2160 p = subparsers.add_parser('bdev_pmem_delete_pool', aliases=['delete_pmem_pool'], 2161 help='Delete pmem pool') 2162 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2163 p.set_defaults(func=bdev_pmem_delete_pool) 2164 2165 # subsystem 2166 def framework_get_subsystems(args): 2167 print_dict(rpc.subsystem.framework_get_subsystems(args.client)) 2168 2169 p = subparsers.add_parser('framework_get_subsystems', aliases=['get_subsystems'], 2170 help="""Print subsystems array in initialization order. Each subsystem 2171 entry contain (unsorted) array of subsystems it depends on.""") 2172 p.set_defaults(func=framework_get_subsystems) 2173 2174 def framework_get_config(args): 2175 print_dict(rpc.subsystem.framework_get_config(args.client, args.name)) 2176 2177 p = subparsers.add_parser('framework_get_config', aliases=['get_subsystem_config'], 2178 help="""Print subsystem configuration""") 2179 p.add_argument('name', help='Name of subsystem to query') 2180 p.set_defaults(func=framework_get_config) 2181 2182 # vhost 2183 def vhost_controller_set_coalescing(args): 2184 rpc.vhost.vhost_controller_set_coalescing(args.client, 2185 ctrlr=args.ctrlr, 2186 delay_base_us=args.delay_base_us, 2187 iops_threshold=args.iops_threshold) 2188 2189 p = subparsers.add_parser('vhost_controller_set_coalescing', aliases=['set_vhost_controller_coalescing'], 2190 help='Set vhost controller coalescing') 2191 p.add_argument('ctrlr', help='controller name') 2192 p.add_argument('delay_base_us', help='Base delay time', type=int) 2193 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 2194 p.set_defaults(func=vhost_controller_set_coalescing) 2195 2196 def vhost_create_scsi_controller(args): 2197 rpc.vhost.vhost_create_scsi_controller(args.client, 2198 ctrlr=args.ctrlr, 2199 cpumask=args.cpumask) 2200 2201 p = subparsers.add_parser( 2202 'vhost_create_scsi_controller', aliases=['construct_vhost_scsi_controller'], 2203 help='Add new vhost controller') 2204 p.add_argument('ctrlr', help='controller name') 2205 p.add_argument('--cpumask', help='cpu mask for this controller') 2206 p.set_defaults(func=vhost_create_scsi_controller) 2207 2208 def vhost_scsi_controller_add_target(args): 2209 print_json(rpc.vhost.vhost_scsi_controller_add_target(args.client, 2210 ctrlr=args.ctrlr, 2211 scsi_target_num=args.scsi_target_num, 2212 bdev_name=args.bdev_name)) 2213 2214 p = subparsers.add_parser('vhost_scsi_controller_add_target', 2215 aliases=['add_vhost_scsi_lun'], 2216 help='Add lun to vhost controller') 2217 p.add_argument('ctrlr', help='conntroller name where add lun') 2218 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 2219 p.add_argument('bdev_name', help='bdev name') 2220 p.set_defaults(func=vhost_scsi_controller_add_target) 2221 2222 def vhost_scsi_controller_remove_target(args): 2223 rpc.vhost.vhost_scsi_controller_remove_target(args.client, 2224 ctrlr=args.ctrlr, 2225 scsi_target_num=args.scsi_target_num) 2226 2227 p = subparsers.add_parser('vhost_scsi_controller_remove_target', 2228 aliases=['remove_vhost_scsi_target'], 2229 help='Remove target from vhost controller') 2230 p.add_argument('ctrlr', help='controller name to remove target from') 2231 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 2232 p.set_defaults(func=vhost_scsi_controller_remove_target) 2233 2234 def vhost_create_blk_controller(args): 2235 rpc.vhost.vhost_create_blk_controller(args.client, 2236 ctrlr=args.ctrlr, 2237 dev_name=args.dev_name, 2238 cpumask=args.cpumask, 2239 readonly=args.readonly, 2240 packed_ring=args.packed_ring, 2241 packed_ring_recovery=args.packed_ring_recovery) 2242 2243 p = subparsers.add_parser('vhost_create_blk_controller', 2244 aliases=['construct_vhost_blk_controller'], 2245 help='Add a new vhost block controller') 2246 p.add_argument('ctrlr', help='controller name') 2247 p.add_argument('dev_name', help='device name') 2248 p.add_argument('--cpumask', help='cpu mask for this controller') 2249 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 2250 p.add_argument("-p", "--packed_ring", action='store_true', help='Set controller as packed ring supported') 2251 p.add_argument("-l", "--packed_ring_recovery", action='store_true', help='Enable packed ring live reocvery') 2252 p.set_defaults(func=vhost_create_blk_controller) 2253 2254 def vhost_get_controllers(args): 2255 print_dict(rpc.vhost.vhost_get_controllers(args.client, args.name)) 2256 2257 p = subparsers.add_parser('vhost_get_controllers', aliases=['get_vhost_controllers'], 2258 help='List all or specific vhost controller(s)') 2259 p.add_argument('-n', '--name', help="Name of vhost controller", required=False) 2260 p.set_defaults(func=vhost_get_controllers) 2261 2262 def vhost_delete_controller(args): 2263 rpc.vhost.vhost_delete_controller(args.client, 2264 ctrlr=args.ctrlr) 2265 2266 p = subparsers.add_parser('vhost_delete_controller', aliases=['remove_vhost_controller'], 2267 help='Delete a vhost controller') 2268 p.add_argument('ctrlr', help='controller name') 2269 p.set_defaults(func=vhost_delete_controller) 2270 2271 def bdev_virtio_attach_controller(args): 2272 print_array(rpc.vhost.bdev_virtio_attach_controller(args.client, 2273 name=args.name, 2274 trtype=args.trtype, 2275 traddr=args.traddr, 2276 dev_type=args.dev_type, 2277 vq_count=args.vq_count, 2278 vq_size=args.vq_size)) 2279 2280 p = subparsers.add_parser('bdev_virtio_attach_controller', aliases=['construct_virtio_dev'], 2281 help="""Attach virtio controller using provided 2282 transport type and device type. This will also create bdevs for any block devices connected to the 2283 controller (for example, SCSI devices for a virtio-scsi controller). 2284 Result is array of added bdevs.""") 2285 p.add_argument('name', help="Use this name as base for new created bdevs") 2286 p.add_argument('-t', '--trtype', 2287 help='Virtio target transport type: pci or user', required=True) 2288 p.add_argument('-a', '--traddr', 2289 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 2290 p.add_argument('-d', '--dev-type', 2291 help='Device type: blk or scsi', required=True) 2292 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 2293 p.add_argument('--vq-size', help='Size of each queue', type=int) 2294 p.set_defaults(func=bdev_virtio_attach_controller) 2295 2296 def bdev_virtio_scsi_get_devices(args): 2297 print_dict(rpc.vhost.bdev_virtio_scsi_get_devices(args.client)) 2298 2299 p = subparsers.add_parser('bdev_virtio_scsi_get_devices', aliases=['get_virtio_scsi_devs'], 2300 help='List all Virtio-SCSI devices.') 2301 p.set_defaults(func=bdev_virtio_scsi_get_devices) 2302 2303 def bdev_virtio_detach_controller(args): 2304 rpc.vhost.bdev_virtio_detach_controller(args.client, 2305 name=args.name) 2306 2307 p = subparsers.add_parser('bdev_virtio_detach_controller', aliases=['remove_virtio_bdev'], 2308 help="""Remove a Virtio device 2309 This will delete all bdevs exposed by this device""") 2310 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 2311 p.set_defaults(func=bdev_virtio_detach_controller) 2312 2313 # OCSSD 2314 def bdev_ocssd_create(args): 2315 nsid = int(args.nsid) if args.nsid is not None else None 2316 print_json(rpc.bdev.bdev_ocssd_create(args.client, 2317 ctrlr_name=args.ctrlr_name, 2318 bdev_name=args.name, 2319 nsid=nsid)) 2320 2321 p = subparsers.add_parser('bdev_ocssd_create', 2322 help='Creates zoned bdev on specified Open Channel controller') 2323 p.add_argument('-c', '--ctrlr_name', help='Name of the OC NVMe controller', required=True) 2324 p.add_argument('-b', '--name', help='Name of the bdev to create', required=True) 2325 p.add_argument('-n', '--nsid', help='Namespace ID', required=False) 2326 p.set_defaults(func=bdev_ocssd_create) 2327 2328 def bdev_ocssd_delete(args): 2329 print_json(rpc.bdev.bdev_ocssd_delete(args.client, 2330 name=args.name)) 2331 2332 p = subparsers.add_parser('bdev_ocssd_delete', 2333 help='Deletes Open Channel bdev') 2334 p.add_argument('name', help='Name of the Open Channel bdev') 2335 p.set_defaults(func=bdev_ocssd_delete) 2336 2337 # ioat 2338 def ioat_scan_accel_engine(args): 2339 rpc.ioat.ioat_scan_accel_engine(args.client) 2340 2341 p = subparsers.add_parser('ioat_scan_accel_engine', 2342 aliases=['ioat_scan_copy_engine', 'scan_ioat_copy_engine'], 2343 help='Enable IOAT accel engine offload.') 2344 p.set_defaults(func=ioat_scan_accel_engine) 2345 2346 # idxd 2347 def idxd_scan_accel_engine(args): 2348 rpc.idxd.idxd_scan_accel_engine(args.client, config_number=args.config_number) 2349 2350 p = subparsers.add_parser('idxd_scan_accel_engine', 2351 help='Set config and enable idxd accel engine offload.') 2352 p.add_argument('-c', '--config-number', help="""Pre-defined configuration number to use. See docs.""", type=int) 2353 p.set_defaults(func=idxd_scan_accel_engine) 2354 2355 # opal 2356 def bdev_nvme_opal_init(args): 2357 rpc.nvme.bdev_nvme_opal_init(args.client, 2358 nvme_ctrlr_name=args.nvme_ctrlr_name, 2359 password=args.password) 2360 2361 p = subparsers.add_parser('bdev_nvme_opal_init', help='take ownership and activate') 2362 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2363 p.add_argument('-p', '--password', help='password for admin') 2364 p.set_defaults(func=bdev_nvme_opal_init) 2365 2366 def bdev_nvme_opal_revert(args): 2367 rpc.nvme.bdev_nvme_opal_revert(args.client, 2368 nvme_ctrlr_name=args.nvme_ctrlr_name, 2369 password=args.password) 2370 p = subparsers.add_parser('bdev_nvme_opal_revert', help='Revert to default factory settings') 2371 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2372 p.add_argument('-p', '--password', help='password') 2373 p.set_defaults(func=bdev_nvme_opal_revert) 2374 2375 def bdev_opal_create(args): 2376 print_json(rpc.bdev.bdev_opal_create(args.client, 2377 nvme_ctrlr_name=args.nvme_ctrlr_name, 2378 nsid=args.nsid, 2379 locking_range_id=args.locking_range_id, 2380 range_start=args.range_start, 2381 range_length=args.range_length, 2382 password=args.password)) 2383 2384 p = subparsers.add_parser('bdev_opal_create', help="""Create opal bdev on specified NVMe controller""") 2385 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name', required=True) 2386 p.add_argument('-n', '--nsid', help='namespace ID (only support nsid=1 for now)', type=int, required=True) 2387 p.add_argument('-i', '--locking-range-id', help='locking range id', type=int, required=True) 2388 p.add_argument('-s', '--range-start', help='locking range start LBA', type=int, required=True) 2389 p.add_argument('-l', '--range-length', help='locking range length (in blocks)', type=int, required=True) 2390 p.add_argument('-p', '--password', help='admin password', required=True) 2391 p.set_defaults(func=bdev_opal_create) 2392 2393 def bdev_opal_get_info(args): 2394 print_dict(rpc.bdev.bdev_opal_get_info(args.client, 2395 bdev_name=args.bdev_name, 2396 password=args.password)) 2397 2398 p = subparsers.add_parser('bdev_opal_get_info', help='get opal locking range info for this bdev') 2399 p.add_argument('-b', '--bdev-name', help='opal bdev') 2400 p.add_argument('-p', '--password', help='password') 2401 p.set_defaults(func=bdev_opal_get_info) 2402 2403 def bdev_opal_delete(args): 2404 rpc.bdev.bdev_opal_delete(args.client, 2405 bdev_name=args.bdev_name, 2406 password=args.password) 2407 2408 p = subparsers.add_parser('bdev_opal_delete', help="""delete a virtual opal bdev""") 2409 p.add_argument('-b', '--bdev-name', help='opal virtual bdev', required=True) 2410 p.add_argument('-p', '--password', help='admin password', required=True) 2411 p.set_defaults(func=bdev_opal_delete) 2412 2413 def bdev_opal_new_user(args): 2414 rpc.bdev.bdev_opal_new_user(args.client, 2415 bdev_name=args.bdev_name, 2416 admin_password=args.admin_password, 2417 user_id=args.user_id, 2418 user_password=args.user_password) 2419 2420 p = subparsers.add_parser('bdev_opal_new_user', help="""Add a user to opal bdev who can set lock state for this bdev""") 2421 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2422 p.add_argument('-p', '--admin-password', help='admin password', required=True) 2423 p.add_argument('-i', '--user-id', help='ID for new user', type=int, required=True) 2424 p.add_argument('-u', '--user-password', help='password set for this user', required=True) 2425 p.set_defaults(func=bdev_opal_new_user) 2426 2427 def bdev_opal_set_lock_state(args): 2428 rpc.bdev.bdev_opal_set_lock_state(args.client, 2429 bdev_name=args.bdev_name, 2430 user_id=args.user_id, 2431 password=args.password, 2432 lock_state=args.lock_state) 2433 2434 p = subparsers.add_parser('bdev_opal_set_lock_state', help="""set lock state for an opal bdev""") 2435 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2436 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', 2437 type=int, required=True) 2438 p.add_argument('-p', '--password', help='password of this user', required=True) 2439 p.add_argument('-l', '--lock-state', help='lock state to set, choose from {readwrite, readonly, rwlock}', required=True) 2440 p.set_defaults(func=bdev_opal_set_lock_state) 2441 2442 # bdev_nvme_send_cmd 2443 def bdev_nvme_send_cmd(args): 2444 print_dict(rpc.nvme.bdev_nvme_send_cmd(args.client, 2445 name=args.nvme_name, 2446 cmd_type=args.cmd_type, 2447 data_direction=args.data_direction, 2448 cmdbuf=args.cmdbuf, 2449 data=args.data, 2450 metadata=args.metadata, 2451 data_len=args.data_length, 2452 metadata_len=args.metadata_length, 2453 timeout_ms=args.timeout_ms)) 2454 2455 p = subparsers.add_parser('bdev_nvme_send_cmd', aliases=['send_nvme_cmd'], 2456 help='NVMe passthrough cmd.') 2457 p.add_argument('-n', '--nvme-name', help="""Name of the operating NVMe controller""") 2458 p.add_argument('-t', '--cmd-type', help="""Type of nvme cmd. Valid values are: admin, io""") 2459 p.add_argument('-r', '--data-direction', help="""Direction of data transfer. Valid values are: c2h, h2c""") 2460 p.add_argument('-c', '--cmdbuf', help="""NVMe command encoded by base64 urlsafe""") 2461 p.add_argument('-d', '--data', help="""Data transferring to controller from host, encoded by base64 urlsafe""") 2462 p.add_argument('-m', '--metadata', help="""Metadata transferring to controller from host, encoded by base64 urlsafe""") 2463 p.add_argument('-D', '--data-length', help="""Data length required to transfer from controller to host""", type=int) 2464 p.add_argument('-M', '--metadata-length', help="""Metadata length required to transfer from controller to host""", type=int) 2465 p.add_argument('-T', '--timeout-ms', 2466 help="""Command execution timeout value, in milliseconds, if 0, don't track timeout""", type=int, default=0) 2467 p.set_defaults(func=bdev_nvme_send_cmd) 2468 2469 # Notifications 2470 def notify_get_types(args): 2471 print_dict(rpc.notify.notify_get_types(args.client)) 2472 2473 p = subparsers.add_parser('notify_get_types', aliases=['get_notification_types'], 2474 help='List available notifications that user can subscribe to.') 2475 p.set_defaults(func=notify_get_types) 2476 2477 def notify_get_notifications(args): 2478 ret = rpc.notify.notify_get_notifications(args.client, 2479 id=args.id, 2480 max=args.max) 2481 print_dict(ret) 2482 2483 p = subparsers.add_parser('notify_get_notifications', aliases=['get_notifications'], 2484 help='Get notifications') 2485 p.add_argument('-i', '--id', help="""First ID to start fetching from""", type=int) 2486 p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int) 2487 p.set_defaults(func=notify_get_notifications) 2488 2489 def thread_get_stats(args): 2490 print_dict(rpc.app.thread_get_stats(args.client)) 2491 2492 p = subparsers.add_parser( 2493 'thread_get_stats', help='Display current statistics of all the threads') 2494 p.set_defaults(func=thread_get_stats) 2495 2496 def thread_set_cpumask(args): 2497 ret = rpc.app.thread_set_cpumask(args.client, 2498 id=args.id, 2499 cpumask=args.cpumask) 2500 p = subparsers.add_parser('thread_set_cpumask', 2501 help="""set the cpumask of the thread whose ID matches to the 2502 specified value. The thread may be migrated to one of the specified CPUs.""") 2503 p.add_argument('-i', '--id', type=int, help='thread ID') 2504 p.add_argument('-m', '--cpumask', help='cpumask for this thread') 2505 p.set_defaults(func=thread_set_cpumask) 2506 2507 def log_enable_timestamps(args): 2508 ret = rpc.app.log_enable_timestamps(args.client, 2509 enabled=args.enabled) 2510 p = subparsers.add_parser('log_enable_timestamps', 2511 help='Enable or disable timestamps.') 2512 p.add_argument('-d', '--disable', dest='enabled', default=False, action='store_false', help="Disable timestamps") 2513 p.add_argument('-e', '--enable', dest='enabled', action='store_true', help="Enable timestamps") 2514 p.set_defaults(func=log_enable_timestamps) 2515 2516 def thread_get_pollers(args): 2517 print_dict(rpc.app.thread_get_pollers(args.client)) 2518 2519 p = subparsers.add_parser( 2520 'thread_get_pollers', help='Display current pollers of all the threads') 2521 p.set_defaults(func=thread_get_pollers) 2522 2523 def thread_get_io_channels(args): 2524 print_dict(rpc.app.thread_get_io_channels(args.client)) 2525 2526 p = subparsers.add_parser( 2527 'thread_get_io_channels', help='Display current IO channels of all the threads') 2528 p.set_defaults(func=thread_get_io_channels) 2529 2530 def env_dpdk_get_mem_stats(args): 2531 print_dict(rpc.env_dpdk.env_dpdk_get_mem_stats(args.client)) 2532 2533 p = subparsers.add_parser( 2534 'env_dpdk_get_mem_stats', help='write the dpdk memory stats to a file.') 2535 p.set_defaults(func=env_dpdk_get_mem_stats) 2536 2537 # blobfs 2538 def blobfs_detect(args): 2539 print(rpc.blobfs.blobfs_detect(args.client, 2540 bdev_name=args.bdev_name)) 2541 2542 p = subparsers.add_parser('blobfs_detect', help='Detect whether a blobfs exists on bdev') 2543 p.add_argument('bdev_name', help='Blockdev name to detect blobfs. Example: Malloc0.') 2544 p.set_defaults(func=blobfs_detect) 2545 2546 def blobfs_create(args): 2547 print(rpc.blobfs.blobfs_create(args.client, 2548 bdev_name=args.bdev_name, 2549 cluster_sz=args.cluster_sz)) 2550 2551 p = subparsers.add_parser('blobfs_create', help='Build a blobfs on bdev') 2552 p.add_argument('bdev_name', help='Blockdev name to build blobfs. Example: Malloc0.') 2553 p.add_argument('-c', '--cluster_sz', 2554 help="""Size of cluster in bytes (Optional). Must be multiple of 4KB page size. Default and minimal value is 1M.""") 2555 p.set_defaults(func=blobfs_create) 2556 2557 def blobfs_mount(args): 2558 print(rpc.blobfs.blobfs_mount(args.client, 2559 bdev_name=args.bdev_name, 2560 mountpoint=args.mountpoint)) 2561 2562 p = subparsers.add_parser('blobfs_mount', help='Mount a blobfs on bdev to host path by FUSE') 2563 p.add_argument('bdev_name', help='Blockdev name where the blobfs is. Example: Malloc0.') 2564 p.add_argument('mountpoint', help='Mountpoint path in host to mount blobfs. Example: /mnt/.') 2565 p.set_defaults(func=blobfs_mount) 2566 2567 def blobfs_set_cache_size(args): 2568 print(rpc.blobfs.blobfs_set_cache_size(args.client, 2569 size_in_mb=args.size_in_mb)) 2570 2571 p = subparsers.add_parser('blobfs_set_cache_size', help='Set cache size for blobfs') 2572 p.add_argument('size_in_mb', help='Cache size for blobfs in megabytes.', type=int) 2573 p.set_defaults(func=blobfs_set_cache_size) 2574 2575 # sock 2576 def sock_impl_get_options(args): 2577 print_json(rpc.sock.sock_impl_get_options(args.client, 2578 impl_name=args.impl)) 2579 2580 p = subparsers.add_parser('sock_impl_get_options', help="""Get options of socket layer implementation""") 2581 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2582 p.set_defaults(func=sock_impl_get_options) 2583 2584 def sock_impl_set_options(args): 2585 rpc.sock.sock_impl_set_options(args.client, 2586 impl_name=args.impl, 2587 recv_buf_size=args.recv_buf_size, 2588 send_buf_size=args.send_buf_size, 2589 enable_recv_pipe=args.enable_recv_pipe, 2590 enable_zerocopy_send=args.enable_zerocopy_send, 2591 enable_quickack=args.enable_quickack, 2592 enable_placement_id=args.enable_placement_id) 2593 2594 p = subparsers.add_parser('sock_impl_set_options', help="""Set options of socket layer implementation""") 2595 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2596 p.add_argument('-r', '--recv-buf-size', help='Size of receive buffer on socket in bytes', type=int) 2597 p.add_argument('-s', '--send-buf-size', help='Size of send buffer on socket in bytes', type=int) 2598 p.add_argument('-p', '--enable-placement-id', help='Option for placement-id. 0:disable,1:incoming_napi,2:incoming_cpu', type=int) 2599 p.add_argument('--enable-recv-pipe', help='Enable receive pipe', 2600 action='store_true', dest='enable_recv_pipe') 2601 p.add_argument('--disable-recv-pipe', help='Disable receive pipe', 2602 action='store_false', dest='enable_recv_pipe') 2603 p.add_argument('--enable-zerocopy-send', help='Enable zerocopy on send', 2604 action='store_true', dest='enable_zerocopy_send') 2605 p.add_argument('--disable-zerocopy-send', help='Disable zerocopy on send', 2606 action='store_false', dest='enable_zerocopy_send') 2607 p.add_argument('--enable-quickack', help='Enable quick ACK', 2608 action='store_true', dest='enable_quickack') 2609 p.add_argument('--disable-quickack', help='Disable quick ACK', 2610 action='store_false', dest='enable_quickack') 2611 p.set_defaults(func=sock_impl_set_options, enable_recv_pipe=None, enable_zerocopy_send=None, 2612 enable_quickack=None, enable_placement_id=None) 2613 2614 def sock_set_default_impl(args): 2615 print_json(rpc.sock.sock_set_default_impl(args.client, 2616 impl_name=args.impl)) 2617 2618 p = subparsers.add_parser('sock_set_default_impl', help="""Set the default sock implementation""") 2619 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2620 p.set_defaults(func=sock_set_default_impl) 2621 2622 def check_called_name(name): 2623 if name in deprecated_aliases: 2624 print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr) 2625 2626 class dry_run_client: 2627 def call(self, method, params=None): 2628 print("Request:\n" + json.dumps({"method": method, "params": params}, indent=2)) 2629 2630 def null_print(arg): 2631 pass 2632 2633 def call_rpc_func(args): 2634 args.func(args) 2635 check_called_name(args.called_rpc_name) 2636 2637 def execute_script(parser, client, fd): 2638 executed_rpc = "" 2639 for rpc_call in map(str.rstrip, fd): 2640 if not rpc_call.strip(): 2641 continue 2642 executed_rpc = "\n".join([executed_rpc, rpc_call]) 2643 args = parser.parse_args(shlex.split(rpc_call)) 2644 args.client = client 2645 try: 2646 call_rpc_func(args) 2647 except JSONRPCException as ex: 2648 print("Exception:") 2649 print(executed_rpc.strip() + " <<<") 2650 print(ex.message) 2651 exit(1) 2652 2653 def load_plugin(args): 2654 # Create temporary parser, pull out the plugin parameter, load the module, and then run the real argument parser 2655 plugin_parser = argparse.ArgumentParser(add_help=False) 2656 plugin_parser.add_argument('--plugin', dest='rpc_plugin', help='Module name of plugin with additional RPC commands') 2657 2658 rpc_module = plugin_parser.parse_known_args()[0].rpc_plugin 2659 if args is not None: 2660 rpc_module = plugin_parser.parse_known_args(args)[0].rpc_plugin 2661 2662 if rpc_module is not None: 2663 try: 2664 rpc_plugin = importlib.import_module(rpc_module) 2665 try: 2666 rpc_plugin.spdk_rpc_plugin_initialize(subparsers) 2667 except AttributeError: 2668 print("Module %s does not contain 'spdk_rpc_plugin_initialize' function" % rpc_module) 2669 except ModuleNotFoundError: 2670 print("Module %s not found" % rpc_module) 2671 2672 load_plugin(None) 2673 2674 args = parser.parse_args() 2675 2676 if sys.stdin.isatty() and not hasattr(args, 'func'): 2677 # No arguments and no data piped through stdin 2678 parser.print_help() 2679 exit(1) 2680 if args.is_server: 2681 for input in sys.stdin: 2682 cmd = shlex.split(input) 2683 try: 2684 load_plugin(cmd) 2685 tmp_args = parser.parse_args(cmd) 2686 except SystemExit as ex: 2687 print("**STATUS=1", flush=True) 2688 continue 2689 2690 try: 2691 tmp_args.client = rpc.client.JSONRPCClient( 2692 tmp_args.server_addr, tmp_args.port, tmp_args.timeout, 2693 log_level=getattr(logging, tmp_args.verbose.upper()), conn_retries=tmp_args.conn_retries) 2694 call_rpc_func(tmp_args) 2695 print("**STATUS=0", flush=True) 2696 except JSONRPCException as ex: 2697 print(ex.message) 2698 print("**STATUS=1", flush=True) 2699 exit(0) 2700 elif args.dry_run: 2701 args.client = dry_run_client() 2702 print_dict = null_print 2703 print_json = null_print 2704 print_array = null_print 2705 else: 2706 try: 2707 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, 2708 log_level=getattr(logging, args.verbose.upper()), 2709 conn_retries=args.conn_retries) 2710 except JSONRPCException as ex: 2711 print(ex.message) 2712 exit(1) 2713 2714 if hasattr(args, 'func'): 2715 try: 2716 call_rpc_func(args) 2717 except JSONRPCException as ex: 2718 print(ex.message) 2719 exit(1) 2720 else: 2721 execute_script(parser, args.client, sys.stdin) 2722