Use rootwrap for fullstack test runner
We plan to switch to devstack-gate for fullstack job, and it revokes direct sudo calls before executing tests, so we can't rely on sudo working anymore. This also moves functional-testing.filters to a more generic filename (testing.filters) because the filters are now deployed and used by fullstack target too. Related-Bug: #1557168 Related-Bug: #1693689 Change-Id: I1718ea51836adbb8ef8dea79822a722dcf111127
This commit is contained in:
parent
b6bd475629
commit
a99897ffb3
@ -45,6 +45,7 @@ from neutron.api.rpc.callbacks.consumer import registry as rpc_consumer_reg
|
|||||||
from neutron.api.rpc.callbacks.producer import registry as rpc_producer_reg
|
from neutron.api.rpc.callbacks.producer import registry as rpc_producer_reg
|
||||||
from neutron.common import config
|
from neutron.common import config
|
||||||
from neutron.common import rpc as n_rpc
|
from neutron.common import rpc as n_rpc
|
||||||
|
from neutron.conf.agent import common as agent_config
|
||||||
from neutron.db import _model_query as model_query
|
from neutron.db import _model_query as model_query
|
||||||
from neutron.db import _resource_extend as resource_extend
|
from neutron.db import _resource_extend as resource_extend
|
||||||
from neutron.db import agentschedulers_db
|
from neutron.db import agentschedulers_db
|
||||||
@ -63,6 +64,8 @@ CONF.import_opt('state_path', 'neutron.conf.common')
|
|||||||
ROOTDIR = os.path.dirname(__file__)
|
ROOTDIR = os.path.dirname(__file__)
|
||||||
ETCDIR = os.path.join(ROOTDIR, 'etc')
|
ETCDIR = os.path.join(ROOTDIR, 'etc')
|
||||||
|
|
||||||
|
SUDO_CMD = 'sudo -n'
|
||||||
|
|
||||||
|
|
||||||
def etcdir(*p):
|
def etcdir(*p):
|
||||||
return os.path.join(ETCDIR, *p)
|
return os.path.join(ETCDIR, *p)
|
||||||
@ -406,6 +409,14 @@ class BaseTestCase(DietTestCase):
|
|||||||
notification_driver = [fake_notifier.__name__]
|
notification_driver = [fake_notifier.__name__]
|
||||||
cfg.CONF.set_override("notification_driver", notification_driver)
|
cfg.CONF.set_override("notification_driver", notification_driver)
|
||||||
|
|
||||||
|
def setup_rootwrap(self):
|
||||||
|
agent_config.register_root_helper(cfg.CONF)
|
||||||
|
self.config(group='AGENT',
|
||||||
|
root_helper=os.environ.get('OS_ROOTWRAP_CMD', SUDO_CMD))
|
||||||
|
self.config(group='AGENT',
|
||||||
|
root_helper_daemon=os.environ.get(
|
||||||
|
'OS_ROOTWRAP_DAEMON_CMD'))
|
||||||
|
|
||||||
|
|
||||||
class PluginFixture(fixtures.Fixture):
|
class PluginFixture(fixtures.Fixture):
|
||||||
|
|
||||||
|
@ -44,3 +44,13 @@ process_spawn: EnvFilter, env, root, PATH=, python
|
|||||||
ip_exec: IpNetnsExecFilter, ip, root
|
ip_exec: IpNetnsExecFilter, ip, root
|
||||||
ps: CommandFilter, ps, root
|
ps: CommandFilter, ps, root
|
||||||
pid_kill: RegExpFilter, kill, root, kill, -\d+, .*
|
pid_kill: RegExpFilter, kill, root, kill, -\d+, .*
|
||||||
|
|
||||||
|
#needed to set up fullstack 'multinode' environment
|
||||||
|
rabbitmqctl: CommandFilter, rabbitmqctl, root
|
||||||
|
linuxbridge_agent: CommandFilter, neutron-linuxbridge-agent, root
|
||||||
|
dhcp_agent: CommandFilter, dhcp_agent.py, root
|
||||||
|
ovs_agent: CommandFilter, ovs_agent.py, root
|
||||||
|
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
|
@ -57,6 +57,10 @@ class BaseFullStackTestCase(testlib_api.MySQLTestCaseMixin,
|
|||||||
# since the latter starts services that may rely on generated port
|
# since the latter starts services that may rely on generated port
|
||||||
# numbers
|
# numbers
|
||||||
tools.reset_random_seed()
|
tools.reset_random_seed()
|
||||||
|
|
||||||
|
# configure test runner to use rootwrap
|
||||||
|
self.setup_rootwrap()
|
||||||
|
|
||||||
self.environment = environment
|
self.environment = environment
|
||||||
self.environment.test_name = self.get_name()
|
self.environment.test_name = self.get_name()
|
||||||
self.useFixture(self.environment)
|
self.useFixture(self.environment)
|
||||||
|
@ -59,12 +59,13 @@ class ProcessFixture(fixtures.Fixture):
|
|||||||
|
|
||||||
timestamp = datetime.datetime.now().strftime("%Y-%m-%d--%H-%M-%S-%f")
|
timestamp = datetime.datetime.now().strftime("%Y-%m-%d--%H-%M-%S-%f")
|
||||||
log_file = "%s--%s.log" % (self.process_name, timestamp)
|
log_file = "%s--%s.log" % (self.process_name, timestamp)
|
||||||
cmd = [spawn.find_executable(self.exec_name),
|
run_as_root = bool(self.namespace)
|
||||||
'--log-dir', log_dir,
|
exec_name = (self.exec_name
|
||||||
'--log-file', log_file]
|
if run_as_root
|
||||||
|
else spawn.find_executable(self.exec_name))
|
||||||
|
cmd = [exec_name, '--log-dir', log_dir, '--log-file', log_file]
|
||||||
for filename in self.config_filenames:
|
for filename in self.config_filenames:
|
||||||
cmd += ['--config-file', filename]
|
cmd += ['--config-file', filename]
|
||||||
run_as_root = bool(self.namespace)
|
|
||||||
self.process = async_process.AsyncProcess(
|
self.process = async_process.AsyncProcess(
|
||||||
cmd, run_as_root=run_as_root, namespace=self.namespace
|
cmd, run_as_root=run_as_root, namespace=self.namespace
|
||||||
)
|
)
|
||||||
@ -261,13 +262,21 @@ class L3AgentFixture(ServiceFixture):
|
|||||||
|
|
||||||
config_filenames = [self.neutron_cfg_fixture.filename,
|
config_filenames = [self.neutron_cfg_fixture.filename,
|
||||||
self.l3_agent_cfg_fixture.filename]
|
self.l3_agent_cfg_fixture.filename]
|
||||||
|
|
||||||
|
# if we execute in namespace as root, then allow rootwrap to find the
|
||||||
|
# executable, otherwise construct full path ourselves
|
||||||
|
if self.namespace:
|
||||||
|
exec_name = 'l3_agent.py'
|
||||||
|
else:
|
||||||
|
exec_name = spawn.find_executable(
|
||||||
|
'l3_agent.py',
|
||||||
|
path=os.path.join(fullstack_base.ROOTDIR, 'cmd'))
|
||||||
|
|
||||||
self.process_fixture = self.useFixture(
|
self.process_fixture = self.useFixture(
|
||||||
ProcessFixture(
|
ProcessFixture(
|
||||||
test_name=self.test_name,
|
test_name=self.test_name,
|
||||||
process_name=self.NEUTRON_L3_AGENT,
|
process_name=self.NEUTRON_L3_AGENT,
|
||||||
exec_name=spawn.find_executable(
|
exec_name=exec_name,
|
||||||
'l3_agent.py',
|
|
||||||
path=os.path.join(fullstack_base.ROOTDIR, 'cmd')),
|
|
||||||
config_filenames=config_filenames,
|
config_filenames=config_filenames,
|
||||||
namespace=self.namespace
|
namespace=self.namespace
|
||||||
)
|
)
|
||||||
@ -296,14 +305,21 @@ class DhcpAgentFixture(fixtures.Fixture):
|
|||||||
|
|
||||||
config_filenames = [self.neutron_cfg_fixture.filename,
|
config_filenames = [self.neutron_cfg_fixture.filename,
|
||||||
self.agent_cfg_fixture.filename]
|
self.agent_cfg_fixture.filename]
|
||||||
|
|
||||||
|
# if we execute in namespace as root, then allow rootwrap to find the
|
||||||
|
# executable, otherwise construct full path ourselves
|
||||||
|
if self.namespace:
|
||||||
|
exec_name = 'dhcp_agent.py'
|
||||||
|
else:
|
||||||
|
exec_name = spawn.find_executable(
|
||||||
|
'dhcp_agent.py',
|
||||||
|
path=os.path.join(fullstack_base.ROOTDIR, 'cmd'))
|
||||||
|
|
||||||
self.process_fixture = self.useFixture(
|
self.process_fixture = self.useFixture(
|
||||||
ProcessFixture(
|
ProcessFixture(
|
||||||
test_name=self.test_name,
|
test_name=self.test_name,
|
||||||
process_name=self.NEUTRON_DHCP_AGENT,
|
process_name=self.NEUTRON_DHCP_AGENT,
|
||||||
exec_name=spawn.find_executable(
|
exec_name=exec_name,
|
||||||
'dhcp_agent.py',
|
|
||||||
path=os.path.join(
|
|
||||||
fullstack_base.ROOTDIR, 'cmd')),
|
|
||||||
config_filenames=config_filenames,
|
config_filenames=config_filenames,
|
||||||
namespace=self.namespace
|
namespace=self.namespace
|
||||||
)
|
)
|
||||||
|
@ -27,9 +27,9 @@ from oslo_config import cfg
|
|||||||
from neutron.agent.common import ovs_lib
|
from neutron.agent.common import ovs_lib
|
||||||
from neutron.agent.linux import ovsdb_monitor
|
from neutron.agent.linux import ovsdb_monitor
|
||||||
from neutron.common import utils
|
from neutron.common import utils
|
||||||
|
from neutron.tests import base
|
||||||
from neutron.tests.common import net_helpers
|
from neutron.tests.common import net_helpers
|
||||||
from neutron.tests.functional.agent.linux import base as linux_base
|
from neutron.tests.functional.agent.linux import base as linux_base
|
||||||
from neutron.tests.functional import base as functional_base
|
|
||||||
|
|
||||||
|
|
||||||
class BaseMonitorTest(linux_base.BaseOVSLinuxTestCase):
|
class BaseMonitorTest(linux_base.BaseOVSLinuxTestCase):
|
||||||
@ -37,14 +37,13 @@ class BaseMonitorTest(linux_base.BaseOVSLinuxTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(BaseMonitorTest, self).setUp()
|
super(BaseMonitorTest, self).setUp()
|
||||||
|
|
||||||
rootwrap_not_configured = (cfg.CONF.AGENT.root_helper ==
|
rootwrap_not_configured = (cfg.CONF.AGENT.root_helper == base.SUDO_CMD)
|
||||||
functional_base.SUDO_CMD)
|
|
||||||
if rootwrap_not_configured:
|
if rootwrap_not_configured:
|
||||||
# The monitor tests require a nested invocation that has
|
# The monitor tests require a nested invocation that has
|
||||||
# to be emulated by double sudo if rootwrap is not
|
# to be emulated by double sudo if rootwrap is not
|
||||||
# configured.
|
# configured.
|
||||||
self.config(group='AGENT',
|
self.config(group='AGENT',
|
||||||
root_helper=" ".join([functional_base.SUDO_CMD] * 2))
|
root_helper=" ".join([base.SUDO_CMD] * 2))
|
||||||
|
|
||||||
self._check_test_requirements()
|
self._check_test_requirements()
|
||||||
# ovsdb-client monitor needs to have a bridge to make any output
|
# ovsdb-client monitor needs to have a bridge to make any output
|
||||||
|
@ -23,8 +23,6 @@ from neutron.tests import base
|
|||||||
from neutron.tests.common import base as common_base
|
from neutron.tests.common import base as common_base
|
||||||
from neutron.tests.common import helpers
|
from neutron.tests.common import helpers
|
||||||
|
|
||||||
SUDO_CMD = 'sudo -n'
|
|
||||||
|
|
||||||
# This is the directory from which infra fetches log files for functional tests
|
# This is the directory from which infra fetches log files for functional tests
|
||||||
DEFAULT_LOG_DIR = os.path.join(helpers.get_test_log_path(),
|
DEFAULT_LOG_DIR = os.path.join(helpers.get_test_log_path(),
|
||||||
'dsvm-functional-logs')
|
'dsvm-functional-logs')
|
||||||
@ -62,13 +60,7 @@ class BaseSudoTestCase(BaseLoggingTestCase):
|
|||||||
super(BaseSudoTestCase, self).setUp()
|
super(BaseSudoTestCase, self).setUp()
|
||||||
if not base.bool_from_env('OS_SUDO_TESTING'):
|
if not base.bool_from_env('OS_SUDO_TESTING'):
|
||||||
self.skipTest('Testing with sudo is not enabled')
|
self.skipTest('Testing with sudo is not enabled')
|
||||||
|
self.setup_rootwrap()
|
||||||
config.register_root_helper(cfg.CONF)
|
|
||||||
self.config(group='AGENT',
|
|
||||||
root_helper=os.environ.get('OS_ROOTWRAP_CMD', SUDO_CMD))
|
|
||||||
self.config(group='AGENT',
|
|
||||||
root_helper_daemon=os.environ.get(
|
|
||||||
'OS_ROOTWRAP_DAEMON_CMD'))
|
|
||||||
config.setup_privsep()
|
config.setup_privsep()
|
||||||
|
|
||||||
@common_base.no_skip_on_missing_deps
|
@common_base.no_skip_on_missing_deps
|
||||||
|
@ -188,6 +188,12 @@ function _install_rootwrap_sudoers {
|
|||||||
ROOTWRAP_SUDOER_CMD="$PROJECT_VENV/bin/neutron-rootwrap $PROJECT_VENV/etc/neutron/rootwrap.conf *"
|
ROOTWRAP_SUDOER_CMD="$PROJECT_VENV/bin/neutron-rootwrap $PROJECT_VENV/etc/neutron/rootwrap.conf *"
|
||||||
ROOTWRAP_DAEMON_SUDOER_CMD="$PROJECT_VENV/bin/neutron-rootwrap-daemon $PROJECT_VENV/etc/neutron/rootwrap.conf"
|
ROOTWRAP_DAEMON_SUDOER_CMD="$PROJECT_VENV/bin/neutron-rootwrap-daemon $PROJECT_VENV/etc/neutron/rootwrap.conf"
|
||||||
TEMPFILE=$(mktemp)
|
TEMPFILE=$(mktemp)
|
||||||
|
|
||||||
|
SECURE_PATH="$PROJECT_VENV/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
if [[ "$VENV" =~ "dsvm-fullstack" ]]; then
|
||||||
|
SECURE_PATH="$REPO_BASE/$PROJECT_NAME/neutron/tests/fullstack/cmd:$SECURE_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
cat << EOF > $TEMPFILE
|
cat << EOF > $TEMPFILE
|
||||||
# A bug in oslo.rootwrap [1] prevents commands executed with 'ip netns
|
# A bug in oslo.rootwrap [1] prevents commands executed with 'ip netns
|
||||||
# exec' from being automatically qualified with a prefix from
|
# exec' from being automatically qualified with a prefix from
|
||||||
@ -201,7 +207,7 @@ function _install_rootwrap_sudoers {
|
|||||||
#
|
#
|
||||||
# 1: https://bugs.launchpad.net/oslo.rootwrap/+bug/1417331
|
# 1: https://bugs.launchpad.net/oslo.rootwrap/+bug/1417331
|
||||||
#
|
#
|
||||||
Defaults:$STACK_USER secure_path="$PROJECT_VENV/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
Defaults:$STACK_USER secure_path="$SECURE_PATH"
|
||||||
$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD
|
$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD
|
||||||
$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_DAEMON_SUDOER_CMD
|
$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_DAEMON_SUDOER_CMD
|
||||||
EOF
|
EOF
|
||||||
|
@ -32,6 +32,8 @@ neutron_path=$1
|
|||||||
target_etc_path=$2
|
target_etc_path=$2
|
||||||
target_bin_path=$3
|
target_bin_path=$3
|
||||||
|
|
||||||
|
fullstack_path=$neutron_path/neutron/tests/fullstack/cmd
|
||||||
|
|
||||||
src_conf_path=${neutron_path}/etc
|
src_conf_path=${neutron_path}/etc
|
||||||
src_conf=${src_conf_path}/rootwrap.conf
|
src_conf=${src_conf_path}/rootwrap.conf
|
||||||
src_rootwrap_path=${src_conf_path}/neutron/rootwrap.d
|
src_rootwrap_path=${src_conf_path}/neutron/rootwrap.d
|
||||||
@ -48,11 +50,11 @@ mkdir -p -m 755 ${dst_rootwrap_path}
|
|||||||
cp -p ${src_rootwrap_path}/* ${dst_rootwrap_path}/
|
cp -p ${src_rootwrap_path}/* ${dst_rootwrap_path}/
|
||||||
cp -p ${src_conf} ${dst_conf}
|
cp -p ${src_conf} ${dst_conf}
|
||||||
sed -i "s:^filters_path=.*$:filters_path=${dst_rootwrap_path}:" ${dst_conf}
|
sed -i "s:^filters_path=.*$:filters_path=${dst_rootwrap_path}:" ${dst_conf}
|
||||||
sed -i "s:^\(exec_dirs=.*\)$:\1,${target_bin_path}:" ${dst_conf}
|
sed -i "s:^\(exec_dirs=.*\)$:\1,${target_bin_path},${fullstack_path}:" ${dst_conf}
|
||||||
|
|
||||||
if [[ "$OS_SUDO_TESTING" = "1" ]]; then
|
if [[ "$OS_SUDO_TESTING" = "1" ]]; then
|
||||||
sed -i 's/use_syslog=False/use_syslog=True/g' ${dst_conf}
|
sed -i 's/use_syslog=False/use_syslog=True/g' ${dst_conf}
|
||||||
sed -i 's/syslog_log_level=ERROR/syslog_log_level=DEBUG/g' ${dst_conf}
|
sed -i 's/syslog_log_level=ERROR/syslog_log_level=DEBUG/g' ${dst_conf}
|
||||||
cp -p ${neutron_path}/neutron/tests/contrib/functional-testing.filters \
|
cp -p ${neutron_path}/neutron/tests/contrib/testing.filters \
|
||||||
${dst_rootwrap_path}/
|
${dst_rootwrap_path}/
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user