Merge pull request #29 from rackerlabs/pluggable_hardware_managers
RFR: Pluggable Hardware Managers
This commit is contained in:
commit
ccb85a7c2f
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user