diff --git a/openstack_dashboard/api/cinder.py b/openstack_dashboard/api/cinder.py index 8c63f12042..f4506e1b52 100644 --- a/openstack_dashboard/api/cinder.py +++ b/openstack_dashboard/api/cinder.py @@ -72,12 +72,6 @@ class BaseCinderAPIResourceWrapper(base.APIResourceWrapper): return (getattr(self._apiresource, 'description', None) or getattr(self._apiresource, 'display_description', None)) - def to_dict(self): - obj = {} - for key in self._attrs: - obj[key] = getattr(self._apiresource, key, None) - return obj - class Volume(BaseCinderAPIResourceWrapper): @@ -140,6 +134,14 @@ class VolumeTransfer(base.APIResourceWrapper): _attrs = ['id', 'name', 'created_at', 'volume_id', 'auth_key'] +class VolumePool(base.APIResourceWrapper): + + _attrs = ['name', 'pool_name', 'total_capacity_gb', 'free_capacity_gb', + 'allocated_capacity_gb', 'QoS_support', 'reserved_percentage', + 'volume_backend_name', 'vendor_name', 'driver_version', + 'storage_protocol', 'extra_specs'] + + @memoized def cinderclient(request): api_version = VERSIONS.get_active_version() @@ -189,6 +191,7 @@ def volume_list(request, search_opts=None): """To see all volumes in the cloud as an admin you can pass in a special search option: {'all_tenants': 1} """ + c_client = cinderclient(request) if c_client is None: return [] @@ -213,8 +216,8 @@ def volume_get(request, volume_id): instance = nova.server_get(request, attachment['server_id']) attachment['instance_name'] = instance.name else: - # Nova volume can occasionally send attachments in error state - # that lack a server_id property; to work around that we'll + # Nova volume can occasionally send back error'd attachments + # the lack a server_id property; to work around that we'll # give the attached instance a generic name. attachment['instance_name'] = _("Unknown instance") @@ -618,3 +621,12 @@ def transfer_accept(request, transfer_id, auth_key): def transfer_delete(request, transfer_id): return cinderclient(request).transfers.delete(transfer_id) + + +def pool_list(request, detailed=False): + c_client = cinderclient(request) + if c_client is None: + return [] + + return [VolumePool(v) for v in c_client.pools.list( + detailed=detailed)] diff --git a/openstack_dashboard/test/api_tests/cinder_tests.py b/openstack_dashboard/test/api_tests/cinder_tests.py index abb92c5238..35ce79ea4f 100644 --- a/openstack_dashboard/test/api_tests/cinder_tests.py +++ b/openstack_dashboard/test/api_tests/cinder_tests.py @@ -116,6 +116,16 @@ class CinderApiTests(test.APITestCase): for key in expected_results.keys(): self.assertEqual(expected_results[key], ret_val[key]) + def test_pool_list(self): + pools = self.cinder_pools.list() + cinderclient = self.stub_cinderclient() + cinderclient.pools = self.mox.CreateMockAnything() + cinderclient.pools.list(detailed=True).AndReturn(pools) + self.mox.ReplayAll() + + # No assertions are necessary. Verification is handled by mox. + api.cinder.pool_list(self.request, detailed=True) + class CinderApiVersionTests(test.TestCase): diff --git a/openstack_dashboard/test/test_data/cinder_data.py b/openstack_dashboard/test/test_data/cinder_data.py index b99696a6c7..2f014c4ae9 100644 --- a/openstack_dashboard/test/test_data/cinder_data.py +++ b/openstack_dashboard/test/test_data/cinder_data.py @@ -13,6 +13,7 @@ # under the License. from cinderclient.v2 import availability_zones +from cinderclient.v2 import pools from cinderclient.v2 import qos_specs from cinderclient.v2 import quotas from cinderclient.v2 import services @@ -44,6 +45,7 @@ def data(TEST): TEST.cinder_quota_usages = utils.TestDataContainer() TEST.cinder_availability_zones = utils.TestDataContainer() TEST.cinder_volume_transfers = utils.TestDataContainer() + TEST.cinder_pools = utils.TestDataContainer() # Services service_1 = services.Service(services.ServiceManager(None), { @@ -314,3 +316,47 @@ def data(TEST): 'auth_key': 'blah', 'created_at': ''}) TEST.cinder_volume_transfers.add(transfer_1) + + # Pools + pool1 = pools.Pool( + pools.PoolManager(None), { + "QoS_support": False, + "allocated_capacity_gb": 0, + "driver_version": "3.0.0", + "free_capacity_gb": 10, + "extra_specs": { + "description": "LVM Extra specs", + "display_name": "LVMDriver", + "namespace": "OS::Cinder::LVMDriver", + "type": "object", + }, + "name": "devstack@lvmdriver-1#lvmdriver-1", + "pool_name": "lvmdriver-1", + "reserved_percentage": 0, + "storage_protocol": "iSCSI", + "total_capacity_gb": 10, + "vendor_name": "Open Source", + "volume_backend_name": "lvmdriver-1"}) + + pool2 = pools.Pool( + pools.PoolManager(None), { + "QoS_support": False, + "allocated_capacity_gb": 2, + "driver_version": "3.0.0", + "free_capacity_gb": 15, + "extra_specs": { + "description": "LVM Extra specs", + "display_name": "LVMDriver", + "namespace": "OS::Cinder::LVMDriver", + "type": "object", + }, + "name": "devstack@lvmdriver-2#lvmdriver-2", + "pool_name": "lvmdriver-2", + "reserved_percentage": 0, + "storage_protocol": "iSCSI", + "total_capacity_gb": 10, + "vendor_name": "Open Source", + "volume_backend_name": "lvmdriver-2"}) + + TEST.cinder_pools.add(pool1) + TEST.cinder_pools.add(pool2)