Merge "Use transient systemd units in Process fixture"

This commit is contained in:
Zuul 2024-06-17 20:52:03 +00:00 committed by Gerrit Code Review
commit 1431a08440
4 changed files with 102 additions and 41 deletions

View File

@ -54,3 +54,7 @@ l3_agent: CommandFilter, l3_agent.py, root
#needed to capture and analyze traffic in fullstack tests (f.e. in DSCP scenarios)
tcpdump: CommandFilter, tcpdump, root
#needed to create transient systemd services for fullstack tests
systemd_run: CommandFilter, systemd-run, root
systemctl: CommandFilter, systemctl, root

View File

@ -16,7 +16,6 @@ import datetime
import os
import re
import shutil
import signal
import fixtures
from neutron_lib import constants
@ -25,7 +24,6 @@ from neutronclient.v2_0 import client
from oslo_log import log as logging
from oslo_utils import fileutils
from neutron.agent.common import async_process
from neutron.agent.linux import ip_lib
from neutron.agent.linux import utils
from neutron.common import utils as common_utils
@ -39,16 +37,25 @@ CMD_FOLDER = 'agents'
class ProcessFixture(fixtures.Fixture):
def __init__(self, test_name, process_name, exec_name, config_filenames,
namespace=None, kill_signal=signal.SIGKILL):
namespace=None, slice_name=None):
super(ProcessFixture, self).__init__()
self.test_name = test_name
self.process_name = process_name
self.exec_name = exec_name
self.config_filenames = config_filenames
self.process = None
self.kill_signal = kill_signal
self.namespace = namespace
self.slice_name = slice_name
self.unit_name = f'{self.test_name}-{self.process_name}'
if self.namespace:
self.unit_name += f'-{self.namespace}'
# Escape special characters in unit names, see man systemd.unit
self.unit_name = utils.execute(
['systemd-escape', self.unit_name],
).strip()
def _setUp(self):
self.start()
self.addCleanup(self.stop)
@ -66,25 +73,58 @@ class ProcessFixture(fixtures.Fixture):
if run_as_root
else shutil.which(self.exec_name))
cmd = [exec_name, '--log-dir', log_dir, '--log-file', log_file]
if self.namespace:
cmd = ip_lib.add_namespace_to_cmd(cmd, self.namespace)
for filename in self.config_filenames:
cmd += ['--config-file', filename]
self.process = async_process.AsyncProcess(
cmd, run_as_root=run_as_root, namespace=self.namespace,
process_name=self.process_name
systemd_run = [
'systemd-run',
'--service-type', 'exec',
'--property', 'TimeoutStopSec=30s',
'--unit', self.unit_name,
'--setenv', f'PATH={os.environ["PATH"]}',
'--same-dir',
'--collect',
]
if not run_as_root:
systemd_run += [
'--uid', os.getuid(),
'--gid', os.getgid(),
]
if self.slice_name:
systemd_run += ['--slice', self.slice_name]
utils.execute(
systemd_run + cmd,
# Always create the systemd unit as root, the process itself will
# run unprivileged if run_as_root is False.
run_as_root=True,
)
self.process.start(block=True)
LOG.debug("Process started: %s", self.process_name)
def stop(self, kill_signal=None):
kill_signal = kill_signal or self.kill_signal
try:
self.process.stop(
block=True, kill_signal=kill_signal,
kill_timeout=15)
except async_process.AsyncProcessException as e:
if "Process is not running" not in str(e):
raise
LOG.debug("Process stopped: %s", self.process_name)
if self.process_is_not_running():
return
if kill_signal:
stop_cmd = [
'systemctl',
'kill',
'--signal', kill_signal.value,
'--kill-who', 'all',
self.unit_name,
]
msg = (f'Process killed with signal {kill_signal}: '
f'{self.process_name}')
else:
stop_cmd = ['systemctl', 'stop', self.unit_name]
msg = f'Process stopped: {self.process_name}'
utils.execute(stop_cmd, run_as_root=True)
LOG.debug(msg)
def restart(self, executor=None):
def _restart():
@ -99,7 +139,13 @@ class ProcessFixture(fixtures.Fixture):
return executor.submit(_restart)
def process_is_running(self):
return self.process.is_running
cmd = ['systemctl', 'is-active', self.unit_name]
return utils.execute(
cmd,
run_as_root=True,
log_fail_as_error=False,
check_exit_code=False,
) == 'active\n'
def process_is_not_running(self):
return not self.process_is_running()
@ -156,6 +202,7 @@ class NeutronServerFixture(ServiceFixture):
self.neutron_cfg_fixture = neutron_cfg_fixture
self.plugin_cfg_fixture = plugin_cfg_fixture
self.service_cfg_fixtures = service_cfg_fixtures
self.hostname = self.neutron_cfg_fixture.config['DEFAULT']['host']
def _setUp(self):
config_filenames = [self.neutron_cfg_fixture.filename,
@ -167,10 +214,9 @@ class NeutronServerFixture(ServiceFixture):
self.process_fixture = self.useFixture(ProcessFixture(
test_name=self.test_name,
process_name=self.NEUTRON_SERVER,
process_name=f'{self.NEUTRON_SERVER}-{self.hostname}',
exec_name=self.NEUTRON_SERVER,
config_filenames=config_filenames,
kill_signal=signal.SIGTERM))
config_filenames=config_filenames))
common_utils.wait_until_true(self.server_is_live)
@ -200,6 +246,7 @@ class OVSAgentFixture(ServiceFixture):
self.neutron_config = self.neutron_cfg_fixture.config
self.agent_cfg_fixture = agent_cfg_fixture
self.agent_config = agent_cfg_fixture.config
self.hostname = self.neutron_config['DEFAULT']['host']
def _setUp(self):
self.br_int = self.useFixture(
@ -211,15 +258,16 @@ class OVSAgentFixture(ServiceFixture):
self.process_fixture = self.useFixture(ProcessFixture(
test_name=self.test_name,
process_name=constants.AGENT_PROCESS_OVS,
process_name=f'{constants.AGENT_PROCESS_OVS}-{self.hostname}',
slice_name=self.hostname,
exec_name=shutil.which(
'ovs_agent.py',
path=os.path.join(fullstack_base.ROOTDIR, CMD_FOLDER)),
config_filenames=config_filenames,
kill_signal=signal.SIGTERM))
))
class PlacementFixture(fixtures.Fixture):
class PlacementFixture(ServiceFixture):
def __init__(self, env_desc, host_desc, test_name, placement_cfg_fixture):
super(PlacementFixture, self).__init__()
@ -237,8 +285,7 @@ class PlacementFixture(fixtures.Fixture):
'placement.py', path=os.path.join(fullstack_base.ROOTDIR,
'servers')
),
config_filenames=[self.placement_cfg_fixture.filename],
kill_signal=signal.SIGTERM))
config_filenames=[self.placement_cfg_fixture.filename]))
class SRIOVAgentFixture(ServiceFixture):
@ -253,16 +300,18 @@ class SRIOVAgentFixture(ServiceFixture):
self.neutron_config = self.neutron_cfg_fixture.config
self.agent_cfg_fixture = agent_cfg_fixture
self.agent_config = agent_cfg_fixture.config
self.hostname = self.neutron_config['DEFAULT']['host']
def _setUp(self):
config_filenames = [self.neutron_cfg_fixture.filename,
self.agent_cfg_fixture.filename]
process_name = f'{constants.AGENT_PROCESS_NIC_SWITCH}-{self.hostname}'
self.process_fixture = self.useFixture(ProcessFixture(
test_name=self.test_name,
process_name=constants.AGENT_PROCESS_NIC_SWITCH,
process_name=process_name,
slice_name=self.hostname,
exec_name=constants.AGENT_PROCESS_NIC_SWITCH,
config_filenames=config_filenames,
kill_signal=signal.SIGTERM))
config_filenames=config_filenames))
class LinuxBridgeAgentFixture(ServiceFixture):
@ -279,15 +328,18 @@ class LinuxBridgeAgentFixture(ServiceFixture):
self.agent_cfg_fixture = agent_cfg_fixture
self.agent_config = agent_cfg_fixture.config
self.namespace = namespace
self.hostname = self.neutron_config['DEFAULT']['host']
def _setUp(self):
config_filenames = [self.neutron_cfg_fixture.filename,
self.agent_cfg_fixture.filename]
process_name = f'{constants.AGENT_PROCESS_LINUXBRIDGE}-{self.hostname}'
self.process_fixture = self.useFixture(
ProcessFixture(
test_name=self.test_name,
process_name=constants.AGENT_PROCESS_LINUXBRIDGE,
process_name=process_name,
slice_name=self.hostname,
exec_name=constants.AGENT_PROCESS_LINUXBRIDGE,
config_filenames=config_filenames,
namespace=self.namespace
@ -307,6 +359,7 @@ class L3AgentFixture(ServiceFixture):
self.neutron_cfg_fixture = neutron_cfg_fixture
self.l3_agent_cfg_fixture = l3_agent_cfg_fixture
self.namespace = namespace
self.hostname = self.neutron_cfg_fixture.config['DEFAULT']['host']
def _setUp(self):
self.plugin_config = self.l3_agent_cfg_fixture.config
@ -326,7 +379,8 @@ class L3AgentFixture(ServiceFixture):
self.process_fixture = self.useFixture(
ProcessFixture(
test_name=self.test_name,
process_name=constants.AGENT_PROCESS_L3,
process_name=f'{constants.AGENT_PROCESS_L3}-{self.hostname}',
slice_name=self.hostname,
exec_name=exec_name,
config_filenames=config_filenames,
namespace=self.namespace
@ -337,7 +391,7 @@ class L3AgentFixture(ServiceFixture):
return self.plugin_config.DEFAULT.test_namespace_suffix
class DhcpAgentFixture(fixtures.Fixture):
class DhcpAgentFixture(ServiceFixture):
def __init__(self, env_desc, host_desc, test_name,
neutron_cfg_fixture, agent_cfg_fixture, namespace=None):
@ -363,11 +417,13 @@ class DhcpAgentFixture(fixtures.Fixture):
exec_name = shutil.which(
'dhcp_agent.py',
path=os.path.join(fullstack_base.ROOTDIR, CMD_FOLDER))
hostname = self.get_agent_hostname()
self.process_fixture = self.useFixture(
ProcessFixture(
test_name=self.test_name,
process_name=constants.AGENT_PROCESS_DHCP,
process_name=f'{constants.AGENT_PROCESS_DHCP}-{hostname}',
slice_name=hostname,
exec_name=exec_name,
config_filenames=config_filenames,
namespace=self.namespace

View File

@ -147,7 +147,7 @@ class _TestUninterruptedConnectivityOnL2AgentRestart(
'l2_pop': False}),
]
def _test_l2_agent_restart(self, agent_restart_timeout=20):
def _test_l2_agent_restart(self, agent_restart_timeout=30):
# Environment preparation is effectively the same as connectivity test
vms = self._prepare_vms_in_single_network()
vms.ping_all()
@ -175,5 +175,5 @@ class TestUninterruptedConnectivityOnL2AgentRestartOvs(
scenario,
_TestUninterruptedConnectivityOnL2AgentRestart.network_scenarios))
def test_l2_agent_restart(self, agent_restart_timeout=20):
def test_l2_agent_restart(self, agent_restart_timeout=30):
self._test_l2_agent_restart(agent_restart_timeout)

View File

@ -34,12 +34,13 @@ class MTUNetworkTestSetup(base.BaseFullStackTestCase):
self.tenant_id = uuidutils.generate_uuid()
def _restart_neutron_server(self, global_mtu):
env = environment.Environment(
environment.EnvironmentDescription(global_mtu=global_mtu),
self.host_desc)
env.test_name = self.get_name()
self.useFixture(env)
env.neutron_server.restart()
neutron_server = self.environment.neutron_server
neutron_server.neutron_cfg_fixture.config['DEFAULT'].update(
{'global_physnet_mtu': str(global_mtu)}
)
neutron_server.neutron_cfg_fixture.write_config_to_configfile()
neutron_server.restart()
self.environment.wait_until_env_is_up()
class TestMTUScenarios(MTUNetworkTestSetup):