From 1ea97654602cf23eeae89fd695202ebd89e3f56b Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Mon, 21 May 2018 13:28:21 -0700 Subject: [PATCH] scripts/rpc.py: pass named args to bdev.py Also add docstrings to all bdev.py methods. Change-Id: Ib980d6141b3933f0df26a09e5242f27afc562f96 Signed-off-by: Daniel Verkamp Reviewed-on: https://review.gerrithub.io/411952 Tested-by: SPDK Automated Test System Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- scripts/rpc.py | 78 +++++++--- scripts/rpc/bdev.py | 281 ++++++++++++++++++++++++++++--------- scripts/spdkcli/ui_node.py | 2 +- scripts/spdkcli/ui_root.py | 11 +- 4 files changed, 278 insertions(+), 94 deletions(-) diff --git a/scripts/rpc.py b/scripts/rpc.py index 941464469..2640639a2 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -103,7 +103,12 @@ if __name__ == "__main__": # bdev @call_cmd def construct_malloc_bdev(args): - print_array(rpc.bdev.construct_malloc_bdev(args.client, args)) + num_blocks = (args.total_size * 1024 * 1024) // args.block_size + print_array(rpc.bdev.construct_malloc_bdev(args.client, + num_blocks=num_blocks, + block_size=args.block_size, + name=args.name, + uuid=args.uuid)) p = subparsers.add_parser('construct_malloc_bdev', help='Add a bdev with malloc backend') @@ -116,7 +121,12 @@ if __name__ == "__main__": @call_cmd def construct_null_bdev(args): - print_array(rpc.bdev.construct_null_bdev(args.client, args)) + num_blocks = (args.total_size * 1024 * 1024) // args.block_size + print_array(rpc.bdev.construct_null_bdev(args.client, + num_blocks=num_blocks, + block_size=args.block_size, + name=args.name, + uuid=args.uuid)) p = subparsers.add_parser('construct_null_bdev', help='Add a bdev with null backend') @@ -129,7 +139,10 @@ if __name__ == "__main__": @call_cmd def construct_aio_bdev(args): - print_array(rpc.bdev.construct_aio_bdev(args.client, args)) + print_array(rpc.bdev.construct_aio_bdev(args.client, + filename=args.filename, + name=args.name, + block_size=args.block_size)) p = subparsers.add_parser('construct_aio_bdev', help='Add a bdev with aio backend') @@ -140,7 +153,13 @@ if __name__ == "__main__": @call_cmd def construct_nvme_bdev(args): - print_array(rpc.bdev.construct_nvme_bdev(args.client, args)) + print_array(rpc.bdev.construct_nvme_bdev(args.client, + name=args.name, + trtype=args.trtype, + traddr=args.traddr, + adrfam=args.adrfam, + trsvcid=args.trsvcid, + subnqn=args.subnqn)) p = subparsers.add_parser('construct_nvme_bdev', help='Add bdev with nvme backend') @@ -158,7 +177,11 @@ if __name__ == "__main__": @call_cmd def construct_rbd_bdev(args): - print_array(rpc.bdev.construct_rbd_bdev(args.client, args)) + print_array(rpc.bdev.construct_rbd_bdev(args.client, + name=args.name, + pool_name=args.pool_name, + rbd_name=args.rbd_name, + block_size=args.block_size)) p = subparsers.add_parser('construct_rbd_bdev', help='Add a bdev with ceph rbd backend') @@ -170,7 +193,8 @@ if __name__ == "__main__": @call_cmd def construct_error_bdev(args): - rpc.bdev.construct_error_bdev(args.client, args) + rpc.bdev.construct_error_bdev(args.client, + base_name=args.base_name) p = subparsers.add_parser('construct_error_bdev', help='Add bdev with error injection backend') @@ -179,7 +203,9 @@ if __name__ == "__main__": @call_cmd def construct_pmem_bdev(args): - print_array(rpc.bdev.construct_pmem_bdev(args.client, args)) + print_array(rpc.bdev.construct_pmem_bdev(args.client, + pmem_file=args.pmem_file, + name=args.name)) p = subparsers.add_parser('construct_pmem_bdev', help='Add a bdev with pmem backend') p.add_argument('pmem_file', help='Path to pmemblk pool file') @@ -188,7 +214,9 @@ if __name__ == "__main__": @call_cmd def construct_passthru_bdev(args): - print_array(rpc.bdev.construct_passthru_bdev(args.client, args)) + print_array(rpc.bdev.construct_passthru_bdev(args.client, + base_bdev_name=args.base_bdev_name, + passthru_bdev_name=args.passthru_bdev_name)) p = subparsers.add_parser('construct_passthru_bdev', help='Add a pass through bdev on existing bdev') @@ -198,7 +226,8 @@ if __name__ == "__main__": @call_cmd def get_bdevs(args): - print_dict(rpc.bdev.get_bdevs(args.client, args)) + print_dict(rpc.bdev.get_bdevs(args.client, + name=args.name)) p = subparsers.add_parser( 'get_bdevs', help='Display current blockdev list or required blockdev') @@ -207,7 +236,8 @@ if __name__ == "__main__": @call_cmd def get_bdevs_config(args): - print_dict(rpc.bdev.get_bdevs_config(args.client, args)) + print_dict(rpc.bdev.get_bdevs_config(args.client, + name=args.name)) p = subparsers.add_parser( 'get_bdevs_config', help='Display current (live) blockdev configuration list or required blockdev') @@ -216,7 +246,8 @@ if __name__ == "__main__": @call_cmd def get_bdevs_iostat(args): - print_dict(rpc.bdev.get_bdevs_iostat(args.client, args)) + print_dict(rpc.bdev.get_bdevs_iostat(args.client, + name=args.name)) p = subparsers.add_parser( 'get_bdevs_iostat', help='Display current I/O statistics of all the blockdevs or required blockdev.') @@ -225,7 +256,8 @@ if __name__ == "__main__": @call_cmd def delete_bdev(args): - rpc.bdev.delete_bdev(args.client, args) + rpc.bdev.delete_bdev(args.client, + bdev_name=args.bdev_name) p = subparsers.add_parser('delete_bdev', help='Delete a blockdev') p.add_argument( @@ -234,7 +266,9 @@ if __name__ == "__main__": @call_cmd def set_bdev_qos_limit_iops(args): - rpc.bdev.set_bdev_qos_limit_iops(args.client, args) + rpc.bdev.set_bdev_qos_limit_iops(args.client, + name=args.name, + ios_per_sec=args.ios_per_sec) p = subparsers.add_parser('set_bdev_qos_limit_iops', help='Set QoS IOPS limit on a blockdev') p.add_argument('name', help='Blockdev name to set QoS. Example: Malloc0') @@ -244,7 +278,11 @@ if __name__ == "__main__": @call_cmd def bdev_inject_error(args): - rpc.bdev.bdev_inject_error(args.client, args) + rpc.bdev.bdev_inject_error(args.client, + name=args.name, + io_type=args.io_type, + error_type=args.error_type, + num=args.num) p = subparsers.add_parser('bdev_inject_error', help='bdev inject error') p.add_argument('name', help="""the name of the error injection bdev""") @@ -256,7 +294,9 @@ if __name__ == "__main__": @call_cmd def apply_firmware(args): - print_dict(rpc.bdev.apply_firmware(args.client, args)) + print_dict(rpc.bdev.apply_firmware(args.client, + bdev_name=args.bdev_name, + filename=args.filename)) p = subparsers.add_parser('apply_firmware', help='Download and commit firmware to NVMe device') p.add_argument('filename', help='filename of the firmware to download') @@ -649,7 +689,10 @@ if __name__ == "__main__": # split def construct_split_vbdev(args): - print_dict(rpc.bdev.construct_split_vbdev(args.client, args)) + print_dict(rpc.bdev.construct_split_vbdev(args.client, + base_bdev=args.base_bdev, + split_count=args.split_count, + split_size_mb=args.split_size_mb)) p = subparsers.add_parser('construct_split_vbdev', help="""Add given disk name to split config. If bdev with base_name name exist the split bdevs will be created right away, if not split bdevs will be created when base bdev became @@ -661,7 +704,8 @@ if __name__ == "__main__": p.set_defaults(func=construct_split_vbdev) def destruct_split_vbdev(args): - rpc.destruct_split_vbdev(args.client, args) + rpc.destruct_split_vbdev(args.client, + base_bdev=args.base_bdev) p = subparsers.add_parser('destruct_split_vbdev', help="""Delete split config with all created splits.""") p.add_argument('base_bdev', help='base bdev name') diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index ecf372c86..602c042c2 100755 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -1,149 +1,290 @@ -def construct_malloc_bdev(client, args): - num_blocks = (args.total_size * 1024 * 1024) // args.block_size - params = {'num_blocks': num_blocks, 'block_size': args.block_size} - if args.name: - params['name'] = args.name - if args.uuid: - params['uuid'] = args.uuid +def construct_malloc_bdev(client, num_blocks, block_size, name=None, uuid=None): + """Construct a malloc block device. + + Args: + num_blocks: size of block device in blocks + block_size: block size of device; must be a power of 2 and at least 512 + name: name of block device (optional) + uuid: UUID of block device (optional) + + Returns: + List of created block devices. + """ + params = {'num_blocks': num_blocks, 'block_size': block_size} + if name: + params['name'] = name + if uuid: + params['uuid'] = uuid return client.call('construct_malloc_bdev', params) -def construct_null_bdev(client, args): - num_blocks = (args.total_size * 1024 * 1024) // args.block_size - params = {'name': args.name, 'num_blocks': num_blocks, - 'block_size': args.block_size} - if args.uuid: - params['uuid'] = args.uuid +def construct_null_bdev(client, num_blocks, block_size, name, uuid=None): + """Construct a null block device. + + Args: + num_blocks: size of block device in blocks + block_size: block size of device; must be a power of 2 and at least 512 + name: name of block device + uuid: UUID of block device (optional) + + Returns: + List of created block devices. + """ + params = {'name': name, 'num_blocks': num_blocks, + 'block_size': block_size} + if uuid: + params['uuid'] = uuid return client.call('construct_null_bdev', params) -def construct_aio_bdev(client, args): - params = {'name': args.name, - 'filename': args.filename} +def construct_aio_bdev(client, filename, name, block_size=None): + """Construct a Linux AIO block device. - if args.block_size: - params['block_size'] = args.block_size + Args: + filename: path to device or file (ex: /dev/sda) + name: name of block device + block_size: block size of device (optional; autodetected if omitted) + + Returns: + List of created block devices. + """ + params = {'name': name, + 'filename': filename} + + if block_size: + params['block_size'] = block_size return client.call('construct_aio_bdev', params) -def construct_nvme_bdev(client, args): - params = {'name': args.name, - 'trtype': args.trtype, - 'traddr': args.traddr} +def construct_nvme_bdev(client, name, trtype, traddr, adrfam=None, trsvcid=None, subnqn=None): + """Construct NVMe namespace block devices. - if args.adrfam: - params['adrfam'] = args.adrfam + Args: + name: bdev name prefix; "n" + namespace ID will be appended to create unique names + trtype: transport type ("PCIe", "RDMA") + traddr: transport address (PCI BDF or IP address) + adrfam: address family ("IPv4", "IPv6", "IB", or "FC") (optional for PCIe) + trsvcid: transport service ID (port number for IP-based addresses; optional for PCIe) + subnqn: subsystem NQN to connect to (optional) - if args.trsvcid: - params['trsvcid'] = args.trsvcid + Returns: + List of created block devices. + """ + params = {'name': name, + 'trtype': trtype, + 'traddr': traddr} - if args.subnqn: - params['subnqn'] = args.subnqn + if adrfam: + params['adrfam'] = adrfam + + if trsvcid: + params['trsvcid'] = trsvcid + + if subnqn: + params['subnqn'] = subnqn return client.call('construct_nvme_bdev', params) -def construct_rbd_bdev(client, args): +def construct_rbd_bdev(client, pool_name, rbd_name, block_size, name=None): + """Construct a Ceph RBD block device. + + Args: + pool_name: Ceph RBD pool name + rbd_name: Ceph RBD image name + block_size: block size of RBD volume + name: name of block device (optional) + + Returns: + List of created block devices. + """ params = { - 'pool_name': args.pool_name, - 'rbd_name': args.rbd_name, - 'block_size': args.block_size, + 'pool_name': pool_name, + 'rbd_name': rbd_name, + 'block_size': block_size, } - if args.name: - params['name'] = args.name + if name: + params['name'] = name return client.call('construct_rbd_bdev', params) -def construct_error_bdev(client, args): - params = {'base_name': args.base_name} +def construct_error_bdev(client, base_name): + """Construct an error injection block device. + + Args: + base_name: base bdev name + """ + params = {'base_name': base_name} return client.call('construct_error_bdev', params) -def construct_pmem_bdev(client, args): +def construct_pmem_bdev(client, pmem_file, name): + """Construct a libpmemblk block device. + + Args: + pmem_file: path to pmemblk pool file + name: name of block device + + Returns: + List of created block devices. + """ params = { - 'pmem_file': args.pmem_file, - 'name': args.name + 'pmem_file': pmem_file, + 'name': name } return client.call('construct_pmem_bdev', params) -def construct_passthru_bdev(client, args): +def construct_passthru_bdev(client, base_bdev_name, passthru_bdev_name): + """Construct a pass-through block device. + + Args: + base_bdev_name: name of the existing bdev + passthru_bdev_name: name of block device + + Returns: + List of created block devices. + """ params = { - 'base_bdev_name': args.base_bdev_name, - 'passthru_bdev_name': args.passthru_bdev_name, + 'base_bdev_name': base_bdev_name, + 'passthru_bdev_name': passthru_bdev_name, } return client.call('construct_passthru_bdev', params) -def construct_split_vbdev(client, args): +def construct_split_vbdev(client, base_bdev, split_count, split_size_mb=None): + """Construct split block devices from a base bdev. + + Args: + base_bdev: name of bdev to split + split_count: number of split bdevs to create + split_size_mb: size of each split volume in MiB (optional) + + Returns: + List of created block devices. + """ params = { - 'base_bdev': args.base_bdev, - 'split_count': args.split_count, + 'base_bdev': base_bdev, + 'split_count': split_count, } if args.split_size_mb: - params['split_size_mb'] = args.split_size_mb + params['split_size_mb'] = split_size_mb return client.call('construct_split_vbdev', params) -def destruct_split_vbdev(client, args): +def destruct_split_vbdev(client, base_bdev): + """Destroy split block devices. + + Args: + base_bdev: name of previously split bdev + """ params = { - 'base_bdev': args.base_bdev, + 'base_bdev': base_bdev, } return client.call('destruct_split_vbdev', params) -def get_bdevs(client, args): +def get_bdevs(client, name=None): + """Get information about block devices. + + Args: + name: bdev name to query (optional; if omitted, query all bdevs) + + Returns: + List of bdev information objects. + """ params = {} - if args.name: - params['name'] = args.name + if name: + params['name'] = name return client.call('get_bdevs', params) -def get_bdevs_config(client, args): +def get_bdevs_config(client, name=None): + """Get configuration for block devices. + + Args: + name: bdev name to query (optional; if omitted, query all bdevs) + + Returns: + List of RPC methods to reproduce the current bdev configuration. + """ params = {} - if args.name: - params['name'] = args.name + if name: + params['name'] = name return client.call('get_bdevs_config', params) -def get_bdevs_iostat(client, args): +def get_bdevs_iostat(client, name=None): + """Get I/O statistics for block devices. + + Args: + name: bdev name to query (optional; if omitted, query all bdevs) + + Returns: + I/O statistics for the requested block devices. + """ params = {} - if args.name: - params['name'] = args.name + if name: + params['name'] = name return client.call('get_bdevs_iostat', params) -def delete_bdev(client, args): - params = {'name': args.bdev_name} +def delete_bdev(client, bdev_name): + """Remove a bdev from the system. + + Args: + bdev_name: name of bdev to delete + """ + params = {'name': bdev_name} return client.call('delete_bdev', params) -def bdev_inject_error(client, args): +def bdev_inject_error(client, name, io_type, error_type, num=1): + """Inject an error via an error bdev. + + Args: + name: name of error bdev + io_type: one of "clear", "read", "write", "unmap", "flush", or "all" + error_type: one of "failure" or "pending" + num: number of commands to fail + """ params = { - 'name': args.name, - 'io_type': args.io_type, - 'error_type': args.error_type, - 'num': args.num, + 'name': name, + 'io_type': io_type, + 'error_type': error_type, + 'num': num, } return client.call('bdev_inject_error', params) -def set_bdev_qos_limit_iops(client, args): +def set_bdev_qos_limit_iops(client, name, ios_per_sec): + """Set QoS IOPS limit on a block device. + + Args: + name: name of block device + ios_per_sec: IOs per second limit (>=10000, example: 20000). 0 means unlimited. + """ params = {} - params['name'] = args.name - params['ios_per_sec'] = args.ios_per_sec + params['name'] = name + params['ios_per_sec'] = ios_per_sec return client.call('set_bdev_qos_limit_iops', params) -def apply_firmware(client, args): +def apply_firmware(client, bdev_name, filename): + """Download and commit firmware to NVMe device. + + Args: + bdev_name: name of NVMe block device + filename: filename of the firmware to download + """ params = { - 'filename': args.filename, - 'bdev_name': args.bdev_name, + 'filename': filename, + 'bdev_name': bdev_name, } return client.call('apply_nvme_firmware', params) diff --git a/scripts/spdkcli/ui_node.py b/scripts/spdkcli/ui_node.py index cdbc8d59f..6feffb527 100644 --- a/scripts/spdkcli/ui_node.py +++ b/scripts/spdkcli/ui_node.py @@ -155,7 +155,7 @@ class UIMallocBdev(UIBdev): size = self.ui_eval_param(size, "number", None) block_size = self.ui_eval_param(block_size, "number", None) - ret_name = self.get_root().create_malloc_bdev(total_size=size, + ret_name = self.get_root().create_malloc_bdev(num_blocks=size * 1024 * 1024 // block_size, block_size=block_size, name=name, uuid=uuid) self.shell.log.info(ret_name) diff --git a/scripts/spdkcli/ui_root.py b/scripts/spdkcli/ui_root.py index e4c349f46..05a20dfbd 100644 --- a/scripts/spdkcli/ui_root.py +++ b/scripts/spdkcli/ui_root.py @@ -1,7 +1,6 @@ from .ui_node import UINode, UIBdevs, UILvolStores import rpc.client import rpc -from argparse import Namespace as an class UIRoot(UINode): @@ -26,7 +25,7 @@ class UIRoot(UINode): return " ".join(a) def get_bdevs(self, bdev_type): - self.current_bdevs = rpc.bdev.get_bdevs(self.client, an(name="")) + self.current_bdevs = rpc.bdev.get_bdevs(self.client) # Following replace needs to be done in order for some of the bdev # listings to work. # For example logical volumes: listing in menu is "Logical_Volume" @@ -38,14 +37,14 @@ class UIRoot(UINode): yield test def delete_bdev(self, name): - rpc.bdev.delete_bdev(self.client, an(bdev_name=name)) + rpc.bdev.delete_bdev(self.client, bdev_name=name) def create_malloc_bdev(self, **kwargs): - response = rpc.bdev.construct_malloc_bdev(self.client, an(**kwargs)) + response = rpc.bdev.construct_malloc_bdev(self.client, **kwargs) return self.print_array(response) def create_aio_bdev(self, **kwargs): - response = rpc.bdev.construct_aio_bdev(self.client, an(**kwargs)) + response = rpc.bdev.construct_aio_bdev(self.client, **kwargs) return self.print_array(response) def create_lvol_bdev(self, **kwargs): @@ -53,7 +52,7 @@ class UIRoot(UINode): return self.print_array(response) def create_nvme_bdev(self, **kwargs): - response = rpc.bdev.construct_nvme_bdev(self.client, an(**kwargs)) + response = rpc.bdev.construct_nvme_bdev(self.client, **kwargs) return self.print_array(response) def get_lvol_stores(self):