Skip to content

Commit 824a825

Browse files
committed
Metadata: handle process exceptions
Both metadata agents (OVN and non-OVN) should handle process exceptions when spawning haproxy processes such that the agent can continue its operation for other haproxy processes. Closes-Bug: #2033305 Change-Id: I6da1b135c83ecfc41ec91e907ebf8500325a7a80 (cherry picked from commit 4698dd8)
1 parent 040a96e commit 824a825

File tree

5 files changed

+90
-14
lines changed

5 files changed

+90
-14
lines changed

neutron/agent/metadata/driver.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,13 @@ def spawn_monitored_metadata_proxy(cls, monitor, ns_name, port, conf,
294294
pm = cls._get_metadata_proxy_process_manager(uuid, conf,
295295
ns_name=ns_name,
296296
callback=callback)
297-
pm.enable()
297+
try:
298+
pm.enable()
299+
except exceptions.ProcessExecutionError as exec_err:
300+
LOG.error("Encountered process execution error %(err)s while "
301+
"starting process in namespace %(ns)s",
302+
{"err": exec_err, "ns": ns_name})
303+
return
298304
monitor.register(uuid, METADATA_SERVICE_NAME, pm)
299305
cls.monitors[router_id] = pm
300306

neutron/agent/ovn/metadata/driver.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,13 @@ def spawn_monitored_metadata_proxy(cls, monitor, ns_name, port, conf,
197197
pm = cls._get_metadata_proxy_process_manager(uuid, conf,
198198
ns_name=ns_name,
199199
callback=callback)
200-
pm.enable()
200+
try:
201+
pm.enable()
202+
except exceptions.ProcessExecutionError as exec_err:
203+
LOG.error("Encountered process execution error %(err)s while "
204+
"starting process in namespace %(ns)s",
205+
{"err": exec_err, "ns": ns_name})
206+
return
201207
monitor.register(uuid, METADATA_SERVICE_NAME, pm)
202208
cls.monitors[router_id] = pm
203209

neutron/tests/unit/agent/dhcp/test_agent.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -875,23 +875,37 @@ def _process_manager_constructor_call(self, ns=FAKE_NETWORK_DHCP_NS):
875875
def _enable_dhcp_helper(self, network, enable_isolated_metadata=False,
876876
is_isolated_network=False, is_ovn_network=False):
877877
self.dhcp._process_monitor = mock.Mock()
878+
# The disable() call
879+
gmppm_expected_calls = [mock.call(FAKE_NETWORK_UUID, cfg.CONF,
880+
ns_name=FAKE_NETWORK_DHCP_NS)]
878881
if enable_isolated_metadata:
879882
cfg.CONF.set_override('enable_isolated_metadata', True)
883+
if is_isolated_network:
884+
# The enable() call
885+
gmppm_expected_calls.append(
886+
mock.call(FAKE_NETWORK_UUID, cfg.CONF,
887+
ns_name=FAKE_NETWORK_DHCP_NS,
888+
callback=mock.ANY))
880889
self.plugin.get_network_info.return_value = network
881-
self.dhcp.enable_dhcp_helper(network.id)
890+
process_instance = mock.Mock(active=False)
891+
with mock.patch.object(metadata_driver.MetadataDriver,
892+
'_get_metadata_proxy_process_manager',
893+
return_value=process_instance) as gmppm:
894+
self.dhcp.enable_dhcp_helper(network.id)
895+
gmppm.assert_has_calls(gmppm_expected_calls)
882896
self.plugin.assert_has_calls([
883897
mock.call.get_network_info(network.id)])
884898
self.call_driver.assert_called_once_with('enable', network)
885899
self.cache.assert_has_calls([mock.call.put(network)])
886900
if (is_isolated_network and enable_isolated_metadata and not
887901
is_ovn_network):
888-
self.external_process.assert_has_calls([
889-
self._process_manager_constructor_call(),
890-
mock.call().enable()], any_order=True)
902+
process_instance.assert_has_calls([
903+
mock.call.disable(sig=str(int(signal.SIGTERM))),
904+
mock.call.get_pid_file_name(),
905+
mock.call.enable()])
891906
else:
892-
self.external_process.assert_has_calls([
893-
self._process_manager_constructor_call(),
894-
mock.call().disable(sig=str(int(signal.SIGTERM)))])
907+
process_instance.assert_has_calls([
908+
mock.call.disable(sig=str(int(signal.SIGTERM)))])
895909

896910
def test_enable_dhcp_helper_enable_metadata_isolated_network(self):
897911
self._enable_dhcp_helper(isolated_network,
@@ -1065,11 +1079,16 @@ def test_disable_dhcp_helper_driver_failure(self):
10651079

10661080
def test_enable_isolated_metadata_proxy(self):
10671081
self.dhcp._process_monitor = mock.Mock()
1068-
self.dhcp.enable_isolated_metadata_proxy(fake_network)
1069-
self.external_process.assert_has_calls([
1070-
self._process_manager_constructor_call(),
1071-
mock.call().enable()
1072-
], any_order=True)
1082+
process_instance = mock.Mock(active=False)
1083+
with mock.patch.object(metadata_driver.MetadataDriver,
1084+
'_get_metadata_proxy_process_manager',
1085+
return_value=process_instance) as gmppm:
1086+
self.dhcp.enable_isolated_metadata_proxy(fake_network)
1087+
gmppm.assert_called_with(FAKE_NETWORK_UUID,
1088+
cfg.CONF,
1089+
ns_name=FAKE_NETWORK_DHCP_NS,
1090+
callback=mock.ANY)
1091+
process_instance.enable.assert_called_once()
10731092

10741093
def test_disable_isolated_metadata_proxy(self):
10751094
method_path = ('neutron.agent.metadata.driver.MetadataDriver'

neutron/tests/unit/agent/metadata/test_driver.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from unittest import mock
1919

2020
from neutron_lib import constants
21+
from neutron_lib import exceptions as lib_exceptions
2122
from neutron_lib import fixture as lib_fixtures
2223
from oslo_config import cfg
2324
from oslo_utils import uuidutils
@@ -241,6 +242,26 @@ def test_spawn_metadata_proxy(self):
241242
def test_spawn_metadata_proxy_dad_failed(self):
242243
self._test_spawn_metadata_proxy(dad_failed=True)
243244

245+
@mock.patch.object(metadata_driver.LOG, 'error')
246+
def test_spawn_metadata_proxy_handles_process_exception(self, error_log):
247+
process_instance = mock.Mock(active=False)
248+
process_instance.enable.side_effect = (
249+
lib_exceptions.ProcessExecutionError('Something happened', -1))
250+
with mock.patch.object(metadata_driver.MetadataDriver,
251+
'_get_metadata_proxy_process_manager',
252+
return_value=process_instance):
253+
process_monitor = mock.Mock()
254+
network_id = 123456
255+
metadata_driver.MetadataDriver.spawn_monitored_metadata_proxy(
256+
process_monitor,
257+
'dummy_namespace',
258+
self.METADATA_PORT,
259+
cfg.CONF,
260+
network_id=network_id)
261+
error_log.assert_called_once()
262+
process_monitor.register.assert_not_called()
263+
self.assertNotIn(network_id, metadata_driver.MetadataDriver.monitors)
264+
244265
def test_create_config_file_wrong_user(self):
245266
with mock.patch('pwd.getpwnam', side_effect=KeyError):
246267
config = metadata_driver.HaproxyConfigurator(_uuid(),

neutron/tests/unit/agent/ovn/metadata/test_driver.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import os
1717
from unittest import mock
1818

19+
from neutron_lib import exceptions as lib_exceptions
1920
from neutron_lib import fixture as lib_fixtures
2021
from oslo_config import cfg
2122
from oslo_utils import uuidutils
@@ -108,6 +109,29 @@ def test_spawn_metadata_proxy(self):
108109
run_as_root=True)
109110
])
110111

112+
@mock.patch.object(metadata_driver.LOG, 'error')
113+
def test_spawn_metadata_proxy_handles_process_exception(self, error_log):
114+
process_instance = mock.Mock(active=False)
115+
process_instance.enable.side_effect = (
116+
lib_exceptions.ProcessExecutionError('Something happened', -1))
117+
118+
with mock.patch.object(metadata_driver.MetadataDriver,
119+
'_get_metadata_proxy_process_manager',
120+
return_value=process_instance):
121+
process_monitor = mock.Mock()
122+
network_id = 123456
123+
124+
metadata_driver.MetadataDriver.spawn_monitored_metadata_proxy(
125+
process_monitor,
126+
'dummy_namespace',
127+
self.METADATA_PORT,
128+
cfg.CONF,
129+
network_id=network_id)
130+
131+
error_log.assert_called_once()
132+
process_monitor.register.assert_not_called()
133+
self.assertNotIn(network_id, metadata_driver.MetadataDriver.monitors)
134+
111135
def test_create_config_file_wrong_user(self):
112136
with mock.patch('pwd.getpwnam', side_effect=KeyError):
113137
config = metadata_driver.HaproxyConfigurator(mock.ANY, mock.ANY,

0 commit comments

Comments
 (0)