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