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 no_discovery_auth=args.no_discovery_auth, 497 req_discovery_auth=args.req_discovery_auth, 498 req_discovery_auth_mutual=args.req_discovery_auth_mutual, 499 discovery_auth_group=args.discovery_auth_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', '--no-discovery-auth', help="""CHAP for discovery session should be disabled. 516 *** Mutually exclusive with --req-discovery-auth""", action='store_true') 517 p.add_argument('-r', '--req-discovery-auth', help="""CHAP for discovery session should be required. 518 *** Mutually exclusive with --no-discovery-auth""", action='store_true') 519 p.add_argument('-m', '--req-discovery-auth-mutual', help='CHAP for discovery session should be mutual', action='store_true') 520 p.add_argument('-g', '--discovery-auth-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 get_portal_groups(args): 535 print_dict(rpc.iscsi.get_portal_groups(args.client)) 536 537 p = subparsers.add_parser( 538 'get_portal_groups', help='Display current portal group configuration') 539 p.set_defaults(func=get_portal_groups) 540 541 @call_cmd 542 def get_initiator_groups(args): 543 print_dict(rpc.iscsi.get_initiator_groups(args.client)) 544 545 p = subparsers.add_parser('get_initiator_groups', 546 help='Display current initiator group configuration') 547 p.set_defaults(func=get_initiator_groups) 548 549 @call_cmd 550 def get_target_nodes(args): 551 print_dict(rpc.iscsi.get_target_nodes(args.client)) 552 553 p = subparsers.add_parser('get_target_nodes', help='Display target nodes') 554 p.set_defaults(func=get_target_nodes) 555 556 @call_cmd 557 def construct_target_node(args): 558 luns = [] 559 for u in args.bdev_name_id_pairs.strip().split(" "): 560 bdev_name, lun_id = u.split(":") 561 luns.append({"bdev_name": bdev_name, "lun_id": int(lun_id)}) 562 563 pg_ig_maps = [] 564 for u in args.pg_ig_mappings.strip().split(" "): 565 pg, ig = u.split(":") 566 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 567 568 rpc.iscsi.construct_target_node( 569 args.client, 570 luns=luns, 571 pg_ig_maps=pg_ig_maps, 572 name=args.name, 573 alias_name=args.alias_name, 574 queue_depth=args.queue_depth, 575 chap_group=args.chap_group, 576 disable_chap=args.disable_chap, 577 require_chap=args.require_chap, 578 mutual_chap=args.mutual_chap, 579 header_digest=args.header_digest, 580 data_digest=args.data_digest) 581 582 p = subparsers.add_parser('construct_target_node', 583 help='Add a target node') 584 p.add_argument('name', help='Target node name (ASCII)') 585 p.add_argument('alias_name', help='Target node alias name (ASCII)') 586 p.add_argument('bdev_name_id_pairs', help="""Whitespace-separated list of <bdev name:LUN ID> pairs enclosed 587 in quotes. Format: 'bdev_name0:id0 bdev_name1:id1' etc 588 Example: 'Malloc0:0 Malloc1:1 Malloc5:2' 589 *** The bdevs must pre-exist *** 590 *** LUN0 (id = 0) is required *** 591 *** bdevs names cannot contain space or colon characters ***""") 592 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 593 Whitespace separated, quoted, mapping defined with colon 594 separated list of "tags" (int > 0) 595 Example: '1:1 2:2 2:1' 596 *** The Portal/Initiator Groups must be precreated ***""") 597 p.add_argument('queue_depth', help='Desired target queue depth', type=int) 598 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 599 *** Authentication group must be precreated ***""", type=int, default=0) 600 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 601 *** Mutually exclusive with --require-chap ***""", action='store_true') 602 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 603 *** Mutually exclusive with --disable-chap ***""", action='store_true') 604 p.add_argument( 605 '-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', action='store_true') 606 p.add_argument('-H', '--header-digest', 607 help='Header Digest should be required for this target node.', action='store_true') 608 p.add_argument('-D', '--data-digest', 609 help='Data Digest should be required for this target node.', action='store_true') 610 p.set_defaults(func=construct_target_node) 611 612 @call_cmd 613 def target_node_add_lun(args): 614 rpc.iscsi.target_node_add_lun( 615 args.client, 616 name=args.name, 617 bdev_name=args.bdev_name, 618 lun_id=args.lun_id) 619 620 p = subparsers.add_parser('target_node_add_lun', help='Add LUN to the target node') 621 p.add_argument('name', help='Target node name (ASCII)') 622 p.add_argument('bdev_name', help="""bdev name enclosed in quotes. 623 *** bdev name cannot contain space or colon characters ***""") 624 p.add_argument('-i', dest='lun_id', help="""LUN ID (integer >= 0) 625 *** If LUN ID is omitted or -1, the lowest free one is assigned ***""", type=int, required=False) 626 p.set_defaults(func=target_node_add_lun) 627 628 @call_cmd 629 def add_pg_ig_maps(args): 630 pg_ig_maps = [] 631 for u in args.pg_ig_mappings.strip().split(" "): 632 pg, ig = u.split(":") 633 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 634 rpc.iscsi.add_pg_ig_maps( 635 args.client, 636 pg_ig_maps=pg_ig_maps, 637 name=args.name) 638 639 p = subparsers.add_parser('add_pg_ig_maps', help='Add PG-IG maps to the target node') 640 p.add_argument('name', help='Target node name (ASCII)') 641 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 642 Whitespace separated, quoted, mapping defined with colon 643 separated list of "tags" (int > 0) 644 Example: '1:1 2:2 2:1' 645 *** The Portal/Initiator Groups must be precreated ***""") 646 p.set_defaults(func=add_pg_ig_maps) 647 648 @call_cmd 649 def delete_pg_ig_maps(args): 650 pg_ig_maps = [] 651 for u in args.pg_ig_mappings.strip().split(" "): 652 pg, ig = u.split(":") 653 pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)}) 654 rpc.iscsi.delete_pg_ig_maps( 655 args.client, pg_ig_maps=pg_ig_maps, name=args.name) 656 657 p = subparsers.add_parser('delete_pg_ig_maps', help='Delete PG-IG maps from the target node') 658 p.add_argument('name', help='Target node name (ASCII)') 659 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 660 Whitespace separated, quoted, mapping defined with colon 661 separated list of "tags" (int > 0) 662 Example: '1:1 2:2 2:1' 663 *** The Portal/Initiator Groups must be precreated ***""") 664 p.set_defaults(func=delete_pg_ig_maps) 665 666 @call_cmd 667 def add_portal_group(args): 668 portals = [] 669 for p in args.portal_list: 670 ip, separator, port_cpumask = p.rpartition(':') 671 split_port_cpumask = port_cpumask.split('@') 672 if len(split_port_cpumask) == 1: 673 port = port_cpumask 674 portals.append({'host': ip, 'port': port}) 675 else: 676 port = split_port_cpumask[0] 677 cpumask = split_port_cpumask[1] 678 portals.append({'host': ip, 'port': port, 'cpumask': cpumask}) 679 rpc.iscsi.add_portal_group( 680 args.client, 681 portals=portals, 682 tag=args.tag) 683 684 p = subparsers.add_parser('add_portal_group', help='Add a portal group') 685 p.add_argument( 686 'tag', help='Portal group tag (unique, integer > 0)', type=int) 687 p.add_argument('portal_list', nargs=argparse.REMAINDER, help="""List of portals in 'host:port@cpumask' format, separated by whitespace 688 (cpumask is optional and can be skipped) 689 Example: '192.168.100.100:3260' '192.168.100.100:3261' '192.168.100.100:3262@0x1""") 690 p.set_defaults(func=add_portal_group) 691 692 @call_cmd 693 def add_initiator_group(args): 694 initiators = [] 695 netmasks = [] 696 for i in args.initiator_list.strip().split(' '): 697 initiators.append(i) 698 for n in args.netmask_list.strip().split(' '): 699 netmasks.append(n) 700 rpc.iscsi.add_initiator_group( 701 args.client, 702 tag=args.tag, 703 initiators=initiators, 704 netmasks=netmasks) 705 706 p = subparsers.add_parser('add_initiator_group', 707 help='Add an initiator group') 708 p.add_argument( 709 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 710 p.add_argument('initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 711 enclosed in quotes. Example: 'ANY' or '127.0.0.1 192.168.200.100'""") 712 p.add_argument('netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 713 Example: '255.255.0.0 255.248.0.0' etc""") 714 p.set_defaults(func=add_initiator_group) 715 716 @call_cmd 717 def add_initiators_to_initiator_group(args): 718 initiators = None 719 netmasks = None 720 if args.initiator_list: 721 initiators = [] 722 for i in args.initiator_list.strip().split(' '): 723 initiators.append(i) 724 if args.netmask_list: 725 netmasks = [] 726 for n in args.netmask_list.strip().split(' '): 727 netmasks.append(n) 728 rpc.iscsi.add_initiators_to_initiator_group( 729 args.client, 730 tag=args.tag, 731 initiators=initiators, 732 netmasks=netmasks) 733 734 p = subparsers.add_parser('add_initiators_to_initiator_group', 735 help='Add initiators to an existing initiator group') 736 p.add_argument( 737 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 738 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 739 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 740 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 741 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 742 p.set_defaults(func=add_initiators_to_initiator_group) 743 744 @call_cmd 745 def delete_initiators_from_initiator_group(args): 746 initiators = None 747 netmasks = None 748 if args.initiator_list: 749 initiators = [] 750 for i in args.initiator_list.strip().split(' '): 751 initiators.append(i) 752 if args.netmask_list: 753 netmasks = [] 754 for n in args.netmask_list.strip().split(' '): 755 netmasks.append(n) 756 rpc.iscsi.delete_initiators_from_initiator_group( 757 args.client, 758 tag=args.tag, 759 initiators=initiators, 760 netmasks=netmasks) 761 762 p = subparsers.add_parser('delete_initiators_from_initiator_group', 763 help='Delete initiators from an existing initiator group') 764 p.add_argument( 765 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 766 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 767 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 768 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 769 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 770 p.set_defaults(func=delete_initiators_from_initiator_group) 771 772 @call_cmd 773 def delete_target_node(args): 774 rpc.iscsi.delete_target_node( 775 args.client, target_node_name=args.target_node_name) 776 777 p = subparsers.add_parser('delete_target_node', 778 help='Delete a target node') 779 p.add_argument('target_node_name', 780 help='Target node name to be deleted. Example: iqn.2016-06.io.spdk:disk1.') 781 p.set_defaults(func=delete_target_node) 782 783 @call_cmd 784 def delete_portal_group(args): 785 rpc.iscsi.delete_portal_group(args.client, tag=args.tag) 786 787 p = subparsers.add_parser('delete_portal_group', 788 help='Delete a portal group') 789 p.add_argument( 790 'tag', help='Portal group tag (unique, integer > 0)', type=int) 791 p.set_defaults(func=delete_portal_group) 792 793 @call_cmd 794 def delete_initiator_group(args): 795 rpc.iscsi.delete_initiator_group(args.client, tag=args.tag) 796 797 p = subparsers.add_parser('delete_initiator_group', 798 help='Delete an initiator group') 799 p.add_argument( 800 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 801 p.set_defaults(func=delete_initiator_group) 802 803 @call_cmd 804 def get_iscsi_connections(args): 805 print_dict(rpc.iscsi.get_iscsi_connections(args.client)) 806 807 p = subparsers.add_parser('get_iscsi_connections', 808 help='Display iSCSI connections') 809 p.set_defaults(func=get_iscsi_connections) 810 811 @call_cmd 812 def get_iscsi_global_params(args): 813 print_dict(rpc.iscsi.get_iscsi_global_params(args.client)) 814 815 p = subparsers.add_parser('get_iscsi_global_params', help='Display iSCSI global parameters') 816 p.set_defaults(func=get_iscsi_global_params) 817 818 @call_cmd 819 def get_scsi_devices(args): 820 print_dict(rpc.iscsi.get_scsi_devices(args.client)) 821 822 p = subparsers.add_parser('get_scsi_devices', help='Display SCSI devices') 823 p.set_defaults(func=get_scsi_devices) 824 825 # log 826 @call_cmd 827 def set_trace_flag(args): 828 rpc.log.set_trace_flag(args.client, flag=args.flag) 829 830 p = subparsers.add_parser('set_trace_flag', help='set trace flag') 831 p.add_argument( 832 'flag', help='trace mask we want to set. (for example "nvme").') 833 p.set_defaults(func=set_trace_flag) 834 835 @call_cmd 836 def clear_trace_flag(args): 837 rpc.log.clear_trace_flag(args.client, flag=args.flag) 838 839 p = subparsers.add_parser('clear_trace_flag', help='clear trace flag') 840 p.add_argument( 841 'flag', help='trace mask we want to clear. (for example "nvme").') 842 p.set_defaults(func=clear_trace_flag) 843 844 @call_cmd 845 def get_trace_flags(args): 846 print_dict(rpc.log.get_trace_flags(args.client)) 847 848 p = subparsers.add_parser('get_trace_flags', help='get trace flags') 849 p.set_defaults(func=get_trace_flags) 850 851 @call_cmd 852 def set_log_level(args): 853 rpc.log.set_log_level(args.client, level=args.level) 854 855 p = subparsers.add_parser('set_log_level', help='set log level') 856 p.add_argument('level', help='log level we want to set. (for example "DEBUG").') 857 p.set_defaults(func=set_log_level) 858 859 @call_cmd 860 def get_log_level(args): 861 print_dict(rpc.log.get_log_level(args.client)) 862 863 p = subparsers.add_parser('get_log_level', help='get log level') 864 p.set_defaults(func=get_log_level) 865 866 @call_cmd 867 def set_log_print_level(args): 868 rpc.log.set_log_print_level(args.client, level=args.level) 869 870 p = subparsers.add_parser('set_log_print_level', help='set log print level') 871 p.add_argument('level', help='log print level we want to set. (for example "DEBUG").') 872 p.set_defaults(func=set_log_print_level) 873 874 @call_cmd 875 def get_log_print_level(args): 876 print_dict(rpc.log.get_log_print_level(args.client)) 877 878 p = subparsers.add_parser('get_log_print_level', help='get log print level') 879 p.set_defaults(func=get_log_print_level) 880 881 # lvol 882 @call_cmd 883 def construct_lvol_store(args): 884 print(rpc.lvol.construct_lvol_store(args.client, 885 bdev_name=args.bdev_name, 886 lvs_name=args.lvs_name, 887 cluster_sz=args.cluster_sz)) 888 889 p = subparsers.add_parser('construct_lvol_store', help='Add logical volume store on base bdev') 890 p.add_argument('bdev_name', help='base bdev name') 891 p.add_argument('lvs_name', help='name for lvol store') 892 p.add_argument('-c', '--cluster-sz', help='size of cluster (in bytes)', type=int, required=False) 893 p.set_defaults(func=construct_lvol_store) 894 895 @call_cmd 896 def rename_lvol_store(args): 897 rpc.lvol.rename_lvol_store(args.client, 898 old_name=args.old_name, 899 new_name=args.new_name) 900 901 p = subparsers.add_parser('rename_lvol_store', help='Change logical volume store name') 902 p.add_argument('old_name', help='old name') 903 p.add_argument('new_name', help='new name') 904 p.set_defaults(func=rename_lvol_store) 905 906 @call_cmd 907 def construct_lvol_bdev(args): 908 print(rpc.lvol.construct_lvol_bdev(args.client, 909 lvol_name=args.lvol_name, 910 size=args.size * 1024 * 1024, 911 thin_provision=args.thin_provision, 912 uuid=args.uuid, 913 lvs_name=args.lvs_name)) 914 915 p = subparsers.add_parser('construct_lvol_bdev', help='Add a bdev with an logical volume backend') 916 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 917 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 918 p.add_argument('-t', '--thin-provision', action='store_true', help='create lvol bdev as thin provisioned') 919 p.add_argument('lvol_name', help='name for this lvol') 920 p.add_argument('size', help='size in MiB for this bdev', type=int) 921 p.set_defaults(func=construct_lvol_bdev) 922 923 @call_cmd 924 def snapshot_lvol_bdev(args): 925 print(rpc.lvol.snapshot_lvol_bdev(args.client, 926 lvol_name=args.lvol_name, 927 snapshot_name=args.snapshot_name)) 928 929 p = subparsers.add_parser('snapshot_lvol_bdev', help='Create a snapshot of an lvol bdev') 930 p.add_argument('lvol_name', help='lvol bdev name') 931 p.add_argument('snapshot_name', help='lvol snapshot name') 932 p.set_defaults(func=snapshot_lvol_bdev) 933 934 @call_cmd 935 def clone_lvol_bdev(args): 936 print(rpc.lvol.clone_lvol_bdev(args.client, 937 snapshot_name=args.snapshot_name, 938 clone_name=args.clone_name)) 939 940 p = subparsers.add_parser('clone_lvol_bdev', help='Create a clone of an lvol snapshot') 941 p.add_argument('snapshot_name', help='lvol snapshot name') 942 p.add_argument('clone_name', help='lvol clone name') 943 p.set_defaults(func=clone_lvol_bdev) 944 945 @call_cmd 946 def rename_lvol_bdev(args): 947 rpc.lvol.rename_lvol_bdev(args.client, 948 old_name=args.old_name, 949 new_name=args.new_name) 950 951 p = subparsers.add_parser('rename_lvol_bdev', help='Change lvol bdev name') 952 p.add_argument('old_name', help='lvol bdev name') 953 p.add_argument('new_name', help='new lvol name') 954 p.set_defaults(func=rename_lvol_bdev) 955 956 @call_cmd 957 def inflate_lvol_bdev(args): 958 rpc.lvol.inflate_lvol_bdev(args.client, 959 name=args.name) 960 961 p = subparsers.add_parser('inflate_lvol_bdev', help='Make thin provisioned lvol a thick provisioned lvol') 962 p.add_argument('name', help='lvol bdev name') 963 p.set_defaults(func=inflate_lvol_bdev) 964 965 @call_cmd 966 def decouple_parent_lvol_bdev(args): 967 rpc.lvol.decouple_parent_lvol_bdev(args.client, 968 name=args.name) 969 970 p = subparsers.add_parser('decouple_parent_lvol_bdev', help='Decouple parent of lvol') 971 p.add_argument('name', help='lvol bdev name') 972 p.set_defaults(func=decouple_parent_lvol_bdev) 973 974 @call_cmd 975 def resize_lvol_bdev(args): 976 rpc.lvol.resize_lvol_bdev(args.client, 977 name=args.name, 978 size=args.size * 1024 * 1024) 979 980 p = subparsers.add_parser('resize_lvol_bdev', help='Resize existing lvol bdev') 981 p.add_argument('name', help='lvol bdev name') 982 p.add_argument('size', help='new size in MiB for this bdev', type=int) 983 p.set_defaults(func=resize_lvol_bdev) 984 985 @call_cmd 986 def destroy_lvol_bdev(args): 987 rpc.lvol.destroy_lvol_bdev(args.client, 988 name=args.name) 989 990 p = subparsers.add_parser('destroy_lvol_bdev', help='Destroy a logical volume') 991 p.add_argument('name', help='lvol bdev name') 992 p.set_defaults(func=destroy_lvol_bdev) 993 994 @call_cmd 995 def destroy_lvol_store(args): 996 rpc.lvol.destroy_lvol_store(args.client, 997 uuid=args.uuid, 998 lvs_name=args.lvs_name) 999 1000 p = subparsers.add_parser('destroy_lvol_store', help='Destroy an logical volume store') 1001 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1002 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1003 p.set_defaults(func=destroy_lvol_store) 1004 1005 @call_cmd 1006 def get_lvol_stores(args): 1007 print_dict(rpc.lvol.get_lvol_stores(args.client, 1008 uuid=args.uuid, 1009 lvs_name=args.lvs_name)) 1010 1011 p = subparsers.add_parser('get_lvol_stores', help='Display current logical volume store list') 1012 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 1013 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 1014 p.set_defaults(func=get_lvol_stores) 1015 1016 @call_cmd 1017 def get_raid_bdevs(args): 1018 print_array(rpc.bdev.get_raid_bdevs(args.client, 1019 category=args.category)) 1020 1021 p = subparsers.add_parser('get_raid_bdevs', help="""This is used to list all the raid bdev names based on the input category 1022 requested. Category should be one of 'all', 'online', 'configuring' or 'offline'. 'all' means all the raid bdevs whether 1023 they are online or configuring or offline. 'online' is the raid bdev which is registered with bdev layer. 'configuring' 1024 is the raid bdev which does not have full configuration discovered yet. 'offline' is the raid bdev which is not registered 1025 with bdev as of now and it has encountered any error or user has requested to offline the raid bdev""") 1026 p.add_argument('category', help='all or online or configuring or offline') 1027 p.set_defaults(func=get_raid_bdevs) 1028 1029 @call_cmd 1030 def construct_raid_bdev(args): 1031 base_bdevs = [] 1032 for u in args.base_bdevs.strip().split(" "): 1033 base_bdevs.append(u) 1034 1035 rpc.bdev.construct_raid_bdev(args.client, 1036 name=args.name, 1037 strip_size=args.strip_size, 1038 raid_level=args.raid_level, 1039 base_bdevs=base_bdevs) 1040 p = subparsers.add_parser('construct_raid_bdev', help='Construct new raid bdev') 1041 p.add_argument('-n', '--name', help='raid bdev name', required=True) 1042 p.add_argument('-s', '--strip-size', help='strip size in KB', type=int, required=True) 1043 p.add_argument('-r', '--raid-level', help='raid level, only raid level 0 is supported', type=int, required=True) 1044 p.add_argument('-b', '--base-bdevs', help='base bdevs name, whitespace separated list in quotes', required=True) 1045 p.set_defaults(func=construct_raid_bdev) 1046 1047 @call_cmd 1048 def destroy_raid_bdev(args): 1049 rpc.bdev.destroy_raid_bdev(args.client, 1050 name=args.name) 1051 p = subparsers.add_parser('destroy_raid_bdev', help='Destroy existing raid bdev') 1052 p.add_argument('name', help='raid bdev name') 1053 p.set_defaults(func=destroy_raid_bdev) 1054 1055 # split 1056 @call_cmd 1057 def construct_split_vbdev(args): 1058 print_array(rpc.bdev.construct_split_vbdev(args.client, 1059 base_bdev=args.base_bdev, 1060 split_count=args.split_count, 1061 split_size_mb=args.split_size_mb)) 1062 1063 p = subparsers.add_parser('construct_split_vbdev', help="""Add given disk name to split config. If bdev with base_name 1064 name exist the split bdevs will be created right away, if not split bdevs will be created when base bdev became 1065 available (during examination process).""") 1066 p.add_argument('base_bdev', help='base bdev name') 1067 p.add_argument('-s', '--split-size-mb', help='size in MiB for each bdev', type=int, default=0) 1068 p.add_argument('split_count', help="""Optional - number of split bdevs to create. Total size * split_count must not 1069 exceed the base bdev size.""", type=int) 1070 p.set_defaults(func=construct_split_vbdev) 1071 1072 @call_cmd 1073 def destruct_split_vbdev(args): 1074 rpc.bdev.destruct_split_vbdev(args.client, 1075 base_bdev=args.base_bdev) 1076 1077 p = subparsers.add_parser('destruct_split_vbdev', help="""Delete split config with all created splits.""") 1078 p.add_argument('base_bdev', help='base bdev name') 1079 p.set_defaults(func=destruct_split_vbdev) 1080 1081 # nbd 1082 @call_cmd 1083 def start_nbd_disk(args): 1084 print(rpc.nbd.start_nbd_disk(args.client, 1085 bdev_name=args.bdev_name, 1086 nbd_device=args.nbd_device)) 1087 1088 p = subparsers.add_parser('start_nbd_disk', help='Export a bdev as a nbd disk') 1089 p.add_argument('bdev_name', help='Blockdev name to be exported. Example: Malloc0.') 1090 p.add_argument('nbd_device', help='Nbd device name to be assigned. Example: /dev/nbd0.') 1091 p.set_defaults(func=start_nbd_disk) 1092 1093 @call_cmd 1094 def stop_nbd_disk(args): 1095 rpc.nbd.stop_nbd_disk(args.client, 1096 nbd_device=args.nbd_device) 1097 1098 p = subparsers.add_parser('stop_nbd_disk', help='Stop a nbd disk') 1099 p.add_argument('nbd_device', help='Nbd device name to be stopped. Example: /dev/nbd0.') 1100 p.set_defaults(func=stop_nbd_disk) 1101 1102 @call_cmd 1103 def get_nbd_disks(args): 1104 print_dict(rpc.nbd.get_nbd_disks(args.client, 1105 nbd_device=args.nbd_device)) 1106 1107 p = subparsers.add_parser('get_nbd_disks', help='Display full or specified nbd device list') 1108 p.add_argument('-n', '--nbd-device', help="Path of the nbd device. Example: /dev/nbd0", required=False) 1109 p.set_defaults(func=get_nbd_disks) 1110 1111 # net 1112 @call_cmd 1113 def add_ip_address(args): 1114 rpc.net.add_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1115 1116 p = subparsers.add_parser('add_ip_address', help='Add IP address') 1117 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1118 p.add_argument('ip_addr', help='ip address will be added.') 1119 p.set_defaults(func=add_ip_address) 1120 1121 @call_cmd 1122 def delete_ip_address(args): 1123 rpc.net.delete_ip_address(args.client, ifc_index=args.ifc_index, ip_addr=args.ip_addr) 1124 1125 p = subparsers.add_parser('delete_ip_address', help='Delete IP address') 1126 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 1127 p.add_argument('ip_addr', help='ip address will be deleted.') 1128 p.set_defaults(func=delete_ip_address) 1129 1130 @call_cmd 1131 def get_interfaces(args): 1132 print_dict(rpc.net.get_interfaces(args.client)) 1133 1134 p = subparsers.add_parser( 1135 'get_interfaces', help='Display current interface list') 1136 p.set_defaults(func=get_interfaces) 1137 1138 # NVMe-oF 1139 @call_cmd 1140 def set_nvmf_target_options(args): 1141 rpc.nvmf.set_nvmf_target_options(args.client, 1142 max_queue_depth=args.max_queue_depth, 1143 max_qpairs_per_ctrlr=args.max_qpairs_per_ctrlr, 1144 in_capsule_data_size=args.in_capsule_data_size, 1145 max_io_size=args.max_io_size, 1146 max_subsystems=args.max_subsystems, 1147 io_unit_size=args.io_unit_size) 1148 1149 p = subparsers.add_parser('set_nvmf_target_options', help='Set NVMf target options') 1150 p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int) 1151 p.add_argument('-p', '--max-qpairs-per-ctrlr', help='Max number of SQ and CQ per controller', type=int) 1152 p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int) 1153 p.add_argument('-i', '--max-io-size', help='Max I/O size (bytes)', type=int) 1154 p.add_argument('-x', '--max-subsystems', help='Max number of NVMf subsystems', type=int) 1155 p.add_argument('-u', '--io-unit-size', help='I/O unit size (bytes)', type=int) 1156 p.set_defaults(func=set_nvmf_target_options) 1157 1158 @call_cmd 1159 def set_nvmf_target_config(args): 1160 rpc.nvmf.set_nvmf_target_config(args.client, 1161 acceptor_poll_rate=args.acceptor_poll_rate) 1162 1163 p = subparsers.add_parser('set_nvmf_target_config', help='Set NVMf target config') 1164 p.add_argument('-r', '--acceptor-poll-rate', help='Polling interval of the acceptor for incoming connections (usec)', type=int) 1165 p.set_defaults(func=set_nvmf_target_config) 1166 1167 @call_cmd 1168 def get_nvmf_subsystems(args): 1169 print_dict(rpc.nvmf.get_nvmf_subsystems(args.client)) 1170 1171 p = subparsers.add_parser('get_nvmf_subsystems', 1172 help='Display nvmf subsystems') 1173 p.set_defaults(func=get_nvmf_subsystems) 1174 1175 @call_cmd 1176 def construct_nvmf_subsystem(args): 1177 listen_addresses = None 1178 hosts = None 1179 namespaces = None 1180 if args.listen: 1181 listen_addresses = [ 1182 dict( 1183 u.split( 1184 ":", 1185 1) for u in a.split(" ")) for a in args.listen.split(",")] 1186 1187 if args.hosts: 1188 hosts = [] 1189 for u in args.hosts.strip().split(" "): 1190 hosts.append(u) 1191 1192 if args.namespaces: 1193 namespaces = [] 1194 for u in args.namespaces.strip().split(" "): 1195 bdev_name = u 1196 nsid = 0 1197 if ':' in u: 1198 (bdev_name, nsid) = u.split(":") 1199 1200 ns_params = {'bdev_name': bdev_name} 1201 1202 nsid = int(nsid) 1203 if nsid != 0: 1204 ns_params['nsid'] = nsid 1205 1206 namespaces.append(ns_params) 1207 1208 rpc.nvmf.construct_nvmf_subsystem(args.client, 1209 nqn=args.nqn, 1210 listen_addresses=listen_addresses, 1211 hosts=hosts, 1212 allow_any_host=args.allow_any_host, 1213 serial_number=args.serial_number, 1214 namespaces=namespaces, 1215 max_namespaces=args.max_namespaces) 1216 1217 p = subparsers.add_parser('construct_nvmf_subsystem', help='Add a nvmf subsystem') 1218 p.add_argument('nqn', help='Target nqn(ASCII)') 1219 p.add_argument('listen', help="""comma-separated list of Listen <trtype:transport_name traddr:address trsvcid:port_id> pairs enclosed 1220 in quotes. Format: 'trtype:transport0 traddr:traddr0 trsvcid:trsvcid0,trtype:transport1 traddr:traddr1 trsvcid:trsvcid1' etc 1221 Example: 'trtype:RDMA traddr:192.168.100.8 trsvcid:4420,trtype:RDMA traddr:192.168.100.9 trsvcid:4420'""") 1222 p.add_argument('hosts', help="""Whitespace-separated list of host nqn list. 1223 Format: 'nqn1 nqn2' etc 1224 Example: 'nqn.2016-06.io.spdk:init nqn.2016-07.io.spdk:init'""") 1225 p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce host NQN whitelist)") 1226 p.add_argument("-s", "--serial-number", help=""" 1227 Format: 'sn' etc 1228 Example: 'SPDK00000000000001'""", default='0000:00:01.0') 1229 p.add_argument("-n", "--namespaces", help="""Whitespace-separated list of namespaces 1230 Format: 'bdev_name1[:nsid1] bdev_name2[:nsid2] bdev_name3[:nsid3]' etc 1231 Example: '1:Malloc0 2:Malloc1 3:Malloc2' 1232 *** The devices must pre-exist ***""") 1233 p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed to added during active connection", 1234 type=int, default=0) 1235 p.set_defaults(func=construct_nvmf_subsystem) 1236 1237 @call_cmd 1238 def delete_nvmf_subsystem(args): 1239 rpc.nvmf.delete_nvmf_subsystem(args.client, 1240 nqn=args.subsystem_nqn) 1241 1242 p = subparsers.add_parser('delete_nvmf_subsystem', 1243 help='Delete a nvmf subsystem') 1244 p.add_argument('subsystem_nqn', 1245 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 1246 p.set_defaults(func=delete_nvmf_subsystem) 1247 1248 @call_cmd 1249 def nvmf_subsystem_add_listener(args): 1250 rpc.nvmf.nvmf_subsystem_add_listener(args.client, 1251 nqn=args.nqn, 1252 trtype=args.trtype, 1253 traddr=args.traddr, 1254 adrfam=args.adrfam, 1255 trsvcid=args.trsvcid) 1256 1257 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 1258 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1259 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1260 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1261 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1262 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1263 p.set_defaults(func=nvmf_subsystem_add_listener) 1264 1265 @call_cmd 1266 def nvmf_subsystem_remove_listener(args): 1267 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, 1268 nqn=args.nqn, 1269 trtype=args.trtype, 1270 traddr=args.traddr, 1271 adrfam=args.adrfam, 1272 trsvcid=args.trsvcid) 1273 1274 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 1275 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1276 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 1277 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 1278 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 1279 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 1280 p.set_defaults(func=nvmf_subsystem_remove_listener) 1281 1282 @call_cmd 1283 def nvmf_subsystem_add_ns(args): 1284 rpc.nvmf.nvmf_subsystem_add_ns(args.client, 1285 nqn=args.nqn, 1286 bdev_name=args.bdev_name, 1287 nsid=args.nsid, 1288 nguid=args.nguid, 1289 eui64=args.eui64, 1290 uuid=args.uuid) 1291 1292 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 1293 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1294 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 1295 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 1296 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 1297 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 1298 p.add_argument('-u', '--uuid', help='Namespace UUID (optional)') 1299 p.set_defaults(func=nvmf_subsystem_add_ns) 1300 1301 @call_cmd 1302 def nvmf_subsystem_remove_ns(args): 1303 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, 1304 nqn=args.nqn, 1305 nsid=args.nsid) 1306 1307 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 1308 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1309 p.add_argument('nsid', help='The requested NSID', type=int) 1310 p.set_defaults(func=nvmf_subsystem_remove_ns) 1311 1312 @call_cmd 1313 def nvmf_subsystem_add_host(args): 1314 rpc.nvmf.nvmf_subsystem_add_host(args.client, 1315 nqn=args.nqn, 1316 host=args.host) 1317 1318 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 1319 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1320 p.add_argument('host', help='Host NQN to allow') 1321 p.set_defaults(func=nvmf_subsystem_add_host) 1322 1323 @call_cmd 1324 def nvmf_subsystem_remove_host(args): 1325 rpc.nvmf.nvmf_subsystem_remove_host(args.client, 1326 nqn=args.nqn, 1327 host=args.host) 1328 1329 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 1330 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1331 p.add_argument('host', help='Host NQN to remove') 1332 p.set_defaults(func=nvmf_subsystem_remove_host) 1333 1334 @call_cmd 1335 def nvmf_subsystem_allow_any_host(args): 1336 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, 1337 nqn=args.nqn, 1338 disable=args.disable) 1339 1340 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 1341 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 1342 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 1343 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 1344 p.set_defaults(func=nvmf_subsystem_allow_any_host) 1345 1346 # pmem 1347 @call_cmd 1348 def create_pmem_pool(args): 1349 num_blocks = int((args.total_size * 1024 * 1024) / args.block_size) 1350 rpc.pmem.create_pmem_pool(args.client, 1351 pmem_file=args.pmem_file, 1352 num_blocks=num_blocks, 1353 block_size=args.block_size) 1354 1355 p = subparsers.add_parser('create_pmem_pool', help='Create pmem pool') 1356 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1357 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 1358 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 1359 p.set_defaults(func=create_pmem_pool) 1360 1361 @call_cmd 1362 def pmem_pool_info(args): 1363 print_dict(rpc.pmem.pmem_pool_info(args.client, 1364 pmem_file=args.pmem_file)) 1365 1366 p = subparsers.add_parser('pmem_pool_info', help='Display pmem pool info and check consistency') 1367 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1368 p.set_defaults(func=pmem_pool_info) 1369 1370 @call_cmd 1371 def delete_pmem_pool(args): 1372 rpc.pmem.delete_pmem_pool(args.client, 1373 pmem_file=args.pmem_file) 1374 1375 p = subparsers.add_parser('delete_pmem_pool', help='Delete pmem pool') 1376 p.add_argument('pmem_file', help='Path to pmemblk pool file') 1377 p.set_defaults(func=delete_pmem_pool) 1378 1379 # subsystem 1380 @call_cmd 1381 def get_subsystems(args): 1382 print_dict(rpc.subsystem.get_subsystems(args.client)) 1383 1384 p = subparsers.add_parser('get_subsystems', help="""Print subsystems array in initialization order. Each subsystem 1385 entry contain (unsorted) array of subsystems it depends on.""") 1386 p.set_defaults(func=get_subsystems) 1387 1388 @call_cmd 1389 def get_subsystem_config(args): 1390 print_dict(rpc.subsystem.get_subsystem_config(args.client, args.name)) 1391 1392 p = subparsers.add_parser('get_subsystem_config', help="""Print subsystem configuration""") 1393 p.add_argument('name', help='Name of subsystem to query') 1394 p.set_defaults(func=get_subsystem_config) 1395 1396 # vhost 1397 @call_cmd 1398 def set_vhost_controller_coalescing(args): 1399 rpc.vhost.set_vhost_controller_coalescing(args.client, 1400 ctrlr=args.ctrlr, 1401 delay_base_us=args.delay_base_us, 1402 iops_threshold=args.iops_threshold) 1403 1404 p = subparsers.add_parser('set_vhost_controller_coalescing', help='Set vhost controller coalescing') 1405 p.add_argument('ctrlr', help='controller name') 1406 p.add_argument('delay_base_us', help='Base delay time', type=int) 1407 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 1408 p.set_defaults(func=set_vhost_controller_coalescing) 1409 1410 @call_cmd 1411 def construct_vhost_scsi_controller(args): 1412 rpc.vhost.construct_vhost_scsi_controller(args.client, 1413 ctrlr=args.ctrlr, 1414 cpumask=args.cpumask) 1415 1416 p = subparsers.add_parser( 1417 'construct_vhost_scsi_controller', help='Add new vhost controller') 1418 p.add_argument('ctrlr', help='controller name') 1419 p.add_argument('--cpumask', help='cpu mask for this controller') 1420 p.set_defaults(func=construct_vhost_scsi_controller) 1421 1422 @call_cmd 1423 def add_vhost_scsi_lun(args): 1424 rpc.vhost.add_vhost_scsi_lun(args.client, 1425 ctrlr=args.ctrlr, 1426 scsi_target_num=args.scsi_target_num, 1427 bdev_name=args.bdev_name) 1428 1429 p = subparsers.add_parser('add_vhost_scsi_lun', 1430 help='Add lun to vhost controller') 1431 p.add_argument('ctrlr', help='conntroller name where add lun') 1432 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 1433 p.add_argument('bdev_name', help='bdev name') 1434 p.set_defaults(func=add_vhost_scsi_lun) 1435 1436 @call_cmd 1437 def remove_vhost_scsi_target(args): 1438 rpc.vhost.remove_vhost_scsi_target(args.client, 1439 ctrlr=args.ctrlr, 1440 scsi_target_num=args.scsi_target_num) 1441 1442 p = subparsers.add_parser('remove_vhost_scsi_target', help='Remove target from vhost controller') 1443 p.add_argument('ctrlr', help='controller name to remove target from') 1444 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 1445 p.set_defaults(func=remove_vhost_scsi_target) 1446 1447 @call_cmd 1448 def construct_vhost_blk_controller(args): 1449 rpc.vhost.construct_vhost_blk_controller(args.client, 1450 ctrlr=args.ctrlr, 1451 dev_name=args.dev_name, 1452 cpumask=args.cpumask, 1453 readonly=args.readonly) 1454 1455 p = subparsers.add_parser('construct_vhost_blk_controller', help='Add a new vhost block controller') 1456 p.add_argument('ctrlr', help='controller name') 1457 p.add_argument('dev_name', help='device name') 1458 p.add_argument('--cpumask', help='cpu mask for this controller') 1459 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 1460 p.set_defaults(func=construct_vhost_blk_controller) 1461 1462 @call_cmd 1463 def construct_vhost_nvme_controller(args): 1464 rpc.vhost.construct_vhost_nvme_controller(args.client, 1465 ctrlr=args.ctrlr, 1466 io_queues=args.io_queues, 1467 cpumask=args.cpumask) 1468 1469 p = subparsers.add_parser('construct_vhost_nvme_controller', help='Add new vhost controller') 1470 p.add_argument('ctrlr', help='controller name') 1471 p.add_argument('io_queues', help='number of IO queues for the controller', type=int) 1472 p.add_argument('--cpumask', help='cpu mask for this controller') 1473 p.set_defaults(func=construct_vhost_nvme_controller) 1474 1475 @call_cmd 1476 def add_vhost_nvme_ns(args): 1477 rpc.vhost.add_vhost_nvme_ns(args.client, 1478 ctrlr=args.ctrlr, 1479 bdev_name=args.bdev_name) 1480 1481 p = subparsers.add_parser('add_vhost_nvme_ns', help='Add a Namespace to vhost controller') 1482 p.add_argument('ctrlr', help='conntroller name where add a Namespace') 1483 p.add_argument('bdev_name', help='block device name for a new Namespace') 1484 p.set_defaults(func=add_vhost_nvme_ns) 1485 1486 @call_cmd 1487 def get_vhost_controllers(args): 1488 print_dict(rpc.vhost.get_vhost_controllers(args.client)) 1489 1490 p = subparsers.add_parser('get_vhost_controllers', help='List vhost controllers') 1491 p.set_defaults(func=get_vhost_controllers) 1492 1493 @call_cmd 1494 def remove_vhost_controller(args): 1495 rpc.vhost.remove_vhost_controller(args.client, 1496 ctrlr=args.ctrlr) 1497 1498 p = subparsers.add_parser('remove_vhost_controller', help='Remove a vhost controller') 1499 p.add_argument('ctrlr', help='controller name') 1500 p.set_defaults(func=remove_vhost_controller) 1501 1502 @call_cmd 1503 def construct_virtio_dev(args): 1504 print_array(rpc.vhost.construct_virtio_dev(args.client, 1505 name=args.name, 1506 trtype=args.trtype, 1507 traddr=args.traddr, 1508 dev_type=args.dev_type, 1509 vq_count=args.vq_count, 1510 vq_size=args.vq_size)) 1511 1512 p = subparsers.add_parser('construct_virtio_dev', help="""Construct new virtio device using provided 1513 transport type and device type. In case of SCSI device type this implies scan and add bdevs offered by 1514 remote side. Result is array of added bdevs.""") 1515 p.add_argument('name', help="Use this name as base for new created bdevs") 1516 p.add_argument('-t', '--trtype', 1517 help='Virtio target transport type: pci or user', required=True) 1518 p.add_argument('-a', '--traddr', 1519 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 1520 p.add_argument('-d', '--dev-type', 1521 help='Device type: blk or scsi', required=True) 1522 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 1523 p.add_argument('--vq-size', help='Size of each queue', type=int) 1524 p.set_defaults(func=construct_virtio_dev) 1525 1526 @call_cmd 1527 def construct_virtio_user_scsi_bdev(args): 1528 print_array(rpc.vhost.construct_virtio_user_scsi_bdev(args.client, 1529 path=args.path, 1530 name=args.name, 1531 vq_count=args.vq_count, 1532 vq_size=args.vq_size)) 1533 1534 p = subparsers.add_parser('construct_virtio_user_scsi_bdev', help="""Connect to virtio user scsi device. 1535 This imply scan and add bdevs offered by remote side. 1536 Result is array of added bdevs.""") 1537 p.add_argument('path', help='Path to Virtio SCSI socket') 1538 p.add_argument('name', help="""Use this name as base instead of 'VirtioScsiN' 1539 Base will be used to construct new bdev's found on target by adding 't<TARGET_ID>' sufix.""") 1540 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 1541 p.add_argument('--vq-size', help='Size of each queue', type=int) 1542 p.set_defaults(func=construct_virtio_user_scsi_bdev) 1543 1544 @call_cmd 1545 def construct_virtio_pci_scsi_bdev(args): 1546 print_array(rpc.vhost.construct_virtio_pci_scsi_bdev(args.client, 1547 pci_address=args.pci_address, 1548 name=args.name)) 1549 1550 p = subparsers.add_parser('construct_virtio_pci_scsi_bdev', help="""Create a Virtio 1551 SCSI device from a virtio-pci device.""") 1552 p.add_argument('pci_address', help="""PCI address in domain:bus:device.function format or 1553 domain.bus.device.function format""") 1554 p.add_argument('name', help="""Name for the virtio device. 1555 It will be inhereted by all created bdevs, which are named n the following format: <name>t<target_id>""") 1556 p.set_defaults(func=construct_virtio_pci_scsi_bdev) 1557 1558 @call_cmd 1559 def get_virtio_scsi_devs(args): 1560 print_dict(rpc.vhost.get_virtio_scsi_devs(args.client)) 1561 1562 p = subparsers.add_parser('get_virtio_scsi_devs', help='List all Virtio-SCSI devices.') 1563 p.set_defaults(func=get_virtio_scsi_devs) 1564 1565 @call_cmd 1566 def remove_virtio_scsi_bdev(args): 1567 rpc.vhost.remove_virtio_scsi_bdev(args.client, 1568 name=args.name) 1569 1570 p = subparsers.add_parser('remove_virtio_scsi_bdev', help="""Remove a Virtio-SCSI device 1571 This will delete all bdevs exposed by this device (this call is deprecated - please use remove_virtio_bdev call instead).""") 1572 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 1573 p.set_defaults(func=remove_virtio_scsi_bdev) 1574 1575 @call_cmd 1576 def remove_virtio_bdev(args): 1577 rpc.vhost.remove_virtio_bdev(args.client, 1578 name=args.name) 1579 1580 p = subparsers.add_parser('remove_virtio_bdev', help="""Remove a Virtio device 1581 This will delete all bdevs exposed by this device""") 1582 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 1583 p.set_defaults(func=remove_virtio_bdev) 1584 1585 @call_cmd 1586 def construct_virtio_user_blk_bdev(args): 1587 print(rpc.vhost.construct_virtio_user_blk_bdev(args.client, 1588 path=args.path, 1589 name=args.name, 1590 vq_count=args.vq_count, 1591 vq_size=args.vq_size)) 1592 1593 p = subparsers.add_parser('construct_virtio_user_blk_bdev', help='Connect to a virtio user blk device.') 1594 p.add_argument('path', help='Path to Virtio BLK socket') 1595 p.add_argument('name', help='Name for the bdev') 1596 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 1597 p.add_argument('--vq-size', help='Size of each queue', type=int) 1598 p.set_defaults(func=construct_virtio_user_blk_bdev) 1599 1600 @call_cmd 1601 def construct_virtio_pci_blk_bdev(args): 1602 print(rpc.vhost.construct_virtio_pci_blk_bdev(args.client, 1603 pci_address=args.pci_address, 1604 name=args.name)) 1605 1606 p = subparsers.add_parser('construct_virtio_pci_blk_bdev', help='Create a Virtio Blk device from a virtio-pci device.') 1607 p.add_argument('pci_address', help="""PCI address in domain:bus:device.function format or 1608 domain.bus.device.function format""") 1609 p.add_argument('name', help='Name for the bdev') 1610 p.set_defaults(func=construct_virtio_pci_blk_bdev) 1611 1612 # ioat 1613 @call_cmd 1614 def scan_ioat_copy_engine(args): 1615 pci_whitelist = [] 1616 if args.pci_whitelist: 1617 for w in args.pci_whitelist.strip().split(" "): 1618 pci_whitelist.append(w) 1619 rpc.ioat.scan_ioat_copy_engine(args.client, pci_whitelist) 1620 1621 p = subparsers.add_parser('scan_ioat_copy_engine', help='Set scan and enable IOAT copy engine offload.') 1622 p.add_argument('-w', '--pci-whitelist', help="""Whitespace-separated list of PCI addresses in 1623 domain:bus:device.function format or domain.bus.device.function format""") 1624 p.set_defaults(func=scan_ioat_copy_engine) 1625 1626 args = parser.parse_args() 1627 1628 try: 1629 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.verbose, args.timeout) 1630 except JSONRPCException as ex: 1631 print(ex.message) 1632 exit(1) 1633 args.func(args) 1634