From d17e75d2675c1acf09adc27249b1e968450c5229 Mon Sep 17 00:00:00 2001 From: Edwin Zhai Date: Tue, 18 Aug 2015 13:19:03 +0800 Subject: [PATCH] Add hypervisor inspector sanity check Based on existed self-disabled pollster, this sanity check would prevent pollsters on mis-configured inspector from being loaded. Change-Id: Ic4a7ce010e17b2f0f356687cc61a59276d59283d Closes-Bug: #1485560 --- ceilometer/compute/pollsters/__init__.py | 5 +++++ ceilometer/compute/virt/inspector.py | 12 ++++++++++ ceilometer/compute/virt/libvirt/inspector.py | 4 ++++ ceilometer/tests/unit/agent/test_manager.py | 6 +++++ .../compute/virt/libvirt/test_inspector.py | 22 +++++++++++++++++++ 5 files changed, 49 insertions(+) diff --git a/ceilometer/compute/pollsters/__init__.py b/ceilometer/compute/pollsters/__init__.py index 9c45a98a..60eb6b65 100644 --- a/ceilometer/compute/pollsters/__init__.py +++ b/ceilometer/compute/pollsters/__init__.py @@ -24,6 +24,11 @@ from ceilometer.compute.virt import inspector as virt_inspector @six.add_metaclass(abc.ABCMeta) class BaseComputePollster(plugin_base.PollsterBase): + def setup_environment(self): + super(BaseComputePollster, self).setup_environment() + # propagate exception from check_sanity + self.inspector.check_sanity() + @property def inspector(self): try: diff --git a/ceilometer/compute/virt/inspector.py b/ceilometer/compute/virt/inspector.py index 245fc2df..484bf82f 100644 --- a/ceilometer/compute/virt/inspector.py +++ b/ceilometer/compute/virt/inspector.py @@ -184,10 +184,22 @@ class NoDataException(InspectorException): pass +class NoSanityException(InspectorException): + pass + + # Main virt inspector abstraction layering over the hypervisor API. # class Inspector(object): + def check_sanity(self): + """Check the sanity of hypervisor inspector. + + Each subclass could overwrite it to throw any exception + when detecting mis-configured inspector + """ + pass + def inspect_cpus(self, instance): """Inspect the CPU statistics for an instance. diff --git a/ceilometer/compute/virt/libvirt/inspector.py b/ceilometer/compute/virt/libvirt/inspector.py index cf029e43..fe6a8ef8 100644 --- a/ceilometer/compute/virt/libvirt/inspector.py +++ b/ceilometer/compute/virt/libvirt/inspector.py @@ -81,6 +81,10 @@ class LibvirtInspector(virt_inspector.Inspector): return self.connection + def check_sanity(self): + if not self._get_connection(): + raise virt_inspector.NoSanityException() + @retry_on_disconnect def _lookup_by_uuid(self, instance): instance_name = util.instance_name(instance) diff --git a/ceilometer/tests/unit/agent/test_manager.py b/ceilometer/tests/unit/agent/test_manager.py index baa35c2d..5e4c4dcc 100644 --- a/ceilometer/tests/unit/agent/test_manager.py +++ b/ceilometer/tests/unit/agent/test_manager.py @@ -39,6 +39,9 @@ class PollingException(Exception): pass +@mock.patch('ceilometer.compute.pollsters.' + 'BaseComputePollster.setup_environment', + mock.Mock(return_value=None)) class TestManager(base.BaseTestCase): @mock.patch('ceilometer.pipeline.setup_polling', mock.MagicMock()) @@ -181,6 +184,9 @@ class TestRunTasks(agentbase.BaseAgentManagerTestCase): resource_metadata=agentbase.default_test_data.resource_metadata) @staticmethod + @mock.patch('ceilometer.compute.pollsters.' + 'BaseComputePollster.setup_environment', + mock.Mock(return_value=None)) def create_manager(): return manager.AgentManager() diff --git a/ceilometer/tests/unit/compute/virt/libvirt/test_inspector.py b/ceilometer/tests/unit/compute/virt/libvirt/test_inspector.py index 9aa9d693..64fe60a0 100644 --- a/ceilometer/tests/unit/compute/virt/libvirt/test_inspector.py +++ b/ceilometer/tests/unit/compute/virt/libvirt/test_inspector.py @@ -341,3 +341,25 @@ class TestLibvirtInspectionWithError(base.BaseTestCase): def test_inspect_unknown_error(self): self.assertRaises(virt_inspector.InspectorException, self.inspector.inspect_cpus, 'foo') + + +class TestLibvirtInitWithError(base.BaseTestCase): + + def setUp(self): + super(TestLibvirtInitWithError, self).setUp() + self.inspector = libvirt_inspector.LibvirtInspector() + libvirt_inspector.libvirt = mock.Mock() + + @mock.patch('ceilometer.compute.virt.libvirt.inspector.' + 'LibvirtInspector._get_connection', + mock.Mock(return_value=None)) + def test_init_error(self): + self.assertRaises(virt_inspector.NoSanityException, + self.inspector.check_sanity) + + @mock.patch('ceilometer.compute.virt.libvirt.inspector.' + 'LibvirtInspector._get_connection', + mock.Mock(side_effect=virt_inspector.NoDataException)) + def test_init_exception(self): + self.assertRaises(virt_inspector.NoDataException, + self.inspector.check_sanity)