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