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:
@@ -102,6 +102,11 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
|
|||||||
def __init__(self, api_url, advertise_address, listen_address,
|
def __init__(self, api_url, advertise_address, listen_address,
|
||||||
lookup_timeout, lookup_interval, driver_name):
|
lookup_timeout, lookup_interval, driver_name):
|
||||||
super(IronicPythonAgent, self).__init__()
|
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.api_url = api_url
|
||||||
self.driver_name = driver_name
|
self.driver_name = driver_name
|
||||||
self.api_client = ironic_api_client.APIClient(self.api_url,
|
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_timeout = lookup_timeout
|
||||||
self.lookup_interval = lookup_interval
|
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):
|
def get_status(self):
|
||||||
"""Retrieve a serializable status."""
|
"""Retrieve a serializable status."""
|
||||||
return IronicPythonAgentStatus(
|
return IronicPythonAgentStatus(
|
||||||
|
@@ -182,3 +182,7 @@ class SystemRebootError(RESTError):
|
|||||||
super(SystemRebootError, self).__init__()
|
super(SystemRebootError, self).__init__()
|
||||||
self.details = 'Reboot script failed with exit code {0}.'
|
self.details = 'Reboot script failed with exit code {0}.'
|
||||||
self.details = self.details.format(exit_code)
|
self.details = self.details.format(exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
class ExtensionError(Exception):
|
||||||
|
pass
|
||||||
|
@@ -131,11 +131,14 @@ class ExecuteCommandMixin(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.command_lock = threading.Lock()
|
self.command_lock = threading.Lock()
|
||||||
self.command_results = utils.get_ordereddict()
|
self.command_results = utils.get_ordereddict()
|
||||||
self.ext_mgr = self.get_extension_manager()
|
self.ext_mgr = None
|
||||||
|
|
||||||
def get_extension_manager(self):
|
def get_extension(self, extension_name):
|
||||||
raise NotImplementedError(
|
if self.ext_mgr is None:
|
||||||
'get_extension_manager should be implemented in successor class')
|
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):
|
def split_command(self, command_name):
|
||||||
command_parts = command_name.split('.', 1)
|
command_parts = command_name.split('.', 1)
|
||||||
@@ -156,7 +159,7 @@ class ExecuteCommandMixin(object):
|
|||||||
raise errors.CommandExecutionError('agent is busy')
|
raise errors.CommandExecutionError('agent is busy')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ext = self.ext_mgr[extension_part].obj
|
ext = self.get_extension(extension_part)
|
||||||
result = ext.execute(command_part, **kwargs)
|
result = ext.execute(command_part, **kwargs)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# Extension Not found
|
# Extension Not found
|
||||||
|
@@ -12,8 +12,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from stevedore import enabled
|
|
||||||
|
|
||||||
from ironic_python_agent import errors
|
from ironic_python_agent import errors
|
||||||
from ironic_python_agent.extensions import base
|
from ironic_python_agent.extensions import base
|
||||||
from ironic_python_agent.openstack.common import log
|
from ironic_python_agent.openstack.common import log
|
||||||
@@ -21,11 +19,6 @@ from ironic_python_agent.openstack.common import log
|
|||||||
LOG = log.getLogger(__name__)
|
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):
|
def _validate_exts(ext, flow=None):
|
||||||
for task in flow:
|
for task in flow:
|
||||||
for method in task:
|
for method in task:
|
||||||
@@ -42,14 +35,6 @@ class FlowExtension(base.BaseAgentExtension, base.ExecuteCommandMixin):
|
|||||||
super(FlowExtension, self).__init__()
|
super(FlowExtension, self).__init__()
|
||||||
self.command_map['start_flow'] = self.start_flow
|
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)
|
@base.async_command(_validate_exts)
|
||||||
def start_flow(self, flow=None):
|
def start_flow(self, flow=None):
|
||||||
for task in flow:
|
for task in flow:
|
||||||
|
@@ -125,15 +125,10 @@ class TestHeartbeater(test_base.BaseTestCase):
|
|||||||
|
|
||||||
class TestBaseAgent(test_base.BaseTestCase):
|
class TestBaseAgent(test_base.BaseTestCase):
|
||||||
|
|
||||||
@mock.patch.object(agent.IronicPythonAgent, 'get_extension_manager')
|
def setUp(self):
|
||||||
def setUp(self, fake_ext_mgr):
|
|
||||||
super(TestBaseAgent, self).setUp()
|
super(TestBaseAgent, self).setUp()
|
||||||
self.encoder = encoding.RESTJSONEncoder(indent=4)
|
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.'
|
self.agent = agent.IronicPythonAgent('https://fake_api.example.'
|
||||||
'org:8081/',
|
'org:8081/',
|
||||||
('203.0.113.1', 9990),
|
('203.0.113.1', 9990),
|
||||||
@@ -141,6 +136,10 @@ class TestBaseAgent(test_base.BaseTestCase):
|
|||||||
300,
|
300,
|
||||||
1,
|
1,
|
||||||
'agent_ipmitool')
|
'agent_ipmitool')
|
||||||
|
self.agent.ext_mgr = extension.ExtensionManager.\
|
||||||
|
make_test_instance([extension.Extension('fake', None,
|
||||||
|
FakeExtension,
|
||||||
|
FakeExtension())])
|
||||||
|
|
||||||
def assertEqualEncoded(self, a, b):
|
def assertEqualEncoded(self, a, b):
|
||||||
# Evidently JSONEncoder.default() can't handle None (??) so we have to
|
# Evidently JSONEncoder.default() can't handle None (??) so we have to
|
||||||
|
@@ -52,9 +52,7 @@ class FakeExtension(base.BaseAgentExtension):
|
|||||||
class FakeAgent(base.ExecuteCommandMixin):
|
class FakeAgent(base.ExecuteCommandMixin):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(FakeAgent, self).__init__()
|
super(FakeAgent, self).__init__()
|
||||||
|
self.ext_mgr = extension.ExtensionManager.make_test_instance(
|
||||||
def get_extension_manager(self):
|
|
||||||
return extension.ExtensionManager.make_test_instance(
|
|
||||||
[extension.Extension('fake', None, FakeExtension,
|
[extension.Extension('fake', None, FakeExtension,
|
||||||
FakeExtension())])
|
FakeExtension())])
|
||||||
|
|
||||||
@@ -88,7 +86,7 @@ class TestExecuteCommandMixin(test_base.BaseTestCase):
|
|||||||
|
|
||||||
def test_execute_command_success(self):
|
def test_execute_command_success(self):
|
||||||
expected_result = base.SyncCommandResult('fake', None, True, None)
|
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 = mock.Mock()
|
||||||
fake_ext.execute.return_value = expected_result
|
fake_ext.execute.return_value = expected_result
|
||||||
result = self.agent.execute_command('fake.sleep',
|
result = self.agent.execute_command('fake.sleep',
|
||||||
|
Reference in New Issue
Block a user