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