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
This commit is contained in:
Vladimir Kozhukalov
2014-05-05 13:57:04 +04:00
parent d69bd2b054
commit b306626e86
6 changed files with 24 additions and 37 deletions

View File

@@ -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(

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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',