Merge pull request #29 from rackerlabs/pluggable_hardware_managers

RFR: Pluggable Hardware Managers
This commit is contained in:
Russell Haering 2014-01-22 14:33:07 -08:00
commit ccb85a7c2f
4 changed files with 66 additions and 5 deletions

View File

@ -21,3 +21,6 @@ console_scripts =
teeth_agent.modes =
standby = teeth_agent.standby:StandbyMode
decom = teeth_agent.decom:DecomMode
teeth_agent.hardware_managers =
generic = teeth_agent.hardware:GenericHardwareManager

View File

@ -118,7 +118,7 @@ class TeethAgent(object):
self.api = api.TeethAgentAPIServer(self)
self.command_results = collections.OrderedDict()
self.heartbeater = TeethAgentHeartbeater(self)
self.hardware = hardware.HardwareInspector()
self.hardware = hardware.load_hardware_manager()
self.command_lock = threading.Lock()
self.log = structlog.get_logger()
self.started_at = None
@ -235,7 +235,7 @@ def build_agent(api_url,
if not listen_host:
listen_host = advertise_host
mac_addr = hardware.HardwareInspector().get_primary_mac_address()
mac_addr = hardware.load_hardware_manager().get_primary_mac_address()
api_client = overlord_agent_api.APIClient(api_url)
log.info('fetching agent configuration from API',

View File

@ -14,7 +14,65 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
import abc
import stevedore
import structlog
_global_manager = None
class HardwareSupport(object):
"""These are just guidelines to suggest values that might be returned by
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
class HardwareInspector(object):
def get_primary_mac_address(self):
return open('/sys/class/net/eth0/address', 'r').read().strip('\n')
def _compare_extensions(ext1, ext2):
mgr1 = ext1.obj
mgr2 = ext2.obj
return mgr1.evaluate_hardware_support() - mgr2.evaluate_hardware_support()
def load_hardware_manager():
log = structlog.get_logger()
extension_manager = stevedore.ExtensionManager(
namespace='teeth_agent.hardware_managers',
invoke_on_load=True)
# There will always be at least one extension available (the
# GenericHardwareManager).
preferred_extension = sorted(extension_manager, _compare_extensions)[0]
preferred_manager = preferred_extension.obj
if preferred_manager.evaluate_hardware_support() <= 0:
raise RuntimeError('No suitable HardwareManager could be found')
log.info('selected hardware manager',
manager_name=preferred_extension.entry_point_target)
return preferred_manager

View File

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