Merge "Add volume backend pool list command"

This commit is contained in:
Zuul 2018-10-12 22:41:43 +00:00 committed by Gerrit Code Review
commit ac9877de46
6 changed files with 191 additions and 2 deletions

View File

@ -33,7 +33,7 @@ failover-host,volume host failover,Failover a replicating cinder-volume host.
force-delete,volume delete --force,"Attempts force-delete of volume, regardless of state."
freeze-host,volume host set --disable,Freeze and disable the specified cinder-volume host.
get-capabilities,volume backend capability show,Show capabilities of a volume backend. Admin only.
get-pools,,Show pool information for backends. Admin only.
get-pools,volume backend pool list,Show pool information for backends. Admin only.
image-metadata,volume set --image-property,Sets or deletes volume image metadata.
image-metadata-show,volume show,Shows volume image metadata.
list,volume list,Lists all volumes.

1 absolute-limits limits show --absolute Lists absolute limits for a user.
33 force-delete volume delete --force Attempts force-delete of volume, regardless of state.
34 freeze-host volume host set --disable Freeze and disable the specified cinder-volume host.
35 get-capabilities volume backend capability show Show capabilities of a volume backend. Admin only.
36 get-pools volume backend pool list Show pool information for backends. Admin only.
37 image-metadata volume set --image-property Sets or deletes volume image metadata.
38 image-metadata-show volume show Shows volume image metadata.
39 list volume list Lists all volumes.

View File

@ -252,6 +252,41 @@ class FakeCapability(object):
return capability
class FakePool(object):
"""Fake Pools."""
@staticmethod
def create_one_pool(attrs=None):
"""Create a fake pool.
:param Dictionary attrs:
A dictionary with all attributes of the pool
:return:
A FakeResource object with pool name and attrs.
"""
# Set default attribute
pool_info = {
'name': 'host@lvmdriver-1#lvmdriver-1',
'storage_protocol': 'iSCSI',
'thick_provisioning_support': False,
'thin_provisioning_support': True,
'total_volumes': 99,
'total_capacity_gb': 1000.00,
'allocated_capacity_gb': 100,
'max_over_subscription_ratio': 200.0,
}
# Overwrite default attributes if there are some attributes set
pool_info.update(attrs or {})
pool = fakes.FakeResource(
None,
pool_info,
loaded=True)
return pool
class FakeVolumeClient(object):
def __init__(self, **kwargs):
@ -294,6 +329,8 @@ class FakeVolumeClient(object):
self.management_url = kwargs['endpoint']
self.capabilities = mock.Mock()
self.capabilities.resource_class = fakes.FakeResource(None, {})
self.pools = mock.Mock()
self.pools.resource_class = fakes.FakeResource(None, {})
class TestVolume(utils.TestCommand):

View File

@ -71,3 +71,98 @@ class TestShowVolumeCapability(volume_fakes.TestVolume):
self.capability_mock.get.assert_called_with(
'fake',
)
class TestListVolumePool(volume_fakes.TestVolume):
"""Tests for volume backend pool listing."""
# The pool to be listed
pools = volume_fakes.FakePool.create_one_pool()
def setUp(self):
super(TestListVolumePool, self).setUp()
self.pool_mock = self.app.client_manager.volume.pools
self.pool_mock.list.return_value = [self.pools]
# Get the command object to test
self.cmd = volume_backend.ListPool(self.app, None)
def test_pool_list(self):
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# In base command class Lister in cliff, abstract method take_action()
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
expected_columns = [
'Name',
]
# confirming if all expected columns are present in the result.
self.assertEqual(expected_columns, columns)
datalist = ((
self.pools.name,
), )
# confirming if all expected values are present in the result.
self.assertEqual(datalist, tuple(data))
# checking if proper call was made to list pools
self.pool_mock.list.assert_called_with(
detailed=False,
)
# checking if long columns are present in output
self.assertNotIn("total_volumes", columns)
self.assertNotIn("storage_protocol", columns)
def test_service_list_with_long_option(self):
arglist = [
'--long'
]
verifylist = [
('long', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# In base command class Lister in cliff, abstract method take_action()
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
expected_columns = [
'Name',
'Protocol',
'Thick',
'Thin',
'Volumes',
'Capacity',
'Allocated',
'Max Over Ratio',
]
# confirming if all expected columns are present in the result.
self.assertEqual(expected_columns, columns)
datalist = ((
self.pools.name,
self.pools.storage_protocol,
self.pools.thick_provisioning_support,
self.pools.thin_provisioning_support,
self.pools.total_volumes,
self.pools.total_capacity_gb,
self.pools.allocated_capacity_gb,
self.pools.max_over_subscription_ratio,
), )
# confirming if all expected values are present in the result.
self.assertEqual(datalist, tuple(data))
self.pool_mock.list.assert_called_with(
detailed=True,
)

View File

@ -12,7 +12,7 @@
# under the License.
#
"""Capability action implementations"""
"""Storage backend action implementations"""
from osc_lib.command import command
from osc_lib import utils
@ -59,3 +59,55 @@ class ShowCapability(command.Lister):
(utils.get_dict_properties(
s, columns,
) for s in print_data))
class ListPool(command.Lister):
_description = _("List pool command")
def get_parser(self, prog_name):
parser = super(ListPool, self).get_parser(prog_name)
parser.add_argument(
"--long",
action="store_true",
default=False,
help=_("Show detailed information about pools.")
)
# TODO(smcginnis): Starting with Cinder microversion 3.33, user is also
# able to pass in --filters with a <key>=<value> pair to filter on.
return parser
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
if parsed_args.long:
columns = [
'name',
'storage_protocol',
'thick_provisioning_support',
'thin_provisioning_support',
'total_volumes',
'total_capacity_gb',
'allocated_capacity_gb',
'max_over_subscription_ratio',
]
headers = [
'Name',
'Protocol',
'Thick',
'Thin',
'Volumes',
'Capacity',
'Allocated',
'Max Over Ratio'
]
else:
columns = [
'Name',
]
headers = columns
data = volume_client.pools.list(detailed=parsed_args.long)
return (headers,
(utils.get_item_properties(
s, columns,
) for s in data))

View File

@ -5,3 +5,7 @@ features:
added which will provide a list of all capabilities that can be configured
for the requested backend. The required `<host>` parameter takes the form
`host@backend-name`.
- |
A new command, ``openstack volume backend pool list`` was added which will
provide a list of all backend storage pools. The optional ``-long``
parameter includes some basic configuration and stats for each pool.

View File

@ -630,6 +630,7 @@ openstack.volume.v2 =
volume_backup_show = openstackclient.volume.v2.backup:ShowVolumeBackup
volume_backend_capability_show = openstackclient.volume.v2.volume_backend:ShowCapability
volume_backend_pool_list = openstackclient.volume.v2.volume_backend:ListPool
volume_host_failover = openstackclient.volume.v2.volume_host:FailoverVolumeHost
volume_host_set = openstackclient.volume.v2.volume_host:SetVolumeHost