Delete HA metadata proxy PID and config with elevated privileges
Both files cannot be deleted with the default permissions because
those files are created by the "root" user.
Conflicts:
neutron/agent/metadata/driver.py
neutron/tests/functional/agent/l3/framework.py
neutron/tests/unit/agent/dhcp/test_agent.py
Change-Id: I73dd37b3104fac8d3172f520f71cffd85d040c4b
Closes-Bug: #1907695
(cherry picked from commit 0a0f647ea0
)
This commit is contained in:
parent
87fce78fee
commit
28cf6786f4
|
@ -113,7 +113,8 @@ class ProcessManager(MonitoredProcess):
|
||||||
utils.execute(cmd, run_as_root=self.run_as_root)
|
utils.execute(cmd, run_as_root=self.run_as_root)
|
||||||
# In the case of shutting down, remove the pid file
|
# In the case of shutting down, remove the pid file
|
||||||
if sig == '9':
|
if sig == '9':
|
||||||
fileutils.delete_if_exists(self.get_pid_file_name())
|
utils.delete_if_exists(self.get_pid_file_name(),
|
||||||
|
run_as_root=self.run_as_root)
|
||||||
elif pid:
|
elif pid:
|
||||||
LOG.debug('%(service)s process for %(uuid)s pid %(pid)d is stale, '
|
LOG.debug('%(service)s process for %(uuid)s pid %(pid)d is stale, '
|
||||||
'ignoring signal %(signal)s',
|
'ignoring signal %(signal)s',
|
||||||
|
|
|
@ -38,6 +38,7 @@ from neutron._i18n import _
|
||||||
from neutron.agent.linux import xenapi_root_helper
|
from neutron.agent.linux import xenapi_root_helper
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
from neutron.conf.agent import common as config
|
from neutron.conf.agent import common as config
|
||||||
|
from neutron.privileged.agent.linux import utils as priv_utils
|
||||||
from neutron import wsgi
|
from neutron import wsgi
|
||||||
|
|
||||||
|
|
||||||
|
@ -394,6 +395,14 @@ def is_effective_group(group_id_or_name):
|
||||||
return group_id_or_name == effective_group_name
|
return group_id_or_name == effective_group_name
|
||||||
|
|
||||||
|
|
||||||
|
def delete_if_exists(path, run_as_root=False):
|
||||||
|
"""Delete a path, executed as normal user or with elevated privileges"""
|
||||||
|
if run_as_root:
|
||||||
|
priv_utils.delete_if_exists(path)
|
||||||
|
else:
|
||||||
|
fileutils.delete_if_exists(path)
|
||||||
|
|
||||||
|
|
||||||
class UnixDomainHTTPConnection(httplib.HTTPConnection):
|
class UnixDomainHTTPConnection(httplib.HTTPConnection):
|
||||||
"""Connection class for HTTP over UNIX domain socket."""
|
"""Connection class for HTTP over UNIX domain socket."""
|
||||||
def __init__(self, host, port=None, strict=None, timeout=None,
|
def __init__(self, host, port=None, strict=None, timeout=None,
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import errno
|
|
||||||
import grp
|
import grp
|
||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
|
@ -30,6 +29,7 @@ from neutron._i18n import _
|
||||||
from neutron.agent.l3 import ha_router
|
from neutron.agent.l3 import ha_router
|
||||||
from neutron.agent.l3 import namespaces
|
from neutron.agent.l3 import namespaces
|
||||||
from neutron.agent.linux import external_process
|
from neutron.agent.linux import external_process
|
||||||
|
from neutron.agent.linux import utils as linux_utils
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -163,13 +163,7 @@ class HaproxyConfigurator(object):
|
||||||
cfg_path = os.path.join(
|
cfg_path = os.path.join(
|
||||||
HaproxyConfigurator.get_config_path(state_path),
|
HaproxyConfigurator.get_config_path(state_path),
|
||||||
"%s.conf" % uuid)
|
"%s.conf" % uuid)
|
||||||
try:
|
linux_utils.delete_if_exists(cfg_path, run_as_root=True)
|
||||||
os.unlink(cfg_path)
|
|
||||||
except OSError as ex:
|
|
||||||
# It can happen that this function is called but metadata proxy
|
|
||||||
# was never spawned so its config file won't exist
|
|
||||||
if ex.errno != errno.ENOENT:
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
class MetadataDriver(object):
|
class MetadataDriver(object):
|
||||||
|
|
|
@ -12,9 +12,11 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
|
from oslo_utils import fileutils
|
||||||
|
|
||||||
from neutron import privileged
|
from neutron import privileged
|
||||||
|
|
||||||
|
@ -40,3 +42,8 @@ def _find_listen_pids_namespace(namespace):
|
||||||
if m:
|
if m:
|
||||||
pids.add(m.group('pid'))
|
pids.add(m.group('pid'))
|
||||||
return list(pids)
|
return list(pids)
|
||||||
|
|
||||||
|
|
||||||
|
@privileged.default.entrypoint
|
||||||
|
def delete_if_exists(path, remove=os.unlink):
|
||||||
|
fileutils.delete_if_exists(path, remove=remove)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import functools
|
import functools
|
||||||
|
import os
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
import netaddr
|
import netaddr
|
||||||
|
@ -435,12 +436,15 @@ class L3AgentTestFramework(base.BaseSudoTestCase):
|
||||||
def _namespace_exists(self, namespace):
|
def _namespace_exists(self, namespace):
|
||||||
return ip_lib.network_namespace_exists(namespace)
|
return ip_lib.network_namespace_exists(namespace)
|
||||||
|
|
||||||
def _metadata_proxy_exists(self, conf, router):
|
def _metadata_proxy(self, conf, router):
|
||||||
pm = external_process.ProcessManager(
|
return external_process.ProcessManager(
|
||||||
conf,
|
conf,
|
||||||
router.router_id,
|
router.router_id,
|
||||||
router.ns_name,
|
router.ns_name,
|
||||||
service=metadata_driver.HAPROXY_SERVICE)
|
service=metadata_driver.HAPROXY_SERVICE)
|
||||||
|
|
||||||
|
def _metadata_proxy_exists(self, conf, router):
|
||||||
|
pm = self._metadata_proxy(conf, router)
|
||||||
return pm.active
|
return pm.active
|
||||||
|
|
||||||
def device_exists_with_ips_and_mac(self, expected_device, name_getter,
|
def device_exists_with_ips_and_mac(self, expected_device, name_getter,
|
||||||
|
@ -501,9 +505,19 @@ class L3AgentTestFramework(base.BaseSudoTestCase):
|
||||||
# then the devices and iptable rules have also been deleted,
|
# then the devices and iptable rules have also been deleted,
|
||||||
# so there's no need to check that explicitly.
|
# so there's no need to check that explicitly.
|
||||||
self.assertFalse(self._namespace_exists(router.ns_name))
|
self.assertFalse(self._namespace_exists(router.ns_name))
|
||||||
|
try:
|
||||||
common_utils.wait_until_true(
|
common_utils.wait_until_true(
|
||||||
lambda: not self._metadata_proxy_exists(self.agent.conf, router),
|
lambda: not self._metadata_proxy_exists(self.agent.conf,
|
||||||
|
router),
|
||||||
timeout=10)
|
timeout=10)
|
||||||
|
except common_utils.WaitTimeout:
|
||||||
|
pm = self._metadata_proxy(self.agent.conf, router)
|
||||||
|
pid_file = pm.get_pid_file_name()
|
||||||
|
if os.path.exists(pid_file):
|
||||||
|
msg = 'PID file %s still exists and it should not.' % pid_file
|
||||||
|
else:
|
||||||
|
msg = 'PID file %s is not present.' % pid_file
|
||||||
|
self.fail(msg)
|
||||||
|
|
||||||
def _assert_snat_chains(self, router):
|
def _assert_snat_chains(self, router):
|
||||||
self.assertFalse(router.iptables_manager.is_chain_empty(
|
self.assertFalse(router.iptables_manager.is_chain_empty(
|
||||||
|
|
|
@ -34,6 +34,7 @@ from neutron.agent.dhcp import agent as dhcp_agent
|
||||||
from neutron.agent import dhcp_agent as entry
|
from neutron.agent import dhcp_agent as entry
|
||||||
from neutron.agent.linux import dhcp
|
from neutron.agent.linux import dhcp
|
||||||
from neutron.agent.linux import interface
|
from neutron.agent.linux import interface
|
||||||
|
from neutron.agent.linux import utils as linux_utils
|
||||||
from neutron.agent.metadata import driver as metadata_driver
|
from neutron.agent.metadata import driver as metadata_driver
|
||||||
from neutron.common import config as common_config
|
from neutron.common import config as common_config
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
|
@ -759,6 +760,12 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
|
||||||
self.mock_resize_p = mock.patch('neutron.agent.dhcp.agent.'
|
self.mock_resize_p = mock.patch('neutron.agent.dhcp.agent.'
|
||||||
'DhcpAgent._resize_process_pool')
|
'DhcpAgent._resize_process_pool')
|
||||||
self.mock_resize = self.mock_resize_p.start()
|
self.mock_resize = self.mock_resize_p.start()
|
||||||
|
self.mock_wait_until_address_ready_p = mock.patch(
|
||||||
|
'neutron.agent.linux.ip_lib.'
|
||||||
|
'IpAddrCommand.wait_until_address_ready')
|
||||||
|
self.mock_wait_until_address_ready_p.start()
|
||||||
|
mock.patch.object(linux_utils, 'delete_if_exists').start()
|
||||||
|
self.addCleanup(self.mock_wait_until_address_ready_p.stop)
|
||||||
|
|
||||||
def _process_manager_constructor_call(self, ns=FAKE_NETWORK_DHCP_NS):
|
def _process_manager_constructor_call(self, ns=FAKE_NETWORK_DHCP_NS):
|
||||||
return mock.call(conf=cfg.CONF,
|
return mock.call(conf=cfg.CONF,
|
||||||
|
|
|
@ -55,6 +55,7 @@ from neutron.agent.linux import ip_lib
|
||||||
from neutron.agent.linux import iptables_manager
|
from neutron.agent.linux import iptables_manager
|
||||||
from neutron.agent.linux import pd
|
from neutron.agent.linux import pd
|
||||||
from neutron.agent.linux import ra
|
from neutron.agent.linux import ra
|
||||||
|
from neutron.agent.linux import utils as linux_utils
|
||||||
from neutron.agent.metadata import driver as metadata_driver
|
from neutron.agent.metadata import driver as metadata_driver
|
||||||
from neutron.agent import rpc as agent_rpc
|
from neutron.agent import rpc as agent_rpc
|
||||||
from neutron.conf.agent import common as agent_config
|
from neutron.conf.agent import common as agent_config
|
||||||
|
@ -3060,6 +3061,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||||
dvr_snat_ns.SNAT_NS_PREFIX + 'foo']
|
dvr_snat_ns.SNAT_NS_PREFIX + 'foo']
|
||||||
other_namespaces = ['unknown']
|
other_namespaces = ['unknown']
|
||||||
|
|
||||||
|
with mock.patch.object(linux_utils, 'delete_if_exists'):
|
||||||
self._cleanup_namespace_test(stale_namespaces,
|
self._cleanup_namespace_test(stale_namespaces,
|
||||||
[],
|
[],
|
||||||
other_namespaces)
|
other_namespaces)
|
||||||
|
@ -3072,6 +3074,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||||
{'id': 'aaaa', 'distributed': False}]
|
{'id': 'aaaa', 'distributed': False}]
|
||||||
other_namespaces = ['qdhcp-aabbcc', 'unknown']
|
other_namespaces = ['qdhcp-aabbcc', 'unknown']
|
||||||
|
|
||||||
|
with mock.patch.object(linux_utils, 'delete_if_exists'):
|
||||||
self._cleanup_namespace_test(stale_namespaces,
|
self._cleanup_namespace_test(stale_namespaces,
|
||||||
router_list,
|
router_list,
|
||||||
other_namespaces)
|
other_namespaces)
|
||||||
|
|
Loading…
Reference in New Issue