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