Add support for remote octavia test_server.bin
Add support to download octavia-tempest-plugin test_server.bin from a remote location. test_server.bin is a golang application that is provided and used by octavia-tempest-plugin, however some FIPS-compliant checkers flag it as non-compliant because it's a static binary. Change-Id: I1246951bc686cbc815a6f0808471c95f5252898d Signed-off-by: Gregory Thiemonge <gthiemon@redhat.com>
This commit is contained in:
@@ -41,6 +41,10 @@ DEFAULT_FLAVOR_RAM_ALT = 192
|
||||
DEFAULT_FLAVOR_DISK = 1
|
||||
DEFAULT_FLAVOR_VCPUS = 1
|
||||
|
||||
DEFAULT_OCTAVIA_TEST_SERVER_FILE = '/tmp/test_server.bin'
|
||||
DEFAULT_OCTAVIA_COMPAT_TEST_SERVER_FILE = (
|
||||
'/usr/libexec/octavia-tempest-plugin-tests-httpd')
|
||||
|
||||
# The dict holds the credentials, which are not supposed to be printed
|
||||
# to a tempest.conf when --test-accounts CLI parameter is used.
|
||||
ALL_CREDENTIALS_KEYS = {
|
||||
|
||||
@@ -625,6 +625,10 @@ def config_tempest(**kwargs):
|
||||
network = services.get_service("network")
|
||||
network.create_tempest_networks(conf, kwargs.get('network'))
|
||||
|
||||
if services.is_service(**{"type": "load-balancer"}):
|
||||
load_balancer = services.get_service("load-balancer")
|
||||
load_balancer.get_test_server_application(conf)
|
||||
|
||||
services.post_configuration()
|
||||
services.set_supported_api_versions()
|
||||
services.set_service_extensions()
|
||||
|
||||
@@ -13,6 +13,15 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import urllib
|
||||
|
||||
from tenacity import retry
|
||||
from tenacity import retry_if_exception_type
|
||||
from tenacity import stop_after_attempt
|
||||
from tenacity import wait_exponential
|
||||
|
||||
from config_tempest import constants as C
|
||||
from config_tempest.services.base import VersionedService
|
||||
import json
|
||||
|
||||
@@ -26,6 +35,11 @@ class LoadBalancerService(VersionedService):
|
||||
conf.set('load_balancer', 'admin_role', 'admin')
|
||||
conf.set('load_balancer', 'RBAC_test_type', 'owner_or_admin')
|
||||
conf.set('network-feature-enabled', 'port_security', 'True')
|
||||
# TOOD(gthiemonge) This is a backward-compatible setting for jobs
|
||||
# that haven't yet migrated to load_balancer.test_server_remote_url
|
||||
# Remove it once all jobs have been migrated.
|
||||
conf.set('load_balancer', 'test_server_path',
|
||||
C.DEFAULT_OCTAVIA_COMPAT_TEST_SERVER_FILE)
|
||||
|
||||
@staticmethod
|
||||
def get_service_type():
|
||||
@@ -55,3 +69,37 @@ class LoadBalancerService(VersionedService):
|
||||
conf.set('load_balancer',
|
||||
'enabled_provider_drivers',
|
||||
','.join(self.list_drivers()))
|
||||
|
||||
@retry(retry=retry_if_exception_type(urllib.error.URLError),
|
||||
stop=stop_after_attempt(3),
|
||||
wait=wait_exponential(multiplier=2, min=3, max=10))
|
||||
def _download_file(self, url, destination):
|
||||
"""Downloads a file specified by `url` to `destination`.
|
||||
|
||||
:type url: string
|
||||
:type destination: string
|
||||
"""
|
||||
if os.path.exists(destination):
|
||||
C.LOG.info("File '%s' already fetched to '%s'.", url, destination)
|
||||
return
|
||||
C.LOG.info("Downloading '%s' and saving as '%s'", url, destination)
|
||||
f = urllib.request.urlopen(url)
|
||||
data = f.read()
|
||||
with open(destination, "wb") as dest:
|
||||
dest.write(data)
|
||||
|
||||
def get_test_server_application(self, conf):
|
||||
if not conf.has_option("load_balancer",
|
||||
"test_server_remote_url"):
|
||||
return
|
||||
|
||||
remote_url = conf.get("load_balancer",
|
||||
"test_server_remote_url")
|
||||
if remote_url:
|
||||
self._download_file(remote_url,
|
||||
C.DEFAULT_OCTAVIA_TEST_SERVER_FILE)
|
||||
os.chmod(C.DEFAULT_OCTAVIA_TEST_SERVER_FILE, 0o755)
|
||||
|
||||
conf.set("load_balancer",
|
||||
"test_server_path",
|
||||
C.DEFAULT_OCTAVIA_TEST_SERVER_FILE)
|
||||
|
||||
@@ -14,7 +14,12 @@
|
||||
# under the License.
|
||||
|
||||
from unittest import mock
|
||||
import urllib
|
||||
|
||||
from tenacity import RetryError
|
||||
from tenacity import wait_fixed
|
||||
|
||||
from config_tempest import constants as C
|
||||
from config_tempest.services.octavia import LoadBalancerService
|
||||
from config_tempest.tests.base import BaseServiceTest
|
||||
|
||||
@@ -56,3 +61,99 @@ class TestOctaviaService(BaseServiceTest):
|
||||
("amphora:The Octavia Amphora driver.,"
|
||||
"octavia:Deprecated alias of the Octavia driver."),
|
||||
)
|
||||
|
||||
@mock.patch("urllib.request.urlopen")
|
||||
@mock.patch("os.path.exists")
|
||||
def test_octavia__download_file(self,
|
||||
mock_path_exists,
|
||||
mock_urlopen):
|
||||
mock_url = mock.Mock()
|
||||
mock_destination = mock.Mock()
|
||||
mock_data = mock.Mock(name='Fake data')
|
||||
|
||||
# File already exists
|
||||
mock_path_exists.return_value = True
|
||||
self.Service._download_file(mock_url, mock_destination)
|
||||
mock_urlopen.assert_not_called()
|
||||
|
||||
# File doesn't exist, normal path
|
||||
mock_path_exists.return_value = False
|
||||
|
||||
mock_response = mock.MagicMock()
|
||||
mock_response.read.return_value = mock_data
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
mock_open = mock.mock_open()
|
||||
with mock.patch("builtins.open", mock_open):
|
||||
self.Service._download_file(mock_url, mock_destination)
|
||||
mock_urlopen.assert_called_once_with(mock_url)
|
||||
mock_open.assert_called_once_with(mock_destination, "wb")
|
||||
handle = mock_open()
|
||||
handle.write.assert_called_once_with(mock_data)
|
||||
|
||||
mock_urlopen.reset_mock()
|
||||
|
||||
# File doesn't exist, with 2 URLErrors then it passes
|
||||
mock_path_exists.return_value = False
|
||||
|
||||
mock_response = mock.MagicMock()
|
||||
mock_response.read.return_value = mock_data
|
||||
mock_urlopen.side_effect = [
|
||||
urllib.error.URLError(reason="reason1"),
|
||||
urllib.error.URLError(reason="reason2"),
|
||||
mock_response]
|
||||
|
||||
mock_open = mock.mock_open()
|
||||
with mock.patch("builtins.open", mock_open):
|
||||
# override tenacity.retry wait param
|
||||
with mock.patch.object(self.Service._download_file.retry,
|
||||
"wait", wait_fixed(0)):
|
||||
self.Service._download_file(mock_url, mock_destination)
|
||||
mock_urlopen.assert_called_with(mock_url)
|
||||
mock_open.assert_called_once_with(mock_destination, "wb")
|
||||
handle = mock_open()
|
||||
handle.write.assert_called_once_with(mock_data)
|
||||
|
||||
# File doesn't exist, with URLErrors
|
||||
mock_path_exists.return_value = False
|
||||
|
||||
mock_urlopen.side_effect = [
|
||||
urllib.error.URLError(reason="reason1"),
|
||||
urllib.error.URLError(reason="reason2"),
|
||||
urllib.error.URLError(reason="reason3"),
|
||||
urllib.error.URLError(reason="reason4")]
|
||||
|
||||
mock_open = mock.mock_open()
|
||||
with mock.patch("builtins.open", mock_open):
|
||||
# override tenacity.retry wait param
|
||||
with mock.patch.object(self.Service._download_file.retry,
|
||||
"wait", wait_fixed(0)):
|
||||
self.assertRaises(RetryError,
|
||||
self.Service._download_file,
|
||||
mock_url,
|
||||
mock_destination)
|
||||
mock_urlopen.assert_called_with(mock_url)
|
||||
mock_open.assert_not_called()
|
||||
|
||||
@mock.patch("config_tempest.services.octavia.LoadBalancerService."
|
||||
"_download_file")
|
||||
@mock.patch("os.chmod")
|
||||
def test_octavia_get_test_server_application(self,
|
||||
mock_chmod,
|
||||
mock_download_file):
|
||||
# test_server_remote_url not configured
|
||||
self.Service.get_test_server_application(self.conf)
|
||||
mock_download_file.assert_not_called()
|
||||
|
||||
# test_server_remote_url set
|
||||
location = "dummy://location"
|
||||
self.conf.set("load_balancer", "test_server_remote_url",
|
||||
location)
|
||||
self.Service.get_test_server_application(self.conf)
|
||||
mock_download_file.assert_called_once_with(
|
||||
location, C.DEFAULT_OCTAVIA_TEST_SERVER_FILE)
|
||||
mock_chmod.assert_called_once_with(
|
||||
C.DEFAULT_OCTAVIA_TEST_SERVER_FILE, 0o755)
|
||||
|
||||
self.assertEqual(self.conf.get("load_balancer", "test_server_path"),
|
||||
C.DEFAULT_OCTAVIA_TEST_SERVER_FILE)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add support for remote Octavia test_server.bin. In case users need to
|
||||
download octavia-tempest-plugin test_server.bin from a remote location,
|
||||
they can set the ``[load_balancer].test_server_remote_url`` to the URL of
|
||||
the application, python-tempestconf will download the binary and set the
|
||||
``[load_balancer].test_server_path`` parameter accordingly.
|
||||
Reference in New Issue
Block a user