Skip to content

Commit f0c7222

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Remove obsolete PID files before start" into stable/2023.1
2 parents 0ed6740 + 7c7a99a commit f0c7222

File tree

8 files changed

+77
-37
lines changed

8 files changed

+77
-37
lines changed

neutron/agent/linux/external_process.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,19 @@ def enable(self, cmd_callback=None, reload_cfg=False, ensure_active=False):
8787
if not self.active:
8888
if not cmd_callback:
8989
cmd_callback = self.default_cmd_callback
90-
cmd = cmd_callback(self.get_pid_file_name())
90+
# Always try and remove the pid file, as it's existence could
91+
# stop the process from starting
92+
pid_file = self.get_pid_file_name()
93+
try:
94+
utils.delete_if_exists(pid_file, run_as_root=self.run_as_root)
95+
except Exception as e:
96+
LOG.error("Could not delete file %(pid_file)s, %(service)s "
97+
"could fail to start. Exception: %(exc)s",
98+
{'pid_file': pid_file,
99+
'service': self.service,
100+
'exc': e})
101+
102+
cmd = cmd_callback(pid_file)
91103

92104
ip_wrapper = ip_lib.IPWrapper(namespace=self.namespace)
93105
ip_wrapper.netns.execute(cmd, addl_env=self.cmd_addl_env,
@@ -99,12 +111,14 @@ def enable(self, cmd_callback=None, reload_cfg=False, ensure_active=False):
99111

100112
def reload_cfg(self):
101113
if self.custom_reload_callback:
102-
self.disable(get_stop_command=self.custom_reload_callback)
114+
self.disable(get_stop_command=self.custom_reload_callback,
115+
delete_pid_file=False)
103116
else:
104-
self.disable('HUP')
117+
self.disable('HUP', delete_pid_file=False)
105118

106-
def disable(self, sig='9', get_stop_command=None):
119+
def disable(self, sig='9', get_stop_command=None, delete_pid_file=True):
107120
pid = self.pid
121+
delete_pid_file = delete_pid_file or sig == '9'
108122

109123
if self.active:
110124
if get_stop_command:
@@ -118,10 +132,10 @@ def disable(self, sig='9', get_stop_command=None):
118132
utils.execute(cmd, addl_env=self.cmd_addl_env,
119133
run_as_root=self.run_as_root,
120134
privsep_exec=True)
121-
# In the case of shutting down, remove the pid file
122-
if sig == '9':
123-
utils.delete_if_exists(self.get_pid_file_name(),
124-
run_as_root=self.run_as_root)
135+
136+
if delete_pid_file:
137+
utils.delete_if_exists(self.get_pid_file_name(),
138+
run_as_root=self.run_as_root)
125139
elif pid:
126140
LOG.debug('%(service)s process for %(uuid)s pid %(pid)d is stale, '
127141
'ignoring signal %(signal)s',

neutron/agent/linux/keepalived.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -427,15 +427,6 @@ def _output_config_file(self):
427427

428428
return config_path
429429

430-
@staticmethod
431-
def _safe_remove_pid_file(pid_file):
432-
try:
433-
os.remove(pid_file)
434-
except OSError as e:
435-
if e.errno != errno.ENOENT:
436-
LOG.error("Could not delete file %s, keepalived can "
437-
"refuse to start.", pid_file)
438-
439430
def get_vrrp_pid_file_name(self, base_pid_file):
440431
return '%s-vrrp' % base_pid_file
441432

@@ -516,9 +507,6 @@ def callback(pid_file):
516507
if vrrp_pm.active:
517508
vrrp_pm.disable()
518509

519-
self._safe_remove_pid_file(pid_file)
520-
self._safe_remove_pid_file(self.get_vrrp_pid_file_name(pid_file))
521-
522510
cmd = ['keepalived', '-P',
523511
'-f', config_path,
524512
'-p', pid_file,

neutron/agent/metadata/driver.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,8 @@ def destroy_monitored_metadata_proxy(cls, monitor, uuid, conf, ns_name):
288288
pm.pid, SIGTERM_TIMEOUT)
289289
pm.disable(sig=str(int(signal.SIGKILL)))
290290

291-
# Delete metadata proxy config and PID files.
291+
# Delete metadata proxy config.
292292
HaproxyConfigurator.cleanup_config_file(uuid, cfg.CONF.state_path)
293-
linux_utils.delete_if_exists(pm.get_pid_file_name(), run_as_root=True)
294293

295294
cls.monitors.pop(uuid, None)
296295

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3267,8 +3267,9 @@ def test_external_gateway_removed_ext_gw_port_no_fip_ns(self):
32673267
self.assertFalse(ri.remove_floating_ip.called)
32683268

32693269
@mock.patch.object(os, 'geteuid', return_value=mock.ANY)
3270+
@mock.patch.object(linux_utils, 'delete_if_exists')
32703271
@mock.patch.object(pwd, 'getpwuid')
3271-
def test_spawn_radvd(self, mock_getpwuid, *args):
3272+
def test_spawn_radvd(self, mock_getpwuid, mock_delete, *args):
32723273
router = l3_test_common.prepare_router_data(
32733274
ip_version=lib_constants.IP_VERSION_6)
32743275

@@ -3304,6 +3305,8 @@ def test_spawn_radvd(self, mock_getpwuid, *args):
33043305
self.conf.set_override('radvd_user', radvd_user)
33053306
mock_getpwuid.return_value = FakeUser(os_user)
33063307
radvd.enable(router['_interfaces'])
3308+
mock_delete.assert_called_once_with(pidfile, run_as_root=True)
3309+
mock_delete.reset_mock()
33073310
cmd = execute.call_args[0][0]
33083311
_join = lambda *args: ' '.join(args)
33093312
cmd = _join(*cmd)

neutron/tests/unit/agent/l3/test_ha_router.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ def setUp(self):
3535
self.device_exists_p = mock.patch(
3636
'neutron.agent.linux.ip_lib.device_exists')
3737
self.device_exists = self.device_exists_p.start()
38+
self.delete_if_exists_p = mock.patch(
39+
'neutron.agent.linux.utils.delete_if_exists')
40+
self.delete_if_exists = self.delete_if_exists_p.start()
3841

3942
def _create_router(self, router=None, **kwargs):
4043
if not router:

neutron/tests/unit/agent/linux/test_external_process.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,11 @@ def setUp(self):
120120
self.execute_p = mock.patch('neutron.agent.common.utils.execute')
121121
self.execute = self.execute_p.start()
122122
self.delete_if_exists = mock.patch(
123-
'oslo_utils.fileutils.delete_if_exists').start()
123+
'neutron.agent.linux.utils.delete_if_exists').start()
124124
self.ensure_dir = mock.patch.object(
125125
fileutils, 'ensure_tree').start()
126+
self.error_log = mock.patch("neutron.agent.linux.external_process."
127+
"LOG.error").start()
126128

127129
self.conf = mock.Mock()
128130
self.conf.external_pids = '/var/path'
@@ -167,6 +169,8 @@ def test_enable_with_namespace(self):
167169
with mock.patch.object(ep, 'ip_lib') as ip_lib:
168170
manager.enable(callback)
169171
callback.assert_called_once_with('pidfile')
172+
self.delete_if_exists.assert_called_once_with(
173+
'pidfile', run_as_root=True)
170174
env = {ep.PROCESS_TAG: ep.DEFAULT_SERVICE_NAME + '-uuid'}
171175
ip_lib.assert_has_calls([
172176
mock.call.IPWrapper(namespace='ns'),
@@ -253,11 +257,34 @@ def _create_cmd(*args):
253257
(service_name, uuid))
254258
self.assertEqual(expected_value, ret_value)
255259

260+
def test_enable_delete_pid_file_raises(self):
261+
callback = mock.Mock()
262+
cmd = ['the', 'cmd']
263+
callback.return_value = cmd
264+
self.delete_if_exists.side_effect = OSError
265+
266+
with mock.patch.object(ep.ProcessManager, 'get_pid_file_name') as name:
267+
name.return_value = 'pidfile'
268+
with mock.patch.object(ep.ProcessManager, 'active') as active:
269+
active.__get__ = mock.Mock(return_value=False)
270+
271+
manager = ep.ProcessManager(self.conf, 'uuid')
272+
manager.enable(callback)
273+
callback.assert_called_once_with('pidfile')
274+
cmd = ['env', DEFAULT_ENVVAR + '-uuid'] + cmd
275+
self.execute.assert_called_once_with(cmd,
276+
check_exit_code=True,
277+
extra_ok_codes=None,
278+
run_as_root=False,
279+
log_fail_as_error=True,
280+
privsep_exec=False)
281+
self.error_log.assert_called_once()
282+
256283
def test_reload_cfg_without_custom_reload_callback(self):
257284
with mock.patch.object(ep.ProcessManager, 'disable') as disable:
258285
manager = ep.ProcessManager(self.conf, 'uuid', namespace='ns')
259286
manager.reload_cfg()
260-
disable.assert_called_once_with('HUP')
287+
disable.assert_called_once_with('HUP', delete_pid_file=False)
261288

262289
def test_reload_cfg_with_custom_reload_callback(self):
263290
reload_callback = mock.sentinel.callback
@@ -266,7 +293,8 @@ def test_reload_cfg_with_custom_reload_callback(self):
266293
self.conf, 'uuid', namespace='ns',
267294
custom_reload_callback=reload_callback)
268295
manager.reload_cfg()
269-
disable.assert_called_once_with(get_stop_command=reload_callback)
296+
disable.assert_called_once_with(get_stop_command=reload_callback,
297+
delete_pid_file=False)
270298

271299
def test_disable_get_stop_command(self):
272300
cmd = ['the', 'cmd']

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def setUp(self):
9393
mock.patch('neutron.agent.l3.ha.AgentMixin'
9494
'._init_ha_conf_path').start()
9595
self.delete_if_exists = mock.patch.object(linux_utils,
96-
'delete_if_exists')
96+
'delete_if_exists').start()
9797
self.mock_get_process = mock.patch.object(
9898
metadata_driver.MetadataDriver,
9999
'_get_metadata_proxy_process_manager')
@@ -239,6 +239,9 @@ def _test_spawn_metadata_proxy(self, dad_failed=False):
239239
router_id, metadata_driver.METADATA_SERVICE_NAME,
240240
mock.ANY)
241241

242+
self.delete_if_exists.assert_called_once_with(
243+
mock.ANY, run_as_root=True)
244+
242245
def test_spawn_metadata_proxy(self):
243246
self._test_spawn_metadata_proxy()
244247

@@ -270,23 +273,19 @@ def test_create_config_file_wrong_group(self):
270273
config.create_config_file)
271274

272275
def test_destroy_monitored_metadata_proxy(self):
273-
delete_if_exists = self.delete_if_exists.start()
274-
mproxy_process = mock.Mock(
275-
active=False, get_pid_file_name=mock.Mock(return_value='pid_file'))
276+
mproxy_process = mock.Mock(active=False)
276277
mock_get_process = self.mock_get_process.start()
277278
mock_get_process.return_value = mproxy_process
278279
driver = metadata_driver.MetadataDriver(FakeL3NATAgent())
279280
driver.destroy_monitored_metadata_proxy(mock.Mock(), 'uuid', 'conf',
280281
'ns_name')
281282
mproxy_process.disable.assert_called_once_with(
282283
sig=str(int(signal.SIGTERM)))
283-
delete_if_exists.assert_has_calls([
284-
mock.call('pid_file', run_as_root=True)])
284+
self.delete_if_exists.assert_called_once_with(
285+
mock.ANY, run_as_root=True)
285286

286287
def test_destroy_monitored_metadata_proxy_force(self):
287-
delete_if_exists = self.delete_if_exists.start()
288-
mproxy_process = mock.Mock(
289-
active=True, get_pid_file_name=mock.Mock(return_value='pid_file'))
288+
mproxy_process = mock.Mock(active=True)
290289
mock_get_process = self.mock_get_process.start()
291290
mock_get_process.return_value = mproxy_process
292291
driver = metadata_driver.MetadataDriver(FakeL3NATAgent())
@@ -296,5 +295,5 @@ def test_destroy_monitored_metadata_proxy_force(self):
296295
mproxy_process.disable.assert_has_calls([
297296
mock.call(sig=str(int(signal.SIGTERM))),
298297
mock.call(sig=str(int(signal.SIGKILL)))])
299-
delete_if_exists.assert_has_calls([
300-
mock.call('pid_file', run_as_root=True)])
298+
self.delete_if_exists.assert_called_once_with(
299+
mock.ANY, run_as_root=True)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from oslo_utils import uuidutils
2222

2323
from neutron.agent.linux import external_process as ep
24+
from neutron.agent.linux import utils as linux_utils
2425
from neutron.agent.ovn.metadata import agent as metadata_agent
2526
from neutron.agent.ovn.metadata import driver as metadata_driver
2627
from neutron.common import metadata as comm_meta
@@ -45,6 +46,8 @@ class TestMetadataDriverProcess(base.BaseTestCase):
4546
def setUp(self):
4647
super(TestMetadataDriverProcess, self).setUp()
4748
mock.patch('eventlet.spawn').start()
49+
self.delete_if_exists = mock.patch.object(linux_utils,
50+
'delete_if_exists').start()
4851

4952
ovn_meta_conf.register_meta_conf_opts(meta_conf.SHARED_OPTS, cfg.CONF)
5053
ovn_conf.register_opts()
@@ -117,6 +120,9 @@ def test_spawn_metadata_proxy(self):
117120
run_as_root=True)
118121
])
119122

123+
self.delete_if_exists.assert_called_once_with(
124+
mock.ANY, run_as_root=True)
125+
120126
def test_create_config_file_wrong_user(self):
121127
with mock.patch('pwd.getpwnam', side_effect=KeyError):
122128
config = metadata_driver.HaproxyConfigurator(mock.ANY, mock.ANY,

0 commit comments

Comments
 (0)