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