Allow setting a rootwrap cmd for functional tests

Previously, sudo-requiring functional tests hardcoded the use of
'sudo' as the root helper.  Devstack gate jobs do not allow
password-less invocation of 'sudo', though, so such tests were unable
to run in the gate.  This patch adds the ability to configure the
rootwrap command installed by devstack by setting the OS_ROOTWRAP_CMD
environment variable in the test execution environment, allowing
sudo-requiring tests to run.

Change-Id: I3b8f6b4f14ac1743e08b9401f73951885165350a
Partial-bug: #1336172
This commit is contained in:
Maru Newby 2014-07-02 00:02:08 +00:00
parent fc91e158f2
commit 798824cab0
4 changed files with 78 additions and 38 deletions

View File

@ -12,36 +12,27 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import random
from neutron.agent.linux import ovs_lib
from neutron.agent.linux import utils
from neutron.common import constants as n_const
from neutron.tests import base
from neutron.tests.functional import base as functional_base
BR_PREFIX = 'test-br'
class BaseLinuxTestCase(base.BaseTestCase):
def setUp(self, root_helper='sudo'):
super(BaseLinuxTestCase, self).setUp()
class BaseLinuxTestCase(functional_base.BaseSudoTestCase):
self.root_helper = root_helper
def check_command(self, cmd, error_text, skip_msg):
def check_command(self, cmd, error_text, skip_msg, root_helper=None):
try:
utils.execute(cmd)
utils.execute(cmd, root_helper=root_helper)
except RuntimeError as e:
if error_text in str(e):
self.skipTest(skip_msg)
raise
def check_sudo_enabled(self):
if os.environ.get('OS_SUDO_TESTING') not in base.TRUE_STRING:
self.skipTest('testing with sudo is not enabled')
def get_rand_name(self, max_length, prefix='test'):
name = prefix + str(random.randint(1, 0x7fffffff))
return name[:max_length]
@ -64,8 +55,8 @@ class BaseLinuxTestCase(base.BaseTestCase):
class BaseOVSLinuxTestCase(BaseLinuxTestCase):
def setUp(self, root_helper='sudo'):
super(BaseOVSLinuxTestCase, self).setUp(root_helper)
def setUp(self):
super(BaseOVSLinuxTestCase, self).setUp()
self.ovs = ovs_lib.BaseOVS(self.root_helper)
def create_ovs_bridge(self, br_prefix=BR_PREFIX):

View File

@ -17,28 +17,30 @@ Tests in this module will be skipped unless:
- ovsdb-client is installed
- ovsdb-client can be invoked via password-less sudo
- ovsdb-client can be invoked password-less via the configured root helper
- OS_SUDO_TESTING is set to '1' or 'True' in the test execution
environment
The jenkins gate does not allow direct sudo invocation during test
runs, but configuring OS_SUDO_TESTING ensures that developers are
still able to execute tests that require the capability.
- sudo testing is enabled (see neutron.tests.functional.base for details)
"""
import eventlet
from neutron.agent.linux import ovsdb_monitor
from neutron.tests.functional.agent.linux import base as base_agent
from neutron.tests.functional.agent.linux import base as linux_base
from neutron.tests.functional import base as functional_base
class BaseMonitorTest(base_agent.BaseOVSLinuxTestCase):
class BaseMonitorTest(linux_base.BaseOVSLinuxTestCase):
def setUp(self):
# Emulate using a rootwrap script with sudo
super(BaseMonitorTest, self).setUp(root_helper='sudo sudo')
super(BaseMonitorTest, self).setUp()
rootwrap_not_configured = (self.root_helper ==
functional_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.root_helper = '%s %s' % (self.root_helper, self.root_helper)
self._check_test_requirements()
self.bridge = self.create_ovs_bridge()
@ -47,9 +49,10 @@ class BaseMonitorTest(base_agent.BaseOVSLinuxTestCase):
self.check_sudo_enabled()
self.check_command(['which', 'ovsdb-client'],
'Exit code: 1', 'ovsdb-client is not installed')
self.check_command(['sudo', '-n', 'ovsdb-client', 'list-dbs'],
self.check_command(['ovsdb-client', 'list-dbs'],
'Exit code: 1',
'password-less sudo not granted for ovsdb-client')
'password-less sudo not granted for ovsdb-client',
root_helper=self.root_helper)
class TestOvsdbMonitor(BaseMonitorTest):

View File

@ -0,0 +1,53 @@
# Copyright (c) 2014 OpenStack Foundation.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
from neutron.tests import base
SUDO_CMD = 'sudo -n'
class BaseSudoTestCase(base.BaseTestCase):
"""
Base class for tests requiring invocation of commands via a root helper.
Inheritors of this class should call check_sudo_enabled() in
setUp() to ensure that tests requiring sudo are skipped unless
OS_SUDO_TESTING is set to '1' or 'True' in the test execution
environment. This is intended to allow developers to run the
functional suite (e.g. tox -e functional) without test failures if
sudo invocations are not allowed.
Running sudo tests in the upstream gate jobs
(*-neutron-dsvm-functional) requires the additional step of
setting OS_ROOTWRAP_CMD to the rootwrap command configured by
devstack, e.g.
sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
Gate jobs do not allow invocations of sudo without rootwrap to
ensure that rootwrap configuration gets as much testing as
possible.
"""
def setUp(self):
super(BaseSudoTestCase, self).setUp()
self.root_helper = os.environ.get('OS_ROOTWRAP_CMD', SUDO_CMD)
def check_sudo_enabled(self):
if os.environ.get('OS_SUDO_TESTING') not in base.TRUE_STRING:
self.skipTest('testing with sudo is not enabled')

View File

@ -13,10 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
from neutron.cmd.sanity import checks
from neutron.tests import base
from neutron.tests.functional import base as functional_base
class SanityTestCase(base.BaseTestCase):
@ -34,7 +33,7 @@ class SanityTestCase(base.BaseTestCase):
checks.nova_notify_supported()
class SanityTestCaseRoot(base.BaseTestCase):
class SanityTestCaseRoot(functional_base.BaseSudoTestCase):
"""Sanity checks that require root access.
Tests that just call checks.some_function() are to ensure that
@ -43,14 +42,8 @@ class SanityTestCaseRoot(base.BaseTestCase):
"""
def setUp(self):
super(SanityTestCaseRoot, self).setUp()
self.root_helper = 'sudo'
self.check_sudo_enabled()
def check_sudo_enabled(self):
if os.environ.get('OS_SUDO_TESTING') not in base.TRUE_STRING:
self.skipTest('testing with sudo is not enabled')
def test_ovs_vxlan_support_runs(self):
checks.vxlan_supported(self.root_helper)