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