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