1#!/usr/bin/env python3 2 3from rpc.client import print_dict, print_string, 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 start_subsystem_init(args): 43 rpc.start_subsystem_init(args.client) 44 45 p = subparsers.add_parser('start_subsystem_init', help='Start initialization of subsystems') 46 p.set_defaults(func=start_subsystem_init) 47 48 def wait_subsystem_init(args): 49 rpc.wait_subsystem_init(args.client) 50 51 p = subparsers.add_parser('wait_subsystem_init', help='Block until subsystems have been initialized') 52 p.set_defaults(func=wait_subsystem_init) 53 54 def rpc_get_methods(args): 55 print_dict(rpc.rpc_get_methods(args.client, 56 current=args.current)) 57 58 p = subparsers.add_parser('rpc_get_methods', help='Get list of supported RPC methods', aliases=['get_rpc_methods']) 59 p.add_argument('-c', '--current', help='Get list of RPC methods only callable in the current state.', action='store_true') 60 p.set_defaults(func=rpc_get_methods) 61 62 def get_spdk_version(args): 63 print_string(rpc.get_spdk_version(args.client)) 64 65 p = subparsers.add_parser('get_spdk_version', help='Get SPDK version') 66 p.set_defaults(func=get_spdk_version) 67 68 def save_config(args): 69 rpc.save_config(args.client, 70 sys.stdout, 71 indent=args.indent) 72 73 p = subparsers.add_parser('save_config', help="""Write current (live) configuration of SPDK subsystems and targets to stdout. 74 """) 75 p.add_argument('-i', '--indent', help="""Indent level. Value less than 0 mean compact mode. Default indent level is 2. 76 """, type=int, default=2) 77 p.set_defaults(func=save_config) 78 79 def load_config(args): 80 rpc.load_config(args.client, sys.stdin) 81 82 p = subparsers.add_parser('load_config', help="""Configure SPDK subsystems and targets using JSON RPC read from stdin.""") 83 p.set_defaults(func=load_config) 84 85 def save_subsystem_config(args): 86 rpc.save_subsystem_config(args.client, 87 sys.stdout, 88 indent=args.indent, 89 name=args.name) 90 91 p = subparsers.add_parser('save_subsystem_config', help="""Write current (live) configuration of SPDK subsystem to stdout. 92 """) 93 p.add_argument('-i', '--indent', help="""Indent level. Value less than 0 mean compact mode. Default indent level is 2. 94 """, type=int, default=2) 95 p.add_argument('-n', '--name', help='Name of subsystem', required=True) 96 p.set_defaults(func=save_subsystem_config) 97 98 def load_subsystem_config(args): 99 rpc.load_subsystem_config(args.client, 100 sys.stdin) 101 102 p = subparsers.add_parser('load_subsystem_config', help="""Configure SPDK subsystem using JSON RPC read from stdin.""") 103 p.set_defaults(func=load_subsystem_config) 104 105 # app 106 def kill_instance(args): 107 rpc.app.kill_instance(args.client, 108 sig_name=args.sig_name) 109 110 p = subparsers.add_parser('kill_instance', help='Send signal to instance') 111 p.add_argument('sig_name', help='signal will be sent to server.') 112 p.set_defaults(func=kill_instance) 113 114 def context_switch_monitor(args): 115 enabled = None 116 if args.enable: 117 enabled = True 118 if args.disable: 119 enabled = False 120 print_dict(rpc.app.context_switch_monitor(args.client, 121 enabled=enabled)) 122 123 p = subparsers.add_parser('context_switch_monitor', help='Control whether the context switch monitor is enabled') 124 p.add_argument('-e', '--enable', action='store_true', help='Enable context switch monitoring') 125 p.add_argument('-d', '--disable', action='store_true', help='Disable context switch monitoring') 126 p.set_defaults(func=context_switch_monitor) 127 128 # bdev 129 def set_bdev_options(args): 130 rpc.bdev.set_bdev_options(args.client, 131 bdev_io_pool_size=args.bdev_io_pool_size, 132 bdev_io_cache_size=args.bdev_io_cache_size) 133 134 p = subparsers.add_parser('set_bdev_options', help="""Set options of bdev subsystem""") 135 p.add_argument('-p', '--bdev-io-pool-size', help='Number of bdev_io structures in shared buffer pool', type=int) 136 p.add_argument('-c', '--bdev-io-cache-size', help='Maximum number of bdev_io structures cached per thread', type=int) 137 p.set_defaults(func=set_bdev_options) 138 139 def construct_compress_bdev(args): 140 print_string(rpc.bdev.construct_compress_bdev(args.client, 141 base_bdev_name=args.base_bdev_name, 142 pm_path=args.pm_path)) 143 p = subparsers.add_parser('construct_compress_bdev', 144 help='Add a compress vbdev') 145 p.add_argument('-b', '--base_bdev_name', help="Name of the base bdev") 146 p.add_argument('-p', '--pm_path', help="Path to persistent memory") 147 p.set_defaults(func=construct_compress_bdev) 148 149 def delete_compress_bdev(args): 150 rpc.bdev.delete_compress_bdev(args.client, 151 name=args.name) 152 153 p = subparsers.add_parser('delete_compress_bdev', help='Delete a compress disk') 154 p.add_argument('name', help='compress bdev name') 155 p.set_defaults(func=delete_compress_bdev) 156 157 def set_compress_pmd(args): 158 rpc.bdev.set_compress_pmd(args.client, 159 pmd=args.pmd) 160 p = subparsers.add_parser('set_compress_pmd', help='Set pmd option for a compress disk') 161 p.add_argument('-p', '--pmd', type=int, help='0 = auto-select, 1= QAT only, 2 = ISAL only') 162 p.set_defaults(func=set_compress_pmd) 163 164 def construct_crypto_bdev(args): 165 print_string(rpc.bdev.construct_crypto_bdev(args.client, 166 base_bdev_name=args.base_bdev_name, 167 name=args.name, 168 crypto_pmd=args.crypto_pmd, 169 key=args.key)) 170 p = subparsers.add_parser('construct_crypto_bdev', 171 help='Add a crypto vbdev') 172 p.add_argument('-b', '--base_bdev_name', help="Name of the base bdev") 173 p.add_argument('-c', '--name', help="Name of the crypto vbdev") 174 p.add_argument('-d', '--crypto_pmd', help="Name of the crypto device driver") 175 p.add_argument('-k', '--key', help="Key") 176 p.set_defaults(func=construct_crypto_bdev) 177 178 def delete_crypto_bdev(args): 179 rpc.bdev.delete_crypto_bdev(args.client, 180 name=args.name) 181 182 p = subparsers.add_parser('delete_crypto_bdev', help='Delete a crypto disk') 183 p.add_argument('name', help='crypto bdev name') 184 p.set_defaults(func=delete_crypto_bdev) 185 186 def construct_ocf_bdev(args): 187 print_string(rpc.bdev.construct_ocf_bdev(args.client, 188 name=args.name, 189 mode=args.mode, 190 cache_bdev_name=args.cache_bdev_name, 191 core_bdev_name=args.core_bdev_name)) 192 p = subparsers.add_parser('construct_ocf_bdev', 193 help='Add an OCF block device') 194 p.add_argument('name', help='Name of resulting OCF bdev') 195 p.add_argument('mode', help='OCF cache mode', choices=['wb', 'wt', 'pt']) 196 p.add_argument('cache_bdev_name', help='Name of underlying cache bdev') 197 p.add_argument('core_bdev_name', help='Name of unerlying core bdev') 198 p.set_defaults(func=construct_ocf_bdev) 199 200 def delete_ocf_bdev(args): 201 rpc.bdev.delete_ocf_bdev(args.client, 202 name=args.name) 203 204 p = subparsers.add_parser('delete_ocf_bdev', 205 help='Delete an OCF block device') 206 p.add_argument('name', help='Name of OCF bdev') 207 p.set_defaults(func=delete_ocf_bdev) 208 209 def get_ocf_stats(args): 210 print_dict(rpc.bdev.get_ocf_stats(args.client, 211 name=args.name)) 212 p = subparsers.add_parser('get_ocf_stats', 213 help='Get statistics of chosen OCF block device') 214 p.add_argument('name', help='Name of OCF bdev') 215 p.set_defaults(func=get_ocf_stats) 216 217 def get_ocf_bdevs(args): 218 print_dict(rpc.bdev.get_ocf_bdevs(args.client, 219 name=args.name)) 220 p = subparsers.add_parser('get_ocf_bdevs', 221 help='Get list of OCF devices including unregistered ones') 222 p.add_argument('name', nargs='?', default=None, help='name of OCF vbdev or name of cache device or name of core device (optional)') 223 p.set_defaults(func=get_ocf_bdevs) 224 225 def construct_malloc_bdev(args): 226 num_blocks = (args.total_size * 1024 * 1024) // args.block_size 227 print_string(rpc.bdev.construct_malloc_bdev(args.client, 228 num_blocks=int(num_blocks), 229 block_size=args.block_size, 230 name=args.name, 231 uuid=args.uuid)) 232 p = subparsers.add_parser('construct_malloc_bdev', 233 help='Add a bdev with malloc backend') 234 p.add_argument('-b', '--name', help="Name of the bdev") 235 p.add_argument('-u', '--uuid', help="UUID of the bdev") 236 p.add_argument( 237 'total_size', help='Size of malloc bdev in MB (float > 0)', type=float) 238 p.add_argument('block_size', help='Block size for this bdev', type=int) 239 p.set_defaults(func=construct_malloc_bdev) 240 241 def delete_malloc_bdev(args): 242 rpc.bdev.delete_malloc_bdev(args.client, 243 name=args.name) 244 245 p = subparsers.add_parser('delete_malloc_bdev', help='Delete a malloc disk') 246 p.add_argument('name', help='malloc bdev name') 247 p.set_defaults(func=delete_malloc_bdev) 248 249 def construct_null_bdev(args): 250 num_blocks = (args.total_size * 1024 * 1024) // args.block_size 251 print_string(rpc.bdev.construct_null_bdev(args.client, 252 num_blocks=num_blocks, 253 block_size=args.block_size, 254 name=args.name, 255 uuid=args.uuid)) 256 257 p = subparsers.add_parser('construct_null_bdev', 258 help='Add a bdev with null backend') 259 p.add_argument('name', help='Block device name') 260 p.add_argument('-u', '--uuid', help='UUID of the bdev') 261 p.add_argument( 262 'total_size', help='Size of null bdev in MB (int > 0)', type=int) 263 p.add_argument('block_size', help='Block size for this bdev', type=int) 264 p.set_defaults(func=construct_null_bdev) 265 266 def delete_null_bdev(args): 267 rpc.bdev.delete_null_bdev(args.client, 268 name=args.name) 269 270 p = subparsers.add_parser('delete_null_bdev', help='Delete a null bdev') 271 p.add_argument('name', help='null bdev name') 272 p.set_defaults(func=delete_null_bdev) 273 274 def construct_aio_bdev(args): 275 print_string(rpc.bdev.construct_aio_bdev(args.client, 276 filename=args.filename, 277 name=args.name, 278 block_size=args.block_size)) 279 280 p = subparsers.add_parser('construct_aio_bdev', 281 help='Add a bdev with aio backend') 282 p.add_argument('filename', help='Path to device or file (ex: /dev/sda)') 283 p.add_argument('name', help='Block device name') 284 p.add_argument('block_size', help='Block size for this bdev', type=int, nargs='?', default=0) 285 p.set_defaults(func=construct_aio_bdev) 286 287 def delete_aio_bdev(args): 288 rpc.bdev.delete_aio_bdev(args.client, 289 name=args.name) 290 291 p = subparsers.add_parser('delete_aio_bdev', help='Delete an aio disk') 292 p.add_argument('name', help='aio bdev name') 293 p.set_defaults(func=delete_aio_bdev) 294 295 def set_bdev_nvme_options(args): 296 rpc.bdev.set_bdev_nvme_options(args.client, 297 action_on_timeout=args.action_on_timeout, 298 timeout_us=args.timeout_us, 299 retry_count=args.retry_count, 300 nvme_adminq_poll_period_us=args.nvme_adminq_poll_period_us, 301 nvme_ioq_poll_period_us=args.nvme_ioq_poll_period_us) 302 303 p = subparsers.add_parser('set_bdev_nvme_options', 304 help='Set options for the bdev nvme type. This is startup command.') 305 p.add_argument('-a', '--action-on-timeout', 306 help="Action to take on command time out. Valid valies are: none, reset, abort") 307 p.add_argument('-t', '--timeout-us', 308 help="Timeout for each command, in microseconds. If 0, don't track timeouts.", type=int) 309 p.add_argument('-n', '--retry-count', 310 help='the number of attempts per I/O when an I/O fails', type=int) 311 p.add_argument('-p', '--nvme-adminq-poll-period-us', 312 help='How often the admin queue is polled for asynchronous events', type=int) 313 p.add_argument('-i', '--nvme-ioq-poll-period-us', 314 help='How often to poll I/O queues for completions', type=int) 315 p.set_defaults(func=set_bdev_nvme_options) 316 317 def set_bdev_nvme_hotplug(args): 318 rpc.bdev.set_bdev_nvme_hotplug(args.client, enable=args.enable, period_us=args.period_us) 319 320 p = subparsers.add_parser('set_bdev_nvme_hotplug', 321 help='Set hotplug options for bdev nvme type.') 322 p.add_argument('-d', '--disable', dest='enable', default=False, action='store_false', help="Disable hotplug (default)") 323 p.add_argument('-e', '--enable', dest='enable', action='store_true', help="Enable hotplug") 324 p.add_argument('-r', '--period-us', 325 help='How often the hotplug is processed for insert and remove events', type=int) 326 p.set_defaults(func=set_bdev_nvme_hotplug) 327 328 def construct_nvme_bdev(args): 329 print_array(rpc.bdev.construct_nvme_bdev(args.client, 330 name=args.name, 331 trtype=args.trtype, 332 traddr=args.traddr, 333 adrfam=args.adrfam, 334 trsvcid=args.trsvcid, 335 subnqn=args.subnqn, 336 hostnqn=args.hostnqn, 337 hostaddr=args.hostaddr, 338 hostsvcid=args.hostsvcid, 339 prchk_reftag=args.prchk_reftag, 340 prchk_guard=args.prchk_guard)) 341 342 p = subparsers.add_parser('construct_nvme_bdev', 343 help='Add bdevs with nvme backend') 344 p.add_argument('-b', '--name', help="Name of the NVMe controller, prefix for each bdev name", required=True) 345 p.add_argument('-t', '--trtype', 346 help='NVMe-oF target trtype: e.g., rdma, pcie', required=True) 347 p.add_argument('-a', '--traddr', 348 help='NVMe-oF target address: e.g., an ip address or BDF', required=True) 349 p.add_argument('-f', '--adrfam', 350 help='NVMe-oF target adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 351 p.add_argument('-s', '--trsvcid', 352 help='NVMe-oF target trsvcid: e.g., a port number') 353 p.add_argument('-n', '--subnqn', help='NVMe-oF target subnqn') 354 p.add_argument('-q', '--hostnqn', help='NVMe-oF host subnqn') 355 p.add_argument('-i', '--hostaddr', 356 help='NVMe-oF host address: e.g., an ip address') 357 p.add_argument('-c', '--hostsvcid', 358 help='NVMe-oF host svcid: e.g., a port number') 359 p.add_argument('-r', '--prchk-reftag', 360 help='Enable checking of PI reference tag for I/O processing.', action='store_true') 361 p.add_argument('-g', '--prchk-guard', 362 help='Enable checking of PI guard for I/O processing.', action='store_true') 363 p.set_defaults(func=construct_nvme_bdev) 364 365 def get_nvme_controllers(args): 366 print_dict(rpc.nvme.get_nvme_controllers(args.client, 367 name=args.name)) 368 369 p = subparsers.add_parser( 370 'get_nvme_controllers', help='Display current NVMe controllers list or required NVMe controller') 371 p.add_argument('-n', '--name', help="Name of the NVMe controller. Example: Nvme0", required=False) 372 p.set_defaults(func=get_nvme_controllers) 373 374 def delete_nvme_controller(args): 375 rpc.bdev.delete_nvme_controller(args.client, 376 name=args.name) 377 378 p = subparsers.add_parser('delete_nvme_controller', 379 help='Delete a NVMe controller using controller name') 380 p.add_argument('name', help="Name of the controller") 381 p.set_defaults(func=delete_nvme_controller) 382 383 def construct_rbd_bdev(args): 384 config = None 385 if args.config: 386 config = {} 387 for entry in args.config: 388 parts = entry.split('=', 1) 389 if len(parts) != 2: 390 raise Exception('--config %s not in key=value form' % entry) 391 config[parts[0]] = parts[1] 392 print_string(rpc.bdev.construct_rbd_bdev(args.client, 393 name=args.name, 394 user=args.user, 395 config=config, 396 pool_name=args.pool_name, 397 rbd_name=args.rbd_name, 398 block_size=args.block_size)) 399 400 p = subparsers.add_parser('construct_rbd_bdev', 401 help='Add a bdev with ceph rbd backend') 402 p.add_argument('-b', '--name', help="Name of the bdev", required=False) 403 p.add_argument('--user', help="Ceph user name (i.e. admin, not client.admin)", required=False) 404 p.add_argument('--config', action='append', metavar='key=value', 405 help="adds a key=value configuration option for rados_conf_set (default: rely on config file)") 406 p.add_argument('pool_name', help='rbd pool name') 407 p.add_argument('rbd_name', help='rbd image name') 408 p.add_argument('block_size', help='rbd block size', type=int) 409 p.set_defaults(func=construct_rbd_bdev) 410 411 def delete_rbd_bdev(args): 412 rpc.bdev.delete_rbd_bdev(args.client, 413 name=args.name) 414 415 p = subparsers.add_parser('delete_rbd_bdev', help='Delete a rbd bdev') 416 p.add_argument('name', help='rbd bdev name') 417 p.set_defaults(func=delete_rbd_bdev) 418 419 def bdev_delay_create(args): 420 print_string(rpc.bdev.bdev_delay_create(args.client, 421 base_bdev_name=args.base_bdev_name, 422 name=args.name, 423 avg_read_latency=args.avg_read_latency, 424 p99_read_latency=args.nine_nine_read_latency, 425 avg_write_latency=args.avg_write_latency, 426 p99_write_latency=args.nine_nine_write_latency)) 427 428 p = subparsers.add_parser('bdev_delay_create', 429 help='Add a delay bdev on existing bdev') 430 p.add_argument('-b', '--base-bdev-name', help="Name of the existing bdev", required=True) 431 p.add_argument('-d', '--name', help="Name of the delay bdev", required=True) 432 p.add_argument('-r', '--avg-read-latency', help="Average latency to apply before completing read ops", required=True, type=int) 433 p.add_argument('-t', '--nine-nine-read-latency', help="latency to apply to 1 in 100 read ops", required=True, type=int) 434 p.add_argument('-w', '--avg-write-latency', help="Average latency to apply before completing write ops", required=True, type=int) 435 p.add_argument('-n', '--nine-nine-write-latency', help="latency to apply to 1 in 100 write ops", required=True, type=int) 436 p.set_defaults(func=bdev_delay_create) 437 438 def bdev_delay_delete(args): 439 rpc.bdev.bdev_delay_delete(args.client, 440 name=args.name) 441 442 p = subparsers.add_parser('bdev_delay_delete', help='Delete a delay bdev') 443 p.add_argument('name', help='delay bdev name') 444 p.set_defaults(func=bdev_delay_delete) 445 446 def construct_error_bdev(args): 447 print_string(rpc.bdev.construct_error_bdev(args.client, 448 base_name=args.base_name)) 449 450 p = subparsers.add_parser('construct_error_bdev', 451 help='Add bdev with error injection backend') 452 p.add_argument('base_name', help='base bdev name') 453 p.set_defaults(func=construct_error_bdev) 454 455 def delete_error_bdev(args): 456 rpc.bdev.delete_error_bdev(args.client, 457 name=args.name) 458 459 p = subparsers.add_parser('delete_error_bdev', help='Delete an error bdev') 460 p.add_argument('name', help='error bdev name') 461 p.set_defaults(func=delete_error_bdev) 462 463 def construct_iscsi_bdev(args): 464 print_string(rpc.bdev.construct_iscsi_bdev(args.client, 465 name=args.name, 466 url=args.url, 467 initiator_iqn=args.initiator_iqn)) 468 469 p = subparsers.add_parser('construct_iscsi_bdev', 470 help='Add bdev with iSCSI initiator backend') 471 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 472 p.add_argument('-i', '--initiator-iqn', help="Initiator IQN", required=True) 473 p.add_argument('--url', help="iSCSI Lun URL", required=True) 474 p.set_defaults(func=construct_iscsi_bdev) 475 476 def delete_iscsi_bdev(args): 477 rpc.bdev.delete_iscsi_bdev(args.client, 478 name=args.name) 479 480 p = subparsers.add_parser('delete_iscsi_bdev', help='Delete an iSCSI bdev') 481 p.add_argument('name', help='iSCSI bdev name') 482 p.set_defaults(func=delete_iscsi_bdev) 483 484 def construct_pmem_bdev(args): 485 print_string(rpc.bdev.construct_pmem_bdev(args.client, 486 pmem_file=args.pmem_file, 487 name=args.name)) 488 489 p = subparsers.add_parser('construct_pmem_bdev', help='Add a bdev with pmem backend') 490 p.add_argument('pmem_file', help='Path to pmemblk pool file') 491 p.add_argument('-n', '--name', help='Block device name', required=True) 492 p.set_defaults(func=construct_pmem_bdev) 493 494 def delete_pmem_bdev(args): 495 rpc.bdev.delete_pmem_bdev(args.client, 496 name=args.name) 497 498 p = subparsers.add_parser('delete_pmem_bdev', help='Delete a pmem bdev') 499 p.add_argument('name', help='pmem bdev name') 500 p.set_defaults(func=delete_pmem_bdev) 501 502 def construct_passthru_bdev(args): 503 print_string(rpc.bdev.construct_passthru_bdev(args.client, 504 base_bdev_name=args.base_bdev_name, 505 name=args.name)) 506 507 p = subparsers.add_parser('construct_passthru_bdev', 508 help='Add a pass through bdev on existing bdev') 509 p.add_argument('-b', '--base-bdev-name', help="Name of the existing bdev", required=True) 510 p.add_argument('-p', '--name', help="Name of the pass through bdev", required=True) 511 p.set_defaults(func=construct_passthru_bdev) 512 513 def delete_passthru_bdev(args): 514 rpc.bdev.delete_passthru_bdev(args.client, 515 name=args.name) 516 517 p = subparsers.add_parser('delete_passthru_bdev', help='Delete a pass through bdev') 518 p.add_argument('name', help='pass through bdev name') 519 p.set_defaults(func=delete_passthru_bdev) 520 521 def get_bdevs(args): 522 print_dict(rpc.bdev.get_bdevs(args.client, 523 name=args.name)) 524 525 p = subparsers.add_parser( 526 'get_bdevs', help='Display current blockdev list or required blockdev') 527 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 528 p.set_defaults(func=get_bdevs) 529 530 def get_bdevs_iostat(args): 531 print_dict(rpc.bdev.get_bdevs_iostat(args.client, 532 name=args.name)) 533 534 p = subparsers.add_parser( 535 'get_bdevs_iostat', help='Display current I/O statistics of all the blockdevs or required blockdev.') 536 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 537 p.set_defaults(func=get_bdevs_iostat) 538 539 def enable_bdev_histogram(args): 540 rpc.bdev.enable_bdev_histogram(args.client, name=args.name, enable=args.enable) 541 542 p = subparsers.add_parser('enable_bdev_histogram', help='Enable or disable histogram for specified bdev') 543 p.add_argument('-e', '--enable', default=True, dest='enable', action='store_true', help='Enable histograms on specified device') 544 p.add_argument('-d', '--disable', dest='enable', action='store_false', help='Disable histograms on specified device') 545 p.add_argument('name', help='bdev name') 546 p.set_defaults(func=enable_bdev_histogram) 547 548 def get_bdev_histogram(args): 549 print_dict(rpc.bdev.get_bdev_histogram(args.client, name=args.name)) 550 551 p = subparsers.add_parser('get_bdev_histogram', help='Get histogram for specified bdev') 552 p.add_argument('name', help='bdev name') 553 p.set_defaults(func=get_bdev_histogram) 554 555 def set_bdev_qd_sampling_period(args): 556 rpc.bdev.set_bdev_qd_sampling_period(args.client, 557 name=args.name, 558 period=args.period) 559 560 p = subparsers.add_parser('set_bdev_qd_sampling_period', help="Enable or disable tracking of a bdev's queue depth.") 561 p.add_argument('name', help='Blockdev name. Example: Malloc0') 562 p.add_argument('period', help='Period with which to poll the block device queue depth in microseconds.' 563 ' If set to 0, polling will be disabled.', 564 type=int) 565 p.set_defaults(func=set_bdev_qd_sampling_period) 566 567 def set_bdev_qos_limit(args): 568 rpc.bdev.set_bdev_qos_limit(args.client, 569 name=args.name, 570 rw_ios_per_sec=args.rw_ios_per_sec, 571 rw_mbytes_per_sec=args.rw_mbytes_per_sec, 572 r_mbytes_per_sec=args.r_mbytes_per_sec, 573 w_mbytes_per_sec=args.w_mbytes_per_sec) 574 575 p = subparsers.add_parser('set_bdev_qos_limit', help='Set QoS rate limit on a blockdev') 576 p.add_argument('name', help='Blockdev name to set QoS. Example: Malloc0') 577 p.add_argument('--rw_ios_per_sec', 578 help='R/W IOs per second limit (>=10000, example: 20000). 0 means unlimited.', 579 type=int, required=False) 580 p.add_argument('--rw_mbytes_per_sec', 581 help="R/W megabytes per second limit (>=10, example: 100). 0 means unlimited.", 582 type=int, required=False) 583 p.add_argument('--r_mbytes_per_sec', 584 help="Read megabytes per second limit (>=10, example: 100). 0 means unlimited.", 585 type=int, required=False) 586 p.add_argument('--w_mbytes_per_sec', 587 help="Write megabytes per second limit (>=10, example: 100). 0 means unlimited.", 588 type=int, required=False) 589 p.set_defaults(func=set_bdev_qos_limit) 590 591 def bdev_inject_error(args): 592 rpc.bdev.bdev_inject_error(args.client, 593 name=args.name, 594 io_type=args.io_type, 595 error_type=args.error_type, 596 num=args.num) 597 598 p = subparsers.add_parser('bdev_inject_error', help='bdev inject error') 599 p.add_argument('name', help="""the name of the error injection bdev""") 600 p.add_argument('io_type', help="""io_type: 'clear' 'read' 'write' 'unmap' 'flush' 'all'""") 601 p.add_argument('error_type', help="""error_type: 'failure' 'pending'""") 602 p.add_argument( 603 '-n', '--num', help='the number of commands you want to fail', type=int, default=1) 604 p.set_defaults(func=bdev_inject_error) 605 606 def apply_firmware(args): 607 print_dict(rpc.bdev.apply_firmware(args.client, 608 bdev_name=args.bdev_name, 609 filename=args.filename)) 610 611 p = subparsers.add_parser('apply_firmware', help='Download and commit firmware to NVMe device') 612 p.add_argument('filename', help='filename of the firmware to download') 613 p.add_argument('bdev_name', help='name of the NVMe device') 614 p.set_defaults(func=apply_firmware) 615 616 # iSCSI 617 def set_iscsi_options(args): 618 rpc.iscsi.set_iscsi_options( 619 args.client, 620 auth_file=args.auth_file, 621 node_base=args.node_base, 622 nop_timeout=args.nop_timeout, 623 nop_in_interval=args.nop_in_interval, 624 disable_chap=args.disable_chap, 625 require_chap=args.require_chap, 626 mutual_chap=args.mutual_chap, 627 chap_group=args.chap_group, 628 max_sessions=args.max_sessions, 629 max_queue_depth=args.max_queue_depth, 630 max_connections_per_session=args.max_connections_per_session, 631 default_time2wait=args.default_time2wait, 632 default_time2retain=args.default_time2retain, 633 first_burst_length=args.first_burst_length, 634 immediate_data=args.immediate_data, 635 error_recovery_level=args.error_recovery_level, 636 allow_duplicated_isid=args.allow_duplicated_isid) 637 638 p = subparsers.add_parser('set_iscsi_options', help="""Set options of iSCSI subsystem""") 639 p.add_argument('-f', '--auth-file', help='Path to CHAP shared secret file') 640 p.add_argument('-b', '--node-base', help='Prefix of the name of iSCSI target node') 641 p.add_argument('-o', '--nop-timeout', help='Timeout in seconds to nop-in request to the initiator', type=int) 642 p.add_argument('-n', '--nop-in-interval', help='Time interval in secs between nop-in requests by the target', type=int) 643 p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled. 644 *** Mutually exclusive with --require-chap""", action='store_true') 645 p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required. 646 *** Mutually exclusive with --disable-chap""", action='store_true') 647 p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true') 648 p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session. 649 *** Authentication group must be precreated ***""", type=int) 650 p.add_argument('-a', '--max-sessions', help='Maximum number of sessions in the host.', type=int) 651 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/Os per queue.', type=int) 652 p.add_argument('-c', '--max-connections-per-session', help='Negotiated parameter, MaxConnections.', type=int) 653 p.add_argument('-w', '--default-time2wait', help='Negotiated parameter, DefaultTime2Wait.', type=int) 654 p.add_argument('-v', '--default-time2retain', help='Negotiated parameter, DefaultTime2Retain.', type=int) 655 p.add_argument('-s', '--first-burst-length', help='Negotiated parameter, FirstBurstLength.', type=int) 656 p.add_argument('-i', '--immediate-data', help='Negotiated parameter, ImmediateData.', action='store_true') 657 p.add_argument('-l', '--error-recovery-level', help='Negotiated parameter, ErrorRecoveryLevel', type=int) 658 p.add_argument('-p', '--allow-duplicated-isid', help='Allow duplicated initiator session ID.', action='store_true') 659 p.set_defaults(func=set_iscsi_options) 660 661 def set_iscsi_discovery_auth(args): 662 rpc.iscsi.set_iscsi_discovery_auth( 663 args.client, 664 disable_chap=args.disable_chap, 665 require_chap=args.require_chap, 666 mutual_chap=args.mutual_chap, 667 chap_group=args.chap_group) 668 669 p = subparsers.add_parser('set_iscsi_discovery_auth', help="""Set CHAP authentication for discovery session.""") 670 p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled. 671 *** Mutually exclusive with --require-chap""", action='store_true') 672 p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required. 673 *** Mutually exclusive with --disable-chap""", action='store_true') 674 p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true') 675 p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session. 676 *** Authentication group must be precreated ***""", type=int) 677 p.set_defaults(func=set_iscsi_discovery_auth) 678 679 def add_iscsi_auth_group(args): 680 secrets = None 681 if args.secrets: 682 secrets = [dict(u.split(":") for u in a.split(" ")) for a in args.secrets.split(",")] 683 684 rpc.iscsi.add_iscsi_auth_group(args.client, tag=args.tag, secrets=secrets) 685 686 p = subparsers.add_parser('add_iscsi_auth_group', help='Add authentication group for CHAP authentication.') 687 p.add_argument('tag', help='Authentication group tag (unique, integer > 0).', type=int) 688 p.add_argument('-c', '--secrets', help="""Comma-separated list of CHAP secrets 689<user:user_name secret:chap_secret muser:mutual_user_name msecret:mutual_chap_secret> enclosed in quotes. 690Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 msecret:ms2'""", required=False) 691 p.set_defaults(func=add_iscsi_auth_group) 692 693 def delete_iscsi_auth_group(args): 694 rpc.iscsi.delete_iscsi_auth_group(args.client, tag=args.tag) 695 696 p = subparsers.add_parser('delete_iscsi_auth_group', help='Delete an authentication group.') 697 p.add_argument('tag', help='Authentication group tag', type=int) 698 p.set_defaults(func=delete_iscsi_auth_group) 699 700 def add_secret_to_iscsi_auth_group(args): 701 rpc.iscsi.add_secret_to_iscsi_auth_group( 702 args.client, 703 tag=args.tag, 704 user=args.user, 705 secret=args.secret, 706 muser=args.muser, 707 msecret=args.msecret) 708 709 p = subparsers.add_parser('add_secret_to_iscsi_auth_group', help='Add a secret to an authentication group.') 710 p.add_argument('tag', help='Authentication group tag', type=int) 711 p.add_argument('-u', '--user', help='User name for one-way CHAP authentication', required=True) 712 p.add_argument('-s', '--secret', help='Secret for one-way CHAP authentication', required=True) 713 p.add_argument('-m', '--muser', help='User name for mutual CHAP authentication') 714 p.add_argument('-r', '--msecret', help='Secret for mutual CHAP authentication') 715 p.set_defaults(func=add_secret_to_iscsi_auth_group) 716 717 def delete_secret_from_iscsi_auth_group(args): 718 rpc.iscsi.delete_secret_from_iscsi_auth_group(args.client, tag=args.tag, user=args.user) 719 720 p = subparsers.add_parser('delete_secret_from_iscsi_auth_group', help='Delete a secret from an authentication group.') 721 p.add_argument('tag', help='Authentication group tag', type=int) 722 p.add_argument('-u', '--user', help='User name for one-way CHAP authentication', required=True) 723 p.set_defaults(func=delete_secret_from_iscsi_auth_group) 724 725 def get_iscsi_auth_groups(args): 726 print_dict(rpc.iscsi.get_iscsi_auth_groups(args.client)) 727 728 p = subparsers.add_parser('get_iscsi_auth_groups', 729 help='Display current authentication group configuration') 730 p.set_defaults(func=get_iscsi_auth_groups) 731 732 def get_portal_groups(args): 733 print_dict(rpc.iscsi.get_portal_groups(args.client)) 734 735 p = subparsers.add_parser( 736 'get_portal_groups', help='Display current portal group configuration') 737 p.set_defaults(func=get_portal_groups) 738 739 def get_initiator_groups(args): 740 print_dict(rpc.iscsi.get_initiator_groups(args.client)) 741 742 p = subparsers.add_parser('get_initiator_groups', 743 help='Display current initiator group configuration') 744 p.set_defaults(func=get_initiator_groups) 745 746 def get_target_nodes(args): 747 print_dict(rpc.iscsi.get_target_nodes(args.client)) 748 749 p = subparsers.add_parser('get_target_nodes', help='Display target nodes') 750 p.set_defaults(func=get_target_nodes) 751 752 def construct_target_node(args): 753 luns = [] 754 for u in args.bdev_name_id_pairs.strip().split(" "): 755 bdev_name, lun_id = u.split(":") 756 luns.append({"bdev_name": bdev_name, "lun_id": int(lun_id)}) 757 758 pg_ig_maps = [] 759 for u in args.pg_ig_mappings.strip().split(" "): 760 pg, ig = u.split(":") 761 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 762 763 rpc.iscsi.construct_target_node( 764 args.client, 765 luns=luns, 766 pg_ig_maps=pg_ig_maps, 767 name=args.name, 768 alias_name=args.alias_name, 769 queue_depth=args.queue_depth, 770 chap_group=args.chap_group, 771 disable_chap=args.disable_chap, 772 require_chap=args.require_chap, 773 mutual_chap=args.mutual_chap, 774 header_digest=args.header_digest, 775 data_digest=args.data_digest) 776 777 p = subparsers.add_parser('construct_target_node', 778 help='Add a target node') 779 p.add_argument('name', help='Target node name (ASCII)') 780 p.add_argument('alias_name', help='Target node alias name (ASCII)') 781 p.add_argument('bdev_name_id_pairs', help="""Whitespace-separated list of <bdev name:LUN ID> pairs enclosed 782 in quotes. Format: 'bdev_name0:id0 bdev_name1:id1' etc 783 Example: 'Malloc0:0 Malloc1:1 Malloc5:2' 784 *** The bdevs must pre-exist *** 785 *** LUN0 (id = 0) is required *** 786 *** bdevs names cannot contain space or colon characters ***""") 787 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 788 Whitespace separated, quoted, mapping defined with colon 789 separated list of "tags" (int > 0) 790 Example: '1:1 2:2 2:1' 791 *** The Portal/Initiator Groups must be precreated ***""") 792 p.add_argument('queue_depth', help='Desired target queue depth', type=int) 793 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 794 *** Authentication group must be precreated ***""", type=int, default=0) 795 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 796 *** Mutually exclusive with --require-chap ***""", action='store_true') 797 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 798 *** Mutually exclusive with --disable-chap ***""", action='store_true') 799 p.add_argument( 800 '-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', action='store_true') 801 p.add_argument('-H', '--header-digest', 802 help='Header Digest should be required for this target node.', action='store_true') 803 p.add_argument('-D', '--data-digest', 804 help='Data Digest should be required for this target node.', action='store_true') 805 p.set_defaults(func=construct_target_node) 806 807 def target_node_add_lun(args): 808 rpc.iscsi.target_node_add_lun( 809 args.client, 810 name=args.name, 811 bdev_name=args.bdev_name, 812 lun_id=args.lun_id) 813 814 p = subparsers.add_parser('target_node_add_lun', help='Add LUN to the target node') 815 p.add_argument('name', help='Target node name (ASCII)') 816 p.add_argument('bdev_name', help="""bdev name enclosed in quotes. 817 *** bdev name cannot contain space or colon characters ***""") 818 p.add_argument('-i', dest='lun_id', help="""LUN ID (integer >= 0) 819 *** If LUN ID is omitted or -1, the lowest free one is assigned ***""", type=int, required=False) 820 p.set_defaults(func=target_node_add_lun) 821 822 def set_iscsi_target_node_auth(args): 823 rpc.iscsi.set_iscsi_target_node_auth( 824 args.client, 825 name=args.name, 826 chap_group=args.chap_group, 827 disable_chap=args.disable_chap, 828 require_chap=args.require_chap, 829 mutual_chap=args.mutual_chap) 830 831 p = subparsers.add_parser('set_iscsi_target_node_auth', help='Set CHAP authentication for the target node') 832 p.add_argument('name', help='Target node name (ASCII)') 833 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 834 *** Authentication group must be precreated ***""", type=int, default=0) 835 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 836 *** Mutually exclusive with --require-chap ***""", action='store_true') 837 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 838 *** Mutually exclusive with --disable-chap ***""", action='store_true') 839 p.add_argument('-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', 840 action='store_true') 841 p.set_defaults(func=set_iscsi_target_node_auth) 842 843 def add_pg_ig_maps(args): 844 pg_ig_maps = [] 845 for u in args.pg_ig_mappings.strip().split(" "): 846 pg, ig = u.split(":") 847 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 848 rpc.iscsi.add_pg_ig_maps( 849 args.client, 850 pg_ig_maps=pg_ig_maps, 851 name=args.name) 852 853 p = subparsers.add_parser('add_pg_ig_maps', help='Add PG-IG maps to the target node') 854 p.add_argument('name', help='Target node name (ASCII)') 855 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 856 Whitespace separated, quoted, mapping defined with colon 857 separated list of "tags" (int > 0) 858 Example: '1:1 2:2 2:1' 859 *** The Portal/Initiator Groups must be precreated ***""") 860 p.set_defaults(func=add_pg_ig_maps) 861 862 def delete_pg_ig_maps(args): 863 pg_ig_maps = [] 864 for u in args.pg_ig_mappings.strip().split(" "): 865 pg, ig = u.split(":") 866 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 867 rpc.iscsi.delete_pg_ig_maps( 868 args.client, pg_ig_maps=pg_ig_maps, name=args.name) 869 870 p = subparsers.add_parser('delete_pg_ig_maps', help='Delete PG-IG maps from the target node') 871 p.add_argument('name', help='Target node name (ASCII)') 872 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 873 Whitespace separated, quoted, mapping defined with colon 874 separated list of "tags" (int > 0) 875 Example: '1:1 2:2 2:1' 876 *** The Portal/Initiator Groups must be precreated ***""") 877 p.set_defaults(func=delete_pg_ig_maps) 878 879 def add_portal_group(args): 880 portals = [] 881 for p in args.portal_list.strip().split(' '): 882 ip, separator, port_cpumask = p.rpartition(':') 883 split_port_cpumask = port_cpumask.split('@') 884 if len(split_port_cpumask) == 1: 885 port = port_cpumask 886 portals.append({'host': ip, 'port': port}) 887 else: 888 port = split_port_cpumask[0] 889 cpumask = split_port_cpumask[1] 890 portals.append({'host': ip, 'port': port, 'cpumask': cpumask}) 891 rpc.iscsi.add_portal_group( 892 args.client, 893 portals=portals, 894 tag=args.tag) 895 896 p = subparsers.add_parser('add_portal_group', help='Add a portal group') 897 p.add_argument( 898 'tag', help='Portal group tag (unique, integer > 0)', type=int) 899 p.add_argument('portal_list', help="""List of portals in host:port@cpumask format, separated by whitespace 900 (cpumask is optional and can be skipped) 901 Example: '192.168.100.100:3260 192.168.100.100:3261 192.168.100.100:3262@0x1""") 902 p.set_defaults(func=add_portal_group) 903 904 def add_initiator_group(args): 905 initiators = [] 906 netmasks = [] 907 for i in args.initiator_list.strip().split(' '): 908 initiators.append(i) 909 for n in args.netmask_list.strip().split(' '): 910 netmasks.append(n) 911 rpc.iscsi.add_initiator_group( 912 args.client, 913 tag=args.tag, 914 initiators=initiators, 915 netmasks=netmasks) 916 917 p = subparsers.add_parser('add_initiator_group', 918 help='Add an initiator group') 919 p.add_argument( 920 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 921 p.add_argument('initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 922 enclosed in quotes. Example: 'ANY' or '127.0.0.1 192.168.200.100'""") 923 p.add_argument('netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 924 Example: '255.255.0.0 255.248.0.0' etc""") 925 p.set_defaults(func=add_initiator_group) 926 927 def add_initiators_to_initiator_group(args): 928 initiators = None 929 netmasks = None 930 if args.initiator_list: 931 initiators = [] 932 for i in args.initiator_list.strip().split(' '): 933 initiators.append(i) 934 if args.netmask_list: 935 netmasks = [] 936 for n in args.netmask_list.strip().split(' '): 937 netmasks.append(n) 938 rpc.iscsi.add_initiators_to_initiator_group( 939 args.client, 940 tag=args.tag, 941 initiators=initiators, 942 netmasks=netmasks) 943 944 p = subparsers.add_parser('add_initiators_to_initiator_group', 945 help='Add initiators to an existing initiator group') 946 p.add_argument( 947 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 948 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 949 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 950 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 951 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 952 p.set_defaults(func=add_initiators_to_initiator_group) 953 954 def delete_initiators_from_initiator_group(args): 955 initiators = None 956 netmasks = None 957 if args.initiator_list: 958 initiators = [] 959 for i in args.initiator_list.strip().split(' '): 960 initiators.append(i) 961 if args.netmask_list: 962 netmasks = [] 963 for n in args.netmask_list.strip().split(' '): 964 netmasks.append(n) 965 rpc.iscsi.delete_initiators_from_initiator_group( 966 args.client, 967 tag=args.tag, 968 initiators=initiators, 969 netmasks=netmasks) 970 971 p = subparsers.add_parser('delete_initiators_from_initiator_group', 972 help='Delete initiators from an existing initiator group') 973 p.add_argument( 974 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 975 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 976 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 977 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 978 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 979 p.set_defaults(func=delete_initiators_from_initiator_group) 980 981 def delete_target_node(args): 982 rpc.iscsi.delete_target_node( 983 args.client, target_node_name=args.target_node_name) 984 985 p = subparsers.add_parser('delete_target_node', 986 help='Delete a target node') 987 p.add_argument('target_node_name', 988 help='Target node name to be deleted. Example: iqn.2016-06.io.spdk:disk1.') 989 p.set_defaults(func=delete_target_node) 990 991 def delete_portal_group(args): 992 rpc.iscsi.delete_portal_group(args.client, tag=args.tag) 993 994 p = subparsers.add_parser('delete_portal_group', 995 help='Delete a portal group') 996 p.add_argument( 997 'tag', help='Portal group tag (unique, integer > 0)', type=int) 998 p.set_defaults(func=delete_portal_group) 999 1000 def delete_initiator_group(args): 1001 rpc.iscsi.delete_initiator_group(args.client, tag=args.tag) 1002 1003 p = subparsers.add_parser('delete_initiator_group', 1004 help='Delete an initiator group') 1005 p.add_argument( 1006 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 1007 p.set_defaults(func=delete_initiator_group) 1008 1009 def get_iscsi_connections(args): 1010 print_dict(rpc.iscsi.get_iscsi_connections(args.client)) 1011 1012 p = subparsers.add_parser('get_iscsi_connections', 1013 help='Display iSCSI connections') 1014 p.set_defaults(func=get_iscsi_connections) 1015 1016 def get_iscsi_global_params(args): 1017 print_dict(rpc.iscsi.get_iscsi_global_params(args.client)) 1018 1019 p = subparsers.add_parser('get_iscsi_global_params', help='Display iSCSI global parameters') 1020 p.set_defaults(func=get_iscsi_global_params) 1021 1022 def get_scsi_devices(args): 1023 print_dict(rpc.iscsi.get_scsi_devices(args.client)) 1024 1025 p = subparsers.add_parser('get_scsi_devices', help='Display SCSI devices') 1026 p.set_defaults(func=get_scsi_devices) 1027 1028 # trace 1029 def enable_tpoint_group(args): 1030 rpc.trace.enable_tpoint_group(args.client, name=args.name) 1031 1032 p = subparsers.add_parser('enable_tpoint_group', help='enable trace on a specific tpoint group') 1033 p.add_argument( 1034 'name', help="""trace group name we want to enable in tpoint_group_mask. 1035 (for example "bdev" for bdev trace group, "all" for all trace groups).""") 1036 p.set_defaults(func=enable_tpoint_group) 1037 1038 def disable_tpoint_group(args): 1039 rpc.trace.disable_tpoint_group(args.client, name=args.name) 1040 1041 p = subparsers.add_parser('disable_tpoint_group', help='disable trace on a specific tpoint group') 1042 p.add_argument( 1043 'name', help="""trace group name we want to disable in tpoint_group_mask. 1044 (for example "bdev" for bdev trace group, "all" for all trace groups).""") 1045 p.set_defaults(func=disable_tpoint_group) 1046 1047 def get_tpoint_group_mask(args): 1048 print_dict(rpc.trace.get_tpoint_group_mask(args.client)) 1049 1050 p = subparsers.add_parser('get_tpoint_group_mask', help='get trace point group mask') 1051 p.set_defaults(func=get_tpoint_group_mask) 1052 1053 # log 1054 def set_log_flag(args): 1055 rpc.log.set_log_flag(args.client, flag=args.flag) 1056 1057 p = subparsers.add_parser('set_log_flag', help='set log flag', aliases=['set_trace_flag']) 1058 p.add_argument( 1059 'flag', help='log flag we want to set. (for example "nvme").') 1060 p.set_defaults(func=set_log_flag) 1061 1062 def clear_log_flag(args): 1063 rpc.log.clear_log_flag(args.client, flag=args.flag) 1064 1065 p = subparsers.add_parser('clear_log_flag', help='clear log flag', aliases=['clear_trace_flag']) 1066 p.add_argument( 1067 'flag', help='log flag we want to clear. (for example "nvme").') 1068 p.set_defaults(func=clear_log_flag) 1069 1070 def get_log_flags(args): 1071 print_dict(rpc.log.get_log_flags(args.client)) 1072 1073 p = subparsers.add_parser('get_log_flags', help='get log flags', aliases=['get_trace_flags']) 1074 p.set_defaults(func=get_log_flags) 1075 1076 def set_log_level(args): 1077 rpc.log.set_log_level(args.client, level=args.level) 1078 1079 p = subparsers.add_parser('set_log_level', help='set log level') 1080 p.add_argument('level', help='log level we want to set. (for example "DEBUG").') 1081 p.set_defaults(func=set_log_level) 1082 1083 def get_log_level(args): 1084 print_dict(rpc.log.get_log_level(args.client)) 1085 1086 p = subparsers.add_parser('get_log_level', help='get log level') 1087 p.set_defaults(func=get_log_level) 1088 1089 def set_log_print_level(args): 1090 rpc.log.set_log_print_level(args.client, level=args.level) 1091 1092 p = subparsers.add_parser('set_log_print_level', help='set log print level') 1093 p.add_argument('level', help='log print level we want to set. (for example "DEBUG").') 1094 p.set_defaults(func=set_log_print_level) 1095 1096 def get_log_print_level(args): 1097 print_dict(rpc.log.get_log_print_level(args.client)) 1098 1099 p = subparsers.add_parser('get_log_print_level', help='get log print level') 1100 p.set_defaults(func=get_log_print_level) 1101 1102 # lvol 1103 def construct_lvol_store(args): 1104 print_string(rpc.lvol.construct_lvol_store(args.client, 1105 bdev_name=args.bdev_name, 1106 lvs_name=args.lvs_name, 1107 cluster_sz=args.cluster_sz, 1108 clear_method=args.clear_method)) 1109 1110 p = subparsers.add_parser('construct_lvol_store', help='Add logical volume store on base bdev') 1111 p.add_argument('bdev_name', help='base bdev name') 1112 p.add_argument('lvs_name', help='name for lvol store') 1113 p.add_argument('-c', '--cluster-sz', help='size of cluster (in bytes)', type=int, required=False) 1114 p.add_argument('--clear-method', help="""Change clear method for data region. 1115 Available: none, unmap, write_zeroes""", required=False) 1116 p.set_defaults(func=construct_lvol_store) 1117 1118 def rename_lvol_store(args): 1119 rpc.lvol.rename_lvol_store(args.client, 1120 old_name=args.old_name, 1121 new_name=args.new_name) 1122 1123 p = subparsers.add_parser('rename_lvol_store', help='Change logical volume store name') 1124 p.add_argument('old_name', help='old name') 1125 p.add_argument('new_name', help='new name') 1126 p.set_defaults(func=rename_lvol_store) 1127 1128 def construct_lvol_bdev(args): 1129 print_string(rpc.lvol.construct_lvol_bdev(args.client, 1130 lvol_name=args.lvol_name, 1131 size=args.size * 1024 * 1024, 1132 thin_provision=args.thin_provision, 1133 clear_method=args.clear_method, 1134 uuid=args.uuid, 1135 lvs_name=args.lvs_name)) 1136 1137 p = subparsers.add_parser('construct_lvol_bdev', help='Add a bdev with an logical volume backend') 1138 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1139 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1140 p.add_argument('-t', '--thin-provision', action='store_true', help='create lvol bdev as thin provisioned') 1141 p.add_argument('-c', '--clear-method', help="""Change default data clusters clear method. 1142 Available: none, unmap, write_zeroes""", required=False) 1143 p.add_argument('lvol_name', help='name for this lvol') 1144 p.add_argument('size', help='size in MiB for this bdev', type=int) 1145 p.set_defaults(func=construct_lvol_bdev) 1146 1147 def snapshot_lvol_bdev(args): 1148 print_string(rpc.lvol.snapshot_lvol_bdev(args.client, 1149 lvol_name=args.lvol_name, 1150 snapshot_name=args.snapshot_name)) 1151 1152 p = subparsers.add_parser('snapshot_lvol_bdev', help='Create a snapshot of an lvol bdev') 1153 p.add_argument('lvol_name', help='lvol bdev name') 1154 p.add_argument('snapshot_name', help='lvol snapshot name') 1155 p.set_defaults(func=snapshot_lvol_bdev) 1156 1157 def clone_lvol_bdev(args): 1158 print_string(rpc.lvol.clone_lvol_bdev(args.client, 1159 snapshot_name=args.snapshot_name, 1160 clone_name=args.clone_name)) 1161 1162 p = subparsers.add_parser('clone_lvol_bdev', help='Create a clone of an lvol snapshot') 1163 p.add_argument('snapshot_name', help='lvol snapshot name') 1164 p.add_argument('clone_name', help='lvol clone name') 1165 p.set_defaults(func=clone_lvol_bdev) 1166 1167 def rename_lvol_bdev(args): 1168 rpc.lvol.rename_lvol_bdev(args.client, 1169 old_name=args.old_name, 1170 new_name=args.new_name) 1171 1172 p = subparsers.add_parser('rename_lvol_bdev', help='Change lvol bdev name') 1173 p.add_argument('old_name', help='lvol bdev name') 1174 p.add_argument('new_name', help='new lvol name') 1175 p.set_defaults(func=rename_lvol_bdev) 1176 1177 def inflate_lvol_bdev(args): 1178 rpc.lvol.inflate_lvol_bdev(args.client, 1179 name=args.name) 1180 1181 p = subparsers.add_parser('inflate_lvol_bdev', help='Make thin provisioned lvol a thick provisioned lvol') 1182 p.add_argument('name', help='lvol bdev name') 1183 p.set_defaults(func=inflate_lvol_bdev) 1184 1185 def decouple_parent_lvol_bdev(args): 1186 rpc.lvol.decouple_parent_lvol_bdev(args.client, 1187 name=args.name) 1188 1189 p = subparsers.add_parser('decouple_parent_lvol_bdev', help='Decouple parent of lvol') 1190 p.add_argument('name', help='lvol bdev name') 1191 p.set_defaults(func=decouple_parent_lvol_bdev) 1192 1193 def resize_lvol_bdev(args): 1194 rpc.lvol.resize_lvol_bdev(args.client, 1195 name=args.name, 1196 size=args.size * 1024 * 1024) 1197 1198 p = subparsers.add_parser('resize_lvol_bdev', help='Resize existing lvol bdev') 1199 p.add_argument('name', help='lvol bdev name') 1200 p.add_argument('size', help='new size in MiB for this bdev', type=int) 1201 p.set_defaults(func=resize_lvol_bdev) 1202 1203 def set_read_only_lvol_bdev(args): 1204 rpc.lvol.set_read_only_lvol_bdev(args.client, 1205 name=args.name) 1206 1207 p = subparsers.add_parser('set_read_only_lvol_bdev', help='Mark lvol bdev as read only') 1208 p.add_argument('name', help='lvol bdev name') 1209 p.set_defaults(func=set_read_only_lvol_bdev) 1210 1211 def destroy_lvol_bdev(args): 1212 rpc.lvol.destroy_lvol_bdev(args.client, 1213 name=args.name) 1214 1215 p = subparsers.add_parser('destroy_lvol_bdev', help='Destroy a logical volume') 1216 p.add_argument('name', help='lvol bdev name') 1217 p.set_defaults(func=destroy_lvol_bdev) 1218 1219 def destroy_lvol_store(args): 1220 rpc.lvol.destroy_lvol_store(args.client, 1221 uuid=args.uuid, 1222 lvs_name=args.lvs_name) 1223 1224 p = subparsers.add_parser('destroy_lvol_store', help='Destroy an logical volume store') 1225 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1226 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1227 p.set_defaults(func=destroy_lvol_store) 1228 1229 def get_lvol_stores(args): 1230 print_dict(rpc.lvol.get_lvol_stores(args.client, 1231 uuid=args.uuid, 1232 lvs_name=args.lvs_name)) 1233 1234 p = subparsers.add_parser('get_lvol_stores', help='Display current logical volume store list') 1235 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1236 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1237 p.set_defaults(func=get_lvol_stores) 1238 1239 def get_raid_bdevs(args): 1240 print_array(rpc.bdev.get_raid_bdevs(args.client, 1241 category=args.category)) 1242 1243 p = subparsers.add_parser('get_raid_bdevs', help="""This is used to list all the raid bdev names based on the input category 1244 requested. Category should be one of 'all', 'online', 'configuring' or 'offline'. 'all' means all the raid bdevs whether 1245 they are online or configuring or offline. 'online' is the raid bdev which is registered with bdev layer. 'configuring' 1246 is the raid bdev which does not have full configuration discovered yet. 'offline' is the raid bdev which is not registered 1247 with bdev as of now and it has encountered any error or user has requested to offline the raid bdev""") 1248 p.add_argument('category', help='all or online or configuring or offline') 1249 p.set_defaults(func=get_raid_bdevs) 1250 1251 def construct_raid_bdev(args): 1252 base_bdevs = [] 1253 for u in args.base_bdevs.strip().split(" "): 1254 base_bdevs.append(u) 1255 1256 rpc.bdev.construct_raid_bdev(args.client, 1257 name=args.name, 1258 strip_size=args.strip_size, 1259 strip_size_kb=args.strip_size_kb, 1260 raid_level=args.raid_level, 1261 base_bdevs=base_bdevs) 1262 p = subparsers.add_parser('construct_raid_bdev', help='Construct new raid bdev') 1263 p.add_argument('-n', '--name', help='raid bdev name', required=True) 1264 p.add_argument('-s', '--strip-size', help='strip size in KB (deprecated)', type=int) 1265 p.add_argument('-z', '--strip-size_kb', help='strip size in KB', type=int) 1266 p.add_argument('-r', '--raid-level', help='raid level, only raid level 0 is supported', type=int, required=True) 1267 p.add_argument('-b', '--base-bdevs', help='base bdevs name, whitespace separated list in quotes', required=True) 1268 p.set_defaults(func=construct_raid_bdev) 1269 1270 def destroy_raid_bdev(args): 1271 rpc.bdev.destroy_raid_bdev(args.client, 1272 name=args.name) 1273 p = subparsers.add_parser('destroy_raid_bdev', help='Destroy existing raid bdev') 1274 p.add_argument('name', help='raid bdev name') 1275 p.set_defaults(func=destroy_raid_bdev) 1276 1277 # split 1278 def construct_split_vbdev(args): 1279 print_array(rpc.bdev.construct_split_vbdev(args.client, 1280 base_bdev=args.base_bdev, 1281 split_count=args.split_count, 1282 split_size_mb=args.split_size_mb)) 1283 1284 p = subparsers.add_parser('construct_split_vbdev', help="""Add given disk name to split config. If bdev with base_name 1285 name exist the split bdevs will be created right away, if not split bdevs will be created when base bdev became 1286 available (during examination process).""") 1287 p.add_argument('base_bdev', help='base bdev name') 1288 p.add_argument('-s', '--split-size-mb', help='size in MiB for each bdev', type=int, default=0) 1289 p.add_argument('split_count', help="""Optional - number of split bdevs to create. Total size * split_count must not 1290 exceed the base bdev size.""", type=int) 1291 p.set_defaults(func=construct_split_vbdev) 1292 1293 def destruct_split_vbdev(args): 1294 rpc.bdev.destruct_split_vbdev(args.client, 1295 base_bdev=args.base_bdev) 1296 1297 p = subparsers.add_parser('destruct_split_vbdev', help="""Delete split config with all created splits.""") 1298 p.add_argument('base_bdev', help='base bdev name') 1299 p.set_defaults(func=destruct_split_vbdev) 1300 1301 # ftl 1302 def construct_ftl_bdev(args): 1303 print_dict(rpc.bdev.construct_ftl_bdev(args.client, 1304 name=args.name, 1305 trtype=args.trtype, 1306 traddr=args.traddr, 1307 punits=args.punits, 1308 uuid=args.uuid, 1309 cache=args.cache, 1310 allow_open_bands=args.allow_open_bands)) 1311 1312 p = subparsers.add_parser('construct_ftl_bdev', 1313 help='Add FTL bdev') 1314 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 1315 p.add_argument('-t', '--trtype', 1316 help='NVMe target trtype: e.g., pcie', default='pcie') 1317 p.add_argument('-a', '--traddr', 1318 help='NVMe target address: e.g., an ip address or BDF', required=True) 1319 p.add_argument('-l', '--punits', help='Parallel unit range in the form of start-end: e.g. 4-8', 1320 required=True) 1321 p.add_argument('-u', '--uuid', help='UUID of restored bdev (not applicable when creating new ' 1322 'instance): e.g. b286d19a-0059-4709-abcd-9f7732b1567d (optional)') 1323 p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache (optional)') 1324 p.add_argument('-o', '--allow_open_bands', help='Restoring after dirty shutdown without cache will' 1325 ' result in partial data recovery, instead of error', action='store_true') 1326 p.set_defaults(func=construct_ftl_bdev) 1327 1328 def delete_ftl_bdev(args): 1329 print_dict(rpc.bdev.delete_ftl_bdev(args.client, name=args.name)) 1330 1331 p = subparsers.add_parser('delete_ftl_bdev', help='Delete FTL bdev') 1332 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 1333 p.set_defaults(func=delete_ftl_bdev) 1334 1335 # nbd 1336 def start_nbd_disk(args): 1337 print(rpc.nbd.start_nbd_disk(args.client, 1338 bdev_name=args.bdev_name, 1339 nbd_device=args.nbd_device)) 1340 1341 p = subparsers.add_parser('start_nbd_disk', help='Export a bdev as a nbd disk') 1342 p.add_argument('bdev_name', help='Blockdev name to be exported. Example: Malloc0.') 1343 p.add_argument('nbd_device', help='Nbd device name to be assigned. Example: /dev/nbd0.', nargs='?') 1344 p.set_defaults(func=start_nbd_disk) 1345 1346 def stop_nbd_disk(args): 1347 rpc.nbd.stop_nbd_disk(args.client, 1348 nbd_device=args.nbd_device) 1349 1350 p = subparsers.add_parser('stop_nbd_disk', help='Stop a nbd disk') 1351 p.add_argument('nbd_device', help='Nbd device name to be stopped. Example: /dev/nbd0.') 1352 p.set_defaults(func=stop_nbd_disk) 1353 1354 def get_nbd_disks(args): 1355 print_dict(rpc.nbd.get_nbd_disks(args.client, 1356 nbd_device=args.nbd_device)) 1357 1358 p = subparsers.add_parser('get_nbd_disks', help='Display full or specified nbd device list') 1359 p.add_argument('-n', '--nbd-device', help="Path of the nbd device. Example: /dev/nbd0", required=False) 1360 p.set_defaults(func=get_nbd_disks) 1361 1362 # net 1363 def add_ip_address(args): 1364 rpc.net.add_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1365 1366 p = subparsers.add_parser('add_ip_address', help='Add IP address') 1367 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1368 p.add_argument('ip_addr', help='ip address will be added.') 1369 p.set_defaults(func=add_ip_address) 1370 1371 def delete_ip_address(args): 1372 rpc.net.delete_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1373 1374 p = subparsers.add_parser('delete_ip_address', help='Delete IP address') 1375 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1376 p.add_argument('ip_addr', help='ip address will be deleted.') 1377 p.set_defaults(func=delete_ip_address) 1378 1379 def get_interfaces(args): 1380 print_dict(rpc.net.get_interfaces(args.client)) 1381 1382 p = subparsers.add_parser( 1383 'get_interfaces', help='Display current interface list') 1384 p.set_defaults(func=get_interfaces) 1385 1386 # NVMe-oF 1387 def set_nvmf_target_max_subsystems(args): 1388 rpc.nvmf.set_nvmf_target_max_subsystems(args.client, 1389 max_subsystems=args.max_subsystems) 1390 1391 p = subparsers.add_parser('set_nvmf_target_max_subsystems', help='Set the maximum number of NVMf target subsystems') 1392 p.add_argument('-x', '--max-subsystems', help='Max number of NVMf subsystems', type=int, required=True) 1393 p.set_defaults(func=set_nvmf_target_max_subsystems) 1394 1395 def set_nvmf_target_config(args): 1396 rpc.nvmf.set_nvmf_target_config(args.client, 1397 acceptor_poll_rate=args.acceptor_poll_rate, 1398 conn_sched=args.conn_sched) 1399 1400 p = subparsers.add_parser('set_nvmf_target_config', help='Set NVMf target config') 1401 p.add_argument('-r', '--acceptor-poll-rate', help='Polling interval of the acceptor for incoming connections (usec)', type=int) 1402 p.add_argument('-s', '--conn-sched', help="""'roundrobin' - Schedule the incoming connections from any host 1403 on the cores in a round robin manner (Default). 'hostip' - Schedule all the incoming connections from a 1404 specific host IP on to the same core. Connections from different IP will be assigned to cores in a round 1405 robin manner""") 1406 p.set_defaults(func=set_nvmf_target_config) 1407 1408 def nvmf_create_transport(args): 1409 rpc.nvmf.nvmf_create_transport(args.client, 1410 trtype=args.trtype, 1411 max_queue_depth=args.max_queue_depth, 1412 max_qpairs_per_ctrlr=args.max_qpairs_per_ctrlr, 1413 in_capsule_data_size=args.in_capsule_data_size, 1414 max_io_size=args.max_io_size, 1415 io_unit_size=args.io_unit_size, 1416 max_aq_depth=args.max_aq_depth, 1417 num_shared_buffers=args.num_shared_buffers, 1418 buf_cache_size=args.buf_cache_size, 1419 max_srq_depth=args.max_srq_depth, 1420 no_srq=args.no_srq, 1421 c2h_success=args.c2h_success) 1422 1423 p = subparsers.add_parser('nvmf_create_transport', help='Create NVMf transport') 1424 p.add_argument('-t', '--trtype', help='Transport type (ex. RDMA)', type=str, required=True) 1425 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int) 1426 p.add_argument('-p', '--max-qpairs-per-ctrlr', help='Max number of SQ and CQ per controller', type=int) 1427 p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int) 1428 p.add_argument('-i', '--max-io-size', help='Max I/O size (bytes)', type=int) 1429 p.add_argument('-u', '--io-unit-size', help='I/O unit size (bytes)', type=int) 1430 p.add_argument('-a', '--max-aq-depth', help='Max number of admin cmds per AQ', type=int) 1431 p.add_argument('-n', '--num-shared-buffers', help='The number of pooled data buffers available to the transport', type=int) 1432 p.add_argument('-b', '--buf-cache-size', help='The number of shared buffers to reserve for each poll group', type=int) 1433 p.add_argument('-s', '--max-srq-depth', help='Max number of outstanding I/O per SRQ. Relevant only for RDMA transport', type=int) 1434 p.add_argument('-r', '--no-srq', action='store_true', help='Disable per-thread shared receive queue. Relevant only for RDMA transport') 1435 p.add_argument('-o', '--c2h-success', help='Enable C2H success optimization. Relevant only for TCP transport', type=bool) 1436 p.set_defaults(func=nvmf_create_transport) 1437 1438 def get_nvmf_transports(args): 1439 print_dict(rpc.nvmf.get_nvmf_transports(args.client)) 1440 1441 p = subparsers.add_parser('get_nvmf_transports', 1442 help='Display nvmf transports') 1443 p.set_defaults(func=get_nvmf_transports) 1444 1445 def get_nvmf_subsystems(args): 1446 print_dict(rpc.nvmf.get_nvmf_subsystems(args.client)) 1447 1448 p = subparsers.add_parser('get_nvmf_subsystems', 1449 help='Display nvmf subsystems') 1450 p.set_defaults(func=get_nvmf_subsystems) 1451 1452 def nvmf_subsystem_create(args): 1453 rpc.nvmf.nvmf_subsystem_create(args.client, 1454 nqn=args.nqn, 1455 serial_number=args.serial_number, 1456 model_number=args.model_number, 1457 allow_any_host=args.allow_any_host, 1458 max_namespaces=args.max_namespaces) 1459 1460 p = subparsers.add_parser('nvmf_subsystem_create', help='Create an NVMe-oF subsystem') 1461 p.add_argument('nqn', help='Subsystem NQN (ASCII)') 1462 p.add_argument("-s", "--serial-number", help=""" 1463 Format: 'sn' etc 1464 Example: 'SPDK00000000000001'""", default='00000000000000000000') 1465 p.add_argument("-d", "--model-number", help=""" 1466 Format: 'mn' etc 1467 Example: 'SPDK Controller'""", default='SPDK bdev Controller') 1468 p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce host NQN whitelist)") 1469 p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed", 1470 type=int, default=0) 1471 p.set_defaults(func=nvmf_subsystem_create) 1472 1473 def delete_nvmf_subsystem(args): 1474 rpc.nvmf.delete_nvmf_subsystem(args.client, 1475 nqn=args.subsystem_nqn) 1476 1477 p = subparsers.add_parser('delete_nvmf_subsystem', 1478 help='Delete a nvmf subsystem') 1479 p.add_argument('subsystem_nqn', 1480 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 1481 p.set_defaults(func=delete_nvmf_subsystem) 1482 1483 def nvmf_subsystem_add_listener(args): 1484 rpc.nvmf.nvmf_subsystem_add_listener(args.client, 1485 nqn=args.nqn, 1486 trtype=args.trtype, 1487 traddr=args.traddr, 1488 adrfam=args.adrfam, 1489 trsvcid=args.trsvcid) 1490 1491 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 1492 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1493 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1494 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1495 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1496 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1497 p.set_defaults(func=nvmf_subsystem_add_listener) 1498 1499 def nvmf_subsystem_remove_listener(args): 1500 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, 1501 nqn=args.nqn, 1502 trtype=args.trtype, 1503 traddr=args.traddr, 1504 adrfam=args.adrfam, 1505 trsvcid=args.trsvcid) 1506 1507 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 1508 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1509 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1510 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1511 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1512 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1513 p.set_defaults(func=nvmf_subsystem_remove_listener) 1514 1515 def nvmf_subsystem_add_ns(args): 1516 rpc.nvmf.nvmf_subsystem_add_ns(args.client, 1517 nqn=args.nqn, 1518 bdev_name=args.bdev_name, 1519 nsid=args.nsid, 1520 nguid=args.nguid, 1521 eui64=args.eui64, 1522 uuid=args.uuid) 1523 1524 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 1525 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1526 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 1527 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 1528 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 1529 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 1530 p.add_argument('-u', '--uuid', help='Namespace UUID (optional)') 1531 p.set_defaults(func=nvmf_subsystem_add_ns) 1532 1533 def nvmf_subsystem_remove_ns(args): 1534 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, 1535 nqn=args.nqn, 1536 nsid=args.nsid) 1537 1538 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 1539 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1540 p.add_argument('nsid', help='The requested NSID', type=int) 1541 p.set_defaults(func=nvmf_subsystem_remove_ns) 1542 1543 def nvmf_subsystem_add_host(args): 1544 rpc.nvmf.nvmf_subsystem_add_host(args.client, 1545 nqn=args.nqn, 1546 host=args.host) 1547 1548 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 1549 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1550 p.add_argument('host', help='Host NQN to allow') 1551 p.set_defaults(func=nvmf_subsystem_add_host) 1552 1553 def nvmf_subsystem_remove_host(args): 1554 rpc.nvmf.nvmf_subsystem_remove_host(args.client, 1555 nqn=args.nqn, 1556 host=args.host) 1557 1558 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 1559 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1560 p.add_argument('host', help='Host NQN to remove') 1561 p.set_defaults(func=nvmf_subsystem_remove_host) 1562 1563 def nvmf_subsystem_allow_any_host(args): 1564 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, 1565 nqn=args.nqn, 1566 disable=args.disable) 1567 1568 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 1569 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1570 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 1571 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 1572 p.set_defaults(func=nvmf_subsystem_allow_any_host) 1573 1574 # pmem 1575 def create_pmem_pool(args): 1576 num_blocks = int((args.total_size * 1024 * 1024) / args.block_size) 1577 rpc.pmem.create_pmem_pool(args.client, 1578 pmem_file=args.pmem_file, 1579 num_blocks=num_blocks, 1580 block_size=args.block_size) 1581 1582 p = subparsers.add_parser('create_pmem_pool', help='Create pmem pool') 1583 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1584 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 1585 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 1586 p.set_defaults(func=create_pmem_pool) 1587 1588 def pmem_pool_info(args): 1589 print_dict(rpc.pmem.pmem_pool_info(args.client, 1590 pmem_file=args.pmem_file)) 1591 1592 p = subparsers.add_parser('pmem_pool_info', help='Display pmem pool info and check consistency') 1593 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1594 p.set_defaults(func=pmem_pool_info) 1595 1596 def delete_pmem_pool(args): 1597 rpc.pmem.delete_pmem_pool(args.client, 1598 pmem_file=args.pmem_file) 1599 1600 p = subparsers.add_parser('delete_pmem_pool', help='Delete pmem pool') 1601 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1602 p.set_defaults(func=delete_pmem_pool) 1603 1604 # subsystem 1605 def get_subsystems(args): 1606 print_dict(rpc.subsystem.get_subsystems(args.client)) 1607 1608 p = subparsers.add_parser('get_subsystems', help="""Print subsystems array in initialization order. Each subsystem 1609 entry contain (unsorted) array of subsystems it depends on.""") 1610 p.set_defaults(func=get_subsystems) 1611 1612 def get_subsystem_config(args): 1613 print_dict(rpc.subsystem.get_subsystem_config(args.client, args.name)) 1614 1615 p = subparsers.add_parser('get_subsystem_config', help="""Print subsystem configuration""") 1616 p.add_argument('name', help='Name of subsystem to query') 1617 p.set_defaults(func=get_subsystem_config) 1618 1619 # vhost 1620 def set_vhost_controller_coalescing(args): 1621 rpc.vhost.set_vhost_controller_coalescing(args.client, 1622 ctrlr=args.ctrlr, 1623 delay_base_us=args.delay_base_us, 1624 iops_threshold=args.iops_threshold) 1625 1626 p = subparsers.add_parser('set_vhost_controller_coalescing', help='Set vhost controller coalescing') 1627 p.add_argument('ctrlr', help='controller name') 1628 p.add_argument('delay_base_us', help='Base delay time', type=int) 1629 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 1630 p.set_defaults(func=set_vhost_controller_coalescing) 1631 1632 def construct_vhost_scsi_controller(args): 1633 rpc.vhost.construct_vhost_scsi_controller(args.client, 1634 ctrlr=args.ctrlr, 1635 cpumask=args.cpumask) 1636 1637 p = subparsers.add_parser( 1638 'construct_vhost_scsi_controller', help='Add new vhost controller') 1639 p.add_argument('ctrlr', help='controller name') 1640 p.add_argument('--cpumask', help='cpu mask for this controller') 1641 p.set_defaults(func=construct_vhost_scsi_controller) 1642 1643 def add_vhost_scsi_lun(args): 1644 print_string(rpc.vhost.add_vhost_scsi_lun(args.client, 1645 ctrlr=args.ctrlr, 1646 scsi_target_num=args.scsi_target_num, 1647 bdev_name=args.bdev_name)) 1648 1649 p = subparsers.add_parser('add_vhost_scsi_lun', 1650 help='Add lun to vhost controller') 1651 p.add_argument('ctrlr', help='conntroller name where add lun') 1652 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 1653 p.add_argument('bdev_name', help='bdev name') 1654 p.set_defaults(func=add_vhost_scsi_lun) 1655 1656 def remove_vhost_scsi_target(args): 1657 rpc.vhost.remove_vhost_scsi_target(args.client, 1658 ctrlr=args.ctrlr, 1659 scsi_target_num=args.scsi_target_num) 1660 1661 p = subparsers.add_parser('remove_vhost_scsi_target', help='Remove target from vhost controller') 1662 p.add_argument('ctrlr', help='controller name to remove target from') 1663 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 1664 p.set_defaults(func=remove_vhost_scsi_target) 1665 1666 def construct_vhost_blk_controller(args): 1667 rpc.vhost.construct_vhost_blk_controller(args.client, 1668 ctrlr=args.ctrlr, 1669 dev_name=args.dev_name, 1670 cpumask=args.cpumask, 1671 readonly=args.readonly) 1672 1673 p = subparsers.add_parser('construct_vhost_blk_controller', help='Add a new vhost block controller') 1674 p.add_argument('ctrlr', help='controller name') 1675 p.add_argument('dev_name', help='device name') 1676 p.add_argument('--cpumask', help='cpu mask for this controller') 1677 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 1678 p.set_defaults(func=construct_vhost_blk_controller) 1679 1680 def construct_vhost_nvme_controller(args): 1681 rpc.vhost.construct_vhost_nvme_controller(args.client, 1682 ctrlr=args.ctrlr, 1683 io_queues=args.io_queues, 1684 cpumask=args.cpumask) 1685 1686 p = subparsers.add_parser('construct_vhost_nvme_controller', help='Add new vhost controller') 1687 p.add_argument('ctrlr', help='controller name') 1688 p.add_argument('io_queues', help='number of IO queues for the controller', type=int) 1689 p.add_argument('--cpumask', help='cpu mask for this controller') 1690 p.set_defaults(func=construct_vhost_nvme_controller) 1691 1692 def add_vhost_nvme_ns(args): 1693 rpc.vhost.add_vhost_nvme_ns(args.client, 1694 ctrlr=args.ctrlr, 1695 bdev_name=args.bdev_name) 1696 1697 p = subparsers.add_parser('add_vhost_nvme_ns', help='Add a Namespace to vhost controller') 1698 p.add_argument('ctrlr', help='conntroller name where add a Namespace') 1699 p.add_argument('bdev_name', help='block device name for a new Namespace') 1700 p.set_defaults(func=add_vhost_nvme_ns) 1701 1702 def get_vhost_controllers(args): 1703 print_dict(rpc.vhost.get_vhost_controllers(args.client, args.name)) 1704 1705 p = subparsers.add_parser('get_vhost_controllers', help='List all or specific vhost controller(s)') 1706 p.add_argument('-n', '--name', help="Name of vhost controller", required=False) 1707 p.set_defaults(func=get_vhost_controllers) 1708 1709 def remove_vhost_controller(args): 1710 rpc.vhost.remove_vhost_controller(args.client, 1711 ctrlr=args.ctrlr) 1712 1713 p = subparsers.add_parser('remove_vhost_controller', help='Remove a vhost controller') 1714 p.add_argument('ctrlr', help='controller name') 1715 p.set_defaults(func=remove_vhost_controller) 1716 1717 def construct_virtio_dev(args): 1718 print_array(rpc.vhost.construct_virtio_dev(args.client, 1719 name=args.name, 1720 trtype=args.trtype, 1721 traddr=args.traddr, 1722 dev_type=args.dev_type, 1723 vq_count=args.vq_count, 1724 vq_size=args.vq_size)) 1725 1726 p = subparsers.add_parser('construct_virtio_dev', help="""Construct new virtio device using provided 1727 transport type and device type. In case of SCSI device type this implies scan and add bdevs offered by 1728 remote side. Result is array of added bdevs.""") 1729 p.add_argument('name', help="Use this name as base for new created bdevs") 1730 p.add_argument('-t', '--trtype', 1731 help='Virtio target transport type: pci or user', required=True) 1732 p.add_argument('-a', '--traddr', 1733 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 1734 p.add_argument('-d', '--dev-type', 1735 help='Device type: blk or scsi', required=True) 1736 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 1737 p.add_argument('--vq-size', help='Size of each queue', type=int) 1738 p.set_defaults(func=construct_virtio_dev) 1739 1740 def get_virtio_scsi_devs(args): 1741 print_dict(rpc.vhost.get_virtio_scsi_devs(args.client)) 1742 1743 p = subparsers.add_parser('get_virtio_scsi_devs', help='List all Virtio-SCSI devices.') 1744 p.set_defaults(func=get_virtio_scsi_devs) 1745 1746 def remove_virtio_bdev(args): 1747 rpc.vhost.remove_virtio_bdev(args.client, 1748 name=args.name) 1749 1750 p = subparsers.add_parser('remove_virtio_bdev', help="""Remove a Virtio device 1751 This will delete all bdevs exposed by this device""") 1752 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 1753 p.set_defaults(func=remove_virtio_bdev) 1754 1755 # ioat 1756 def scan_ioat_copy_engine(args): 1757 pci_whitelist = [] 1758 if args.pci_whitelist: 1759 for w in args.pci_whitelist.strip().split(" "): 1760 pci_whitelist.append(w) 1761 rpc.ioat.scan_ioat_copy_engine(args.client, pci_whitelist) 1762 1763 p = subparsers.add_parser('scan_ioat_copy_engine', help='Set scan and enable IOAT copy engine offload.') 1764 p.add_argument('-w', '--pci-whitelist', help="""Whitespace-separated list of PCI addresses in 1765 domain:bus:device.function format or domain.bus.device.function format""") 1766 p.set_defaults(func=scan_ioat_copy_engine) 1767 1768 # send_nvme_cmd 1769 def send_nvme_cmd(args): 1770 print_dict(rpc.nvme.send_nvme_cmd(args.client, 1771 name=args.nvme_name, 1772 cmd_type=args.cmd_type, 1773 data_direction=args.data_direction, 1774 cmdbuf=args.cmdbuf, 1775 data=args.data, 1776 metadata=args.metadata, 1777 data_len=args.data_length, 1778 metadata_len=args.metadata_length, 1779 timeout_ms=args.timeout_ms)) 1780 1781 p = subparsers.add_parser('send_nvme_cmd', help='NVMe passthrough cmd.') 1782 p.add_argument('-n', '--nvme-name', help="""Name of the operating NVMe controller""") 1783 p.add_argument('-t', '--cmd-type', help="""Type of nvme cmd. Valid values are: admin, io""") 1784 p.add_argument('-r', '--data-direction', help="""Direction of data transfer. Valid values are: c2h, h2c""") 1785 p.add_argument('-c', '--cmdbuf', help="""NVMe command encoded by base64 urlsafe""") 1786 p.add_argument('-d', '--data', help="""Data transferring to controller from host, encoded by base64 urlsafe""") 1787 p.add_argument('-m', '--metadata', help="""Metadata transferring to controller from host, encoded by base64 urlsafe""") 1788 p.add_argument('-D', '--data-length', help="""Data length required to transfer from controller to host""", type=int) 1789 p.add_argument('-M', '--metadata-length', help="""Metadata length required to transfer from controller to host""", type=int) 1790 p.add_argument('-T', '--timeout-ms', 1791 help="""Command execution timeout value, in milliseconds, if 0, don't track timeout""", type=int, default=0) 1792 p.set_defaults(func=send_nvme_cmd) 1793 1794 # Notifications 1795 def get_notification_types(args): 1796 print_dict(rpc.notify.get_notification_types(args.client)) 1797 1798 p = subparsers.add_parser('get_notification_types', help='List available notifications that user can subscribe to.') 1799 p.set_defaults(func=get_notification_types) 1800 1801 def get_notifications(args): 1802 ret = rpc.notify.get_notifications(args.client, 1803 id=args.id, 1804 max=args.max) 1805 print_dict(ret) 1806 1807 p = subparsers.add_parser('get_notifications', help='Get notifications') 1808 p.add_argument('-i', '--id', help="""First ID to start fetching from""", type=int) 1809 p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int) 1810 p.set_defaults(func=get_notifications) 1811 1812 def check_called_name(name): 1813 if name in deprecated_aliases: 1814 print("{} is deprecated, use {} instead.".format(name, deprecated_aliases[name]), file=sys.stderr) 1815 1816 class mock_client: 1817 def call(self, method, params=None): 1818 print("Request:\n" + json.dumps({"method": method, "params": params}, indent=2)) 1819 1820 def mock_print(arg): 1821 pass 1822 1823 def call_rpc_func(args): 1824 args.func(args) 1825 check_called_name(args.called_rpc_name) 1826 1827 def execute_script(parser, client, fd): 1828 executed_rpc = "" 1829 for rpc_call in map(str.rstrip, fd): 1830 if not rpc_call.strip(): 1831 continue 1832 executed_rpc = "\n".join([executed_rpc, rpc_call]) 1833 args = parser.parse_args(shlex.split(rpc_call)) 1834 args.client = client 1835 try: 1836 call_rpc_func(args) 1837 except JSONRPCException as ex: 1838 print("Exception:") 1839 print(executed_rpc.strip() + " <<<") 1840 print(ex.message) 1841 exit(1) 1842 1843 args = parser.parse_args() 1844 if args.dry_run: 1845 args.client = mock_client() 1846 print_dict = mock_print 1847 print_string = mock_print 1848 print_array = mock_print 1849 else: 1850 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, log_level=getattr(logging, args.verbose.upper())) 1851 if hasattr(args, 'func'): 1852 try: 1853 call_rpc_func(args) 1854 except JSONRPCException as ex: 1855 print(ex) 1856 exit(1) 1857 elif sys.stdin.isatty(): 1858 # No arguments and no data piped through stdin 1859 parser.print_help() 1860 exit(1) 1861 else: 1862 execute_script(parser, args.client, sys.stdin) 1863