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