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