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