Fix HardwareManager loading order bug

The agent attempts to sort the HardwareManager implementations found
by stevedore in order of suitability. This patch fixes a bug in the
sorting order that caused the GenericHardwareManager to always be
loaded.

Fixes bug 1327923

Change-Id: I1cc20e5351a704325f0cf41dab205c9164799f6a
This commit is contained in:
Russell Haering 2014-06-08 18:45:40 -07:00
parent 263f97c0e0
commit 5d5d443d16
2 changed files with 48 additions and 3 deletions

View File

@ -84,7 +84,7 @@ class Memory(encoding.Serializable):
@six.add_metaclass(abc.ABCMeta)
class HardwareManager(object):
@abc.abstractmethod
def evaluate_hardware_support(cls):
def evaluate_hardware_support(self):
pass
@abc.abstractmethod
@ -159,7 +159,7 @@ class GenericHardwareManager(HardwareManager):
if os.path.isdir('/mnt/sys'):
self.sys_path = '/mnt/sys'
def evaluate_hardware_support(cls):
def evaluate_hardware_support(self):
return HardwareSupport.GENERIC
def _get_interface_info(self, interface_name):
@ -287,7 +287,7 @@ class GenericHardwareManager(HardwareManager):
def _compare_extensions(ext1, ext2):
mgr1 = ext1.obj
mgr2 = ext2.obj
return mgr1.evaluate_hardware_support() - mgr2.evaluate_hardware_support()
return mgr2.evaluate_hardware_support() - mgr1.evaluate_hardware_support()
def get_manager():

View File

@ -15,6 +15,7 @@
import mock
from oslotest import base as test_base
import six
from stevedore import extension
from ironic_python_agent import errors
from ironic_python_agent import hardware
@ -113,6 +114,50 @@ HDPARM_INFO_TEMPLATE = (
)
class FakeHardwareManager(hardware.GenericHardwareManager):
def __init__(self, hardware_support):
self._hardware_support = hardware_support
def evaluate_hardware_support(self):
return self._hardware_support
class TestHardwareManagerLoading(test_base.BaseTestCase):
def setUp(self):
super(TestHardwareManagerLoading, self).setUp()
# In order to use ExtensionManager.make_test_instance() without
# creating a new only-for-test codepath, we instantiate the test
# instance outside of the test case in setUp, where we can access
# make_test_instance() before it gets mocked. Inside of the test case
# we set this as the return value of the mocked constructor, so we can
# verify that the constructor is called correctly while still using a
# more realistic ExtensionManager
fake_ep = mock.Mock()
fake_ep.module_name = 'fake'
fake_ep.attrs = ['fake attrs']
ext1 = extension.Extension('fake_generic0', fake_ep, None,
FakeHardwareManager(hardware.HardwareSupport.GENERIC))
ext2 = extension.Extension('fake_mainline0', fake_ep, None,
FakeHardwareManager(hardware.HardwareSupport.MAINLINE))
ext3 = extension.Extension('fake_generic1', fake_ep, None,
FakeHardwareManager(hardware.HardwareSupport.GENERIC))
self.correct_hw_manager = ext2.obj
self.fake_ext_mgr = extension.ExtensionManager.make_test_instance([
ext1, ext2, ext3
])
@mock.patch('stevedore.ExtensionManager')
def test_hardware_manager_loading(self, mocked_extension_mgr_constructor):
hardware._global_manager = None
mocked_extension_mgr_constructor.return_value = self.fake_ext_mgr
preferred_hw_manager = hardware.get_manager()
mocked_extension_mgr_constructor.assert_called_once_with(
namespace='ironic_python_agent.hardware_managers',
invoke_on_load=True)
self.assertEqual(self.correct_hw_manager, preferred_hw_manager)
class TestGenericHardwareManager(test_base.BaseTestCase):
def setUp(self):
super(TestGenericHardwareManager, self).setUp()