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