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, args)) 53 54 p = subparsers.add_parser('get_rpc_methods', help='Get list of supported RPC methods') 55 p.add_argument('-c', '--current', help='Get list of RPC methods only callable in the current state.', action='store_true') 56 p.set_defaults(func=get_rpc_methods) 57 58 @call_cmd 59 def save_config(args): 60 rpc.save_config(args.client, args) 61 62 p = subparsers.add_parser('save_config', help="""Write current (live) configuration of SPDK subsystems and targets. 63 If no filename is given write configuration to stdout.""") 64 p.add_argument('-f', '--filename', help="""File where to save JSON configuration to.""") 65 p.add_argument('-i', '--indent', help="""Indent level. Value less than 0 mean compact mode. If filename is not given default 66 indent level is 2. If writing to file of filename is '-' then default is compact mode.""", type=int, default=2) 67 p.set_defaults(func=save_config) 68 69 @call_cmd 70 def load_config(args): 71 rpc.load_config(args.client, args) 72 73 p = subparsers.add_parser('load_config', help="""Configure SPDK subsystems and tagets using JSON RPC. If no file is 74 provided or file is '-' read configuration from stdin.""") 75 p.add_argument('--filename', help="""JSON Configuration file.""") 76 p.set_defaults(func=load_config) 77 78 # app 79 @call_cmd 80 def kill_instance(args): 81 rpc.app.kill_instance(args.client, args) 82 83 p = subparsers.add_parser('kill_instance', help='Send signal to instance') 84 p.add_argument('sig_name', help='signal will be sent to server.') 85 p.set_defaults(func=kill_instance) 86 87 @call_cmd 88 def context_switch_monitor(args): 89 print_dict(rpc.app.context_switch_monitor(args.client, args)) 90 91 p = subparsers.add_parser('context_switch_monitor', help='Control whether the context switch monitor is enabled') 92 p.add_argument('-e', '--enable', action='store_true', help='Enable context switch monitoring') 93 p.add_argument('-d', '--disable', action='store_true', help='Disable context switch monitoring') 94 p.set_defaults(func=context_switch_monitor) 95 96 # bdev 97 @call_cmd 98 def construct_malloc_bdev(args): 99 print_array(rpc.bdev.construct_malloc_bdev(args.client, args)) 100 101 p = subparsers.add_parser('construct_malloc_bdev', 102 help='Add a bdev with malloc backend') 103 p.add_argument('-b', '--name', help="Name of the bdev") 104 p.add_argument('-u', '--uuid', help="UUID of the bdev") 105 p.add_argument( 106 'total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 107 p.add_argument('block_size', help='Block size for this bdev', type=int) 108 p.set_defaults(func=construct_malloc_bdev) 109 110 @call_cmd 111 def construct_null_bdev(args): 112 print_array(rpc.bdev.construct_null_bdev(args.client, args)) 113 114 p = subparsers.add_parser('construct_null_bdev', 115 help='Add a bdev with null backend') 116 p.add_argument('name', help='Block device name') 117 p.add_argument('-u', '--uuid', help='UUID of the bdev') 118 p.add_argument( 119 'total_size', help='Size of null bdev in MB (int > 0)', type=int) 120 p.add_argument('block_size', help='Block size for this bdev', type=int) 121 p.set_defaults(func=construct_null_bdev) 122 123 @call_cmd 124 def construct_aio_bdev(args): 125 print_array(rpc.bdev.construct_aio_bdev(args.client, args)) 126 127 p = subparsers.add_parser('construct_aio_bdev', 128 help='Add a bdev with aio backend') 129 p.add_argument('filename', help='Path to device or file (ex: /dev/sda)') 130 p.add_argument('name', help='Block device name') 131 p.add_argument('block_size', help='Block size for this bdev', type=int, default=argparse.SUPPRESS) 132 p.set_defaults(func=construct_aio_bdev) 133 134 @call_cmd 135 def construct_nvme_bdev(args): 136 print_array(rpc.bdev.construct_nvme_bdev(args.client, args)) 137 138 p = subparsers.add_parser('construct_nvme_bdev', 139 help='Add bdev with nvme backend') 140 p.add_argument('-b', '--name', help="Name of the bdev", required=True) 141 p.add_argument('-t', '--trtype', 142 help='NVMe-oF target trtype: e.g., rdma, pcie', required=True) 143 p.add_argument('-a', '--traddr', 144 help='NVMe-oF target address: e.g., an ip address or BDF', required=True) 145 p.add_argument('-f', '--adrfam', 146 help='NVMe-oF target adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 147 p.add_argument('-s', '--trsvcid', 148 help='NVMe-oF target trsvcid: e.g., a port number') 149 p.add_argument('-n', '--subnqn', help='NVMe-oF target subnqn') 150 p.set_defaults(func=construct_nvme_bdev) 151 152 @call_cmd 153 def construct_rbd_bdev(args): 154 print_array(rpc.bdev.construct_rbd_bdev(args.client, args)) 155 156 p = subparsers.add_parser('construct_rbd_bdev', 157 help='Add a bdev with ceph rbd backend') 158 p.add_argument('-b', '--name', help="Name of the bdev", required=False) 159 p.add_argument('pool_name', help='rbd pool name') 160 p.add_argument('rbd_name', help='rbd image name') 161 p.add_argument('block_size', help='rbd block size', type=int) 162 p.set_defaults(func=construct_rbd_bdev) 163 164 @call_cmd 165 def construct_error_bdev(args): 166 rpc.bdev.construct_error_bdev(args.client, args) 167 168 p = subparsers.add_parser('construct_error_bdev', 169 help='Add bdev with error injection backend') 170 p.add_argument('base_name', help='base bdev name') 171 p.set_defaults(func=construct_error_bdev) 172 173 @call_cmd 174 def construct_pmem_bdev(args): 175 print_array(rpc.bdev.construct_pmem_bdev(args.client, args)) 176 177 p = subparsers.add_parser('construct_pmem_bdev', help='Add a bdev with pmem backend') 178 p.add_argument('pmem_file', help='Path to pmemblk pool file') 179 p.add_argument('-n', '--name', help='Block device name', required=True) 180 p.set_defaults(func=construct_pmem_bdev) 181 182 @call_cmd 183 def construct_passthru_bdev(args): 184 print_array(rpc.bdev.construct_passthru_bdev(args.client, args)) 185 186 p = subparsers.add_parser('construct_passthru_bdev', 187 help='Add a pass through bdev on existing bdev') 188 p.add_argument('-b', '--base-bdev-name', help="Name of the existing bdev", required=True) 189 p.add_argument('-p', '--passthru-bdev-name', help="Name of the passthru bdev", required=True) 190 p.set_defaults(func=construct_passthru_bdev) 191 192 @call_cmd 193 def get_bdevs(args): 194 print_dict(rpc.bdev.get_bdevs(args.client, args)) 195 196 p = subparsers.add_parser( 197 'get_bdevs', help='Display current blockdev list or required blockdev') 198 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 199 p.set_defaults(func=get_bdevs) 200 201 @call_cmd 202 def get_bdevs_config(args): 203 print_dict(rpc.bdev.get_bdevs_config(args.client, args)) 204 205 p = subparsers.add_parser( 206 'get_bdevs_config', help='Display current (live) blockdev configuration list or required blockdev') 207 p.add_argument('-b', '--name', help="Name of the Blockdev. Example: Nvme0n1", required=False) 208 p.set_defaults(func=get_bdevs_config) 209 210 @call_cmd 211 def delete_bdev(args): 212 rpc.bdev.delete_bdev(args.client, args) 213 214 p = subparsers.add_parser('delete_bdev', help='Delete a blockdev') 215 p.add_argument( 216 'bdev_name', help='Blockdev name to be deleted. Example: Malloc0.') 217 p.set_defaults(func=delete_bdev) 218 219 @call_cmd 220 def set_bdev_qos_limit_iops(args): 221 rpc.bdev.set_bdev_qos_limit_iops(args.client, args) 222 223 p = subparsers.add_parser('set_bdev_qos_limit_iops', help='Set QoS IOPS limit on a blockdev') 224 p.add_argument('name', help='Blockdev name to set QoS. Example: Malloc0') 225 p.add_argument('ios_per_sec', 226 help='IOs per second limit (>=10000, example: 20000). 0 means unlimited.', type=int) 227 p.set_defaults(func=set_bdev_qos_limit_iops) 228 229 @call_cmd 230 def bdev_inject_error(args): 231 rpc.bdev.bdev_inject_error(args.client, args) 232 233 p = subparsers.add_parser('bdev_inject_error', help='bdev inject error') 234 p.add_argument('name', help="""the name of the error injection bdev""") 235 p.add_argument('io_type', help="""io_type: 'clear' 'read' 'write' 'unmap' 'flush' 'all'""") 236 p.add_argument('error_type', help="""error_type: 'failure' 'pending'""") 237 p.add_argument( 238 '-n', '--num', help='the number of commands you want to fail', type=int, default=1) 239 p.set_defaults(func=bdev_inject_error) 240 241 @call_cmd 242 def apply_firmware(args): 243 print_dict(rpc.bdev.apply_firmware(args.client, args)) 244 245 p = subparsers.add_parser('apply_firmware', help='Download and commit firmware to NVMe device') 246 p.add_argument('filename', help='filename of the firmware to download') 247 p.add_argument('bdev_name', help='name of the NVMe device') 248 p.set_defaults(func=apply_firmware) 249 250 # iSCSI 251 @call_cmd 252 def get_portal_groups(args): 253 print_dict(rpc.iscsi.get_portal_groups(args.client, args)) 254 255 p = subparsers.add_parser( 256 'get_portal_groups', help='Display current portal group configuration') 257 p.set_defaults(func=get_portal_groups) 258 259 @call_cmd 260 def get_initiator_groups(args): 261 print_dict(rpc.iscsi.get_initiator_groups(args.client, args)) 262 263 p = subparsers.add_parser('get_initiator_groups', 264 help='Display current initiator group configuration') 265 p.set_defaults(func=get_initiator_groups) 266 267 @call_cmd 268 def get_target_nodes(args): 269 print_dict(rpc.iscsi.get_target_nodes(args.client, args)) 270 271 p = subparsers.add_parser('get_target_nodes', help='Display target nodes') 272 p.set_defaults(func=get_target_nodes) 273 274 @call_cmd 275 def construct_target_node(args): 276 rpc.iscsi.construct_target_node(args.client, args) 277 278 p = subparsers.add_parser('construct_target_node', 279 help='Add a target node') 280 p.add_argument('name', help='Target node name (ASCII)') 281 p.add_argument('alias_name', help='Target node alias name (ASCII)') 282 p.add_argument('bdev_name_id_pairs', help="""Whitespace-separated list of <bdev name:LUN ID> pairs enclosed 283 in quotes. Format: 'bdev_name0:id0 bdev_name1:id1' etc 284 Example: 'Malloc0:0 Malloc1:1 Malloc5:2' 285 *** The bdevs must pre-exist *** 286 *** LUN0 (id = 0) is required *** 287 *** bdevs names cannot contain space or colon characters ***""") 288 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 289 Whitespace separated, quoted, mapping defined with colon 290 separated list of "tags" (int > 0) 291 Example: '1:1 2:2 2:1' 292 *** The Portal/Initiator Groups must be precreated ***""") 293 p.add_argument('queue_depth', help='Desired target queue depth', type=int) 294 p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node. 295 *** Authentication group must be precreated ***""", type=int, default=0) 296 p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node. 297 *** Mutually exclusive with --require-chap ***""", action='store_true') 298 p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node. 299 *** Mutually exclusive with --disable-chap ***""", action='store_true') 300 p.add_argument( 301 '-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.', action='store_true') 302 p.add_argument('-H', '--header-digest', 303 help='Header Digest should be required for this target node.', action='store_true') 304 p.add_argument('-D', '--data-digest', 305 help='Data Digest should be required for this target node.', action='store_true') 306 p.set_defaults(func=construct_target_node) 307 308 @call_cmd 309 def target_node_add_lun(args): 310 rpc.iscsi.target_node_add_lun(args.client, args) 311 312 p = subparsers.add_parser('target_node_add_lun', help='Add LUN to the target node') 313 p.add_argument('name', help='Target node name (ASCII)') 314 p.add_argument('bdev_name', help="""bdev name enclosed in quotes. 315 *** bdev name cannot contain space or colon characters ***""") 316 p.add_argument('-i', dest='lun_id', help="""LUN ID (integer >= 0) 317 *** If LUN ID is omitted or -1, the lowest free one is assigned ***""", type=int, required=False) 318 p.set_defaults(func=target_node_add_lun) 319 320 @call_cmd 321 def add_pg_ig_maps(args): 322 rpc.iscsi.add_pg_ig_maps(args.client, args) 323 324 p = subparsers.add_parser('add_pg_ig_maps', help='Add PG-IG maps to the target node') 325 p.add_argument('name', help='Target node name (ASCII)') 326 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 327 Whitespace separated, quoted, mapping defined with colon 328 separated list of "tags" (int > 0) 329 Example: '1:1 2:2 2:1' 330 *** The Portal/Initiator Groups must be precreated ***""") 331 p.set_defaults(func=add_pg_ig_maps) 332 333 @call_cmd 334 def delete_pg_ig_maps(args): 335 rpc.iscsi.delete_pg_ig_maps(args.client, args) 336 337 p = subparsers.add_parser('delete_pg_ig_maps', help='Delete PG-IG maps from the target node') 338 p.add_argument('name', help='Target node name (ASCII)') 339 p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings 340 Whitespace separated, quoted, mapping defined with colon 341 separated list of "tags" (int > 0) 342 Example: '1:1 2:2 2:1' 343 *** The Portal/Initiator Groups must be precreated ***""") 344 p.set_defaults(func=delete_pg_ig_maps) 345 346 @call_cmd 347 def add_portal_group(args): 348 rpc.iscsi.add_portal_group(args.client, args) 349 350 p = subparsers.add_parser('add_portal_group', help='Add a portal group') 351 p.add_argument( 352 'tag', help='Portal group tag (unique, integer > 0)', type=int) 353 p.add_argument('portal_list', nargs=argparse.REMAINDER, help="""List of portals in 'host:port@cpumask' format, separated by whitespace 354 (cpumask is optional and can be skipped) 355 Example: '192.168.100.100:3260' '192.168.100.100:3261' '192.168.100.100:3262@0x1""") 356 p.set_defaults(func=add_portal_group) 357 358 @call_cmd 359 def add_initiator_group(args): 360 rpc.iscsi.add_initiator_group(args.client, args) 361 362 p = subparsers.add_parser('add_initiator_group', 363 help='Add an initiator group') 364 p.add_argument( 365 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 366 p.add_argument('initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 367 enclosed in quotes. Example: 'ANY' or '127.0.0.1 192.168.200.100'""") 368 p.add_argument('netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 369 Example: '255.255.0.0 255.248.0.0' etc""") 370 p.set_defaults(func=add_initiator_group) 371 372 @call_cmd 373 def add_initiators_to_initiator_group(args): 374 rpc.iscsi.add_initiators_to_initiator_group(args.client, args) 375 376 p = subparsers.add_parser('add_initiators_to_initiator_group', 377 help='Add initiators to an existing initiator group') 378 p.add_argument( 379 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 380 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 381 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 382 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 383 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 384 p.set_defaults(func=add_initiators_to_initiator_group) 385 386 @call_cmd 387 def delete_initiators_from_initiator_group(args): 388 rpc.iscsi.delete_initiators_from_initiator_group(args.client, args) 389 390 p = subparsers.add_parser('delete_initiators_from_initiator_group', 391 help='Delete initiators from an existing initiator group') 392 p.add_argument( 393 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 394 p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses, 395 enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False) 396 p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes. 397 This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False) 398 p.set_defaults(func=delete_initiators_from_initiator_group) 399 400 @call_cmd 401 def delete_target_node(args): 402 rpc.iscsi.delete_target_node(args.client, args) 403 404 p = subparsers.add_parser('delete_target_node', 405 help='Delete a target node') 406 p.add_argument('target_node_name', 407 help='Target node name to be deleted. Example: iqn.2016-06.io.spdk:disk1.') 408 p.set_defaults(func=delete_target_node) 409 410 @call_cmd 411 def delete_portal_group(args): 412 rpc.iscsi.delete_portal_group(args.client, args) 413 414 p = subparsers.add_parser('delete_portal_group', 415 help='Delete a portal group') 416 p.add_argument( 417 'tag', help='Portal group tag (unique, integer > 0)', type=int) 418 p.set_defaults(func=delete_portal_group) 419 420 @call_cmd 421 def delete_initiator_group(args): 422 rpc.iscsi.delete_initiator_group(args.client, args) 423 424 p = subparsers.add_parser('delete_initiator_group', 425 help='Delete an initiator group') 426 p.add_argument( 427 'tag', help='Initiator group tag (unique, integer > 0)', type=int) 428 p.set_defaults(func=delete_initiator_group) 429 430 @call_cmd 431 def get_iscsi_connections(args): 432 print_dict(rpc.iscsi.get_iscsi_connections(args.client, args)) 433 434 p = subparsers.add_parser('get_iscsi_connections', 435 help='Display iSCSI connections') 436 p.set_defaults(func=get_iscsi_connections) 437 438 @call_cmd 439 def get_iscsi_global_params(args): 440 print_dict(rpc.iscsi.get_iscsi_global_params(args.client, args)) 441 442 p = subparsers.add_parser('get_iscsi_global_params', help='Display iSCSI global parameters') 443 p.set_defaults(func=get_iscsi_global_params) 444 445 @call_cmd 446 def get_scsi_devices(args): 447 print_dict(rpc.iscsi.get_scsi_devices(args.client, args)) 448 449 p = subparsers.add_parser('get_scsi_devices', help='Display SCSI devices') 450 p.set_defaults(func=get_scsi_devices) 451 452 # log 453 @call_cmd 454 def set_trace_flag(args): 455 rpc.log.set_trace_flag(args.client, args) 456 457 p = subparsers.add_parser('set_trace_flag', help='set trace flag') 458 p.add_argument( 459 'flag', help='trace mask we want to set. (for example "nvme").') 460 p.set_defaults(func=set_trace_flag) 461 462 @call_cmd 463 def clear_trace_flag(args): 464 rpc.log.clear_trace_flag(args.client, args) 465 466 p = subparsers.add_parser('clear_trace_flag', help='clear trace flag') 467 p.add_argument( 468 'flag', help='trace mask we want to clear. (for example "nvme").') 469 p.set_defaults(func=clear_trace_flag) 470 471 @call_cmd 472 def get_trace_flags(args): 473 print_dict(rpc.log.get_trace_flags(args.client, args)) 474 475 p = subparsers.add_parser('get_trace_flags', help='get trace flags') 476 p.set_defaults(func=get_trace_flags) 477 478 @call_cmd 479 def set_log_level(args): 480 rpc.log.set_log_level(args.client, args) 481 482 p = subparsers.add_parser('set_log_level', help='set log level') 483 p.add_argument('level', help='log level we want to set. (for example "DEBUG").') 484 p.set_defaults(func=set_log_level) 485 486 @call_cmd 487 def get_log_level(args): 488 print_dict(rpc.log.get_log_level(args.client, args)) 489 490 p = subparsers.add_parser('get_log_level', help='get log level') 491 p.set_defaults(func=get_log_level) 492 493 @call_cmd 494 def set_log_print_level(args): 495 rpc.log.set_log_print_level(args.client, args) 496 497 p = subparsers.add_parser('set_log_print_level', help='set log print level') 498 p.add_argument('level', help='log print level we want to set. (for example "DEBUG").') 499 p.set_defaults(func=set_log_print_level) 500 501 @call_cmd 502 def get_log_print_level(args): 503 print_dict(rpc.log.get_log_print_level(args.client, args)) 504 505 p = subparsers.add_parser('get_log_print_level', help='get log print level') 506 p.set_defaults(func=get_log_print_level) 507 508 # lvol 509 @call_cmd 510 def construct_lvol_store(args): 511 print_array(rpc.lvol.construct_lvol_store(args.client, 512 bdev_name=args.bdev_name, 513 lvs_name=args.lvs_name, 514 cluster_sz=args.cluster_sz)) 515 516 p = subparsers.add_parser('construct_lvol_store', help='Add logical volume store on base bdev') 517 p.add_argument('bdev_name', help='base bdev name') 518 p.add_argument('lvs_name', help='name for lvol store') 519 p.add_argument('-c', '--cluster-sz', help='size of cluster (in bytes)', type=int, required=False) 520 p.set_defaults(func=construct_lvol_store) 521 522 @call_cmd 523 def rename_lvol_store(args): 524 rpc.lvol.rename_lvol_store(args.client, 525 old_name=args.old_name, 526 new_name=args.new_name) 527 528 p = subparsers.add_parser('rename_lvol_store', help='Change logical volume store name') 529 p.add_argument('old_name', help='old name') 530 p.add_argument('new_name', help='new name') 531 p.set_defaults(func=rename_lvol_store) 532 533 @call_cmd 534 def construct_lvol_bdev(args): 535 print_array(rpc.lvol.construct_lvol_bdev(args.client, 536 lvol_name=args.lvol_name, 537 size=args.size * 1024 * 1024, 538 thin_provision=args.thin_provision, 539 uuid=args.uuid, 540 lvs_name=args.lvs_name)) 541 542 p = subparsers.add_parser('construct_lvol_bdev', help='Add a bdev with an logical volume backend') 543 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 544 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 545 p.add_argument('-t', '--thin-provision', action='store_true', help='create lvol bdev as thin provisioned') 546 p.add_argument('lvol_name', help='name for this lvol') 547 p.add_argument('size', help='size in MiB for this bdev', type=int) 548 p.set_defaults(func=construct_lvol_bdev) 549 550 @call_cmd 551 def snapshot_lvol_bdev(args): 552 rpc.lvol.snapshot_lvol_bdev(args.client, 553 lvol_name=args.lvol_name, 554 snapshot_name=args.snapshot_name) 555 556 p = subparsers.add_parser('snapshot_lvol_bdev', help='Create a snapshot of an lvol bdev') 557 p.add_argument('lvol_name', help='lvol bdev name') 558 p.add_argument('snapshot_name', help='lvol snapshot name') 559 p.set_defaults(func=snapshot_lvol_bdev) 560 561 @call_cmd 562 def clone_lvol_bdev(args): 563 rpc.lvol.clone_lvol_bdev(args.client, 564 snapshot_name=args.snapshot_name, 565 clone_name=args.clone_name) 566 567 p = subparsers.add_parser('clone_lvol_bdev', help='Create a clone of an lvol snapshot') 568 p.add_argument('snapshot_name', help='lvol snapshot name') 569 p.add_argument('clone_name', help='lvol clone name') 570 p.set_defaults(func=clone_lvol_bdev) 571 572 @call_cmd 573 def rename_lvol_bdev(args): 574 rpc.lvol.rename_lvol_bdev(args.client, 575 old_name=args.old_name, 576 new_name=args.new_name) 577 578 p = subparsers.add_parser('rename_lvol_bdev', help='Change lvol bdev name') 579 p.add_argument('old_name', help='lvol bdev name') 580 p.add_argument('new_name', help='new lvol name') 581 p.set_defaults(func=rename_lvol_bdev) 582 583 @call_cmd 584 def resize_lvol_bdev(args): 585 rpc.lvol.resize_lvol_bdev(args.client, 586 name=args.name, 587 size=args.size * 1024 * 1024) 588 589 p = subparsers.add_parser('resize_lvol_bdev', help='Resize existing lvol bdev') 590 p.add_argument('name', help='lvol bdev name') 591 p.add_argument('size', help='new size in MiB for this bdev', type=int) 592 p.set_defaults(func=resize_lvol_bdev) 593 594 @call_cmd 595 def destroy_lvol_bdev(args): 596 rpc.lvol.destroy_lvol_bdev(args.client, 597 name=args.name) 598 599 p = subparsers.add_parser('destroy_lvol_bdev', help='Destroy a logical volume') 600 p.add_argument('name', help='lvol bdev name') 601 p.set_defaults(func=destroy_lvol_bdev) 602 603 @call_cmd 604 def destroy_lvol_store(args): 605 rpc.lvol.destroy_lvol_store(args.client, 606 uuid=args.uuid, 607 lvs_name=args.lvs_name) 608 609 p = subparsers.add_parser('destroy_lvol_store', help='Destroy an logical volume store') 610 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 611 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 612 p.set_defaults(func=destroy_lvol_store) 613 614 @call_cmd 615 def get_lvol_stores(args): 616 print_dict(rpc.lvol.get_lvol_stores(args.client, 617 uuid=args.uuid, 618 lvs_name=args.lvs_name)) 619 620 p = subparsers.add_parser('get_lvol_stores', help='Display current logical volume store list') 621 p.add_argument('-u', '--uuid', help='lvol store UUID', required=False) 622 p.add_argument('-l', '--lvs-name', help='lvol store name', required=False) 623 p.set_defaults(func=get_lvol_stores) 624 625 # split 626 def construct_split_vbdev(args): 627 print_dict(rpc.bdev.construct_split_vbdev(args.client, args)) 628 629 p = subparsers.add_parser('construct_split_vbdev', help="""Add given disk name to split config. If bdev with base_name 630 name exist the split bdevs will be created right away, if not split bdevs will be created when base bdev became 631 available (during examination process).""") 632 p.add_argument('base_bdev', help='base bdev name') 633 p.add_argument('-s', '--split-size-mb', help='size in MiB for each bdev', type=int, default=0) 634 p.add_argument('split_count', help="""Optional - number of split bdevs to create. Total size * split_count must not 635 exceed the base bdev size.""", type=int) 636 p.set_defaults(func=construct_split_vbdev) 637 638 def destruct_split_vbdev(args): 639 rpc.destruct_split_vbdev(args.client, args) 640 641 p = subparsers.add_parser('destruct_split_vbdev', help="""Delete split config with all created splits.""") 642 p.add_argument('base_bdev', help='base bdev name') 643 p.set_defaults(func=destruct_split_vbdev) 644 645 # nbd 646 @call_cmd 647 def start_nbd_disk(args): 648 rpc.nbd.start_nbd_disk(args.client, 649 bdev_name=args.bdev_name, 650 nbd_device=args.nbd_device) 651 652 p = subparsers.add_parser('start_nbd_disk', help='Export a bdev as a nbd disk') 653 p.add_argument('bdev_name', help='Blockdev name to be exported. Example: Malloc0.') 654 p.add_argument('nbd_device', help='Nbd device name to be assigned. Example: /dev/nbd0.') 655 p.set_defaults(func=start_nbd_disk) 656 657 @call_cmd 658 def stop_nbd_disk(args): 659 rpc.nbd.stop_nbd_disk(args.client, 660 nbd_device=args.nbd_device) 661 662 p = subparsers.add_parser('stop_nbd_disk', help='Stop a nbd disk') 663 p.add_argument('nbd_device', help='Nbd device name to be stopped. Example: /dev/nbd0.') 664 p.set_defaults(func=stop_nbd_disk) 665 666 @call_cmd 667 def get_nbd_disks(args): 668 print_dict(rpc.nbd.get_nbd_disks(args.client, 669 nbd_device=args.nbd_device)) 670 671 p = subparsers.add_parser('get_nbd_disks', help='Display full or specified nbd device list') 672 p.add_argument('-n', '--nbd-device', help="Path of the nbd device. Example: /dev/nbd0", required=False) 673 p.set_defaults(func=get_nbd_disks) 674 675 # net 676 @call_cmd 677 def add_ip_address(args): 678 rpc.net.add_ip_address(args.client, args) 679 680 p = subparsers.add_parser('add_ip_address', help='Add IP address') 681 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 682 p.add_argument('ip_addr', help='ip address will be added.') 683 p.set_defaults(func=add_ip_address) 684 685 @call_cmd 686 def delete_ip_address(args): 687 rpc.net.delete_ip_address(args.client, args) 688 689 p = subparsers.add_parser('delete_ip_address', help='Delete IP address') 690 p.add_argument('ifc_index', help='ifc index of the nic device.', type=int) 691 p.add_argument('ip_addr', help='ip address will be deleted.') 692 p.set_defaults(func=delete_ip_address) 693 694 @call_cmd 695 def get_interfaces(args): 696 print_dict(rpc.net.get_interfaces(args.client, args)) 697 698 p = subparsers.add_parser( 699 'get_interfaces', help='Display current interface list') 700 p.set_defaults(func=get_interfaces) 701 702 # NVMe-oF 703 @call_cmd 704 def get_nvmf_subsystems(args): 705 print_dict(rpc.nvmf.get_nvmf_subsystems(args.client, args)) 706 707 p = subparsers.add_parser('get_nvmf_subsystems', 708 help='Display nvmf subsystems') 709 p.set_defaults(func=get_nvmf_subsystems) 710 711 @call_cmd 712 def construct_nvmf_subsystem(args): 713 rpc.nvmf.construct_nvmf_subsystem(args.client, args) 714 715 p = subparsers.add_parser('construct_nvmf_subsystem', help='Add a nvmf subsystem') 716 p.add_argument('nqn', help='Target nqn(ASCII)') 717 p.add_argument('listen', help="""comma-separated list of Listen <trtype:transport_name traddr:address trsvcid:port_id> pairs enclosed 718 in quotes. Format: 'trtype:transport0 traddr:traddr0 trsvcid:trsvcid0,trtype:transport1 traddr:traddr1 trsvcid:trsvcid1' etc 719 Example: 'trtype:RDMA traddr:192.168.100.8 trsvcid:4420,trtype:RDMA traddr:192.168.100.9 trsvcid:4420'""") 720 p.add_argument('hosts', help="""Whitespace-separated list of host nqn list. 721 Format: 'nqn1 nqn2' etc 722 Example: 'nqn.2016-06.io.spdk:init nqn.2016-07.io.spdk:init'""") 723 p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce host NQN whitelist)") 724 p.add_argument("-s", "--serial-number", help=""" 725 Format: 'sn' etc 726 Example: 'SPDK00000000000001'""", default='0000:00:01.0') 727 p.add_argument("-n", "--namespaces", help="""Whitespace-separated list of namespaces 728 Format: 'bdev_name1[:nsid1] bdev_name2[:nsid2] bdev_name3[:nsid3]' etc 729 Example: '1:Malloc0 2:Malloc1 3:Malloc2' 730 *** The devices must pre-exist ***""") 731 p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed to added during active connection", 732 type=int, default=0) 733 p.set_defaults(func=construct_nvmf_subsystem) 734 735 @call_cmd 736 def delete_nvmf_subsystem(args): 737 rpc.nvmf.delete_nvmf_subsystem(args.client, args) 738 739 p = subparsers.add_parser('delete_nvmf_subsystem', 740 help='Delete a nvmf subsystem') 741 p.add_argument('subsystem_nqn', 742 help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') 743 p.set_defaults(func=delete_nvmf_subsystem) 744 745 @call_cmd 746 def nvmf_subsystem_add_listener(args): 747 rpc.nvmf.nvmf_subsystem_add_listener(args.client, args) 748 749 p = subparsers.add_parser('nvmf_subsystem_add_listener', help='Add a listener to an NVMe-oF subsystem') 750 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 751 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 752 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 753 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 754 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 755 p.set_defaults(func=nvmf_subsystem_add_listener) 756 757 @call_cmd 758 def nvmf_subsystem_remove_listener(args): 759 rpc.nvmf.nvmf_subsystem_remove_listener(args.client, args) 760 761 p = subparsers.add_parser('nvmf_subsystem_remove_listener', help='Remove a listener from an NVMe-oF subsystem') 762 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 763 p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True) 764 p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True) 765 p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host') 766 p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number') 767 p.set_defaults(func=nvmf_subsystem_remove_listener) 768 769 @call_cmd 770 def nvmf_subsystem_add_ns(args): 771 rpc.nvmf.nvmf_subsystem_add_ns(args.client, args) 772 773 p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem') 774 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 775 p.add_argument('bdev_name', help='The name of the bdev that will back this namespace') 776 p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int) 777 p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)') 778 p.add_argument('-e', '--eui64', help='Namespace EUI-64 identifier (optional)') 779 p.set_defaults(func=nvmf_subsystem_add_ns) 780 781 @call_cmd 782 def nvmf_subsystem_remove_ns(args): 783 rpc.nvmf.nvmf_subsystem_remove_ns(args.client, args) 784 785 p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem') 786 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 787 p.add_argument('nsid', help='The requested NSID', type=int) 788 p.set_defaults(func=nvmf_subsystem_remove_ns) 789 790 @call_cmd 791 def nvmf_subsystem_add_host(args): 792 rpc.nvmf.nvmf_subsystem_add_host(args.client, args) 793 794 p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem') 795 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 796 p.add_argument('host', help='Host NQN to allow') 797 p.set_defaults(func=nvmf_subsystem_add_host) 798 799 @call_cmd 800 def nvmf_subsystem_remove_host(args): 801 rpc.nvmf.nvmf_subsystem_remove_host(args.client, args) 802 803 p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem') 804 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 805 p.add_argument('host', help='Host NQN to remove') 806 p.set_defaults(func=nvmf_subsystem_remove_host) 807 808 @call_cmd 809 def nvmf_subsystem_allow_any_host(args): 810 rpc.nvmf.nvmf_subsystem_allow_any_host(args.client, args) 811 812 p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem') 813 p.add_argument('nqn', help='NVMe-oF subsystem NQN') 814 p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host') 815 p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host') 816 p.set_defaults(func=nvmf_subsystem_allow_any_host) 817 818 # pmem 819 @call_cmd 820 def create_pmem_pool(args): 821 rpc.pmem.create_pmem_pool(args.client, args) 822 823 p = subparsers.add_parser('create_pmem_pool', help='Create pmem pool') 824 p.add_argument('pmem_file', help='Path to pmemblk pool file') 825 p.add_argument('total_size', help='Size of malloc bdev in MB (int > 0)', type=int) 826 p.add_argument('block_size', help='Block size for this pmem pool', type=int) 827 p.set_defaults(func=create_pmem_pool) 828 829 @call_cmd 830 def pmem_pool_info(args): 831 print_dict(rpc.pmem.pmem_pool_info(args.client, args)) 832 833 p = subparsers.add_parser('pmem_pool_info', help='Display pmem pool info and check consistency') 834 p.add_argument('pmem_file', help='Path to pmemblk pool file') 835 p.set_defaults(func=pmem_pool_info) 836 837 @call_cmd 838 def delete_pmem_pool(args): 839 rpc.pmem.delete_pmem_pool(args.client, args) 840 841 p = subparsers.add_parser('delete_pmem_pool', help='Delete pmem pool') 842 p.add_argument('pmem_file', help='Path to pmemblk pool file') 843 p.set_defaults(func=delete_pmem_pool) 844 845 # subsystem 846 @call_cmd 847 def get_subsystems(args): 848 print_dict(rpc.subsystem.get_subsystems(args.client)) 849 850 p = subparsers.add_parser('get_subsystems', help="""Print subsystems array in initialization order. Each subsystem 851 entry contain (unsorted) array of subsystems it depends on.""") 852 p.set_defaults(func=get_subsystems) 853 854 @call_cmd 855 def get_subsystem_config(args): 856 print_dict(rpc.subsystem.get_subsystem_config(args.client, args.name)) 857 858 p = subparsers.add_parser('get_subsystem_config', help="""Print subsystem configuration""") 859 p.add_argument('name', help='Name of subsystem to query') 860 p.set_defaults(func=get_subsystem_config) 861 862 # vhost 863 @call_cmd 864 def set_vhost_controller_coalescing(args): 865 rpc.vhost.set_vhost_controller_coalescing(args.client, args) 866 867 p = subparsers.add_parser('set_vhost_controller_coalescing', help='Set vhost controller coalescing') 868 p.add_argument('ctrlr', help='controller name') 869 p.add_argument('delay_base_us', help='Base delay time', type=int) 870 p.add_argument('iops_threshold', help='IOPS threshold when coalescing is enabled', type=int) 871 p.set_defaults(func=set_vhost_controller_coalescing) 872 873 @call_cmd 874 def construct_vhost_scsi_controller(args): 875 rpc.vhost.construct_vhost_scsi_controller(args.client, args) 876 877 p = subparsers.add_parser( 878 'construct_vhost_scsi_controller', help='Add new vhost controller') 879 p.add_argument('ctrlr', help='controller name') 880 p.add_argument('--cpumask', help='cpu mask for this controller') 881 p.set_defaults(func=construct_vhost_scsi_controller) 882 883 @call_cmd 884 def add_vhost_scsi_lun(args): 885 rpc.vhost.add_vhost_scsi_lun(args.client, args) 886 887 p = subparsers.add_parser('add_vhost_scsi_lun', 888 help='Add lun to vhost controller') 889 p.add_argument('ctrlr', help='conntroller name where add lun') 890 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 891 p.add_argument('bdev_name', help='bdev name') 892 p.set_defaults(func=add_vhost_scsi_lun) 893 894 @call_cmd 895 def remove_vhost_scsi_target(args): 896 rpc.vhost.remove_vhost_scsi_target(args.client, args) 897 898 p = subparsers.add_parser('remove_vhost_scsi_target', help='Remove target from vhost controller') 899 p.add_argument('ctrlr', help='controller name to remove target from') 900 p.add_argument('scsi_target_num', help='scsi_target_num', type=int) 901 p.set_defaults(func=remove_vhost_scsi_target) 902 903 @call_cmd 904 def construct_vhost_blk_controller(args): 905 rpc.vhost.construct_vhost_blk_controller(args.client, args) 906 907 p = subparsers.add_parser('construct_vhost_blk_controller', help='Add a new vhost block controller') 908 p.add_argument('ctrlr', help='controller name') 909 p.add_argument('dev_name', help='device name') 910 p.add_argument('--cpumask', help='cpu mask for this controller') 911 p.add_argument("-r", "--readonly", action='store_true', help='Set controller as read-only') 912 p.set_defaults(func=construct_vhost_blk_controller) 913 914 @call_cmd 915 def construct_vhost_nvme_controller(args): 916 rpc.vhost.construct_vhost_nvme_controller(args.client, args) 917 918 p = subparsers.add_parser('construct_vhost_nvme_controller', help='Add new vhost controller') 919 p.add_argument('ctrlr', help='controller name') 920 p.add_argument('io_queues', help='number of IO queues for the controller', type=int) 921 p.add_argument('--cpumask', help='cpu mask for this controller') 922 p.set_defaults(func=construct_vhost_nvme_controller) 923 924 @call_cmd 925 def add_vhost_nvme_ns(args): 926 rpc.vhost.add_vhost_nvme_ns(args.client, args) 927 928 p = subparsers.add_parser('add_vhost_nvme_ns', help='Add a Namespace to vhost controller') 929 p.add_argument('ctrlr', help='conntroller name where add a Namespace') 930 p.add_argument('bdev_name', help='block device name for a new Namespace') 931 p.set_defaults(func=add_vhost_nvme_ns) 932 933 @call_cmd 934 def get_vhost_controllers(args): 935 print_dict(rpc.vhost.get_vhost_controllers(args.client, args)) 936 937 p = subparsers.add_parser('get_vhost_controllers', help='List vhost controllers') 938 p.set_defaults(func=get_vhost_controllers) 939 940 @call_cmd 941 def remove_vhost_controller(args): 942 rpc.vhost.remove_vhost_controller(args.client, args) 943 944 p = subparsers.add_parser('remove_vhost_controller', help='Remove a vhost controller') 945 p.add_argument('ctrlr', help='controller name') 946 p.set_defaults(func=remove_vhost_controller) 947 948 @call_cmd 949 def construct_virtio_dev(args): 950 print_dict(rpc.vhost.construct_virtio_dev(args.client, args)) 951 952 p = subparsers.add_parser('construct_virtio_dev', help="""Construct new virtio device using provided 953 transport type and device type. In case of SCSI device type this implies scan and add bdevs offered by 954 remote side. Result is array of added bdevs.""") 955 p.add_argument('name', help="Use this name as base for new created bdevs") 956 p.add_argument('-t', '--trtype', 957 help='Virtio target transport type: pci or user', required=True) 958 p.add_argument('-a', '--traddr', 959 help='Transport type specific target address: e.g. UNIX domain socket path or BDF', required=True) 960 p.add_argument('-d', '--dev-type', 961 help='Device type: blk or scsi', required=True) 962 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 963 p.add_argument('--vq-size', help='Size of each queue', type=int) 964 p.set_defaults(func=construct_virtio_dev) 965 966 @call_cmd 967 def construct_virtio_user_scsi_bdev(args): 968 print_dict(rpc.vhost.construct_virtio_user_scsi_bdev(args.client, args)) 969 970 p = subparsers.add_parser('construct_virtio_user_scsi_bdev', help="""Connect to virtio user scsi device. 971 This imply scan and add bdevs offered by remote side. 972 Result is array of added bdevs.""") 973 p.add_argument('path', help='Path to Virtio SCSI socket') 974 p.add_argument('name', help="""Use this name as base instead of 'VirtioScsiN' 975 Base will be used to construct new bdev's found on target by adding 't<TARGET_ID>' sufix.""") 976 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 977 p.add_argument('--vq-size', help='Size of each queue', type=int) 978 p.set_defaults(func=construct_virtio_user_scsi_bdev) 979 980 @call_cmd 981 def construct_virtio_pci_scsi_bdev(args): 982 print_dict(rpc.vhost.construct_virtio_pci_scsi_bdev(args.client, args)) 983 984 p = subparsers.add_parser('construct_virtio_pci_scsi_bdev', help="""Create a Virtio 985 SCSI device from a virtio-pci device.""") 986 p.add_argument('pci_address', help="""PCI address in domain:bus:device.function format or 987 domain.bus.device.function format""") 988 p.add_argument('name', help="""Name for the virtio device. 989 It will be inhereted by all created bdevs, which are named n the following format: <name>t<target_id>""") 990 p.set_defaults(func=construct_virtio_pci_scsi_bdev) 991 992 @call_cmd 993 def get_virtio_scsi_devs(args): 994 print_dict(rpc.vhost.get_virtio_scsi_devs(args.client, args)) 995 996 p = subparsers.add_parser('get_virtio_scsi_devs', help='List all Virtio-SCSI devices.') 997 p.set_defaults(func=get_virtio_scsi_devs) 998 999 @call_cmd 1000 def remove_virtio_scsi_bdev(args): 1001 rpc.vhost.remove_virtio_scsi_bdev(args.client, args) 1002 1003 p = subparsers.add_parser('remove_virtio_scsi_bdev', help="""Remove a Virtio-SCSI device 1004 This will delete all bdevs exposed by this device""") 1005 p.add_argument('name', help='Virtio device name. E.g. VirtioUser0') 1006 p.set_defaults(func=remove_virtio_scsi_bdev) 1007 1008 @call_cmd 1009 def construct_virtio_user_blk_bdev(args): 1010 print_dict(rpc.vhost.construct_virtio_user_blk_bdev(args.client, args)) 1011 1012 p = subparsers.add_parser('construct_virtio_user_blk_bdev', help='Connect to a virtio user blk device.') 1013 p.add_argument('path', help='Path to Virtio BLK socket') 1014 p.add_argument('name', help='Name for the bdev') 1015 p.add_argument('--vq-count', help='Number of virtual queues to be used.', type=int) 1016 p.add_argument('--vq-size', help='Size of each queue', type=int) 1017 p.set_defaults(func=construct_virtio_user_blk_bdev) 1018 1019 @call_cmd 1020 def construct_virtio_pci_blk_bdev(args): 1021 print_dict(rpc.vhost.construct_virtio_pci_blk_bdev(args.client, args)) 1022 1023 p = subparsers.add_parser('construct_virtio_pci_blk_bdev', help='Create a Virtio Blk device from a virtio-pci device.') 1024 p.add_argument('pci_address', help="""PCI address in domain:bus:device.function format or 1025 domain.bus.device.function format""") 1026 p.add_argument('name', help='Name for the bdev') 1027 p.set_defaults(func=construct_virtio_pci_blk_bdev) 1028 1029 args = parser.parse_args() 1030 1031 try: 1032 args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.verbose, args.timeout) 1033 except JSONRPCException as ex: 1034 print(ex.message) 1035 exit(1) 1036 args.func(args) 1037