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