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