diff --git a/neutron/tests/functional/agent/linux/base.py b/neutron/tests/functional/agent/linux/base.py index bdd718c85e..5891c872e9 100644 --- a/neutron/tests/functional/agent/linux/base.py +++ b/neutron/tests/functional/agent/linux/base.py @@ -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): diff --git a/neutron/tests/functional/agent/linux/test_ovsdb_monitor.py b/neutron/tests/functional/agent/linux/test_ovsdb_monitor.py index 35ad48d1ca..9d8570deda 100644 --- a/neutron/tests/functional/agent/linux/test_ovsdb_monitor.py +++ b/neutron/tests/functional/agent/linux/test_ovsdb_monitor.py @@ -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): diff --git a/neutron/tests/functional/base.py b/neutron/tests/functional/base.py new file mode 100644 index 0000000000..471acaea64 --- /dev/null +++ b/neutron/tests/functional/base.py @@ -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') diff --git a/neutron/tests/functional/sanity/test_sanity.py b/neutron/tests/functional/sanity/test_sanity.py index be35484cb4..2873dc7a58 100644 --- a/neutron/tests/functional/sanity/test_sanity.py +++ b/neutron/tests/functional/sanity/test_sanity.py @@ -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)