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