Merge "Skip API related work if no api url configured" into stable/newton
This commit is contained in:
commit
442950be3e
|
@ -170,14 +170,15 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
|
|||
)
|
||||
self.api_url = api_url
|
||||
self.driver_name = driver_name
|
||||
self.api_client = ironic_api_client.APIClient(self.api_url,
|
||||
self.driver_name)
|
||||
if self.api_url:
|
||||
self.api_client = ironic_api_client.APIClient(self.api_url,
|
||||
self.driver_name)
|
||||
self.heartbeater = IronicPythonAgentHeartbeater(self)
|
||||
self.listen_address = listen_address
|
||||
self.advertise_address = advertise_address
|
||||
self.version = pkg_resources.get_distribution('ironic-python-agent')\
|
||||
.version
|
||||
self.api = app.VersionSelectorApplication(self)
|
||||
self.heartbeater = IronicPythonAgentHeartbeater(self)
|
||||
self.heartbeat_timeout = None
|
||||
self.started_at = None
|
||||
self.node = None
|
||||
|
@ -331,30 +332,40 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
|
|||
if not self.standalone:
|
||||
# Inspection should be started before call to lookup, otherwise
|
||||
# lookup will fail due to unknown MAC.
|
||||
uuid = inspector.inspect()
|
||||
uuid = None
|
||||
if cfg.CONF.inspection_callback_url:
|
||||
uuid = inspector.inspect()
|
||||
|
||||
self._wait_for_interface()
|
||||
content = self.api_client.lookup_node(
|
||||
hardware_info=hardware.dispatch_to_managers(
|
||||
'list_hardware_info'),
|
||||
timeout=self.lookup_timeout,
|
||||
starting_interval=self.lookup_interval,
|
||||
node_uuid=uuid)
|
||||
if self.api_url:
|
||||
self._wait_for_interface()
|
||||
content = self.api_client.lookup_node(
|
||||
hardware_info=hardware.dispatch_to_managers(
|
||||
'list_hardware_info'),
|
||||
timeout=self.lookup_timeout,
|
||||
starting_interval=self.lookup_interval,
|
||||
node_uuid=uuid)
|
||||
|
||||
LOG.debug('Received lookup results: %s', content)
|
||||
self.node = content['node']
|
||||
LOG.info('Lookup succeeded, node UUID is %s', self.node['uuid'])
|
||||
hardware.cache_node(self.node)
|
||||
self.heartbeat_timeout = content['config']['heartbeat_timeout']
|
||||
LOG.debug('Received lookup results: %s', content)
|
||||
self.node = content['node']
|
||||
LOG.info('Lookup succeeded, node UUID is %s',
|
||||
self.node['uuid'])
|
||||
hardware.cache_node(self.node)
|
||||
self.heartbeat_timeout = content['config']['heartbeat_timeout']
|
||||
|
||||
# Update config with values from Ironic
|
||||
config = content.get('config', {})
|
||||
if config.get('metrics'):
|
||||
for opt, val in config.items():
|
||||
setattr(cfg.CONF.metrics, opt, val)
|
||||
if config.get('metrics_statsd'):
|
||||
for opt, val in config.items():
|
||||
setattr(cfg.CONF.metrics_statsd, opt, val)
|
||||
# Update config with values from Ironic
|
||||
config = content.get('config', {})
|
||||
if config.get('metrics'):
|
||||
for opt, val in config.items():
|
||||
setattr(cfg.CONF.metrics, opt, val)
|
||||
if config.get('metrics_statsd'):
|
||||
for opt, val in config.items():
|
||||
setattr(cfg.CONF.metrics_statsd, opt, val)
|
||||
elif cfg.CONF.inspection_callback_url:
|
||||
LOG.info('No ipa-api-url configured, Heartbeat and lookup '
|
||||
'skipped for inspector.')
|
||||
else:
|
||||
LOG.error('Neither ipa-api-url nor inspection_callback_url'
|
||||
'found, please check your pxe append parameters.')
|
||||
|
||||
wsgi = simple_server.make_server(
|
||||
self.listen_address.hostname,
|
||||
|
@ -362,7 +373,7 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
|
|||
self.api,
|
||||
server_class=simple_server.WSGIServer)
|
||||
|
||||
if not self.standalone:
|
||||
if not self.standalone and self.api_url:
|
||||
# Don't start heartbeating until the server is listening
|
||||
self.heartbeater.start()
|
||||
|
||||
|
@ -371,5 +382,5 @@ class IronicPythonAgent(base.ExecuteCommandMixin):
|
|||
except BaseException:
|
||||
LOG.exception('shutting down')
|
||||
|
||||
if not self.standalone:
|
||||
if not self.standalone and self.api_url:
|
||||
self.heartbeater.stop()
|
||||
|
|
|
@ -23,7 +23,7 @@ APARAMS = utils.get_agent_params()
|
|||
|
||||
cli_opts = [
|
||||
cfg.StrOpt('api_url',
|
||||
default=APARAMS.get('ipa-api-url', 'http://127.0.0.1:6385'),
|
||||
default=APARAMS.get('ipa-api-url'),
|
||||
deprecated_name='api-url',
|
||||
help='URL of the Ironic API'),
|
||||
|
||||
|
|
|
@ -249,6 +249,104 @@ class TestBaseAgent(test_base.BaseTestCase):
|
|||
mocked_dispatch.assert_called_once_with("list_hardware_info")
|
||||
self.agent.heartbeater.start.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(agent.IronicPythonAgent,
|
||||
'_wait_for_interface')
|
||||
@mock.patch.object(inspector, 'inspect', autospec=True)
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
@mock.patch('wsgiref.simple_server.make_server', autospec=True)
|
||||
@mock.patch.object(hardware.HardwareManager, 'list_hardware_info')
|
||||
def test_run_with_inspection_without_apiurl(self,
|
||||
mocked_list_hardware,
|
||||
mocked_server_maker,
|
||||
mocked_dispatch,
|
||||
mocked_inspector,
|
||||
mocked_wait):
|
||||
# If inspection_callback_url is configured and api_url is not when the
|
||||
# agent starts, ensure that the inspection will be called and wsgi
|
||||
# server will work as usual. Also, make sure api_client and heartbeater
|
||||
# will not be initialized in this case.
|
||||
CONF.set_override('inspection_callback_url', 'http://foo/bar',
|
||||
enforce_type=True)
|
||||
|
||||
self.agent = agent.IronicPythonAgent(None,
|
||||
agent.Host('203.0.113.1', 9990),
|
||||
agent.Host('192.0.2.1', 9999),
|
||||
3,
|
||||
10,
|
||||
'eth0',
|
||||
300,
|
||||
1,
|
||||
'agent_ssh',
|
||||
False)
|
||||
self.assertFalse(hasattr(self.agent, 'api_client'))
|
||||
self.assertFalse(hasattr(self.agent, 'heartbeater'))
|
||||
|
||||
wsgi_server = mocked_server_maker.return_value
|
||||
wsgi_server.start.side_effect = KeyboardInterrupt()
|
||||
|
||||
self.agent.run()
|
||||
|
||||
listen_addr = agent.Host('192.0.2.1', 9999)
|
||||
mocked_server_maker.assert_called_once_with(
|
||||
listen_addr.hostname,
|
||||
listen_addr.port,
|
||||
self.agent.api,
|
||||
server_class=simple_server.WSGIServer)
|
||||
wsgi_server.serve_forever.assert_called_once_with()
|
||||
mocked_inspector.assert_called_once_with()
|
||||
|
||||
self.assertFalse(mocked_wait.called)
|
||||
self.assertFalse(mocked_dispatch.called)
|
||||
|
||||
@mock.patch.object(agent.IronicPythonAgent,
|
||||
'_wait_for_interface')
|
||||
@mock.patch.object(inspector, 'inspect', autospec=True)
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
@mock.patch('wsgiref.simple_server.make_server', autospec=True)
|
||||
@mock.patch.object(hardware.HardwareManager, 'list_hardware_info')
|
||||
def test_run_without_inspection_and_apiurl(self,
|
||||
mocked_list_hardware,
|
||||
mocked_server_maker,
|
||||
mocked_dispatch,
|
||||
mocked_inspector,
|
||||
mocked_wait):
|
||||
# If both api_url and inspection_callback_url are not configured when
|
||||
# the agent starts, ensure that the inspection will be skipped and wsgi
|
||||
# server will work as usual. Also, make sure api_client and heartbeater
|
||||
# will not be initialized in this case.
|
||||
CONF.set_override('inspection_callback_url', None,
|
||||
enforce_type=True)
|
||||
|
||||
self.agent = agent.IronicPythonAgent(None,
|
||||
agent.Host('203.0.113.1', 9990),
|
||||
agent.Host('192.0.2.1', 9999),
|
||||
3,
|
||||
10,
|
||||
'eth0',
|
||||
300,
|
||||
1,
|
||||
'agent_ssh',
|
||||
False)
|
||||
self.assertFalse(hasattr(self.agent, 'api_client'))
|
||||
self.assertFalse(hasattr(self.agent, 'heartbeater'))
|
||||
|
||||
wsgi_server = mocked_server_maker.return_value
|
||||
wsgi_server.start.side_effect = KeyboardInterrupt()
|
||||
|
||||
self.agent.run()
|
||||
|
||||
listen_addr = agent.Host('192.0.2.1', 9999)
|
||||
mocked_server_maker.assert_called_once_with(
|
||||
listen_addr.hostname,
|
||||
listen_addr.port,
|
||||
self.agent.api,
|
||||
server_class=simple_server.WSGIServer)
|
||||
wsgi_server.serve_forever.assert_called_once_with()
|
||||
|
||||
self.assertFalse(mocked_inspector.called)
|
||||
self.assertFalse(mocked_wait.called)
|
||||
self.assertFalse(mocked_dispatch.called)
|
||||
|
||||
@mock.patch.object(time, 'time', autospec=True)
|
||||
@mock.patch.object(time, 'sleep', autospec=True)
|
||||
@mock.patch.object(hardware, 'dispatch_to_managers', autospec=True)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
fixes:
|
||||
- If ipa-api-url is not configured in pxe parameters, skip lookup and heartbeat
|
||||
to avoid ConnectionError when the IPA starts. See https://bugs.launchpad.net/bugs/1643966
|
||||
for details.
|
Loading…
Reference in New Issue