simplify HardwareManager comparison

This commit is contained in:
Russell Haering 2014-01-22 11:09:02 -08:00
parent ea588b264a
commit 802969b7dd
3 changed files with 49 additions and 41 deletions

@ -23,4 +23,4 @@ teeth_agent.modes =
decom = teeth_agent.decom:DecomMode decom = teeth_agent.decom:DecomMode
teeth_agent.hardware_managers = teeth_agent.hardware_managers =
base = teeth_agent.hardware:BaseHardwareManager generic = teeth_agent.hardware:GenericHardwareManager

@ -14,57 +14,65 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
from stevedore import enabled import abc
from stevedore import extension
import structlog import structlog
_global_manager = None
class BaseHardwareManager(object):
@staticmethod class HardwareSupport(object):
def supports_hardware(): """These are just guidelines to suggest values that might be returned by
return True calls to `evaluate_hardware_support`. No HardwareManager in mainline
teeth-agent will ever offer a value greater than `MAINLINE`. Service
Providers should feel free to return values greater than SERVICE_PROVIDER
to distinguish between additional levels of support.
"""
NONE = 0
GENERIC = 1
MAINLINE = 2
SERVICE_PROVIDER = 3
class HardwareManager(object):
@abc.abstractmethod
def evaluate_hardware_support(cls):
pass
@abc.abstractmethod
def get_primary_mac_address(self):
pass
class GenericHardwareManager(HardwareManager):
def evaluate_hardware_support(cls):
return HardwareSupport.GENERIC
def get_primary_mac_address(self): def get_primary_mac_address(self):
return open('/sys/class/net/eth0/address', 'r').read().strip('\n') return open('/sys/class/net/eth0/address', 'r').read().strip('\n')
def extension_supports_hardware(extension): def _compare_extensions(ext1, ext2):
return extension.plugin.supports_hardware() mgr1 = ext1.obj
mgr2 = ext2.obj
return mgr1.evaluate_hardware_support() - mgr2.evaluate_hardware_support()
def load_hardware_manager(): def load_hardware_manager():
# The idea here is that there is an inheritance tree of Hardware Managers.
# For example:
#
# BaseHardwareManager
# / \
# SmallServerManager LargeServerManager
# / \ / \
# v1 v2 v1 v2
#
# In this hierarchy, any manager can claim to support the hardware, but any
# of its subclasses may supercede its claim. In cases where two managers
# with no ancestral relationship both claim to support the hardware, the
# result is undefined.
#
# NOTE(russellhaering): I don't know if this is actually a good idea, I
# just want to be able to have a base manager which
# tries to supply reasonable defaults, and be able to
# override it simply by installing an appropriate
# plugin.
log = structlog.get_logger() log = structlog.get_logger()
selected_plugin = BaseHardwareManager extension_manager = extension.ExtensionManager(
extension_manager = enabled.EnabledExtensionManager(
namespace='teeth_agent.hardware_managers', namespace='teeth_agent.hardware_managers',
check_func=extension_supports_hardware) invoke_on_load=True)
for extension in extension_manager: # There will always be at least one extension available (the
plugin = extension.plugin # GenericHardwareManager).
log.info('found qualified hardware manager', preferred_extension = sorted(extension_manager, _compare_extensions)[0]
manager_name=plugin.__name__) preferred_manager = preferred_extension.obj
if issubclass(plugin, selected_plugin):
selected_plugin = plugin if preferred_manager.evaluate_hardware_support() <= 0:
raise RuntimeError('No suitable HardwareManager could be found')
log.info('selected hardware manager', log.info('selected hardware manager',
manager_name=selected_plugin.__name__) manager_name=preferred_extension.entry_point_target)
return preferred_manager
return selected_plugin()

@ -20,9 +20,9 @@ import unittest
from teeth_agent import hardware from teeth_agent import hardware
class TestBaseHardwareManager(unittest.TestCase): class TestGenericHardwareManager(unittest.TestCase):
def setUp(self): def setUp(self):
self.hardware = hardware.BaseHardwareManager() self.hardware = hardware.GenericHardwareManager()
@mock.patch('__builtin__.open') @mock.patch('__builtin__.open')
def test_decom_mode(self, mocked_open): def test_decom_mode(self, mocked_open):