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