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