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 acceptor_backlog=args.acceptor_backlog, 1731 abort_timeout_sec=args.abort_timeout_sec) 1732 1733 p = subparsers.add_parser('nvmf_create_transport', help='Create NVMf transport') 1734 p.add_argument('-t', '--trtype', help='Transport type (ex. RDMA)', type=str, required=True) 1735 p.add_argument('-g', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1736 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int) 1737 p.add_argument('-p', '--max-qpairs-per-ctrlr', help="""Max number of SQ and CQ per controller. 1738 Deprecated, use max-io-qpairs-per-ctrlr""", type=int) 1739 p.add_argument('-m', '--max-io-qpairs-per-ctrlr', help='Max number of IO qpairs per controller', type=int) 1740 p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int) 1741 p.add_argument('-i', '--max-io-size', help='Max I/O size (bytes)', type=int) 1742 p.add_argument('-u', '--io-unit-size', help='I/O unit size (bytes)', type=int) 1743 p.add_argument('-a', '--max-aq-depth', help='Max number of admin cmds per AQ', type=int) 1744 p.add_argument('-n', '--num-shared-buffers', help='The number of pooled data buffers available to the transport', type=int) 1745 p.add_argument('-b', '--buf-cache-size', help='The number of shared buffers to reserve for each poll group', type=int) 1746 p.add_argument('-s', '--max-srq-depth', help='Max number of outstanding I/O per SRQ. Relevant only for RDMA transport', type=int) 1747 p.add_argument('-r', '--no-srq', action='store_true', help='Disable per-thread shared receive queue. Relevant only for RDMA transport') 1748 p.add_argument('-o', '--c2h-success', action='store_false', help='Disable C2H success optimization. Relevant only for TCP transport') 1749 p.add_argument('-f', '--dif-insert-or-strip', action='store_true', help='Enable DIF insert/strip. Relevant only for TCP transport') 1750 p.add_argument('-y', '--sock-priority', help='The sock priority of the tcp connection. Relevant only for TCP transport', type=int) 1751 p.add_argument('-l', '--acceptor_backlog', help='Pending connections allowed at one time. Relevant only for RDMA transport', type=int) 1752 p.add_argument('-x', '--abort-timeout-sec', help='Abort execution timeout value, in seconds', type=int) 1753 p.set_defaults(func=nvmf_create_transport) 1754 1755 def nvmf_get_transports(args): 1756 print_dict(rpc.nvmf.nvmf_get_transports(args.client, tgt_name=args.tgt_name)) 1757 1758 p = subparsers.add_parser('nvmf_get_transports', aliases=['get_nvmf_transports'], 1759 help='Display nvmf transports') 1760 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1761 p.set_defaults(func=nvmf_get_transports) 1762 1763 def nvmf_get_subsystems(args): 1764 print_dict(rpc.nvmf.nvmf_get_subsystems(args.client, tgt_name=args.tgt_name)) 1765 1766 p = subparsers.add_parser('nvmf_get_subsystems', aliases=['get_nvmf_subsystems'], 1767 help='Display nvmf subsystems') 1768 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1769 p.set_defaults(func=nvmf_get_subsystems) 1770 1771 def nvmf_create_subsystem(args): 1772 rpc.nvmf.nvmf_create_subsystem(args.client, 1773 nqn=args.nqn, 1774 tgt_name=args.tgt_name, 1775 serial_number=args.serial_number, 1776 model_number=args.model_number, 1777 allow_any_host=args.allow_any_host, 1778 max_namespaces=args.max_namespaces) 1779 1780 p = subparsers.add_parser('nvmf_create_subsystem', aliases=['nvmf_subsystem_create'], 1781 help='Create an NVMe-oF subsystem') 1782 p.add_argument('nqn', help='Subsystem NQN (ASCII)') 1783 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1784 p.add_argument("-s", "--serial-number", help=""" 1785 Format: 'sn' etc 1786 Example: 'SPDK00000000000001'""", default='00000000000000000000') 1787 p.add_argument("-d", "--model-number", help=""" 1788 Format: 'mn' etc 1789 Example: 'SPDK Controller'""", default='SPDK bdev Controller') 1790 p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce host NQN whitelist)") 1791 p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed", 1792 type=int, default=0) 1793 p.set_defaults(func=nvmf_create_subsystem) 1794 1795 def nvmf_delete_subsystem(args): 1796 rpc.nvmf.nvmf_delete_subsystem(args.client, 1797 nqn=args.subsystem_nqn, 1798 tgt_name=args.tgt_name) 1799 1800 p = subparsers.add_parser('nvmf_delete_subsystem', aliases=['delete_nvmf_subsystem'], 1801 help='Delete a nvmf subsystem') 1802 p.add_argument('subsystem_nqn', 1803 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 1804 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1805 p.set_defaults(func=nvmf_delete_subsystem) 1806 1807 def nvmf_subsystem_add_listener(args): 1808 rpc.nvmf.nvmf_subsystem_add_listener(args.client, 1809 nqn=args.nqn, 1810 trtype=args.trtype, 1811 traddr=args.traddr, 1812 tgt_name=args.tgt_name, 1813 adrfam=args.adrfam, 1814 trsvcid=args.trsvcid) 1815 1816 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 1817 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1818 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1819 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1820 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1821 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1822 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1823 p.set_defaults(func=nvmf_subsystem_add_listener) 1824 1825 def nvmf_subsystem_remove_listener(args): 1826 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, 1827 nqn=args.nqn, 1828 trtype=args.trtype, 1829 traddr=args.traddr, 1830 tgt_name=args.tgt_name, 1831 adrfam=args.adrfam, 1832 trsvcid=args.trsvcid) 1833 1834 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 1835 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1836 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1837 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1838 p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1839 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1840 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1841 p.set_defaults(func=nvmf_subsystem_remove_listener) 1842 1843 def nvmf_subsystem_add_ns(args): 1844 rpc.nvmf.nvmf_subsystem_add_ns(args.client, 1845 nqn=args.nqn, 1846 bdev_name=args.bdev_name, 1847 tgt_name=args.tgt_name, 1848 ptpl_file=args.ptpl_file, 1849 nsid=args.nsid, 1850 nguid=args.nguid, 1851 eui64=args.eui64, 1852 uuid=args.uuid) 1853 1854 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 1855 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1856 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 1857 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1858 p.add_argument('-p', '--ptpl-file', help='The persistent reservation storage location (optional)', type=str) 1859 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 1860 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 1861 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 1862 p.add_argument('-u', '--uuid', help='Namespace UUID (optional)') 1863 p.set_defaults(func=nvmf_subsystem_add_ns) 1864 1865 def nvmf_subsystem_remove_ns(args): 1866 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, 1867 nqn=args.nqn, 1868 nsid=args.nsid, 1869 tgt_name=args.tgt_name) 1870 1871 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 1872 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1873 p.add_argument('nsid', help='The requested NSID', type=int) 1874 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1875 p.set_defaults(func=nvmf_subsystem_remove_ns) 1876 1877 def nvmf_subsystem_add_host(args): 1878 rpc.nvmf.nvmf_subsystem_add_host(args.client, 1879 nqn=args.nqn, 1880 host=args.host, 1881 tgt_name=args.tgt_name) 1882 1883 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 1884 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1885 p.add_argument('host', help='Host NQN to allow') 1886 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1887 p.set_defaults(func=nvmf_subsystem_add_host) 1888 1889 def nvmf_subsystem_remove_host(args): 1890 rpc.nvmf.nvmf_subsystem_remove_host(args.client, 1891 nqn=args.nqn, 1892 host=args.host, 1893 tgt_name=args.tgt_name) 1894 1895 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 1896 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1897 p.add_argument('host', help='Host NQN to remove') 1898 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1899 p.set_defaults(func=nvmf_subsystem_remove_host) 1900 1901 def nvmf_subsystem_allow_any_host(args): 1902 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, 1903 nqn=args.nqn, 1904 disable=args.disable, 1905 tgt_name=args.tgt_name) 1906 1907 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 1908 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1909 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 1910 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 1911 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1912 p.set_defaults(func=nvmf_subsystem_allow_any_host) 1913 1914 def nvmf_get_stats(args): 1915 print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name)) 1916 1917 p = subparsers.add_parser( 1918 'nvmf_get_stats', help='Display current statistics for NVMf subsystem') 1919 p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str) 1920 p.set_defaults(func=nvmf_get_stats) 1921 1922 # pmem 1923 def bdev_pmem_create_pool(args): 1924 num_blocks = int((args.total_size * 1024 * 1024) / args.block_size) 1925 rpc.pmem.bdev_pmem_create_pool(args.client, 1926 pmem_file=args.pmem_file, 1927 num_blocks=num_blocks, 1928 block_size=args.block_size) 1929 1930 p = subparsers.add_parser('bdev_pmem_create_pool', aliases=['create_pmem_pool'], 1931 help='Create pmem pool') 1932 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1933 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 1934 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 1935 p.set_defaults(func=bdev_pmem_create_pool) 1936 1937 def bdev_pmem_get_pool_info(args): 1938 print_dict(rpc.pmem.bdev_pmem_get_pool_info(args.client, 1939 pmem_file=args.pmem_file)) 1940 1941 p = subparsers.add_parser('bdev_pmem_get_pool_info', aliases=['pmem_pool_info'], 1942 help='Display pmem pool info and check consistency') 1943 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1944 p.set_defaults(func=bdev_pmem_get_pool_info) 1945 1946 def bdev_pmem_delete_pool(args): 1947 rpc.pmem.bdev_pmem_delete_pool(args.client, 1948 pmem_file=args.pmem_file) 1949 1950 p = subparsers.add_parser('bdev_pmem_delete_pool', aliases=['delete_pmem_pool'], 1951 help='Delete pmem pool') 1952 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1953 p.set_defaults(func=bdev_pmem_delete_pool) 1954 1955 # subsystem 1956 def framework_get_subsystems(args): 1957 print_dict(rpc.subsystem.framework_get_subsystems(args.client)) 1958 1959 p = subparsers.add_parser('framework_get_subsystems', aliases=['get_subsystems'], 1960 help="""Print subsystems array in initialization order. Each subsystem 1961 entry contain (unsorted) array of subsystems it depends on.""") 1962 p.set_defaults(func=framework_get_subsystems) 1963 1964 def framework_get_config(args): 1965 print_dict(rpc.subsystem.framework_get_config(args.client, args.name)) 1966 1967 p = subparsers.add_parser('framework_get_config', aliases=['get_subsystem_config'], 1968 help="""Print subsystem configuration""") 1969 p.add_argument('name', help='Name of subsystem to query') 1970 p.set_defaults(func=framework_get_config) 1971 1972 # vhost 1973 def vhost_controller_set_coalescing(args): 1974 rpc.vhost.vhost_controller_set_coalescing(args.client, 1975 ctrlr=args.ctrlr, 1976 delay_base_us=args.delay_base_us, 1977 iops_threshold=args.iops_threshold) 1978 1979 p = subparsers.add_parser('vhost_controller_set_coalescing', aliases=['set_vhost_controller_coalescing'], 1980 help='Set vhost controller coalescing') 1981 p.add_argument('ctrlr', help='controller name') 1982 p.add_argument('delay_base_us', help='Base delay time', type=int) 1983 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 1984 p.set_defaults(func=vhost_controller_set_coalescing) 1985 1986 def vhost_create_scsi_controller(args): 1987 rpc.vhost.vhost_create_scsi_controller(args.client, 1988 ctrlr=args.ctrlr, 1989 cpumask=args.cpumask) 1990 1991 p = subparsers.add_parser( 1992 'vhost_create_scsi_controller', aliases=['construct_vhost_scsi_controller'], 1993 help='Add new vhost controller') 1994 p.add_argument('ctrlr', help='controller name') 1995 p.add_argument('--cpumask', help='cpu mask for this controller') 1996 p.set_defaults(func=vhost_create_scsi_controller) 1997 1998 def vhost_scsi_controller_add_target(args): 1999 print_json(rpc.vhost.vhost_scsi_controller_add_target(args.client, 2000 ctrlr=args.ctrlr, 2001 scsi_target_num=args.scsi_target_num, 2002 bdev_name=args.bdev_name)) 2003 2004 p = subparsers.add_parser('vhost_scsi_controller_add_target', 2005 aliases=['add_vhost_scsi_lun'], 2006 help='Add lun to vhost controller') 2007 p.add_argument('ctrlr', help='conntroller name where add lun') 2008 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 2009 p.add_argument('bdev_name', help='bdev name') 2010 p.set_defaults(func=vhost_scsi_controller_add_target) 2011 2012 def vhost_scsi_controller_remove_target(args): 2013 rpc.vhost.vhost_scsi_controller_remove_target(args.client, 2014 ctrlr=args.ctrlr, 2015 scsi_target_num=args.scsi_target_num) 2016 2017 p = subparsers.add_parser('vhost_scsi_controller_remove_target', 2018 aliases=['remove_vhost_scsi_target'], 2019 help='Remove target from vhost controller') 2020 p.add_argument('ctrlr', help='controller name to remove target from') 2021 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 2022 p.set_defaults(func=vhost_scsi_controller_remove_target) 2023 2024 def vhost_create_blk_controller(args): 2025 rpc.vhost.vhost_create_blk_controller(args.client, 2026 ctrlr=args.ctrlr, 2027 dev_name=args.dev_name, 2028 cpumask=args.cpumask, 2029 readonly=args.readonly, 2030 packed_ring=args.packed_ring) 2031 2032 p = subparsers.add_parser('vhost_create_blk_controller', 2033 aliases=['construct_vhost_blk_controller'], 2034 help='Add a new vhost block controller') 2035 p.add_argument('ctrlr', help='controller name') 2036 p.add_argument('dev_name', help='device name') 2037 p.add_argument('--cpumask', help='cpu mask for this controller') 2038 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 2039 p.add_argument("-p", "--packed_ring", action='store_true', help='Set controller as packed ring supported') 2040 p.set_defaults(func=vhost_create_blk_controller) 2041 2042 def vhost_create_nvme_controller(args): 2043 rpc.vhost.vhost_create_nvme_controller(args.client, 2044 ctrlr=args.ctrlr, 2045 io_queues=args.io_queues, 2046 cpumask=args.cpumask) 2047 2048 p = subparsers.add_parser('vhost_create_nvme_controller', aliases=['vhost_create_nvme_controller'], 2049 help='Add new vhost controller') 2050 p.add_argument('ctrlr', help='controller name') 2051 p.add_argument('io_queues', help='number of IO queues for the controller', type=int) 2052 p.add_argument('--cpumask', help='cpu mask for this controller') 2053 p.set_defaults(func=vhost_create_nvme_controller) 2054 2055 def vhost_nvme_controller_add_ns(args): 2056 rpc.vhost.vhost_nvme_controller_add_ns(args.client, 2057 ctrlr=args.ctrlr, 2058 bdev_name=args.bdev_name) 2059 2060 p = subparsers.add_parser('vhost_nvme_controller_add_ns', aliases=['add_vhost_nvme_ns'], 2061 help='Add a Namespace to vhost controller') 2062 p.add_argument('ctrlr', help='conntroller name where add a Namespace') 2063 p.add_argument('bdev_name', help='block device name for a new Namespace') 2064 p.set_defaults(func=vhost_nvme_controller_add_ns) 2065 2066 def vhost_get_controllers(args): 2067 print_dict(rpc.vhost.vhost_get_controllers(args.client, args.name)) 2068 2069 p = subparsers.add_parser('vhost_get_controllers', aliases=['get_vhost_controllers'], 2070 help='List all or specific vhost controller(s)') 2071 p.add_argument('-n', '--name', help="Name of vhost controller", required=False) 2072 p.set_defaults(func=vhost_get_controllers) 2073 2074 def vhost_delete_controller(args): 2075 rpc.vhost.vhost_delete_controller(args.client, 2076 ctrlr=args.ctrlr) 2077 2078 p = subparsers.add_parser('vhost_delete_controller', aliases=['remove_vhost_controller'], 2079 help='Delete a vhost controller') 2080 p.add_argument('ctrlr', help='controller name') 2081 p.set_defaults(func=vhost_delete_controller) 2082 2083 def bdev_virtio_attach_controller(args): 2084 print_array(rpc.vhost.bdev_virtio_attach_controller(args.client, 2085 name=args.name, 2086 trtype=args.trtype, 2087 traddr=args.traddr, 2088 dev_type=args.dev_type, 2089 vq_count=args.vq_count, 2090 vq_size=args.vq_size)) 2091 2092 p = subparsers.add_parser('bdev_virtio_attach_controller', aliases=['construct_virtio_dev'], 2093 help="""Attach virtio controller using provided 2094 transport type and device type. This will also create bdevs for any block devices connected to the 2095 controller (for example, SCSI devices for a virtio-scsi controller). 2096 Result is array of added bdevs.""") 2097 p.add_argument('name', help="Use this name as base for new created bdevs") 2098 p.add_argument('-t', '--trtype', 2099 help='Virtio target transport type: pci or user', required=True) 2100 p.add_argument('-a', '--traddr', 2101 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 2102 p.add_argument('-d', '--dev-type', 2103 help='Device type: blk or scsi', required=True) 2104 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 2105 p.add_argument('--vq-size', help='Size of each queue', type=int) 2106 p.set_defaults(func=bdev_virtio_attach_controller) 2107 2108 def bdev_virtio_scsi_get_devices(args): 2109 print_dict(rpc.vhost.bdev_virtio_scsi_get_devices(args.client)) 2110 2111 p = subparsers.add_parser('bdev_virtio_scsi_get_devices', aliases=['get_virtio_scsi_devs'], 2112 help='List all Virtio-SCSI devices.') 2113 p.set_defaults(func=bdev_virtio_scsi_get_devices) 2114 2115 def bdev_virtio_detach_controller(args): 2116 rpc.vhost.bdev_virtio_detach_controller(args.client, 2117 name=args.name) 2118 2119 p = subparsers.add_parser('bdev_virtio_detach_controller', aliases=['remove_virtio_bdev'], 2120 help="""Remove a Virtio device 2121 This will delete all bdevs exposed by this device""") 2122 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 2123 p.set_defaults(func=bdev_virtio_detach_controller) 2124 2125 # OCSSD 2126 def bdev_ocssd_create(args): 2127 nsid = int(args.nsid) if args.nsid is not None else None 2128 print_json(rpc.bdev.bdev_ocssd_create(args.client, 2129 ctrlr_name=args.ctrlr_name, 2130 bdev_name=args.name, 2131 nsid=nsid, 2132 range=args.range)) 2133 2134 p = subparsers.add_parser('bdev_ocssd_create', 2135 help='Creates zoned bdev on specified Open Channel controller') 2136 p.add_argument('-c', '--ctrlr_name', help='Name of the OC NVMe controller', required=True) 2137 p.add_argument('-b', '--name', help='Name of the bdev to create', required=True) 2138 p.add_argument('-n', '--nsid', help='Namespace ID', required=False) 2139 p.add_argument('-r', '--range', help='Parallel unit range (in the form of BEGIN-END (inclusive))', 2140 required=False) 2141 p.set_defaults(func=bdev_ocssd_create) 2142 2143 def bdev_ocssd_delete(args): 2144 print_json(rpc.bdev.bdev_ocssd_delete(args.client, 2145 name=args.name)) 2146 2147 p = subparsers.add_parser('bdev_ocssd_delete', 2148 help='Deletes Open Channel bdev') 2149 p.add_argument('name', help='Name of the Open Channel bdev') 2150 p.set_defaults(func=bdev_ocssd_delete) 2151 2152 # ioat 2153 def ioat_scan_accel_engine(args): 2154 pci_whitelist = [] 2155 if args.pci_whitelist: 2156 for w in args.pci_whitelist.strip().split(" "): 2157 pci_whitelist.append(w) 2158 rpc.ioat.ioat_scan_accel_engine(args.client, pci_whitelist) 2159 2160 p = subparsers.add_parser('ioat_scan_accel_engine', 2161 aliases=['ioat_scan_copy_engine', 'scan_ioat_copy_engine'], 2162 help='Set scan and enable IOAT accel engine offload.') 2163 p.add_argument('-w', '--pci-whitelist', help="""Whitespace-separated list of PCI addresses in 2164 domain:bus:device.function format or domain.bus.device.function format""") 2165 p.set_defaults(func=ioat_scan_accel_engine) 2166 2167 # idxd 2168 def idxd_scan_accel_engine(args): 2169 rpc.idxd.idxd_scan_accel_engine(args.client, config_number=args.config_number) 2170 2171 p = subparsers.add_parser('idxd_scan_accel_engine', 2172 help='Set config and enable idxd accel engine offload.') 2173 p.add_argument('-c', '--config-number', help="""Pre-defined configuration number to use. See docs.""", type=int) 2174 p.set_defaults(func=idxd_scan_accel_engine) 2175 2176 # opal 2177 def bdev_nvme_opal_init(args): 2178 rpc.nvme.bdev_nvme_opal_init(args.client, 2179 nvme_ctrlr_name=args.nvme_ctrlr_name, 2180 password=args.password) 2181 2182 p = subparsers.add_parser('bdev_nvme_opal_init', help='take ownership and activate') 2183 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2184 p.add_argument('-p', '--password', help='password for admin') 2185 p.set_defaults(func=bdev_nvme_opal_init) 2186 2187 def bdev_nvme_opal_revert(args): 2188 rpc.nvme.bdev_nvme_opal_revert(args.client, 2189 nvme_ctrlr_name=args.nvme_ctrlr_name, 2190 password=args.password) 2191 p = subparsers.add_parser('bdev_nvme_opal_revert', help='Revert to default factory settings') 2192 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name') 2193 p.add_argument('-p', '--password', help='password') 2194 p.set_defaults(func=bdev_nvme_opal_revert) 2195 2196 def bdev_opal_create(args): 2197 print_json(rpc.bdev.bdev_opal_create(args.client, 2198 nvme_ctrlr_name=args.nvme_ctrlr_name, 2199 nsid=args.nsid, 2200 locking_range_id=args.locking_range_id, 2201 range_start=args.range_start, 2202 range_length=args.range_length, 2203 password=args.password)) 2204 2205 p = subparsers.add_parser('bdev_opal_create', help="""Create opal bdev on specified NVMe controller""") 2206 p.add_argument('-b', '--nvme-ctrlr-name', help='nvme ctrlr name', required=True) 2207 p.add_argument('-n', '--nsid', help='namespace ID (only support nsid=1 for now)', type=int, required=True) 2208 p.add_argument('-i', '--locking-range-id', help='locking range id', type=int, required=True) 2209 p.add_argument('-s', '--range-start', help='locking range start LBA', type=int, required=True) 2210 p.add_argument('-l', '--range-length', help='locking range length (in blocks)', type=int, required=True) 2211 p.add_argument('-p', '--password', help='admin password', required=True) 2212 p.set_defaults(func=bdev_opal_create) 2213 2214 def bdev_opal_get_info(args): 2215 print_dict(rpc.bdev.bdev_opal_get_info(args.client, 2216 bdev_name=args.bdev_name, 2217 password=args.password)) 2218 2219 p = subparsers.add_parser('bdev_opal_get_info', help='get opal locking range info for this bdev') 2220 p.add_argument('-b', '--bdev-name', help='opal bdev') 2221 p.add_argument('-p', '--password', help='password') 2222 p.set_defaults(func=bdev_opal_get_info) 2223 2224 def bdev_opal_delete(args): 2225 rpc.bdev.bdev_opal_delete(args.client, 2226 bdev_name=args.bdev_name, 2227 password=args.password) 2228 2229 p = subparsers.add_parser('bdev_opal_delete', help="""delete a virtual opal bdev""") 2230 p.add_argument('-b', '--bdev-name', help='opal virtual bdev', required=True) 2231 p.add_argument('-p', '--password', help='admin password', required=True) 2232 p.set_defaults(func=bdev_opal_delete) 2233 2234 def bdev_opal_new_user(args): 2235 rpc.bdev.bdev_opal_new_user(args.client, 2236 bdev_name=args.bdev_name, 2237 admin_password=args.admin_password, 2238 user_id=args.user_id, 2239 user_password=args.user_password) 2240 2241 p = subparsers.add_parser('bdev_opal_new_user', help="""Add a user to opal bdev who can set lock state for this bdev""") 2242 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2243 p.add_argument('-p', '--admin-password', help='admin password', required=True) 2244 p.add_argument('-i', '--user-id', help='ID for new user', type=int, required=True) 2245 p.add_argument('-u', '--user-password', help='password set for this user', required=True) 2246 p.set_defaults(func=bdev_opal_new_user) 2247 2248 def bdev_opal_set_lock_state(args): 2249 rpc.bdev.bdev_opal_set_lock_state(args.client, 2250 bdev_name=args.bdev_name, 2251 user_id=args.user_id, 2252 password=args.password, 2253 lock_state=args.lock_state) 2254 2255 p = subparsers.add_parser('bdev_opal_set_lock_state', help="""set lock state for an opal bdev""") 2256 p.add_argument('-b', '--bdev-name', help='opal bdev', required=True) 2257 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', 2258 type=int, required=True) 2259 p.add_argument('-p', '--password', help='password of this user', required=True) 2260 p.add_argument('-l', '--lock-state', help='lock state to set, choose from {readwrite, readonly, rwlock}', required=True) 2261 p.set_defaults(func=bdev_opal_set_lock_state) 2262 2263 # bdev_nvme_send_cmd 2264 def bdev_nvme_send_cmd(args): 2265 print_dict(rpc.nvme.bdev_nvme_send_cmd(args.client, 2266 name=args.nvme_name, 2267 cmd_type=args.cmd_type, 2268 data_direction=args.data_direction, 2269 cmdbuf=args.cmdbuf, 2270 data=args.data, 2271 metadata=args.metadata, 2272 data_len=args.data_length, 2273 metadata_len=args.metadata_length, 2274 timeout_ms=args.timeout_ms)) 2275 2276 p = subparsers.add_parser('bdev_nvme_send_cmd', aliases=['send_nvme_cmd'], 2277 help='NVMe passthrough cmd.') 2278 p.add_argument('-n', '--nvme-name', help="""Name of the operating NVMe controller""") 2279 p.add_argument('-t', '--cmd-type', help="""Type of nvme cmd. Valid values are: admin, io""") 2280 p.add_argument('-r', '--data-direction', help="""Direction of data transfer. Valid values are: c2h, h2c""") 2281 p.add_argument('-c', '--cmdbuf', help="""NVMe command encoded by base64 urlsafe""") 2282 p.add_argument('-d', '--data', help="""Data transferring to controller from host, encoded by base64 urlsafe""") 2283 p.add_argument('-m', '--metadata', help="""Metadata transferring to controller from host, encoded by base64 urlsafe""") 2284 p.add_argument('-D', '--data-length', help="""Data length required to transfer from controller to host""", type=int) 2285 p.add_argument('-M', '--metadata-length', help="""Metadata length required to transfer from controller to host""", type=int) 2286 p.add_argument('-T', '--timeout-ms', 2287 help="""Command execution timeout value, in milliseconds, if 0, don't track timeout""", type=int, default=0) 2288 p.set_defaults(func=bdev_nvme_send_cmd) 2289 2290 # Notifications 2291 def notify_get_types(args): 2292 print_dict(rpc.notify.notify_get_types(args.client)) 2293 2294 p = subparsers.add_parser('notify_get_types', aliases=['get_notification_types'], 2295 help='List available notifications that user can subscribe to.') 2296 p.set_defaults(func=notify_get_types) 2297 2298 def notify_get_notifications(args): 2299 ret = rpc.notify.notify_get_notifications(args.client, 2300 id=args.id, 2301 max=args.max) 2302 print_dict(ret) 2303 2304 p = subparsers.add_parser('notify_get_notifications', aliases=['get_notifications'], 2305 help='Get notifications') 2306 p.add_argument('-i', '--id', help="""First ID to start fetching from""", type=int) 2307 p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int) 2308 p.set_defaults(func=notify_get_notifications) 2309 2310 def thread_get_stats(args): 2311 print_dict(rpc.app.thread_get_stats(args.client)) 2312 2313 p = subparsers.add_parser( 2314 'thread_get_stats', help='Display current statistics of all the threads') 2315 p.set_defaults(func=thread_get_stats) 2316 2317 def thread_set_cpumask(args): 2318 ret = rpc.app.thread_set_cpumask(args.client, 2319 id=args.id, 2320 cpumask=args.cpumask) 2321 p = subparsers.add_parser('thread_set_cpumask', 2322 help="""set the cpumask of the thread whose ID matches to the 2323 specified value. The thread may be migrated to one of the specified CPUs.""") 2324 p.add_argument('-i', '--id', type=int, help='thread ID') 2325 p.add_argument('-m', '--cpumask', help='cpumask for this thread') 2326 p.set_defaults(func=thread_set_cpumask) 2327 2328 def thread_get_pollers(args): 2329 print_dict(rpc.app.thread_get_pollers(args.client)) 2330 2331 p = subparsers.add_parser( 2332 'thread_get_pollers', help='Display current pollers of all the threads') 2333 p.set_defaults(func=thread_get_pollers) 2334 2335 def thread_get_io_channels(args): 2336 print_dict(rpc.app.thread_get_io_channels(args.client)) 2337 2338 p = subparsers.add_parser( 2339 'thread_get_io_channels', help='Display current IO channels of all the threads') 2340 p.set_defaults(func=thread_get_io_channels) 2341 2342 def env_dpdk_get_mem_stats(args): 2343 print_dict(rpc.env_dpdk.env_dpdk_get_mem_stats(args.client)) 2344 2345 p = subparsers.add_parser( 2346 'env_dpdk_get_mem_stats', help='write the dpdk memory stats to a file.') 2347 p.set_defaults(func=env_dpdk_get_mem_stats) 2348 2349 # blobfs 2350 def blobfs_detect(args): 2351 print(rpc.blobfs.blobfs_detect(args.client, 2352 bdev_name=args.bdev_name)) 2353 2354 p = subparsers.add_parser('blobfs_detect', help='Detect whether a blobfs exists on bdev') 2355 p.add_argument('bdev_name', help='Blockdev name to detect blobfs. Example: Malloc0.') 2356 p.set_defaults(func=blobfs_detect) 2357 2358 def blobfs_create(args): 2359 print(rpc.blobfs.blobfs_create(args.client, 2360 bdev_name=args.bdev_name, 2361 cluster_sz=args.cluster_sz)) 2362 2363 p = subparsers.add_parser('blobfs_create', help='Build a blobfs on bdev') 2364 p.add_argument('bdev_name', help='Blockdev name to build blobfs. Example: Malloc0.') 2365 p.add_argument('-c', '--cluster_sz', 2366 help="""Size of cluster in bytes (Optional). Must be multiple of 4KB page size. Default and minimal value is 1M.""") 2367 p.set_defaults(func=blobfs_create) 2368 2369 def blobfs_mount(args): 2370 print(rpc.blobfs.blobfs_mount(args.client, 2371 bdev_name=args.bdev_name, 2372 mountpoint=args.mountpoint)) 2373 2374 p = subparsers.add_parser('blobfs_mount', help='Mount a blobfs on bdev to host path by FUSE') 2375 p.add_argument('bdev_name', help='Blockdev name where the blobfs is. Example: Malloc0.') 2376 p.add_argument('mountpoint', help='Mountpoint path in host to mount blobfs. Example: /mnt/.') 2377 p.set_defaults(func=blobfs_mount) 2378 2379 def blobfs_set_cache_size(args): 2380 print(rpc.blobfs.blobfs_set_cache_size(args.client, 2381 size_in_mb=args.size_in_mb)) 2382 2383 p = subparsers.add_parser('blobfs_set_cache_size', help='Set cache size for blobfs') 2384 p.add_argument('size_in_mb', help='Cache size for blobfs in megabytes.', type=int) 2385 p.set_defaults(func=blobfs_set_cache_size) 2386 2387 # sock 2388 def sock_impl_get_options(args): 2389 print_json(rpc.sock.sock_impl_get_options(args.client, 2390 impl_name=args.impl)) 2391 2392 p = subparsers.add_parser('sock_impl_get_options', help="""Get options of socket layer implementation""") 2393 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2394 p.set_defaults(func=sock_impl_get_options) 2395 2396 def sock_impl_set_options(args): 2397 rpc.sock.sock_impl_set_options(args.client, 2398 impl_name=args.impl, 2399 recv_buf_size=args.recv_buf_size, 2400 send_buf_size=args.send_buf_size, 2401 enable_recv_pipe=args.enable_recv_pipe, 2402 enable_zerocopy_send=args.enable_zerocopy_send) 2403 2404 p = subparsers.add_parser('sock_impl_set_options', help="""Set options of socket layer implementation""") 2405 p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) 2406 p.add_argument('-r', '--recv-buf-size', help='Size of receive buffer on socket in bytes', type=int) 2407 p.add_argument('-s', '--send-buf-size', help='Size of send buffer on socket in bytes', type=int) 2408 p.add_argument('--enable-recv-pipe', help='Enable receive pipe', 2409 action='store_true', dest='enable_recv_pipe') 2410 p.add_argument('--disable-recv-pipe', help='Disable receive pipe', 2411 action='store_false', dest='enable_recv_pipe') 2412 p.add_argument('--enable-zerocopy-send', help='Enable zerocopy on send', 2413 action='store_true', dest='enable_zerocopy_send') 2414 p.add_argument('--disable-zerocopy-send', help='Disable zerocopy on send', 2415 action='store_false', dest='enable_zerocopy_send') 2416 p.set_defaults(func=sock_impl_set_options, enable_recv_pipe=None, enable_zerocopy_send=None) 2417 2418 def check_called_name(name): 2419 if name in deprecated_aliases: 2420 print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr) 2421 2422 class dry_run_client: 2423 def call(self, method, params=None): 2424 print("Request:\n" + json.dumps({"method": method, "params": params}, indent=2)) 2425 2426 def null_print(arg): 2427 pass 2428 2429 def call_rpc_func(args): 2430 args.func(args) 2431 check_called_name(args.called_rpc_name) 2432 2433 def execute_script(parser, client, fd): 2434 executed_rpc = "" 2435 for rpc_call in map(str.rstrip, fd): 2436 if not rpc_call.strip(): 2437 continue 2438 executed_rpc = "\n".join([executed_rpc, rpc_call]) 2439 args = parser.parse_args(shlex.split(rpc_call)) 2440 args.client = client 2441 try: 2442 call_rpc_func(args) 2443 except JSONRPCException as ex: 2444 print("Exception:") 2445 print(executed_rpc.strip() + " <<<") 2446 print(ex.message) 2447 exit(1) 2448 2449 # Create temporary parser, pull out the plugin parameter, load the module, and then run the real argument parser 2450 plugin_parser = argparse.ArgumentParser(add_help=False) 2451 plugin_parser.add_argument('--plugin', dest='rpc_plugin', help='Module name of plugin with additional RPC commands') 2452 2453 rpc_module = plugin_parser.parse_known_args()[0].rpc_plugin 2454 if rpc_module is not None: 2455 try: 2456 rpc_plugin = importlib.import_module(rpc_module) 2457 try: 2458 rpc_plugin.spdk_rpc_plugin_initialize(subparsers) 2459 except AttributeError: 2460 print("Module %s does not contain 'spdk_rpc_plugin_initialize' function" % rpc_module) 2461 except ModuleNotFoundError: 2462 print("Module %s not found" % rpc_module) 2463 2464 args = parser.parse_args() 2465 2466 if sys.stdin.isatty() and not hasattr(args, 'func'): 2467 # No arguments and no data piped through stdin 2468 parser.print_help() 2469 exit(1) 2470 if args.is_server: 2471 for input in sys.stdin: 2472 cmd = shlex.split(input) 2473 try: 2474 tmp_args = parser.parse_args(cmd) 2475 except SystemExit as ex: 2476 print("**STATUS=1", flush=True) 2477 continue 2478 2479 try: 2480 tmp_args.client = rpc.client.JSONRPCClient( 2481 tmp_args.server_addr, tmp_args.port, tmp_args.timeout, 2482 log_level=getattr(logging, tmp_args.verbose.upper()), conn_retries=tmp_args.conn_retries) 2483 call_rpc_func(tmp_args) 2484 print("**STATUS=0", flush=True) 2485 except JSONRPCException as ex: 2486 print(ex.message) 2487 print("**STATUS=1", flush=True) 2488 exit(0) 2489 elif args.dry_run: 2490 args.client = dry_run_client() 2491 print_dict = null_print 2492 print_json = null_print 2493 print_array = null_print 2494 else: 2495 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, 2496 log_level=getattr(logging, args.verbose.upper()), 2497 conn_retries=args.conn_retries) 2498 if hasattr(args, 'func'): 2499 try: 2500 call_rpc_func(args) 2501 except JSONRPCException as ex: 2502 print(ex.message) 2503 exit(1) 2504 else: 2505 execute_script(parser, args.client, sys.stdin) 2506