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