diff --git a/watcher/common/exception.py b/watcher/common/exception.py index 1ecc284b8..eba875424 100644 --- a/watcher/common/exception.py +++ b/watcher/common/exception.py @@ -516,3 +516,7 @@ class NegativeLimitError(WatcherException): class NotificationPayloadError(WatcherException): _msg_fmt = _("Payload not populated when trying to send notification " "\"%(class_name)s\"") + + +class InvalidPoolAttributeValue(Invalid): + msg_fmt = _("The %(name)s pool %(attribute)s is not integer") diff --git a/watcher/decision_engine/model/collector/cinder.py b/watcher/decision_engine/model/collector/cinder.py index 0c1f98b02..5de05b1f0 100644 --- a/watcher/decision_engine/model/collector/cinder.py +++ b/watcher/decision_engine/model/collector/cinder.py @@ -222,8 +222,21 @@ class ModelBuilder(object): :param pool: A storage pool :type pool: :py:class:`~cinderlient.v2.capabilities.Capabilities` + :raises: exception.InvalidPoolAttributeValue """ # build up the storage pool. + + attrs = ["total_volumes", "total_capacity_gb", + "free_capacity_gb", "provisioned_capacity_gb", + "allocated_capacity_gb"] + + for attr in attrs: + try: + int(getattr(pool, attr)) + except ValueError: + raise exception.InvalidPoolAttributeValue( + name=pool.name, attribute=attr) + node_attributes = { "name": pool.name, "total_volumes": pool.total_volumes, diff --git a/watcher/tests/decision_engine/cluster/test_cinder_cdmc.py b/watcher/tests/decision_engine/cluster/test_cinder_cdmc.py index 9c275319b..ef4f4cd0b 100644 --- a/watcher/tests/decision_engine/cluster/test_cinder_cdmc.py +++ b/watcher/tests/decision_engine/cluster/test_cinder_cdmc.py @@ -14,6 +14,7 @@ import mock from watcher.common import cinder_helper +from watcher.common import exception from watcher.decision_engine.model.collector import cinder from watcher.tests import base from watcher.tests import conf_fixture @@ -101,3 +102,51 @@ class TestCinderClusterDataModelCollector(base.TestCase): self.assertEqual(storage_node.host, 'host@backend') self.assertEqual(storage_pool.name, 'host@backend#pool') self.assertEqual(volume.uuid, '1') + + @mock.patch('keystoneclient.v3.client.Client', mock.Mock()) + @mock.patch.object(cinder_helper, 'CinderHelper') + def test_cinder_cdmc_total_capacity_gb_not_integer( + self, m_cinder_helper_cls): + + m_cinder_helper = mock.Mock(name="cinder_helper") + m_cinder_helper_cls.return_value = m_cinder_helper + + fake_storage_node = mock.Mock( + host='host@backend', + zone='zone', + status='enabled', + state='up', + volume_type=['fake_type'] + ) + + fake_storage_pool = mock.Mock( + total_volumes=1, + total_capacity_gb="unknown", + free_capacity_gb=20, + provisioned_capacity_gb=10, + allocated_capacity_gb=10, + virtual_free=20 + ) + setattr(fake_storage_pool, 'name', 'host@backend#pool') + + # storage node list + m_cinder_helper.get_storage_node_list.return_value = [ + fake_storage_node] + m_cinder_helper.get_volume_type_by_backendname.return_value = [ + 'fake_type'] + + # storage pool list + m_cinder_helper.get_storage_pool_list.return_value = [ + fake_storage_pool] + + # volume list + m_cinder_helper.get_volume_list.return_value = [] + + m_config = mock.Mock() + m_osc = mock.Mock() + + cinder_cdmc = cinder.CinderClusterDataModelCollector( + config=m_config, osc=m_osc) + + self.assertRaises(exception.InvalidPoolAttributeValue, + cinder_cdmc.execute)