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 domain socket path or IP 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='Timeout as a floating point number expressed in seconds waiting for response. 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 enable_bdev_histogram(args): 469 rpc.bdev.enable_bdev_histogram(args.client, name=args.name, enable=args.enable) 470 471 p = subparsers.add_parser('enable_bdev_histogram', help='Enable or disable histogram for specified bdev') 472 p.add_argument('-e', '--enable', default=True, dest='enable', action='store_true', help='Enable histograms on specified device') 473 p.add_argument('-d', '--disable', dest='enable', action='store_false', help='Disable histograms on specified device') 474 p.add_argument('name', help='bdev name') 475 p.set_defaults(func=enable_bdev_histogram) 476 477 def get_bdev_histogram(args): 478 print_dict(rpc.bdev.get_bdev_histogram(args.client, name=args.name)) 479 480 p = subparsers.add_parser('get_bdev_histogram', help='Get histogram for specified bdev') 481 p.add_argument('name', help='bdev name') 482 p.set_defaults(func=get_bdev_histogram) 483 484 def set_bdev_qd_sampling_period(args): 485 rpc.bdev.set_bdev_qd_sampling_period(args.client, 486 name=args.name, 487 period=args.period) 488 489 p = subparsers.add_parser('set_bdev_qd_sampling_period', help="Enable or disable tracking of a bdev's queue depth.") 490 p.add_argument('name', help='Blockdev name. Example: Malloc0') 491 p.add_argument('period', help='Period with which to poll the block device queue depth in microseconds.' 492 ' If set to 0, polling will be disabled.', 493 type=int) 494 p.set_defaults(func=set_bdev_qd_sampling_period) 495 496 def set_bdev_qos_limit(args): 497 rpc.bdev.set_bdev_qos_limit(args.client, 498 name=args.name, 499 rw_ios_per_sec=args.rw_ios_per_sec, 500 rw_mbytes_per_sec=args.rw_mbytes_per_sec, 501 r_mbytes_per_sec=args.r_mbytes_per_sec, 502 w_mbytes_per_sec=args.w_mbytes_per_sec) 503 504 p = subparsers.add_parser('set_bdev_qos_limit', help='Set QoS rate limit on a blockdev') 505 p.add_argument('name', help='Blockdev name to set QoS. Example: Malloc0') 506 p.add_argument('--rw_ios_per_sec', 507 help='R/W IOs per second limit (>=10000, example: 20000). 0 means unlimited.', 508 type=int, required=False) 509 p.add_argument('--rw_mbytes_per_sec', 510 help="R/W megabytes per second limit (>=10, example: 100). 0 means unlimited.", 511 type=int, required=False) 512 p.add_argument('--r_mbytes_per_sec', 513 help="Read megabytes per second limit (>=10, example: 100). 0 means unlimited.", 514 type=int, required=False) 515 p.add_argument('--w_mbytes_per_sec', 516 help="Write megabytes per second limit (>=10, example: 100). 0 means unlimited.", 517 type=int, required=False) 518 p.set_defaults(func=set_bdev_qos_limit) 519 520 def bdev_inject_error(args): 521 rpc.bdev.bdev_inject_error(args.client, 522 name=args.name, 523 io_type=args.io_type, 524 error_type=args.error_type, 525 num=args.num) 526 527 p = subparsers.add_parser('bdev_inject_error', help='bdev inject error') 528 p.add_argument('name', help="""the name of the error injection bdev""") 529 p.add_argument('io_type', help="""io_type: 'clear' 'read' 'write' 'unmap' 'flush' 'all'""") 530 p.add_argument('error_type', help="""error_type: 'failure' 'pending'""") 531 p.add_argument( 532 '-n', '--num', help='the number of commands you want to fail', type=int, default=1) 533 p.set_defaults(func=bdev_inject_error) 534 535 def apply_firmware(args): 536 print_dict(rpc.bdev.apply_firmware(args.client, 537 bdev_name=args.bdev_name, 538 filename=args.filename)) 539 540 p = subparsers.add_parser('apply_firmware', help='Download and commit firmware to NVMe device') 541 p.add_argument('filename', help='filename of the firmware to download') 542 p.add_argument('bdev_name', help='name of the NVMe device') 543 p.set_defaults(func=apply_firmware) 544 545 # iSCSI 546 def set_iscsi_options(args): 547 rpc.iscsi.set_iscsi_options( 548 args.client, 549 auth_file=args.auth_file, 550 node_base=args.node_base, 551 nop_timeout=args.nop_timeout, 552 nop_in_interval=args.nop_in_interval, 553 disable_chap=args.disable_chap, 554 require_chap=args.require_chap, 555 mutual_chap=args.mutual_chap, 556 chap_group=args.chap_group, 557 max_sessions=args.max_sessions, 558 max_queue_depth=args.max_queue_depth, 559 max_connections_per_session=args.max_connections_per_session, 560 default_time2wait=args.default_time2wait, 561 default_time2retain=args.default_time2retain, 562 first_burst_length=args.first_burst_length, 563 immediate_data=args.immediate_data, 564 error_recovery_level=args.error_recovery_level, 565 allow_duplicated_isid=args.allow_duplicated_isid, 566 min_connections_per_core=args.min_connections_per_core) 567 568 p = subparsers.add_parser('set_iscsi_options', help="""Set options of iSCSI subsystem""") 569 p.add_argument('-f', '--auth-file', help='Path to CHAP shared secret file') 570 p.add_argument('-b', '--node-base', help='Prefix of the name of iSCSI target node') 571 p.add_argument('-o', '--nop-timeout', help='Timeout in seconds to nop-in request to the initiator', type=int) 572 p.add_argument('-n', '--nop-in-interval', help='Time interval in secs between nop-in requests by the target', type=int) 573 p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled. 574 *** Mutually exclusive with --require-chap""", action='store_true') 575 p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required. 576 *** Mutually exclusive with --disable-chap""", action='store_true') 577 p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true') 578 p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session. 579 *** Authentication group must be precreated ***""", type=int) 580 p.add_argument('-a', '--max-sessions', help='Maximum number of sessions in the host.', type=int) 581 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/Os per queue.', type=int) 582 p.add_argument('-c', '--max-connections-per-session', help='Negotiated parameter, MaxConnections.', type=int) 583 p.add_argument('-w', '--default-time2wait', help='Negotiated parameter, DefaultTime2Wait.', type=int) 584 p.add_argument('-v', '--default-time2retain', help='Negotiated parameter, DefaultTime2Retain.', type=int) 585 p.add_argument('-s', '--first-burst-length', help='Negotiated parameter, FirstBurstLength.', type=int) 586 p.add_argument('-i', '--immediate-data', help='Negotiated parameter, ImmediateData.', action='store_true') 587 p.add_argument('-l', '--error-recovery-level', help='Negotiated parameter, ErrorRecoveryLevel', type=int) 588 p.add_argument('-p', '--allow-duplicated-isid', help='Allow duplicated initiator session ID.', action='store_true') 589 p.add_argument('-u', '--min-connections-per-core', help='Allocation unit of connections per core', type=int) 590 p.set_defaults(func=set_iscsi_options) 591 592 def set_iscsi_discovery_auth(args): 593 rpc.iscsi.set_iscsi_discovery_auth( 594 args.client, 595 disable_chap=args.disable_chap, 596 require_chap=args.require_chap, 597 mutual_chap=args.mutual_chap, 598 chap_group=args.chap_group) 599 600 p = subparsers.add_parser('set_iscsi_discovery_auth', help="""Set CHAP authentication for discovery session.""") 601 p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled. 602 *** Mutually exclusive with --require-chap""", action='store_true') 603 p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required. 604 *** Mutually exclusive with --disable-chap""", action='store_true') 605 p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true') 606 p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session. 607 *** Authentication group must be precreated ***""", type=int) 608 p.set_defaults(func=set_iscsi_discovery_auth) 609 610 def add_iscsi_auth_group(args): 611 secrets = None 612 if args.secrets: 613 secrets = [dict(u.split(":") for u in a.split(" ")) for a in args.secrets.split(",")] 614 615 rpc.iscsi.add_iscsi_auth_group(args.client, tag=args.tag, secrets=secrets) 616 617 p = subparsers.add_parser('add_iscsi_auth_group', help='Add authentication group for CHAP authentication.') 618 p.add_argument('tag', help='Authentication group tag (unique, integer > 0).', type=int) 619 p.add_argument('-c', '--secrets', help="""Comma-separated list of CHAP secrets 620<user:user_name secret:chap_secret muser:mutual_user_name msecret:mutual_chap_secret> enclosed in quotes. 621Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 msecret:ms2'""", required=False) 622 p.set_defaults(func=add_iscsi_auth_group) 623 624 def delete_iscsi_auth_group(args): 625 rpc.iscsi.delete_iscsi_auth_group(args.client, tag=args.tag) 626 627 p = subparsers.add_parser('delete_iscsi_auth_group', help='Delete an authentication group.') 628 p.add_argument('tag', help='Authentication group tag', type=int) 629 p.set_defaults(func=delete_iscsi_auth_group) 630 631 def add_secret_to_iscsi_auth_group(args): 632 rpc.iscsi.add_secret_to_iscsi_auth_group( 633 args.client, 634 tag=args.tag, 635 user=args.user, 636 secret=args.secret, 637 muser=args.muser, 638 msecret=args.msecret) 639 640 p = subparsers.add_parser('add_secret_to_iscsi_auth_group', help='Add a secret to an authentication group.') 641 p.add_argument('tag', help='Authentication group tag', type=int) 642 p.add_argument('-u', '--user', help='User name for one-way CHAP authentication', required=True) 643 p.add_argument('-s', '--secret', help='Secret for one-way CHAP authentication', required=True) 644 p.add_argument('-m', '--muser', help='User name for mutual CHAP authentication') 645 p.add_argument('-r', '--msecret', help='Secret for mutual CHAP authentication') 646 p.set_defaults(func=add_secret_to_iscsi_auth_group) 647 648 def delete_secret_from_iscsi_auth_group(args): 649 rpc.iscsi.delete_secret_from_iscsi_auth_group(args.client, tag=args.tag, user=args.user) 650 651 p = subparsers.add_parser('delete_secret_from_iscsi_auth_group', help='Delete a secret from an authentication group.') 652 p.add_argument('tag', help='Authentication group tag', type=int) 653 p.add_argument('-u', '--user', help='User name for one-way CHAP authentication', required=True) 654 p.set_defaults(func=delete_secret_from_iscsi_auth_group) 655 656 def get_iscsi_auth_groups(args): 657 print_dict(rpc.iscsi.get_iscsi_auth_groups(args.client)) 658 659 p = subparsers.add_parser('get_iscsi_auth_groups', 660 help='Display current authentication group configuration') 661 p.set_defaults(func=get_iscsi_auth_groups) 662 663 def get_portal_groups(args): 664 print_dict(rpc.iscsi.get_portal_groups(args.client)) 665 666 p = subparsers.add_parser( 667 'get_portal_groups', help='Display current portal group configuration') 668 p.set_defaults(func=get_portal_groups) 669 670 def get_initiator_groups(args): 671 print_dict(rpc.iscsi.get_initiator_groups(args.client)) 672 673 p = subparsers.add_parser('get_initiator_groups', 674 help='Display current initiator group configuration') 675 p.set_defaults(func=get_initiator_groups) 676 677 def get_target_nodes(args): 678 print_dict(rpc.iscsi.get_target_nodes(args.client)) 679 680 p = subparsers.add_parser('get_target_nodes', help='Display target nodes') 681 p.set_defaults(func=get_target_nodes) 682 683 def construct_target_node(args): 684 luns = [] 685 for u in args.bdev_name_id_pairs.strip().split(" "): 686 bdev_name, lun_id = u.split(":") 687 luns.append({"bdev_name": bdev_name, "lun_id": int(lun_id)}) 688 689 pg_ig_maps = [] 690 for u in args.pg_ig_mappings.strip().split(" "): 691 pg, ig = u.split(":") 692 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 693 694 rpc.iscsi.construct_target_node( 695 args.client, 696 luns=luns, 697 pg_ig_maps=pg_ig_maps, 698 name=args.name, 699 alias_name=args.alias_name, 700 queue_depth=args.queue_depth, 701 chap_group=args.chap_group, 702 disable_chap=args.disable_chap, 703 require_chap=args.require_chap, 704 mutual_chap=args.mutual_chap, 705 header_digest=args.header_digest, 706 data_digest=args.data_digest) 707 708 p = subparsers.add_parser('construct_target_node', 709 help='Add a target node') 710 p.add_argument('name', help='Target node name (ASCII)') 711 p.add_argument('alias_name', help='Target node alias name (ASCII)') 712 p.add_argument('bdev_name_id_pairs', help="""Whitespace-separated list of <bdev name:LUN ID> pairs enclosed 713 in quotes. Format: 'bdev_name0:id0 bdev_name1:id1' etc 714 Example: 'Malloc0:0 Malloc1:1 Malloc5:2' 715 *** The bdevs must pre-exist *** 716 *** LUN0 (id = 0) is required *** 717 *** bdevs names cannot contain space or colon characters ***""") 718 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 719 Whitespace separated, quoted, mapping defined with colon 720 separated list of "tags" (int > 0) 721 Example: '1:1 2:2 2:1' 722 *** The Portal/Initiator Groups must be precreated ***""") 723 p.add_argument('queue_depth', help='Desired target queue depth', type=int) 724 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 725 *** Authentication group must be precreated ***""", type=int, default=0) 726 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 727 *** Mutually exclusive with --require-chap ***""", action='store_true') 728 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 729 *** Mutually exclusive with --disable-chap ***""", action='store_true') 730 p.add_argument( 731 '-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', action='store_true') 732 p.add_argument('-H', '--header-digest', 733 help='Header Digest should be required for this target node.', action='store_true') 734 p.add_argument('-D', '--data-digest', 735 help='Data Digest should be required for this target node.', action='store_true') 736 p.set_defaults(func=construct_target_node) 737 738 def target_node_add_lun(args): 739 rpc.iscsi.target_node_add_lun( 740 args.client, 741 name=args.name, 742 bdev_name=args.bdev_name, 743 lun_id=args.lun_id) 744 745 p = subparsers.add_parser('target_node_add_lun', help='Add LUN to the target node') 746 p.add_argument('name', help='Target node name (ASCII)') 747 p.add_argument('bdev_name', help="""bdev name enclosed in quotes. 748 *** bdev name cannot contain space or colon characters ***""") 749 p.add_argument('-i', dest='lun_id', help="""LUN ID (integer >= 0) 750 *** If LUN ID is omitted or -1, the lowest free one is assigned ***""", type=int, required=False) 751 p.set_defaults(func=target_node_add_lun) 752 753 def set_iscsi_target_node_auth(args): 754 rpc.iscsi.set_iscsi_target_node_auth( 755 args.client, 756 name=args.name, 757 chap_group=args.chap_group, 758 disable_chap=args.disable_chap, 759 require_chap=args.require_chap, 760 mutual_chap=args.mutual_chap) 761 762 p = subparsers.add_parser('set_iscsi_target_node_auth', help='Set CHAP authentication for the target node') 763 p.add_argument('name', help='Target node name (ASCII)') 764 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 765 *** Authentication group must be precreated ***""", type=int, default=0) 766 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 767 *** Mutually exclusive with --require-chap ***""", action='store_true') 768 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 769 *** Mutually exclusive with --disable-chap ***""", action='store_true') 770 p.add_argument('-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', 771 action='store_true') 772 p.set_defaults(func=set_iscsi_target_node_auth) 773 774 def add_pg_ig_maps(args): 775 pg_ig_maps = [] 776 for u in args.pg_ig_mappings.strip().split(" "): 777 pg, ig = u.split(":") 778 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 779 rpc.iscsi.add_pg_ig_maps( 780 args.client, 781 pg_ig_maps=pg_ig_maps, 782 name=args.name) 783 784 p = subparsers.add_parser('add_pg_ig_maps', help='Add PG-IG maps to the target node') 785 p.add_argument('name', help='Target node name (ASCII)') 786 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 787 Whitespace separated, quoted, mapping defined with colon 788 separated list of "tags" (int > 0) 789 Example: '1:1 2:2 2:1' 790 *** The Portal/Initiator Groups must be precreated ***""") 791 p.set_defaults(func=add_pg_ig_maps) 792 793 def delete_pg_ig_maps(args): 794 pg_ig_maps = [] 795 for u in args.pg_ig_mappings.strip().split(" "): 796 pg, ig = u.split(":") 797 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 798 rpc.iscsi.delete_pg_ig_maps( 799 args.client, pg_ig_maps=pg_ig_maps, name=args.name) 800 801 p = subparsers.add_parser('delete_pg_ig_maps', help='Delete PG-IG maps from the target node') 802 p.add_argument('name', help='Target node name (ASCII)') 803 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 804 Whitespace separated, quoted, mapping defined with colon 805 separated list of "tags" (int > 0) 806 Example: '1:1 2:2 2:1' 807 *** The Portal/Initiator Groups must be precreated ***""") 808 p.set_defaults(func=delete_pg_ig_maps) 809 810 def add_portal_group(args): 811 portals = [] 812 for p in args.portal_list: 813 ip, separator, port_cpumask = p.rpartition(':') 814 split_port_cpumask = port_cpumask.split('@') 815 if len(split_port_cpumask) == 1: 816 port = port_cpumask 817 portals.append({'host': ip, 'port': port}) 818 else: 819 port = split_port_cpumask[0] 820 cpumask = split_port_cpumask[1] 821 portals.append({'host': ip, 'port': port, 'cpumask': cpumask}) 822 rpc.iscsi.add_portal_group( 823 args.client, 824 portals=portals, 825 tag=args.tag) 826 827 p = subparsers.add_parser('add_portal_group', help='Add a portal group') 828 p.add_argument( 829 'tag', help='Portal group tag (unique, integer > 0)', type=int) 830 p.add_argument('portal_list', nargs=argparse.REMAINDER, help="""List of portals in 'host:port@cpumask' format, separated by whitespace 831 (cpumask is optional and can be skipped) 832 Example: '192.168.100.100:3260' '192.168.100.100:3261' '192.168.100.100:3262@0x1""") 833 p.set_defaults(func=add_portal_group) 834 835 def add_initiator_group(args): 836 initiators = [] 837 netmasks = [] 838 for i in args.initiator_list.strip().split(' '): 839 initiators.append(i) 840 for n in args.netmask_list.strip().split(' '): 841 netmasks.append(n) 842 rpc.iscsi.add_initiator_group( 843 args.client, 844 tag=args.tag, 845 initiators=initiators, 846 netmasks=netmasks) 847 848 p = subparsers.add_parser('add_initiator_group', 849 help='Add an initiator group') 850 p.add_argument( 851 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 852 p.add_argument('initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 853 enclosed in quotes. Example: 'ANY' or '127.0.0.1 192.168.200.100'""") 854 p.add_argument('netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 855 Example: '255.255.0.0 255.248.0.0' etc""") 856 p.set_defaults(func=add_initiator_group) 857 858 def add_initiators_to_initiator_group(args): 859 initiators = None 860 netmasks = None 861 if args.initiator_list: 862 initiators = [] 863 for i in args.initiator_list.strip().split(' '): 864 initiators.append(i) 865 if args.netmask_list: 866 netmasks = [] 867 for n in args.netmask_list.strip().split(' '): 868 netmasks.append(n) 869 rpc.iscsi.add_initiators_to_initiator_group( 870 args.client, 871 tag=args.tag, 872 initiators=initiators, 873 netmasks=netmasks) 874 875 p = subparsers.add_parser('add_initiators_to_initiator_group', 876 help='Add initiators to an existing initiator group') 877 p.add_argument( 878 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 879 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 880 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 881 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 882 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 883 p.set_defaults(func=add_initiators_to_initiator_group) 884 885 def delete_initiators_from_initiator_group(args): 886 initiators = None 887 netmasks = None 888 if args.initiator_list: 889 initiators = [] 890 for i in args.initiator_list.strip().split(' '): 891 initiators.append(i) 892 if args.netmask_list: 893 netmasks = [] 894 for n in args.netmask_list.strip().split(' '): 895 netmasks.append(n) 896 rpc.iscsi.delete_initiators_from_initiator_group( 897 args.client, 898 tag=args.tag, 899 initiators=initiators, 900 netmasks=netmasks) 901 902 p = subparsers.add_parser('delete_initiators_from_initiator_group', 903 help='Delete initiators from an existing initiator group') 904 p.add_argument( 905 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 906 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 907 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 908 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 909 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 910 p.set_defaults(func=delete_initiators_from_initiator_group) 911 912 def delete_target_node(args): 913 rpc.iscsi.delete_target_node( 914 args.client, target_node_name=args.target_node_name) 915 916 p = subparsers.add_parser('delete_target_node', 917 help='Delete a target node') 918 p.add_argument('target_node_name', 919 help='Target node name to be deleted. Example: iqn.2016-06.io.spdk:disk1.') 920 p.set_defaults(func=delete_target_node) 921 922 def delete_portal_group(args): 923 rpc.iscsi.delete_portal_group(args.client, tag=args.tag) 924 925 p = subparsers.add_parser('delete_portal_group', 926 help='Delete a portal group') 927 p.add_argument( 928 'tag', help='Portal group tag (unique, integer > 0)', type=int) 929 p.set_defaults(func=delete_portal_group) 930 931 def delete_initiator_group(args): 932 rpc.iscsi.delete_initiator_group(args.client, tag=args.tag) 933 934 p = subparsers.add_parser('delete_initiator_group', 935 help='Delete an initiator group') 936 p.add_argument( 937 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 938 p.set_defaults(func=delete_initiator_group) 939 940 def get_iscsi_connections(args): 941 print_dict(rpc.iscsi.get_iscsi_connections(args.client)) 942 943 p = subparsers.add_parser('get_iscsi_connections', 944 help='Display iSCSI connections') 945 p.set_defaults(func=get_iscsi_connections) 946 947 def get_iscsi_global_params(args): 948 print_dict(rpc.iscsi.get_iscsi_global_params(args.client)) 949 950 p = subparsers.add_parser('get_iscsi_global_params', help='Display iSCSI global parameters') 951 p.set_defaults(func=get_iscsi_global_params) 952 953 def get_scsi_devices(args): 954 print_dict(rpc.iscsi.get_scsi_devices(args.client)) 955 956 p = subparsers.add_parser('get_scsi_devices', help='Display SCSI devices') 957 p.set_defaults(func=get_scsi_devices) 958 959 # trace 960 def enable_tpoint_group(args): 961 rpc.trace.enable_tpoint_group(args.client, name=args.name) 962 963 p = subparsers.add_parser('enable_tpoint_group', help='enable trace on a specific tpoint group') 964 p.add_argument( 965 'name', help="""trace group name we want to enable in tpoint_group_mask. 966 (for example "bdev" for bdev trace group, "all" for all trace groups).""") 967 p.set_defaults(func=enable_tpoint_group) 968 969 def disable_tpoint_group(args): 970 rpc.trace.disable_tpoint_group(args.client, name=args.name) 971 972 p = subparsers.add_parser('disable_tpoint_group', help='disable trace on a specific tpoint group') 973 p.add_argument( 974 'name', help="""trace group name we want to disable in tpoint_group_mask. 975 (for example "bdev" for bdev trace group, "all" for all trace groups).""") 976 p.set_defaults(func=disable_tpoint_group) 977 978 def get_tpoint_group_mask(args): 979 print_dict(rpc.trace.get_tpoint_group_mask(args.client)) 980 981 p = subparsers.add_parser('get_tpoint_group_mask', help='get trace point group mask') 982 p.set_defaults(func=get_tpoint_group_mask) 983 984 # log 985 def set_log_flag(args): 986 rpc.log.set_log_flag(args.client, flag=args.flag) 987 988 p = subparsers.add_parser('set_log_flag', help='set log flag') 989 p.add_argument( 990 'flag', help='log flag we want to set. (for example "nvme").') 991 p.set_defaults(func=set_log_flag) 992 993 def set_trace_flag(args): 994 print("set_trace_flag is deprecated - use set_log_flag instead") 995 rpc.log.set_trace_flag(args.client, flag=args.flag) 996 997 p = subparsers.add_parser('set_trace_flag', help='set trace flag') 998 p.add_argument( 999 'flag', help='trace mask we want to set. (for example "nvme").') 1000 p.set_defaults(func=set_trace_flag) 1001 1002 def clear_log_flag(args): 1003 rpc.log.clear_log_flag(args.client, flag=args.flag) 1004 1005 p = subparsers.add_parser('clear_log_flag', help='clear log flag') 1006 p.add_argument( 1007 'flag', help='log flag we want to clear. (for example "nvme").') 1008 p.set_defaults(func=clear_log_flag) 1009 1010 def clear_trace_flag(args): 1011 print("clear_trace_flag is deprecated - use clear_log_flag instead") 1012 rpc.log.clear_trace_flag(args.client, flag=args.flag) 1013 1014 p = subparsers.add_parser('clear_trace_flag', help='clear trace flag') 1015 p.add_argument( 1016 'flag', help='trace mask we want to clear. (for example "nvme").') 1017 p.set_defaults(func=clear_trace_flag) 1018 1019 def get_log_flags(args): 1020 print_dict(rpc.log.get_log_flags(args.client)) 1021 1022 p = subparsers.add_parser('get_log_flags', help='get log flags') 1023 p.set_defaults(func=get_log_flags) 1024 1025 def get_trace_flags(args): 1026 print("get_trace_flags is deprecated - use get_log_flags instead") 1027 print_dict(rpc.log.get_trace_flags(args.client)) 1028 1029 p = subparsers.add_parser('get_trace_flags', help='get trace flags') 1030 p.set_defaults(func=get_trace_flags) 1031 1032 def set_log_level(args): 1033 rpc.log.set_log_level(args.client, level=args.level) 1034 1035 p = subparsers.add_parser('set_log_level', help='set log level') 1036 p.add_argument('level', help='log level we want to set. (for example "DEBUG").') 1037 p.set_defaults(func=set_log_level) 1038 1039 def get_log_level(args): 1040 print_dict(rpc.log.get_log_level(args.client)) 1041 1042 p = subparsers.add_parser('get_log_level', help='get log level') 1043 p.set_defaults(func=get_log_level) 1044 1045 def set_log_print_level(args): 1046 rpc.log.set_log_print_level(args.client, level=args.level) 1047 1048 p = subparsers.add_parser('set_log_print_level', help='set log print level') 1049 p.add_argument('level', help='log print level we want to set. (for example "DEBUG").') 1050 p.set_defaults(func=set_log_print_level) 1051 1052 def get_log_print_level(args): 1053 print_dict(rpc.log.get_log_print_level(args.client)) 1054 1055 p = subparsers.add_parser('get_log_print_level', help='get log print level') 1056 p.set_defaults(func=get_log_print_level) 1057 1058 # lvol 1059 def construct_lvol_store(args): 1060 print(rpc.lvol.construct_lvol_store(args.client, 1061 bdev_name=args.bdev_name, 1062 lvs_name=args.lvs_name, 1063 cluster_sz=args.cluster_sz, 1064 clear_method=args.clear_method)) 1065 1066 p = subparsers.add_parser('construct_lvol_store', help='Add logical volume store on base bdev') 1067 p.add_argument('bdev_name', help='base bdev name') 1068 p.add_argument('lvs_name', help='name for lvol store') 1069 p.add_argument('-c', '--cluster-sz', help='size of cluster (in bytes)', type=int, required=False) 1070 p.add_argument('--clear-method', help="""Change clear method for data region. 1071 Available: none, unmap, write_zeroes""", 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