From b306626e86721f27a1eeba4f54cda02d5ad632d6 Mon Sep 17 00:00:00 2001 From: Vladimir Kozhukalov Date: Mon, 5 May 2014 13:57:04 +0400 Subject: [PATCH] Flow extension uses extension manager from agent Removed creating separate extension manager for flow extension. Instead, have made flow extension using the same extension manager instance which is initialized in agent. It fixes circular extension loading in stevedore. Closes-Bug: #1316145 Change-Id: Id339f1876168a41ca43ba7473f3ff6949a233ef3 --- ironic_python_agent/agent.py | 12 +++++------- ironic_python_agent/errors.py | 4 ++++ ironic_python_agent/extensions/base.py | 13 ++++++++----- ironic_python_agent/extensions/flow.py | 15 --------------- ironic_python_agent/tests/agent.py | 11 +++++------ ironic_python_agent/tests/extensions/base.py | 6 ++---- 6 files changed, 24 insertions(+), 37 deletions(-) diff --git a/ironic_python_agent/agent.py b/ironic_python_agent/agent.py index 1fb6f556d..ed60c6818 100644 --- a/ironic_python_agent/agent.py +++ b/ironic_python_agent/agent.py @@ -102,6 +102,11 @@ class IronicPythonAgent(base.ExecuteCommandMixin): def __init__(self, api_url, advertise_address, listen_address, lookup_timeout, lookup_interval, driver_name): super(IronicPythonAgent, self).__init__() + self.ext_mgr = extension.ExtensionManager( + namespace='ironic_python_agent.extensions', + invoke_on_load=True, + propagate_map_exceptions=True, + ) self.api_url = api_url self.driver_name = driver_name self.api_client = ironic_api_client.APIClient(self.api_url, @@ -121,13 +126,6 @@ class IronicPythonAgent(base.ExecuteCommandMixin): self.lookup_timeout = lookup_timeout self.lookup_interval = lookup_interval - def get_extension_manager(self): - return extension.ExtensionManager( - namespace='ironic_python_agent.extensions', - invoke_on_load=True, - propagate_map_exceptions=True, - ) - def get_status(self): """Retrieve a serializable status.""" return IronicPythonAgentStatus( diff --git a/ironic_python_agent/errors.py b/ironic_python_agent/errors.py index 0cb9ad4a2..0d86ebac2 100644 --- a/ironic_python_agent/errors.py +++ b/ironic_python_agent/errors.py @@ -182,3 +182,7 @@ class SystemRebootError(RESTError): super(SystemRebootError, self).__init__() self.details = 'Reboot script failed with exit code {0}.' self.details = self.details.format(exit_code) + + +class ExtensionError(Exception): + pass diff --git a/ironic_python_agent/extensions/base.py b/ironic_python_agent/extensions/base.py index 3ef5c4ea7..8d75d7a2d 100644 --- a/ironic_python_agent/extensions/base.py +++ b/ironic_python_agent/extensions/base.py @@ -131,11 +131,14 @@ class ExecuteCommandMixin(object): def __init__(self): self.command_lock = threading.Lock() self.command_results = utils.get_ordereddict() - self.ext_mgr = self.get_extension_manager() + self.ext_mgr = None - def get_extension_manager(self): - raise NotImplementedError( - 'get_extension_manager should be implemented in successor class') + def get_extension(self, extension_name): + if self.ext_mgr is None: + raise errors.ExtensionError('Extension manager is not initialized') + ext = self.ext_mgr[extension_name].obj + ext.ext_mgr = self.ext_mgr + return ext def split_command(self, command_name): command_parts = command_name.split('.', 1) @@ -156,7 +159,7 @@ class ExecuteCommandMixin(object): raise errors.CommandExecutionError('agent is busy') try: - ext = self.ext_mgr[extension_part].obj + ext = self.get_extension(extension_part) result = ext.execute(command_part, **kwargs) except KeyError: # Extension Not found diff --git a/ironic_python_agent/extensions/flow.py b/ironic_python_agent/extensions/flow.py index 1d8a21b10..9690a3206 100644 --- a/ironic_python_agent/extensions/flow.py +++ b/ironic_python_agent/extensions/flow.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from stevedore import enabled - from ironic_python_agent import errors from ironic_python_agent.extensions import base from ironic_python_agent.openstack.common import log @@ -21,11 +19,6 @@ from ironic_python_agent.openstack.common import log LOG = log.getLogger(__name__) -def _load_extension(ext): - disabled_extension_list = ['flow'] - return ext.name not in disabled_extension_list - - def _validate_exts(ext, flow=None): for task in flow: for method in task: @@ -42,14 +35,6 @@ class FlowExtension(base.BaseAgentExtension, base.ExecuteCommandMixin): super(FlowExtension, self).__init__() self.command_map['start_flow'] = self.start_flow - def get_extension_manager(self): - return enabled.EnabledExtensionManager( - 'ironic_python_agent.extensions', - _load_extension, - invoke_on_load=True, - propagate_map_exceptions=True, - ) - @base.async_command(_validate_exts) def start_flow(self, flow=None): for task in flow: diff --git a/ironic_python_agent/tests/agent.py b/ironic_python_agent/tests/agent.py index adda81300..43d3c6930 100644 --- a/ironic_python_agent/tests/agent.py +++ b/ironic_python_agent/tests/agent.py @@ -125,15 +125,10 @@ class TestHeartbeater(test_base.BaseTestCase): class TestBaseAgent(test_base.BaseTestCase): - @mock.patch.object(agent.IronicPythonAgent, 'get_extension_manager') - def setUp(self, fake_ext_mgr): + def setUp(self): super(TestBaseAgent, self).setUp() self.encoder = encoding.RESTJSONEncoder(indent=4) - fake_ext_mgr.return_value = extension.ExtensionManager.\ - make_test_instance([extension.Extension('fake', None, - FakeExtension, - FakeExtension())]) self.agent = agent.IronicPythonAgent('https://fake_api.example.' 'org:8081/', ('203.0.113.1', 9990), @@ -141,6 +136,10 @@ class TestBaseAgent(test_base.BaseTestCase): 300, 1, 'agent_ipmitool') + self.agent.ext_mgr = extension.ExtensionManager.\ + make_test_instance([extension.Extension('fake', None, + FakeExtension, + FakeExtension())]) def assertEqualEncoded(self, a, b): # Evidently JSONEncoder.default() can't handle None (??) so we have to diff --git a/ironic_python_agent/tests/extensions/base.py b/ironic_python_agent/tests/extensions/base.py index f9f6bede1..1797c9280 100644 --- a/ironic_python_agent/tests/extensions/base.py +++ b/ironic_python_agent/tests/extensions/base.py @@ -52,9 +52,7 @@ class FakeExtension(base.BaseAgentExtension): class FakeAgent(base.ExecuteCommandMixin): def __init__(self): super(FakeAgent, self).__init__() - - def get_extension_manager(self): - return extension.ExtensionManager.make_test_instance( + self.ext_mgr = extension.ExtensionManager.make_test_instance( [extension.Extension('fake', None, FakeExtension, FakeExtension())]) @@ -88,7 +86,7 @@ class TestExecuteCommandMixin(test_base.BaseTestCase): def test_execute_command_success(self): expected_result = base.SyncCommandResult('fake', None, True, None) - fake_ext = self.agent.ext_mgr['fake'].obj + fake_ext = self.agent.get_extension('fake') fake_ext.execute = mock.Mock() fake_ext.execute.return_value = expected_result result = self.agent.execute_command('fake.sleep',