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 compress_set_pmd(args): 209 rpc.bdev.compress_set_pmd(args.client, 210 pmd=args.pmd) 211 p = subparsers.add_parser('compress_set_pmd', aliases=['set_compress_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=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_delete_subsystem(args): 1875 rpc.nvmf.nvmf_delete_subsystem(args.client, 1876 nqn=args.subsystem_nqn, 1877 tgt_name=args.tgt_name) 1878 1879 p = subparsers.add_parser('nvmf_delete_subsystem', aliases=['delete_nvmf_subsystem'], 1880 help='Delete a nvmf subsystem') 1881 p.add_argument('subsystem_nqn', 1882 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 1883 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1884 p.set_defaults(func=nvmf_delete_subsystem) 1885 1886 def nvmf_subsystem_add_listener(args): 1887 rpc.nvmf.nvmf_subsystem_add_listener(args.client, 1888 nqn=args.nqn, 1889 trtype=args.trtype, 1890 traddr=args.traddr, 1891 tgt_name=args.tgt_name, 1892 adrfam=args.adrfam, 1893 trsvcid=args.trsvcid) 1894 1895 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 1896 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1897 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1898 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1899 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1900 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1901 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1902 p.set_defaults(func=nvmf_subsystem_add_listener) 1903 1904 def nvmf_subsystem_remove_listener(args): 1905 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, 1906 nqn=args.nqn, 1907 trtype=args.trtype, 1908 traddr=args.traddr, 1909 tgt_name=args.tgt_name, 1910 adrfam=args.adrfam, 1911 trsvcid=args.trsvcid) 1912 1913 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 1914 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1915 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1916 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1917 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1918 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1919 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1920 p.set_defaults(func=nvmf_subsystem_remove_listener) 1921 1922 def nvmf_subsystem_add_ns(args): 1923 rpc.nvmf.nvmf_subsystem_add_ns(args.client, 1924 nqn=args.nqn, 1925 bdev_name=args.bdev_name, 1926 tgt_name=args.tgt_name, 1927 ptpl_file=args.ptpl_file, 1928 nsid=args.nsid, 1929 nguid=args.nguid, 1930 eui64=args.eui64, 1931 uuid=args.uuid) 1932 1933 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 1934 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1935 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 1936 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1937 p.add_argument('-p', '--ptpl-file', help='The persistent reservation storage location (optional)', type=str) 1938 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 1939 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 1940 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 1941 p.add_argument('-u', '--uuid', help='Namespace UUID (optional)') 1942 p.set_defaults(func=nvmf_subsystem_add_ns) 1943 1944 def nvmf_subsystem_remove_ns(args): 1945 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, 1946 nqn=args.nqn, 1947 nsid=args.nsid, 1948 tgt_name=args.tgt_name) 1949 1950 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 1951 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1952 p.add_argument('nsid', help='The requested NSID', type=int) 1953 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1954 p.set_defaults(func=nvmf_subsystem_remove_ns) 1955 1956 def nvmf_subsystem_add_host(args): 1957 rpc.nvmf.nvmf_subsystem_add_host(args.client, 1958 nqn=args.nqn, 1959 host=args.host, 1960 tgt_name=args.tgt_name) 1961 1962 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 1963 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1964 p.add_argument('host', help='Host NQN to allow') 1965 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1966 p.set_defaults(func=nvmf_subsystem_add_host) 1967 1968 def nvmf_subsystem_remove_host(args): 1969 rpc.nvmf.nvmf_subsystem_remove_host(args.client, 1970 nqn=args.nqn, 1971 host=args.host, 1972 tgt_name=args.tgt_name) 1973 1974 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 1975 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1976 p.add_argument('host', help='Host NQN to remove') 1977 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1978 p.set_defaults(func=nvmf_subsystem_remove_host) 1979 1980 def nvmf_subsystem_allow_any_host(args): 1981 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, 1982 nqn=args.nqn, 1983 disable=args.disable, 1984 tgt_name=args.tgt_name) 1985 1986 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 1987 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1988 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 1989 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 1990 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1991 p.set_defaults(func=nvmf_subsystem_allow_any_host) 1992 1993 def nvmf_subsystem_get_controllers(args): 1994 print_dict(rpc.nvmf.nvmf_subsystem_get_controllers(args.client, 1995 nqn=args.nqn, 1996 tgt_name=args.tgt_name)) 1997 1998 p = subparsers.add_parser('nvmf_subsystem_get_controllers', 1999 help='Display controllers of an NVMe-oF subsystem.') 2000 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 2001 p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str) 2002 p.set_defaults(func=nvmf_subsystem_get_controllers) 2003 2004 def nvmf_get_stats(args): 2005 print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name)) 2006 2007 p = subparsers.add_parser( 2008 'nvmf_get_stats', help='Display current statistics for NVMf subsystem') 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_get_stats) 2011 2012 # pmem 2013 def bdev_pmem_create_pool(args): 2014 num_blocks = int((args.total_size * 1024 * 1024) / args.block_size) 2015 rpc.pmem.bdev_pmem_create_pool(args.client, 2016 pmem_file=args.pmem_file, 2017 num_blocks=num_blocks, 2018 block_size=args.block_size) 2019 2020 p = subparsers.add_parser('bdev_pmem_create_pool', aliases=['create_pmem_pool'], 2021 help='Create pmem pool') 2022 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2023 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 2024 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 2025 p.set_defaults(func=bdev_pmem_create_pool) 2026 2027 def bdev_pmem_get_pool_info(args): 2028 print_dict(rpc.pmem.bdev_pmem_get_pool_info(args.client, 2029 pmem_file=args.pmem_file)) 2030 2031 p = subparsers.add_parser('bdev_pmem_get_pool_info', aliases=['pmem_pool_info'], 2032 help='Display pmem pool info and check consistency') 2033 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2034 p.set_defaults(func=bdev_pmem_get_pool_info) 2035 2036 def bdev_pmem_delete_pool(args): 2037 rpc.pmem.bdev_pmem_delete_pool(args.client, 2038 pmem_file=args.pmem_file) 2039 2040 p = subparsers.add_parser('bdev_pmem_delete_pool', aliases=['delete_pmem_pool'], 2041 help='Delete pmem pool') 2042 p.add_argument('pmem_file', help='Path to pmemblk pool file') 2043 p.set_defaults(func=bdev_pmem_delete_pool) 2044 2045 # subsystem 2046 def framework_get_subsystems(args): 2047 print_dict(rpc.subsystem.framework_get_subsystems(args.client)) 2048 2049 p = subparsers.add_parser('framework_get_subsystems', aliases=['get_subsystems'], 2050 help="""Print subsystems array in initialization order. Each subsystem 2051 entry contain (unsorted) array of subsystems it depends on.""") 2052 p.set_defaults(func=framework_get_subsystems) 2053 2054 def framework_get_config(args): 2055 print_dict(rpc.subsystem.framework_get_config(args.client, args.name)) 2056 2057 p = subparsers.add_parser('framework_get_config', aliases=['get_subsystem_config'], 2058 help="""Print subsystem configuration""") 2059 p.add_argument('name', help='Name of subsystem to query') 2060 p.set_defaults(func=framework_get_config) 2061 2062 # vhost 2063 def vhost_controller_set_coalescing(args): 2064 rpc.vhost.vhost_controller_set_coalescing(args.client, 2065 ctrlr=args.ctrlr, 2066 delay_base_us=args.delay_base_us, 2067 iops_threshold=args.iops_threshold) 2068 2069 p = subparsers.add_parser('vhost_controller_set_coalescing', aliases=['set_vhost_controller_coalescing'], 2070 help='Set vhost controller coalescing') 2071 p.add_argument('ctrlr', help='controller name') 2072 p.add_argument('delay_base_us', help='Base delay time', type=int) 2073 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 2074 p.set_defaults(func=vhost_controller_set_coalescing) 2075 2076 def vhost_create_scsi_controller(args): 2077 rpc.vhost.vhost_create_scsi_controller(args.client, 2078 ctrlr=args.ctrlr, 2079 cpumask=args.cpumask) 2080 2081 p = subparsers.add_parser( 2082 'vhost_create_scsi_controller', aliases=['construct_vhost_scsi_controller'], 2083 help='Add new vhost controller') 2084 p.add_argument('ctrlr', help='controller name') 2085 p.add_argument('--cpumask', help='cpu mask for this controller') 2086 p.set_defaults(func=vhost_create_scsi_controller) 2087 2088 def vhost_scsi_controller_add_target(args): 2089 print_json(rpc.vhost.vhost_scsi_controller_add_target(args.client, 2090 ctrlr=args.ctrlr, 2091 scsi_target_num=args.scsi_target_num, 2092 bdev_name=args.bdev_name)) 2093 2094 p = subparsers.add_parser('vhost_scsi_controller_add_target', 2095 aliases=['add_vhost_scsi_lun'], 2096 help='Add lun to vhost controller') 2097 p.add_argument('ctrlr', help='conntroller name where add lun') 2098 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 2099 p.add_argument('bdev_name', help='bdev name') 2100 p.set_defaults(func=vhost_scsi_controller_add_target) 2101 2102 def vhost_scsi_controller_remove_target(args): 2103 rpc.vhost.vhost_scsi_controller_remove_target(args.client, 2104 ctrlr=args.ctrlr, 2105 scsi_target_num=args.scsi_target_num) 2106 2107 p = subparsers.add_parser('vhost_scsi_controller_remove_target', 2108 aliases=['remove_vhost_scsi_target'], 2109 help='Remove target from vhost controller') 2110 p.add_argument('ctrlr', help='controller name to remove target from') 2111 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 2112 p.set_defaults(func=vhost_scsi_controller_remove_target) 2113 2114 def vhost_create_blk_controller(args): 2115 rpc.vhost.vhost_create_blk_controller(args.client, 2116 ctrlr=args.ctrlr, 2117 dev_name=args.dev_name, 2118 cpumask=args.cpumask, 2119 readonly=args.readonly, 2120 packed_ring=args.packed_ring) 2121 2122 p = subparsers.add_parser('vhost_create_blk_controller', 2123 aliases=['construct_vhost_blk_controller'], 2124 help='Add a new vhost block controller') 2125 p.add_argument('ctrlr', help='controller name') 2126 p.add_argument('dev_name', help='device name') 2127 p.add_argument('--cpumask', help='cpu mask for this controller') 2128 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 2129 p.add_argument("-p", "--packed_ring", action='store_true', help='Set controller as packed ring supported') 2130 p.set_defaults(func=vhost_create_blk_controller) 2131 2132 def vhost_create_nvme_controller(args): 2133 rpc.vhost.vhost_create_nvme_controller(args.client, 2134 ctrlr=args.ctrlr, 2135 io_queues=args.io_queues, 2136 cpumask=args.cpumask) 2137 2138 p = subparsers.add_parser('vhost_create_nvme_controller', aliases=['vhost_create_nvme_controller'], 2139 help='Add new vhost controller') 2140 p.add_argument('ctrlr', help='controller name') 2141 p.add_argument('io_queues', help='number of IO queues for the controller', type=int) 2142 p.add_argument('--cpumask', help='cpu mask for this controller') 2143 p.set_defaults(func=vhost_create_nvme_controller) 2144 2145 def vhost_nvme_controller_add_ns(args): 2146 rpc.vhost.vhost_nvme_controller_add_ns(args.client, 2147 ctrlr=args.ctrlr, 2148 bdev_name=args.bdev_name) 2149 2150 p = subparsers.add_parser('vhost_nvme_controller_add_ns', aliases=['add_vhost_nvme_ns'], 2151 help='Add a Namespace to vhost controller') 2152 p.add_argument('ctrlr', help='conntroller name where add a Namespace') 2153 p.add_argument('bdev_name', help='block device name for a new Namespace') 2154 p.set_defaults(func=vhost_nvme_controller_add_ns) 2155 2156 def vhost_get_controllers(args): 2157 print_dict(rpc.vhost.vhost_get_controllers(args.client, args.name)) 2158 2159 p = subparsers.add_parser('vhost_get_controllers', aliases=['get_vhost_controllers'], 2160 help='List all or specific vhost controller(s)') 2161 p.add_argument('-n', '--name', help="Name of vhost controller", required=False) 2162 p.set_defaults(func=vhost_get_controllers) 2163 2164 def vhost_delete_controller(args): 2165 rpc.vhost.vhost_delete_controller(args.client, 2166 ctrlr=args.ctrlr) 2167 2168 p = subparsers.add_parser('vhost_delete_controller', aliases=['remove_vhost_controller'], 2169 help='Delete a vhost controller') 2170 p.add_argument('ctrlr', help='controller name') 2171 p.set_defaults(func=vhost_delete_controller) 2172 2173 def bdev_virtio_attach_controller(args): 2174 print_array(rpc.vhost.bdev_virtio_attach_controller(args.client, 2175 name=args.name, 2176 trtype=args.trtype, 2177 traddr=args.traddr, 2178 dev_type=args.dev_type, 2179 vq_count=args.vq_count, 2180 vq_size=args.vq_size)) 2181 2182 p = subparsers.add_parser('bdev_virtio_attach_controller', aliases=['construct_virtio_dev'], 2183 help="""Attach virtio controller using provided 2184 transport type and device type. This will also create bdevs for any block devices connected to the 2185 controller (for example, SCSI devices for a virtio-scsi controller). 2186 Result is array of added bdevs.""") 2187 p.add_argument('name', help="Use this name as base for new created bdevs") 2188 p.add_argument('-t', '--trtype', 2189 help='Virtio target transport type: pci or user', required=True) 2190 p.add_argument('-a', '--traddr', 2191 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 2192 p.add_argument('-d', '--dev-type', 2193 help='Device type: blk or scsi', required=True) 2194 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 2195 p.add_argument('--vq-size', help='Size of each queue', type=int) 2196 p.set_defaults(func=bdev_virtio_attach_controller) 2197 2198 def bdev_virtio_scsi_get_devices(args): 2199 print_dict(rpc.vhost.bdev_virtio_scsi_get_devices(args.client)) 2200 2201 p = subparsers.add_parser('bdev_virtio_scsi_get_devices', aliases=['get_virtio_scsi_devs'], 2202 help='List all Virtio-SCSI devices.') 2203 p.set_defaults(func=bdev_virtio_scsi_get_devices) 2204 2205 def bdev_virtio_detach_controller(args): 2206 rpc.vhost.bdev_virtio_detach_controller(args.client, 2207 name=args.name) 2208 2209 p = subparsers.add_parser('bdev_virtio_detach_controller', aliases=['remove_virtio_bdev'], 2210 help="""Remove a Virtio device 2211 This will delete all bdevs exposed by this device""") 2212 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 2213 p.set_defaults(func=bdev_virtio_detach_controller) 2214 2215 # OCSSD 2216 def bdev_ocssd_create(args): 2217 nsid = int(args.nsid) if args.nsid is not None else None 2218 print_json(rpc.bdev.bdev_ocssd_create(args.client, 2219 ctrlr_name=args.ctrlr_name, 2220 bdev_name=args.name, 2221 nsid=nsid, 2222 range=args.range)) 2223 2224 p = subparsers.add_parser('bdev_ocssd_create', 2225 help='Creates zoned bdev on specified Open Channel controller') 2226 p.add_argument('-c', '--ctrlr_name', help='Name of the OC NVMe controller', required=True) 2227 p.add_argument('-b', '--name', help='Name of the bdev to create', required=True) 2228 p.add_argument('-n', '--nsid', help='Namespace ID', required=False) 2229 p.add_argument('-r', '--range', help='Parallel unit range (in the form of BEGIN-END (inclusive))', 2230 required=False) 2231 p.set_defaults(func=bdev_ocssd_create) 2232 2233 def bdev_ocssd_delete(args): 2234 print_json(rpc.bdev.bdev_ocssd_delete(args.client, 2235 name=args.name)) 2236 2237 p = subparsers.add_parser('bdev_ocssd_delete', 2238 help='Deletes Open Channel bdev') 2239 p.add_argument('name', help='Name of the Open Channel bdev') 2240 p.set_defaults(func=bdev_ocssd_delete) 2241 2242 # ioat 2243 def ioat_scan_accel_engine(args): 2244 pci_whitelist = [] 2245 if args.pci_whitelist: 2246 for w in args.pci_whitelist.strip().split(" "): 2247 pci_whitelist.append(w) 2248 rpc.ioat.ioat_scan_accel_engine(args.client, pci_whitelist) 2249 2250 p = subparsers.add_parser('ioat_scan_accel_engine', 2251 aliases=['ioat_scan_copy_engine', 'scan_ioat_copy_engine'], 2252 help='Set scan and enable IOAT accel engine offload.') 2253 p.add_argument('-w', '--pci-whitelist', help="""Whitespace-separated list of PCI addresses in 2254 domain:bus:device.function format or domain.bus.device.function format""") 2255 p.set_defaults(func=ioat_scan_accel_engine) 2256 2257 # idxd 2258 def idxd_scan_accel_engine(args): 2259 rpc.idxd.idxd_scan_accel_engine(args.client, config_number=args.config_number) 2260 2261 p = subparsers.add_parser('idxd_scan_accel_engine', 2262 help='Set config and enable idxd accel engine offload.') 2263 p.add_argument('-c', '--config-number', help="""Pre-defined configuration number to use. See docs.""", type=int) 2264 p.set_defaults(func=idxd_scan_accel_engine) 2265 2266 # opal 2267 def bdev_nvme_opal_init(args): 2268 rpc.nvme.bdev_nvme_opal_init(args.client, 2269 nvme_ctrlr_name=args.nvme_ctrlr_name, 2270 password=args.password) 2271 2272 p = subparsers.add_parser('bdev_nvme_opal_init', help='take ownership and activate') 2273 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2274 p.add_argument('-p', '--password', help='password for admin') 2275 p.set_defaults(func=bdev_nvme_opal_init) 2276 2277 def bdev_nvme_opal_revert(args): 2278 rpc.nvme.bdev_nvme_opal_revert(args.client, 2279 nvme_ctrlr_name=args.nvme_ctrlr_name, 2280 password=args.password) 2281 p = subparsers.add_parser('bdev_nvme_opal_revert', help='Revert to default factory settings') 2282 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2283 p.add_argument('-p', '--password', help='password') 2284 p.set_defaults(func=bdev_nvme_opal_revert) 2285 2286 def bdev_opal_create(args): 2287 print_json(rpc.bdev.bdev_opal_create(args.client, 2288 nvme_ctrlr_name=args.nvme_ctrlr_name, 2289 nsid=args.nsid, 2290 locking_range_id=args.locking_range_id, 2291 range_start=args.range_start, 2292 range_length=args.range_length, 2293 password=args.password)) 2294 2295 p = subparsers.add_parser('bdev_opal_create', help="""Create opal bdev on specified NVMe controller""") 2296 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name', required=True) 2297 p.add_argument('-n', '--nsid', help='namespace ID (only support nsid=1 for now)', type=int, required=True) 2298 p.add_argument('-i', '--locking-range-id', help='locking range id', type=int, required=True) 2299 p.add_argument('-s', '--range-start', help='locking range start LBA', type=int, required=True) 2300 p.add_argument('-l', '--range-length', help='locking range length (in blocks)', type=int, required=True) 2301 p.add_argument('-p', '--password', help='admin password', required=True) 2302 p.set_defaults(func=bdev_opal_create) 2303 2304 def bdev_opal_get_info(args): 2305 print_dict(rpc.bdev.bdev_opal_get_info(args.client, 2306 bdev_name=args.bdev_name, 2307 password=args.password)) 2308 2309 p = subparsers.add_parser('bdev_opal_get_info', help='get opal locking range info for this bdev') 2310 p.add_argument('-b', '--bdev-name', help='opal bdev') 2311 p.add_argument('-p', '--password', help='password') 2312 p.set_defaults(func=bdev_opal_get_info) 2313 2314 def bdev_opal_delete(args): 2315 rpc.bdev.bdev_opal_delete(args.client, 2316 bdev_name=args.bdev_name, 2317 password=args.password) 2318 2319 p = subparsers.add_parser('bdev_opal_delete', help="""delete a virtual opal bdev""") 2320 p.add_argument('-b', '--bdev-name', help='opal virtual bdev', required=True) 2321 p.add_argument('-p', '--password', help='admin password', required=True) 2322 p.set_defaults(func=bdev_opal_delete) 2323 2324 def bdev_opal_new_user(args): 2325 rpc.bdev.bdev_opal_new_user(args.client, 2326 bdev_name=args.bdev_name, 2327 admin_password=args.admin_password, 2328 user_id=args.user_id, 2329 user_password=args.user_password) 2330 2331 p = subparsers.add_parser('bdev_opal_new_user', help="""Add a user to opal bdev who can set lock state for this bdev""") 2332 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2333 p.add_argument('-p', '--admin-password', help='admin password', required=True) 2334 p.add_argument('-i', '--user-id', help='ID for new user', type=int, required=True) 2335 p.add_argument('-u', '--user-password', help='password set for this user', required=True) 2336 p.set_defaults(func=bdev_opal_new_user) 2337 2338 def bdev_opal_set_lock_state(args): 2339 rpc.bdev.bdev_opal_set_lock_state(args.client, 2340 bdev_name=args.bdev_name, 2341 user_id=args.user_id, 2342 password=args.password, 2343 lock_state=args.lock_state) 2344 2345 p = subparsers.add_parser('bdev_opal_set_lock_state', help="""set lock state for an opal bdev""") 2346 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2347 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', 2348 type=int, required=True) 2349 p.add_argument('-p', '--password', help='password of this user', required=True) 2350 p.add_argument('-l', '--lock-state', help='lock state to set, choose from {readwrite, readonly, rwlock}', required=True) 2351 p.set_defaults(func=bdev_opal_set_lock_state) 2352 2353 # bdev_nvme_send_cmd 2354 def bdev_nvme_send_cmd(args): 2355 print_dict(rpc.nvme.bdev_nvme_send_cmd(args.client, 2356 name=args.nvme_name, 2357 cmd_type=args.cmd_type, 2358 data_direction=args.data_direction, 2359 cmdbuf=args.cmdbuf, 2360 data=args.data, 2361 metadata=args.metadata, 2362 data_len=args.data_length, 2363 metadata_len=args.metadata_length, 2364 timeout_ms=args.timeout_ms)) 2365 2366 p = subparsers.add_parser('bdev_nvme_send_cmd', aliases=['send_nvme_cmd'], 2367 help='NVMe passthrough cmd.') 2368 p.add_argument('-n', '--nvme-name', help="""Name of the operating NVMe controller""") 2369 p.add_argument('-t', '--cmd-type', help="""Type of nvme cmd. Valid values are: admin, io""") 2370 p.add_argument('-r', '--data-direction', help="""Direction of data transfer. Valid values are: c2h, h2c""") 2371 p.add_argument('-c', '--cmdbuf', help="""NVMe command encoded by base64 urlsafe""") 2372 p.add_argument('-d', '--data', help="""Data transferring to controller from host, encoded by base64 urlsafe""") 2373 p.add_argument('-m', '--metadata', help="""Metadata transferring to controller from host, encoded by base64 urlsafe""") 2374 p.add_argument('-D', '--data-length', help="""Data length required to transfer from controller to host""", type=int) 2375 p.add_argument('-M', '--metadata-length', help="""Metadata length required to transfer from controller to host""", type=int) 2376 p.add_argument('-T', '--timeout-ms', 2377 help="""Command execution timeout value, in milliseconds, if 0, don't track timeout""", type=int, default=0) 2378 p.set_defaults(func=bdev_nvme_send_cmd) 2379 2380 # Notifications 2381 def notify_get_types(args): 2382 print_dict(rpc.notify.notify_get_types(args.client)) 2383 2384 p = subparsers.add_parser('notify_get_types', aliases=['get_notification_types'], 2385 help='List available notifications that user can subscribe to.') 2386 p.set_defaults(func=notify_get_types) 2387 2388 def notify_get_notifications(args): 2389 ret = rpc.notify.notify_get_notifications(args.client, 2390 id=args.id, 2391 max=args.max) 2392 print_dict(ret) 2393 2394 p = subparsers.add_parser('notify_get_notifications', aliases=['get_notifications'], 2395 help='Get notifications') 2396 p.add_argument('-i', '--id', help="""First ID to start fetching from""", type=int) 2397 p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int) 2398 p.set_defaults(func=notify_get_notifications) 2399 2400 def thread_get_stats(args): 2401 print_dict(rpc.app.thread_get_stats(args.client)) 2402 2403 p = subparsers.add_parser( 2404 'thread_get_stats', help='Display current statistics of all the threads') 2405 p.set_defaults(func=thread_get_stats) 2406 2407 def thread_set_cpumask(args): 2408 ret = rpc.app.thread_set_cpumask(args.client, 2409 id=args.id, 2410 cpumask=args.cpumask) 2411 p = subparsers.add_parser('thread_set_cpumask', 2412 help="""set the cpumask of the thread whose ID matches to the 2413 specified value. The thread may be migrated to one of the specified CPUs.""") 2414 p.add_argument('-i', '--id', type=int, help='thread ID') 2415 p.add_argument('-m', '--cpumask', help='cpumask for this thread') 2416 p.set_defaults(func=thread_set_cpumask) 2417 2418 def log_enable_timestamps(args): 2419 ret = rpc.app.log_enable_timestamps(args.client, 2420 enabled=args.enabled) 2421 p = subparsers.add_parser('log_enable_timestamps', 2422 help='Enable or disable timestamps.') 2423 p.add_argument('-d', '--disable', dest='enabled', default=False, action='store_false', help="Disable timestamps") 2424 p.add_argument('-e', '--enable', dest='enabled', action='store_true', help="Enable timestamps") 2425 p.set_defaults(func=log_enable_timestamps) 2426 2427 def thread_get_pollers(args): 2428 print_dict(rpc.app.thread_get_pollers(args.client)) 2429 2430 p = subparsers.add_parser( 2431 'thread_get_pollers', help='Display current pollers of all the threads') 2432 p.set_defaults(func=thread_get_pollers) 2433 2434 def thread_get_io_channels(args): 2435 print_dict(rpc.app.thread_get_io_channels(args.client)) 2436 2437 p = subparsers.add_parser( 2438 'thread_get_io_channels', help='Display current IO channels of all the threads') 2439 p.set_defaults(func=thread_get_io_channels) 2440 2441 def env_dpdk_get_mem_stats(args): 2442 print_dict(rpc.env_dpdk.env_dpdk_get_mem_stats(args.client)) 2443 2444 p = subparsers.add_parser( 2445 'env_dpdk_get_mem_stats', help='write the dpdk memory stats to a file.') 2446 p.set_defaults(func=env_dpdk_get_mem_stats) 2447 2448 # blobfs 2449 def blobfs_detect(args): 2450 print(rpc.blobfs.blobfs_detect(args.client, 2451 bdev_name=args.bdev_name)) 2452 2453 p = subparsers.add_parser('blobfs_detect', help='Detect whether a blobfs exists on bdev') 2454 p.add_argument('bdev_name', help='Blockdev name to detect blobfs. Example: Malloc0.') 2455 p.set_defaults(func=blobfs_detect) 2456 2457 def blobfs_create(args): 2458 print(rpc.blobfs.blobfs_create(args.client, 2459 bdev_name=args.bdev_name, 2460 cluster_sz=args.cluster_sz)) 2461 2462 p = subparsers.add_parser('blobfs_create', help='Build a blobfs on bdev') 2463 p.add_argument('bdev_name', help='Blockdev name to build blobfs. Example: Malloc0.') 2464 p.add_argument('-c', '--cluster_sz', 2465 help="""Size of cluster in bytes (Optional). Must be multiple of 4KB page size. Default and minimal value is 1M.""") 2466 p.set_defaults(func=blobfs_create) 2467 2468 def blobfs_mount(args): 2469 print(rpc.blobfs.blobfs_mount(args.client, 2470 bdev_name=args.bdev_name, 2471 mountpoint=args.mountpoint)) 2472 2473 p = subparsers.add_parser('blobfs_mount', help='Mount a blobfs on bdev to host path by FUSE') 2474 p.add_argument('bdev_name', help='Blockdev name where the blobfs is. Example: Malloc0.') 2475 p.add_argument('mountpoint', help='Mountpoint path in host to mount blobfs. Example: /mnt/.') 2476 p.set_defaults(func=blobfs_mount) 2477 2478 def blobfs_set_cache_size(args): 2479 print(rpc.blobfs.blobfs_set_cache_size(args.client, 2480 size_in_mb=args.size_in_mb)) 2481 2482 p = subparsers.add_parser('blobfs_set_cache_size', help='Set cache size for blobfs') 2483 p.add_argument('size_in_mb', help='Cache size for blobfs in megabytes.', type=int) 2484 p.set_defaults(func=blobfs_set_cache_size) 2485 2486 # sock 2487 def sock_impl_get_options(args): 2488 print_json(rpc.sock.sock_impl_get_options(args.client, 2489 impl_name=args.impl)) 2490 2491 p = subparsers.add_parser('sock_impl_get_options', help="""Get options of socket layer implementation""") 2492 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2493 p.set_defaults(func=sock_impl_get_options) 2494 2495 def sock_impl_set_options(args): 2496 rpc.sock.sock_impl_set_options(args.client, 2497 impl_name=args.impl, 2498 recv_buf_size=args.recv_buf_size, 2499 send_buf_size=args.send_buf_size, 2500 enable_recv_pipe=args.enable_recv_pipe, 2501 enable_zerocopy_send=args.enable_zerocopy_send, 2502 enable_quickack=args.enable_quickack) 2503 2504 p = subparsers.add_parser('sock_impl_set_options', help="""Set options of socket layer implementation""") 2505 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2506 p.add_argument('-r', '--recv-buf-size', help='Size of receive buffer on socket in bytes', type=int) 2507 p.add_argument('-s', '--send-buf-size', help='Size of send buffer on socket in bytes', type=int) 2508 p.add_argument('--enable-recv-pipe', help='Enable receive pipe', 2509 action='store_true', dest='enable_recv_pipe') 2510 p.add_argument('--disable-recv-pipe', help='Disable receive pipe', 2511 action='store_false', dest='enable_recv_pipe') 2512 p.add_argument('--enable-zerocopy-send', help='Enable zerocopy on send', 2513 action='store_true', dest='enable_zerocopy_send') 2514 p.add_argument('--disable-zerocopy-send', help='Disable zerocopy on send', 2515 action='store_false', dest='enable_zerocopy_send') 2516 p.add_argument('--enable-quickack', help='Enable quick ACK', 2517 action='store_true', dest='enable_quickack') 2518 p.add_argument('--disable-quickack', help='Disable quick ACK', 2519 action='store_false', dest='enable_quickack') 2520 p.set_defaults(func=sock_impl_set_options, enable_recv_pipe=None, enable_zerocopy_send=None, 2521 enable_quickack=None) 2522 2523 def check_called_name(name): 2524 if name in deprecated_aliases: 2525 print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr) 2526 2527 class dry_run_client: 2528 def call(self, method, params=None): 2529 print("Request:\n" + json.dumps({"method": method, "params": params}, indent=2)) 2530 2531 def null_print(arg): 2532 pass 2533 2534 def call_rpc_func(args): 2535 args.func(args) 2536 check_called_name(args.called_rpc_name) 2537 2538 def execute_script(parser, client, fd): 2539 executed_rpc = "" 2540 for rpc_call in map(str.rstrip, fd): 2541 if not rpc_call.strip(): 2542 continue 2543 executed_rpc = "\n".join([executed_rpc, rpc_call]) 2544 args = parser.parse_args(shlex.split(rpc_call)) 2545 args.client = client 2546 try: 2547 call_rpc_func(args) 2548 except JSONRPCException as ex: 2549 print("Exception:") 2550 print(executed_rpc.strip() + " <<<") 2551 print(ex.message) 2552 exit(1) 2553 2554 # Create temporary parser, pull out the plugin parameter, load the module, and then run the real argument parser 2555 plugin_parser = argparse.ArgumentParser(add_help=False) 2556 plugin_parser.add_argument('--plugin', dest='rpc_plugin', help='Module name of plugin with additional RPC commands') 2557 2558 rpc_module = plugin_parser.parse_known_args()[0].rpc_plugin 2559 if rpc_module is not None: 2560 try: 2561 rpc_plugin = importlib.import_module(rpc_module) 2562 try: 2563 rpc_plugin.spdk_rpc_plugin_initialize(subparsers) 2564 except AttributeError: 2565 print("Module %s does not contain 'spdk_rpc_plugin_initialize' function" % rpc_module) 2566 except ModuleNotFoundError: 2567 print("Module %s not found" % rpc_module) 2568 2569 args = parser.parse_args() 2570 2571 if sys.stdin.isatty() and not hasattr(args, 'func'): 2572 # No arguments and no data piped through stdin 2573 parser.print_help() 2574 exit(1) 2575 if args.is_server: 2576 for input in sys.stdin: 2577 cmd = shlex.split(input) 2578 try: 2579 tmp_args = parser.parse_args(cmd) 2580 except SystemExit as ex: 2581 print("**STATUS=1", flush=True) 2582 continue 2583 2584 try: 2585 tmp_args.client = rpc.client.JSONRPCClient( 2586 tmp_args.server_addr, tmp_args.port, tmp_args.timeout, 2587 log_level=getattr(logging, tmp_args.verbose.upper()), conn_retries=tmp_args.conn_retries) 2588 call_rpc_func(tmp_args) 2589 print("**STATUS=0", flush=True) 2590 except JSONRPCException as ex: 2591 print(ex.message) 2592 print("**STATUS=1", flush=True) 2593 exit(0) 2594 elif args.dry_run: 2595 args.client = dry_run_client() 2596 print_dict = null_print 2597 print_json = null_print 2598 print_array = null_print 2599 else: 2600 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, 2601 log_level=getattr(logging, args.verbose.upper()), 2602 conn_retries=args.conn_retries) 2603 if hasattr(args, 'func'): 2604 try: 2605 call_rpc_func(args) 2606 except JSONRPCException as ex: 2607 print(ex.message) 2608 exit(1) 2609 else: 2610 execute_script(parser, args.client, sys.stdin) 2611