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:
Ihar Hrachyshka 2017-06-05 18:54:39 +00:00
parent b6bd475629
commit a99897ffb3
8 changed files with 67 additions and 27 deletions

View File

@ -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.common import config
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 _resource_extend as resource_extend
from neutron.db import agentschedulers_db
@ -63,6 +64,8 @@ CONF.import_opt('state_path', 'neutron.conf.common')
ROOTDIR = os.path.dirname(__file__)
ETCDIR = os.path.join(ROOTDIR, 'etc')
SUDO_CMD = 'sudo -n'
def etcdir(*p):
return os.path.join(ETCDIR, *p)
@ -406,6 +409,14 @@ class BaseTestCase(DietTestCase):
notification_driver = [fake_notifier.__name__]
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):

View File

@ -44,3 +44,13 @@ process_spawn: EnvFilter, env, root, PATH=, python
ip_exec: IpNetnsExecFilter, ip, root
ps: CommandFilter, ps, root
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

View File

@ -57,6 +57,10 @@ class BaseFullStackTestCase(testlib_api.MySQLTestCaseMixin,
# since the latter starts services that may rely on generated port
# numbers
tools.reset_random_seed()
# configure test runner to use rootwrap
self.setup_rootwrap()
self.environment = environment
self.environment.test_name = self.get_name()
self.useFixture(self.environment)

View File

@ -59,12 +59,13 @@ class ProcessFixture(fixtures.Fixture):
timestamp = datetime.datetime.now().strftime("%Y-%m-%d--%H-%M-%S-%f")
log_file = "%s--%s.log" % (self.process_name, timestamp)
cmd = [spawn.find_executable(self.exec_name),
'--log-dir', log_dir,
'--log-file', log_file]
run_as_root = bool(self.namespace)
exec_name = (self.exec_name
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:
cmd += ['--config-file', filename]
run_as_root = bool(self.namespace)
self.process = async_process.AsyncProcess(
cmd, run_as_root=run_as_root, namespace=self.namespace
)
@ -261,13 +262,21 @@ class L3AgentFixture(ServiceFixture):
config_filenames = [self.neutron_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(
ProcessFixture(
test_name=self.test_name,
process_name=self.NEUTRON_L3_AGENT,
exec_name=spawn.find_executable(
'l3_agent.py',
path=os.path.join(fullstack_base.ROOTDIR, 'cmd')),
exec_name=exec_name,
config_filenames=config_filenames,
namespace=self.namespace
)
@ -296,14 +305,21 @@ class DhcpAgentFixture(fixtures.Fixture):
config_filenames = [self.neutron_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(
ProcessFixture(
test_name=self.test_name,
process_name=self.NEUTRON_DHCP_AGENT,
exec_name=spawn.find_executable(
'dhcp_agent.py',
path=os.path.join(
fullstack_base.ROOTDIR, 'cmd')),
exec_name=exec_name,
config_filenames=config_filenames,
namespace=self.namespace
)

View File

@ -27,9 +27,9 @@ from oslo_config import cfg
from neutron.agent.common import ovs_lib
from neutron.agent.linux import ovsdb_monitor
from neutron.common import utils
from neutron.tests import base
from neutron.tests.common import net_helpers
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):
@ -37,14 +37,13 @@ class BaseMonitorTest(linux_base.BaseOVSLinuxTestCase):
def setUp(self):
super(BaseMonitorTest, self).setUp()
rootwrap_not_configured = (cfg.CONF.AGENT.root_helper ==
functional_base.SUDO_CMD)
rootwrap_not_configured = (cfg.CONF.AGENT.root_helper == base.SUDO_CMD)
if rootwrap_not_configured:
# The monitor tests require a nested invocation that has
# to be emulated by double sudo if rootwrap is not
# configured.
self.config(group='AGENT',
root_helper=" ".join([functional_base.SUDO_CMD] * 2))
root_helper=" ".join([base.SUDO_CMD] * 2))
self._check_test_requirements()
# ovsdb-client monitor needs to have a bridge to make any output

View File

@ -23,8 +23,6 @@ from neutron.tests import base
from neutron.tests.common import base as common_base
from neutron.tests.common import helpers
SUDO_CMD = 'sudo -n'
# This is the directory from which infra fetches log files for functional tests
DEFAULT_LOG_DIR = os.path.join(helpers.get_test_log_path(),
'dsvm-functional-logs')
@ -62,13 +60,7 @@ class BaseSudoTestCase(BaseLoggingTestCase):
super(BaseSudoTestCase, self).setUp()
if not base.bool_from_env('OS_SUDO_TESTING'):
self.skipTest('Testing with sudo is not enabled')
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'))
self.setup_rootwrap()
config.setup_privsep()
@common_base.no_skip_on_missing_deps

View File

@ -188,6 +188,12 @@ function _install_rootwrap_sudoers {
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"
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
# A bug in oslo.rootwrap [1] prevents commands executed with 'ip netns
# 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
#
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_DAEMON_SUDOER_CMD
EOF

View File

@ -32,6 +32,8 @@ neutron_path=$1
target_etc_path=$2
target_bin_path=$3
fullstack_path=$neutron_path/neutron/tests/fullstack/cmd
src_conf_path=${neutron_path}/etc
src_conf=${src_conf_path}/rootwrap.conf
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_conf} ${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
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}
cp -p ${neutron_path}/neutron/tests/contrib/functional-testing.filters \
cp -p ${neutron_path}/neutron/tests/contrib/testing.filters \
${dst_rootwrap_path}/
fi