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