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