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