Merge "Change to use memory_tracker variable"
diff --git a/devstack/README.rst b/devstack/README.rst
new file mode 100644
index 0000000..d1755e5
--- /dev/null
+++ b/devstack/README.rst
@@ -0,0 +1,17 @@
+====================
+Enabling in Devstack
+====================
+
+1. Download DevStack::
+
+ git clone https://opendev.org/openstack/devstack.git
+ cd devstack
+
+2. Add this repo as an external repository::
+
+ > cat local.conf
+ [[local|localrc]]
+ enable_plugin octavia-tempest-plugin https://opendev.org/openstack/octavia-tempest-plugin
+
+3. run ``stack.sh``
+
diff --git a/devstack/plugin.sh b/devstack/plugin.sh
new file mode 100644
index 0000000..babf033
--- /dev/null
+++ b/devstack/plugin.sh
@@ -0,0 +1,14 @@
+
+# install_octavia_tempest_plugin
+function install_octavia_tempest_plugin {
+ setup_dev_lib "octavia-tempest-plugin"
+}
+
+if [[ "$1" == "stack" ]]; then
+ case "$2" in
+ install)
+ echo_summary "Installing octavia-tempest-plugin"
+ install_octavia_tempest_plugin
+ ;;
+ esac
+fi
diff --git a/devstack/settings b/devstack/settings
new file mode 100644
index 0000000..a905fac
--- /dev/null
+++ b/devstack/settings
@@ -0,0 +1,3 @@
+GITREPO["octavia-tempest-plugin"]=${OCTAVIA_TEMPEST_REPO:-${GIT_BASE}/openstack/octavia-tempest-plugin.git}
+GITDIR["octavia-tempest-plugin"]=$DEST/octavia-tempest-plugin
+GITBRANCH["octavia-tempest-plugin"]=${OCTAVIA_TEMPEST_REF:-master}
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 90ae115..2a94e8b 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -3,12 +3,11 @@
# process, which may cause wedges in the gate later.
sphinxcontrib-apidoc>=0.2.0 # BSD
-sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD
-sphinx!=1.6.6,!=1.6.7,>=1.6.2,!=2.1.0;python_version>='3.4' # BSD
-openstackdocstheme>=1.18.1 # Apache-2.0
+sphinx>=2.0.0,!=2.1.0 # BSD
+openstackdocstheme>=2.2.1 # Apache-2.0
# releasenotes
-reno>=2.5.0 # Apache-2.0
+reno>=3.1.0 # Apache-2.0
# PDF Docs
sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 5bbe295..ff6a826 100755
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -16,8 +16,6 @@
import os
import sys
-import openstackdocstheme
-
sys.path.insert(0, os.path.abspath('../..'))
sys.path.insert(0, os.path.abspath('.'))
@@ -49,16 +47,6 @@
project = u'octavia-tempest-plugin'
copyright = u'2017-2019, OpenStack Foundation'
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# Version info
-from octavia_tempest_plugin.version import version_info as octavia_tempest_ver
-release = octavia_tempest_ver.release_string()
-# The short X.Y version.
-version = octavia_tempest_ver.version_string()
-
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
@@ -67,14 +55,14 @@
add_module_names = False
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = 'native'
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['octavia_tempest_plugin.']
-repository_name = 'openstack/octavia-tempest-plugin'
-bug_project = '910'
-bug_tag = 'docs'
+openstackdocs_repo_name = 'openstack/octavia-tempest-plugin'
+openstackdocs_pdf_link = True
+openstackdocs_use_storyboard = True
apidoc_output_dir = '_build/modules'
apidoc_module_dir = '../../octavia_tempest_plugin'
@@ -90,7 +78,6 @@
html_theme = 'openstackdocs'
-html_last_updated_fmt = '%Y-%m-%d %H:%M'
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
diff --git a/octavia_tempest_plugin/contrib/test_server/README.rst b/octavia_tempest_plugin/contrib/test_server/README.rst
index da719b7..ba959f9 100644
--- a/octavia_tempest_plugin/contrib/test_server/README.rst
+++ b/octavia_tempest_plugin/contrib/test_server/README.rst
@@ -2,8 +2,8 @@
Amphorae test server
====================
-test_server is a static application that simulates an HTTP and a UDP server.
-
+test_server.bin is a static application that simulates HTTP, HTTPS, and UDP
+servers. This server can properly handle concurrent requests.
Building
--------
@@ -12,15 +12,55 @@
Install dependencies for Ubuntu/Debian:
+::
+
sudo apt-get install -y golang
Install dependencies for Centos (use golang 1.10 from go-toolset-7) and launch
a shell into the new environment:
+::
+
sudo yum install -y centos-release-scl
sudo yum install -y go-toolset-7-golang-bin glibc-static openssl-static zlib-static
scl enable go-toolset-7 bash
Build the binary:
+::
+
CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-s -w -extldflags -static' -o test_server.bin test_server.go
+
+
+Usage
+-----
+
+The usage string can be output from the command by running:
+
+::
+
+ ./test_server.bin --help
+
+Example output:
+
+::
+
+ Usage of ./test_server.bin:
+ -cert string
+ Server side PEM format certificate.
+ -client_ca string
+ Client side PEM format CA certificate.
+ -https_port int
+ HTTPS port to listen on, -1 is disabled. (default -1)
+ -id string
+ Server ID (default "1")
+ -key string
+ Server side PEM format key.
+ -port int
+ Port to listen on (default 8080)
+
+If -https_port is not specified, the server will not accept HTTPS requests.
+When --https_port is specified, -cert and -key are required parameters.
+If -https_port is specified, the -client_ca parameter is optional. When
+-client_ca is specified, it will configure the HTTPS port to require a valid
+client certificate to connect.
diff --git a/octavia_tempest_plugin/contrib/test_server/test_server.bin b/octavia_tempest_plugin/contrib/test_server/test_server.bin
index e3cc7ba..75ec2f2 100755
--- a/octavia_tempest_plugin/contrib/test_server/test_server.bin
+++ b/octavia_tempest_plugin/contrib/test_server/test_server.bin
Binary files differ
diff --git a/octavia_tempest_plugin/contrib/test_server/test_server.go b/octavia_tempest_plugin/contrib/test_server/test_server.go
index 8139580..f8bc1e0 100644
--- a/octavia_tempest_plugin/contrib/test_server/test_server.go
+++ b/octavia_tempest_plugin/contrib/test_server/test_server.go
@@ -1,11 +1,17 @@
package main
import (
+ "crypto/rand"
+ "crypto/tls"
+ "crypto/x509"
"flag"
"fmt"
"io"
+ "io/ioutil"
+ "log"
"net"
"net/http"
+ "os"
"sync"
"time"
)
@@ -83,13 +89,23 @@
fmt.Fprintf(w, "max_conn=%d\ntotal_conn=%d\n", max_conn, total_conn)
}
+func https_wrapper(base_handler func(http.ResponseWriter,
+ *http.Request)) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+
+ w.Header().Add("Strict-Transport-Security",
+ "max-age=66012000; includeSubDomains")
+ base_handler(w, r)
+ })
+}
+
func reset_handler(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &sess_cookie)
scoreboard.reset()
fmt.Fprintf(w, "reset\n")
}
-func http_serve(port int, id string) {
+func http_setup(id string) {
sess_cookie.Name = "JSESSIONID"
sess_cookie.Value = id
@@ -97,8 +113,65 @@
http.HandleFunc("/slow", slow_handler)
http.HandleFunc("/stats", stats_handler)
http.HandleFunc("/reset", reset_handler)
+}
+
+func http_serve(port int, id string) {
portStr := fmt.Sprintf(":%d", port)
- http.ListenAndServe(portStr, nil)
+ log.Fatal(http.ListenAndServe(portStr, nil))
+}
+
+func https_serve(port int, id string, cert tls.Certificate,
+ certpool *x509.CertPool, server_cert_pem string,
+ server_key_pem string) {
+ mux := http.NewServeMux()
+ mux.Handle("/", https_wrapper(root_handler))
+ mux.Handle("/slow", https_wrapper(slow_handler))
+ mux.Handle("/stats", https_wrapper(stats_handler))
+ mux.Handle("/reset", https_wrapper(reset_handler))
+
+ var tls_config *tls.Config
+ if certpool != nil {
+ tls_config = &tls.Config{
+ Certificates: []tls.Certificate{cert},
+ ClientAuth: tls.RequireAndVerifyClientCert,
+ ClientCAs: certpool,
+ MinVersion: tls.VersionTLS12,
+ CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384,
+ tls.CurveP256},
+ PreferServerCipherSuites: true,
+ CipherSuites: []uint16{
+ tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+ },
+ }
+ } else {
+ tls_config = &tls.Config{
+ Certificates: []tls.Certificate{cert},
+ ClientAuth: tls.NoClientCert,
+ MinVersion: tls.VersionTLS12,
+ CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384,
+ tls.CurveP256},
+ PreferServerCipherSuites: true,
+ CipherSuites: []uint16{
+ tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+ },
+ }
+ }
+ tls_config.Rand = rand.Reader
+ portStr := fmt.Sprintf(":%d", port)
+ srv := &http.Server{
+ Addr: portStr,
+ Handler: mux,
+ TLSConfig: tls_config,
+ TLSNextProto: make(map[string]func(*http.Server, *tls.Conn,
+ http.Handler), 0),
+ }
+ log.Fatal(srv.ListenAndServeTLS(server_cert_pem, server_key_pem))
}
func udp_serve(port int, id string) {
@@ -129,11 +202,44 @@
func main() {
portPtr := flag.Int("port", 8080, "Port to listen on")
idPtr := flag.String("id", "1", "Server ID")
+ https_portPtr := flag.Int("https_port", -1,
+ "HTTPS port to listen on, -1 is disabled.")
+ server_cert_pem := flag.String("cert", "",
+ "Server side PEM format certificate.")
+ server_key := flag.String("key", "", "Server side PEM format key.")
+ client_ca_cert_pem := flag.String("client_ca", "",
+ "Client side PEM format CA certificate.")
flag.Parse()
resp = fmt.Sprintf("%s", *idPtr)
+ http_setup(*idPtr)
+
+ if *https_portPtr > -1 {
+ cert, err := tls.LoadX509KeyPair(*server_cert_pem, *server_key)
+ if err != nil {
+ fmt.Println("Error load server certificate and key.\n")
+ os.Exit(1)
+ }
+ certpool := x509.NewCertPool()
+ if *client_ca_cert_pem != "" {
+ ca_pem, err := ioutil.ReadFile(*client_ca_cert_pem)
+ if err != nil {
+ fmt.Println("Error load client side CA cert.\n")
+ os.Exit(1)
+ }
+ if !certpool.AppendCertsFromPEM(ca_pem) {
+ fmt.Println("Can't parse client side certificate authority")
+ os.Exit(1)
+ }
+ } else {
+ certpool = nil
+ }
+ go https_serve(*https_portPtr, *idPtr, cert, certpool,
+ *server_cert_pem, *server_key)
+ }
+
go http_serve(*portPtr, *idPtr)
udp_serve(*portPtr, *idPtr)
}
diff --git a/octavia_tempest_plugin/hacking/__init__.py b/octavia_tempest_plugin/hacking/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/octavia_tempest_plugin/hacking/__init__.py
diff --git a/octavia_tempest_plugin/hacking/checks.py b/octavia_tempest_plugin/hacking/checks.py
new file mode 100644
index 0000000..eec7476
--- /dev/null
+++ b/octavia_tempest_plugin/hacking/checks.py
@@ -0,0 +1,277 @@
+# Copyright (c) 2014 OpenStack Foundation.
+#
+# 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.
+
+
+"""
+Guidelines for writing new hacking checks
+
+ - Use only for Octavia specific tests. OpenStack general tests
+ should be submitted to the common 'hacking' module.
+ - Pick numbers in the range O3xx. Find the current test with
+ the highest allocated number and then pick the next value.
+ - Keep the test method code in the source file ordered based
+ on the O3xx value.
+ - List the new rule in the top level HACKING.rst file
+ - Add test cases for each new rule to
+ octavia/tests/unit/test_hacking.py
+
+"""
+
+import re
+
+from hacking import core
+
+
+_all_log_levels = {'critical', 'error', 'exception', 'info', 'warning'}
+_all_hints = {'_LC', '_LE', '_LI', '_', '_LW'}
+
+_log_translation_hint = re.compile(
+ r".*LOG\.(%(levels)s)\(\s*(%(hints)s)\(" % {
+ 'levels': '|'.join(_all_log_levels),
+ 'hints': '|'.join(_all_hints),
+ })
+
+assert_trueinst_re = re.compile(
+ r"(.)*assertTrue\(isinstance\((\w|\.|\'|\"|\[|\])+, "
+ r"(\w|\.|\'|\"|\[|\])+\)\)")
+assert_equal_in_end_with_true_or_false_re = re.compile(
+ r"assertEqual\((\w|[][.'\"])+ in (\w|[][.'\", ])+, (True|False)\)")
+assert_equal_in_start_with_true_or_false_re = re.compile(
+ r"assertEqual\((True|False), (\w|[][.'\"])+ in (\w|[][.'\", ])+\)")
+assert_equal_with_true_re = re.compile(
+ r"assertEqual\(True,")
+assert_equal_with_false_re = re.compile(
+ r"assertEqual\(False,")
+mutable_default_args = re.compile(r"^\s*def .+\((.+=\{\}|.+=\[\])")
+assert_equal_end_with_none_re = re.compile(r"(.)*assertEqual\(.+, None\)")
+assert_equal_start_with_none_re = re.compile(r".*assertEqual\(None, .+\)")
+assert_not_equal_end_with_none_re = re.compile(
+ r"(.)*assertNotEqual\(.+, None\)")
+assert_not_equal_start_with_none_re = re.compile(
+ r"(.)*assertNotEqual\(None, .+\)")
+revert_must_have_kwargs_re = re.compile(
+ r'[ ]*def revert\(.+,[ ](?!\*\*kwargs)\w+\):')
+untranslated_exception_re = re.compile(r"raise (?:\w*)\((.*)\)")
+no_eventlet_re = re.compile(r'(import|from)\s+[(]?eventlet')
+no_line_continuation_backslash_re = re.compile(r'.*(\\)\n')
+no_logging_re = re.compile(r'(import|from)\s+[(]?logging')
+import_mock_re = re.compile(r"\bimport[\s]+mock\b")
+import_from_mock_re = re.compile(r"\bfrom[\s]+mock[\s]+import\b")
+
+
+def _translation_checks_not_enforced(filename):
+ # Do not do these validations on tests
+ return any(pat in filename for pat in ["/tests/", "rally-jobs/plugins/"])
+
+
+@core.flake8ext
+def assert_true_instance(logical_line):
+ """Check for assertTrue(isinstance(a, b)) sentences
+
+ O316
+ """
+ if assert_trueinst_re.match(logical_line):
+ yield (0, "O316: assertTrue(isinstance(a, b)) sentences not allowed. "
+ "Use assertIsInstance instead.")
+
+
+@core.flake8ext
+def assert_equal_or_not_none(logical_line):
+ """Check for assertEqual(A, None) or assertEqual(None, A) sentences,
+
+ assertNotEqual(A, None) or assertNotEqual(None, A) sentences
+
+ O318
+ """
+ msg = ("O318: assertEqual/assertNotEqual(A, None) or "
+ "assertEqual/assertNotEqual(None, A) sentences not allowed")
+ res = (assert_equal_start_with_none_re.match(logical_line) or
+ assert_equal_end_with_none_re.match(logical_line) or
+ assert_not_equal_start_with_none_re.match(logical_line) or
+ assert_not_equal_end_with_none_re.match(logical_line))
+ if res:
+ yield (0, msg)
+
+
+@core.flake8ext
+def assert_equal_true_or_false(logical_line):
+ """Check for assertEqual(True, A) or assertEqual(False, A) sentences
+
+ O323
+ """
+ res = (assert_equal_with_true_re.search(logical_line) or
+ assert_equal_with_false_re.search(logical_line))
+ if res:
+ yield (0, "O323: assertEqual(True, A) or assertEqual(False, A) "
+ "sentences not allowed")
+
+
+@core.flake8ext
+def no_mutable_default_args(logical_line):
+ msg = "O324: Method's default argument shouldn't be mutable!"
+ if mutable_default_args.match(logical_line):
+ yield (0, msg)
+
+
+@core.flake8ext
+def assert_equal_in(logical_line):
+ """Check for assertEqual(A in B, True), assertEqual(True, A in B),
+
+ assertEqual(A in B, False) or assertEqual(False, A in B) sentences
+
+ O338
+ """
+ res = (assert_equal_in_start_with_true_or_false_re.search(logical_line) or
+ assert_equal_in_end_with_true_or_false_re.search(logical_line))
+ if res:
+ yield (0, "O338: Use assertIn/NotIn(A, B) rather than "
+ "assertEqual(A in B, True/False) when checking collection "
+ "contents.")
+
+
+@core.flake8ext
+def no_log_warn(logical_line):
+ """Disallow 'LOG.warn('
+
+ O339
+ """
+ if logical_line.startswith('LOG.warn('):
+ yield(0, "O339:Use LOG.warning() rather than LOG.warn()")
+
+
+@core.flake8ext
+def no_translate_logs(logical_line, filename):
+ """O341 - Don't translate logs.
+
+ Check for 'LOG.*(_(' and 'LOG.*(_Lx('
+
+ Translators don't provide translations for log messages, and operators
+ asked not to translate them.
+
+ * This check assumes that 'LOG' is a logger.
+
+ :param logical_line: The logical line to check.
+ :param filename: The file name where the logical line exists.
+ :returns: None if the logical line passes the check, otherwise a tuple
+ is yielded that contains the offending index in logical line
+ and a message describe the check validation failure.
+ """
+ if _translation_checks_not_enforced(filename):
+ return
+
+ msg = "O341: Log messages should not be translated!"
+ match = _log_translation_hint.match(logical_line)
+ if match:
+ yield (logical_line.index(match.group()), msg)
+
+
+@core.flake8ext
+def check_raised_localized_exceptions(logical_line, filename):
+ """O342 - Untranslated exception message.
+
+ :param logical_line: The logical line to check.
+ :param filename: The file name where the logical line exists.
+ :returns: None if the logical line passes the check, otherwise a tuple
+ is yielded that contains the offending index in logical line
+ and a message describe the check validation failure.
+ """
+ if _translation_checks_not_enforced(filename):
+ return
+
+ logical_line = logical_line.strip()
+ raised_search = untranslated_exception_re.match(logical_line)
+ if raised_search:
+ exception_msg = raised_search.groups()[0]
+ if exception_msg.startswith("\"") or exception_msg.startswith("\'"):
+ msg = "O342: Untranslated exception message."
+ yield (logical_line.index(exception_msg), msg)
+
+
+@core.flake8ext
+def check_no_eventlet_imports(logical_line):
+ """O345 - Usage of Python eventlet module not allowed.
+
+ :param logical_line: The logical line to check.
+ :returns: None if the logical line passes the check, otherwise a tuple
+ is yielded that contains the offending index in logical line
+ and a message describe the check validation failure.
+ """
+ if no_eventlet_re.match(logical_line):
+ msg = 'O345 Usage of Python eventlet module not allowed'
+ yield logical_line.index('eventlet'), msg
+
+
+@core.flake8ext
+def check_line_continuation_no_backslash(logical_line, tokens):
+ """O346 - Don't use backslashes for line continuation.
+
+ :param logical_line: The logical line to check. Not actually used.
+ :param tokens: List of tokens to check.
+ :returns: None if the tokens don't contain any issues, otherwise a tuple
+ is yielded that contains the offending index in the logical
+ line and a message describe the check validation failure.
+ """
+ backslash = None
+ for token_type, text, start, end, orig_line in tokens:
+ m = no_line_continuation_backslash_re.match(orig_line)
+ if m:
+ backslash = (start[0], m.start(1))
+ break
+
+ if backslash is not None:
+ msg = 'O346 Backslash line continuations not allowed'
+ yield backslash, msg
+
+
+@core.flake8ext
+def revert_must_have_kwargs(logical_line):
+ """O347 - Taskflow revert methods must have \\*\\*kwargs.
+
+ :param logical_line: The logical line to check.
+ :returns: None if the logical line passes the check, otherwise a tuple
+ is yielded that contains the offending index in logical line
+ and a message describe the check validation failure.
+ """
+ if revert_must_have_kwargs_re.match(logical_line):
+ msg = 'O347 Taskflow revert methods must have **kwargs'
+ yield 0, msg
+
+
+@core.flake8ext
+def check_no_logging_imports(logical_line):
+ """O348 - Usage of Python logging module not allowed.
+
+ :param logical_line: The logical line to check.
+ :returns: None if the logical line passes the check, otherwise a tuple
+ is yielded that contains the offending index in logical line
+ and a message describe the check validation failure.
+ """
+ if no_logging_re.match(logical_line):
+ msg = 'O348 Usage of Python logging module not allowed, use oslo_log'
+ yield logical_line.index('logging'), msg
+
+
+@core.flake8ext
+def check_no_import_mock(logical_line):
+ """O349 - Test code must not import mock library.
+
+ :param logical_line: The logical line to check.
+ :returns: None if the logical line passes the check, otherwise a tuple
+ is yielded that contains the offending index in logical line
+ and a message describe the check validation failure.
+ """
+ if (import_mock_re.match(logical_line) or
+ import_from_mock_re.match(logical_line)):
+ msg = 'O349 Test code must not import mock library, use unittest.mock'
+ yield 0, msg
diff --git a/octavia_tempest_plugin/services/load_balancer/v2/__init__.py b/octavia_tempest_plugin/services/load_balancer/v2/__init__.py
index d31d6cf..04cb473 100644
--- a/octavia_tempest_plugin/services/load_balancer/v2/__init__.py
+++ b/octavia_tempest_plugin/services/load_balancer/v2/__init__.py
@@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from octavia_tempest_plugin.services.load_balancer.v2.loadbalancer_client \
- import LoadbalancerClient
+from .loadbalancer_client import LoadbalancerClient
__all__ = ['LoadbalancerClient']
diff --git a/octavia_tempest_plugin/tests/act_stdby_scenario/v2/test_active_standby.py b/octavia_tempest_plugin/tests/act_stdby_scenario/v2/test_active_standby.py
index 612bbe2..5655b3f 100644
--- a/octavia_tempest_plugin/tests/act_stdby_scenario/v2/test_active_standby.py
+++ b/octavia_tempest_plugin/tests/act_stdby_scenario/v2/test_active_standby.py
@@ -270,7 +270,7 @@
connections = 0
for listener in amphora_stats:
connections += listener[const.TOTAL_CONNECTIONS]
- self.assertTrue(connections > 0)
+ self.assertGreater(connections, 0)
LOG.info('Backup amphora is now Master.')
# Wait for the amphora failover to start
waiters.wait_for_status(
diff --git a/octavia_tempest_plugin/tests/api/v2/test_amphora.py b/octavia_tempest_plugin/tests/api/v2/test_amphora.py
index 7cf77dd..d1106e6 100644
--- a/octavia_tempest_plugin/tests/api/v2/test_amphora.py
+++ b/octavia_tempest_plugin/tests/api/v2/test_amphora.py
@@ -12,6 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from uuid import UUID
+
+from dateutil import parser
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
@@ -57,6 +60,98 @@
CONF.load_balancer.lb_build_interval,
CONF.load_balancer.lb_build_timeout)
+ def _expected_amp_count(self, amp_list):
+ self.assertNotEmpty(amp_list)
+ if amp_list[0][const.ROLE] in (const.ROLE_MASTER, const.ROLE_BACKUP):
+ return 2
+ return 1
+
+ @decorators.idempotent_id('a0e9ff99-2c4f-45d5-81c9-78d3107c236f')
+ def test_amphora_list_and_show(self):
+ """Tests amphora show API.
+
+ * Show amphora details.
+ * Validate the show reflects the requested values.
+ * Validates that other accounts cannot see the amphora.
+ """
+ lb_name = data_utils.rand_name("lb_member_lb2_amphora-list")
+ lb = self.mem_lb_client.create_loadbalancer(
+ name=lb_name, provider=CONF.load_balancer.provider,
+ vip_network_id=self.lb_member_vip_net[const.ID])
+ lb_id = lb[const.ID]
+ self.addCleanup(self.mem_lb_client.cleanup_loadbalancer, lb_id)
+
+ waiters.wait_for_status(self.mem_lb_client.show_loadbalancer,
+ lb_id,
+ const.PROVISIONING_STATUS,
+ const.ACTIVE,
+ CONF.load_balancer.lb_build_interval,
+ CONF.load_balancer.lb_build_timeout)
+
+ # Test that a user, without the load balancer member role, cannot
+ # list amphorae
+ if CONF.load_balancer.RBAC_test_type == const.ADVANCED:
+ self.assertRaises(
+ exceptions.Forbidden,
+ self.os_primary.amphora_client.list_amphorae)
+
+ # Get an actual list of the amphorae
+ amphorae = self.lb_admin_amphora_client.list_amphorae()
+
+ # There should be AT LEAST 2, there may be more depending on the
+ # configured topology
+ self.assertGreaterEqual(
+ len(amphorae), 2 * self._expected_amp_count(amphorae))
+
+ # Test filtering by loadbalancer_id
+ amphorae = self.lb_admin_amphora_client.list_amphorae(
+ query_params='{loadbalancer_id}={lb_id}'.format(
+ loadbalancer_id=const.LOADBALANCER_ID, lb_id=self.lb_id))
+ self.assertEqual(self._expected_amp_count(amphorae), len(amphorae))
+ self.assertEqual(self.lb_id, amphorae[0][const.LOADBALANCER_ID])
+
+ # Test that a different user, with load balancer member role, cannot
+ # see this amphora
+ if not CONF.load_balancer.RBAC_test_type == const.NONE:
+ member2_client = self.os_roles_lb_member2.amphora_client
+ self.assertRaises(exceptions.Forbidden,
+ member2_client.show_amphora,
+ amphora_id=amphorae[0][const.ID])
+
+ show_amphora_response_fields = const.SHOW_AMPHORA_RESPONSE_FIELDS
+ if self.lb_admin_amphora_client.is_version_supported(
+ self.api_version, '2.1'):
+ show_amphora_response_fields.append('created_at')
+ show_amphora_response_fields.append('updated_at')
+ show_amphora_response_fields.append('image_id')
+
+ for amp in amphorae:
+
+ # Make sure all of the fields exist on the amp list records
+ for field in show_amphora_response_fields:
+ self.assertIn(field, amp)
+
+ # Verify a few of the fields are the right type
+ if self.lb_admin_amphora_client.is_version_supported(
+ self.api_version, '2.1'):
+ parser.parse(amp[const.CREATED_AT])
+ parser.parse(amp[const.UPDATED_AT])
+
+ UUID(amp[const.ID])
+ UUID(amp[const.HA_PORT_ID])
+ UUID(amp[const.LOADBALANCER_ID])
+ UUID(amp[const.COMPUTE_ID])
+ UUID(amp[const.VRRP_PORT_ID])
+ self.assertEqual(amp[const.STATUS], const.STATUS_ALLOCATED)
+ self.assertIn(amp[const.ROLE], const.AMPHORA_ROLES)
+
+ # Test that all of the fields from the amp list match those
+ # from a show for the LB we created.
+ amp_obj = self.lb_admin_amphora_client.show_amphora(
+ amphora_id=amp[const.ID])
+ for field in show_amphora_response_fields:
+ self.assertEqual(amp[field], amp_obj[field])
+
@decorators.idempotent_id('b7fc231b-dcfa-47a5-99f3-ec5ddcc48f30')
def test_amphora_update(self):
"""Tests the amphora agent configuration update API
diff --git a/octavia_tempest_plugin/tests/api/v2/test_l7rule.py b/octavia_tempest_plugin/tests/api/v2/test_l7rule.py
index aaad8a0..9a73034 100644
--- a/octavia_tempest_plugin/tests/api/v2/test_l7rule.py
+++ b/octavia_tempest_plugin/tests/api/v2/test_l7rule.py
@@ -573,7 +573,7 @@
l7rule_check = self.mem_l7rule_client.show_l7rule(
l7rule[const.ID], l7policy_id=self.l7policy_id)
self.assertEqual(const.ACTIVE, l7rule_check[const.PROVISIONING_STATUS])
- self.assertEqual(False, l7rule_check[const.ADMIN_STATE_UP])
+ self.assertFalse(l7rule_check[const.ADMIN_STATE_UP])
# Test that a user, without the load balancer member role, cannot
# update this l7rule
@@ -588,7 +588,7 @@
l7rule_check = self.mem_l7rule_client.show_l7rule(
l7rule[const.ID], l7policy_id=self.l7policy_id)
self.assertEqual(const.ACTIVE, l7rule_check[const.PROVISIONING_STATUS])
- self.assertEqual(False, l7rule_check[const.ADMIN_STATE_UP])
+ self.assertFalse(l7rule_check[const.ADMIN_STATE_UP])
l7rule_update_kwargs = {
const.L7POLICY_ID: self.l7policy_id,
diff --git a/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py b/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
index 84bfc20..a753a5c 100644
--- a/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
+++ b/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
@@ -749,8 +749,8 @@
CONF.load_balancer.build_timeout)
# Test that no client certificate fails to connect
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*certificate required.*",
+ self.assertRaises(
+ requests.exceptions.SSLError,
requests.get,
'https://{0}:{1}'.format(self.lb_vip_address, LISTENER1_TCP_PORT),
timeout=12, verify=False)
@@ -764,8 +764,8 @@
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
serialization.NoEncryption()))
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*revoked.*", requests.get,
+ self.assertRaises(
+ requests.exceptions.SSLError, requests.get,
'https://{0}:{1}'.format(self.lb_vip_address,
LISTENER1_TCP_PORT),
timeout=12, verify=False, cert=(cert_file.name,
@@ -836,8 +836,8 @@
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
serialization.NoEncryption()))
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*revoked.*", requests.get,
+ self.assertRaises(
+ requests.exceptions.SSLError, requests.get,
'https://{0}:{1}'.format(self.lb_vip_address,
LISTENER1_TCP_PORT),
timeout=12, verify=False, cert=(cert_file.name,
@@ -954,15 +954,15 @@
CONF.load_balancer.build_timeout)
# Test that no client certificate fails to connect to listener1
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*certificate required.*",
+ self.assertRaises(
+ requests.exceptions.SSLError,
requests.get,
'https://{0}:{1}'.format(self.lb_vip_address, LISTENER1_TCP_PORT),
timeout=12, verify=False)
# Test that no client certificate fails to connect to listener2
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*certificate required.*",
+ self.assertRaises(
+ requests.exceptions.SSLError,
requests.get,
'https://{0}:{1}'.format(self.lb_vip_address, LISTENER2_TCP_PORT),
timeout=12, verify=False)
@@ -976,8 +976,8 @@
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
serialization.NoEncryption()))
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*revoked.*", requests.get,
+ self.assertRaises(
+ requests.exceptions.SSLError, requests.get,
'https://{0}:{1}'.format(self.lb_vip_address,
LISTENER1_TCP_PORT),
timeout=12, verify=False, cert=(cert_file.name,
@@ -992,8 +992,8 @@
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
serialization.NoEncryption()))
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*revoked.*", requests.get,
+ self.assertRaises(
+ requests.exceptions.SSLError, requests.get,
'https://{0}:{1}'.format(self.lb_vip_address,
LISTENER2_TCP_PORT),
timeout=12, verify=False, cert=(cert_file.name,
@@ -1040,8 +1040,8 @@
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
serialization.NoEncryption()))
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*decrypt error.*",
+ self.assertRaises(
+ requests.exceptions.SSLError,
requests.get, 'https://{0}:{1}'.format(self.lb_vip_address,
LISTENER2_TCP_PORT),
timeout=12, verify=False, cert=(cert_file.name,
@@ -1056,8 +1056,8 @@
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
serialization.NoEncryption()))
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*decrypt error.*",
+ self.assertRaises(
+ requests.exceptions.SSLError,
requests.get, 'https://{0}:{1}'.format(self.lb_vip_address,
LISTENER1_TCP_PORT),
timeout=12, verify=False, cert=(cert_file.name,
@@ -1072,8 +1072,8 @@
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
serialization.NoEncryption()))
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*decrypt error.*",
+ self.assertRaises(
+ requests.exceptions.SSLError,
requests.get, 'https://{0}:{1}'.format(self.lb_vip_address,
LISTENER2_TCP_PORT),
timeout=12, verify=False, cert=(cert_file.name,
@@ -1088,8 +1088,8 @@
serialization.Encoding.PEM,
serialization.PrivateFormat.TraditionalOpenSSL,
serialization.NoEncryption()))
- self.assertRaisesRegex(
- requests.exceptions.SSLError, ".*decrypt error.*",
+ self.assertRaises(
+ requests.exceptions.SSLError,
requests.get, 'https://{0}:{1}'.format(self.lb_vip_address,
LISTENER1_TCP_PORT),
timeout=12, verify=False, cert=(cert_file.name,
diff --git a/octavia_tempest_plugin/tests/scenario/v2/test_amphora.py b/octavia_tempest_plugin/tests/scenario/v2/test_amphora.py
deleted file mode 100644
index 9101321..0000000
--- a/octavia_tempest_plugin/tests/scenario/v2/test_amphora.py
+++ /dev/null
@@ -1,188 +0,0 @@
-# Copyright 2018 GoDaddy
-#
-# 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.
-
-from uuid import UUID
-
-from dateutil import parser
-from tempest import config
-from tempest.lib.common.utils import data_utils
-from tempest.lib import decorators
-from tempest.lib import exceptions
-
-from octavia_tempest_plugin.common import constants as const
-from octavia_tempest_plugin.tests import test_base
-from octavia_tempest_plugin.tests import waiters
-
-CONF = config.CONF
-
-
-class AmphoraScenarioTest(test_base.LoadBalancerBaseTest):
- """Test the amphora object API."""
-
- @classmethod
- def skip_checks(cls):
- super(AmphoraScenarioTest, cls).skip_checks()
-
- if CONF.load_balancer.provider not in const.AMPHORA_PROVIDERS:
- raise cls.skipException("Amphora tests require provider 'amphora' "
- "or 'octavia' (alias to 'amphora', "
- " deprecated) set")
-
- @classmethod
- def resource_setup(cls):
- """Setup resources needed by the tests."""
- super(AmphoraScenarioTest, cls).resource_setup()
-
- lb_name = data_utils.rand_name("lb_member_lb1_amphora")
- lb_kwargs = {const.PROVIDER: CONF.load_balancer.provider,
- const.NAME: lb_name}
-
- cls._setup_lb_network_kwargs(lb_kwargs)
-
- lb = cls.mem_lb_client.create_loadbalancer(**lb_kwargs)
- cls.lb_id = lb[const.ID]
- cls.addClassResourceCleanup(
- cls.mem_lb_client.cleanup_loadbalancer,
- cls.lb_id)
-
- waiters.wait_for_status(cls.mem_lb_client.show_loadbalancer,
- cls.lb_id, const.PROVISIONING_STATUS,
- const.ACTIVE,
- CONF.load_balancer.lb_build_interval,
- CONF.load_balancer.lb_build_timeout)
-
- def _expected_amp_count(self, amp_list):
- self.assertNotEmpty(amp_list)
- if amp_list[0][const.ROLE] in (const.ROLE_MASTER, const.ROLE_BACKUP):
- return 2
- return 1
-
- @decorators.idempotent_id('a0e9ff99-2c4f-45d5-81c9-78d3107c236f')
- def test_amphora_list_and_show(self):
- """Tests amphora show API.
-
- * Show amphora details.
- * Validate the show reflects the requested values.
- * Validates that other accounts cannot see the amphora.
- """
- lb_name = data_utils.rand_name("lb_member_lb2_amphora-list")
- lb = self.mem_lb_client.create_loadbalancer(
- name=lb_name, provider=CONF.load_balancer.provider,
- vip_network_id=self.lb_member_vip_net[const.ID])
- lb_id = lb[const.ID]
- self.addCleanup(
- self.mem_lb_client.cleanup_loadbalancer,
- lb_id)
-
- waiters.wait_for_status(self.mem_lb_client.show_loadbalancer,
- lb_id,
- const.PROVISIONING_STATUS,
- const.ACTIVE,
- CONF.load_balancer.lb_build_interval,
- CONF.load_balancer.lb_build_timeout)
-
- # Test that a user with lb_admin role can list the amphora
- if CONF.load_balancer.RBAC_test_type == const.ADVANCED:
- amphora_client = self.os_roles_lb_admin.amphora_client
- amphora_adm = amphora_client.list_amphorae()
- self.assertTrue(
- len(amphora_adm) >= 2 * self._expected_amp_count(amphora_adm))
-
- # Test that a different user, with load balancer member role, cannot
- # see this amphora
- if not CONF.load_balancer.RBAC_test_type == const.NONE:
- member2_client = self.os_roles_lb_member2.amphora_client
- self.assertRaises(exceptions.Forbidden,
- member2_client.list_amphorae)
-
- # Test that a user, without the load balancer member role, cannot
- # list amphorae
- if CONF.load_balancer.RBAC_test_type == const.ADVANCED:
- self.assertRaises(
- exceptions.Forbidden,
- self.os_primary.amphora_client.list_amphorae)
-
- # Test that a user with cloud admin role can list the amphorae
- if not CONF.load_balancer.RBAC_test_type == const.NONE:
- adm = self.lb_admin_amphora_client.list_amphorae()
- self.assertTrue(len(adm) >= 2 * self._expected_amp_count(adm))
-
- # Get an actual list of the amphorae
- amphorae = self.lb_admin_amphora_client.list_amphorae()
-
- # There should be AT LEAST 2, there may be more depending on the
- # configured topology, or if there are other LBs created besides ours
- self.assertTrue(
- len(amphorae) >= 2 * self._expected_amp_count(amphorae))
-
- show_amphora_response_fields = const.SHOW_AMPHORA_RESPONSE_FIELDS
- if self.lb_admin_amphora_client.is_version_supported(
- self.api_version, '2.1'):
- show_amphora_response_fields.append('created_at')
- show_amphora_response_fields.append('updated_at')
- show_amphora_response_fields.append('image_id')
-
- for amp in amphorae:
-
- # Make sure all of the fields exist on the amp list records
- for field in show_amphora_response_fields:
- self.assertIn(field, amp)
-
- amp_id = amp[const.ID]
- amp_obj = self.lb_admin_amphora_client.show_amphora(
- amphora_id=amp_id)
-
- # Make sure all of the fields exist on the amp show record
- for field in show_amphora_response_fields:
- self.assertIn(field, amp_obj)
-
- # Verify a few of the fields are the right type
- if self.lb_admin_amphora_client.is_version_supported(
- self.api_version, '2.1'):
- parser.parse(amp_obj[const.CREATED_AT])
- parser.parse(amp_obj[const.UPDATED_AT])
- UUID(amp_obj[const.ID])
- self.assertIn(amp_obj[const.STATUS], const.AMPHORA_STATUSES)
-
- # We might have gotten unassigned/spare amps?
- if amp_obj[const.STATUS] == const.STATUS_ALLOCATED:
- # Only check the state of fields for the LB we created,
- # otherwise some fields (HA_PORT_ID) may not yet be
- # populated in amps for parallel tests.
- if lb_id == amp_obj[const.LOADBALANCER_ID]:
- UUID(amp_obj[const.HA_PORT_ID])
- UUID(amp_obj[const.LOADBALANCER_ID])
- UUID(amp_obj[const.COMPUTE_ID])
- UUID(amp_obj[const.VRRP_PORT_ID])
- self.assertIn(amp_obj[const.ROLE], const.AMPHORA_ROLES)
- else:
- self.assertIsNone(amp_obj[const.ROLE])
-
- # Test that all of the fields from the amp list match those
- # from a show
- for field in show_amphora_response_fields:
- self.assertEqual(amp[field], amp_obj[field])
-
- # Test filtering by loadbalancer_id
- amphorae = self.lb_admin_amphora_client.list_amphorae(
- query_params='{loadbalancer_id}={lb_id}'.format(
- loadbalancer_id=const.LOADBALANCER_ID, lb_id=self.lb_id))
- self.assertEqual(self._expected_amp_count(amphorae), len(amphorae))
- self.assertEqual(self.lb_id, amphorae[0][const.LOADBALANCER_ID])
-
- amphorae = self.lb_admin_amphora_client.list_amphorae(
- query_params='{loadbalancer_id}={lb_id}'.format(
- loadbalancer_id=const.LOADBALANCER_ID, lb_id=lb_id))
- self.assertEqual(self._expected_amp_count(amphorae), len(amphorae))
- self.assertEqual(lb_id, amphorae[0][const.LOADBALANCER_ID])
diff --git a/octavia_tempest_plugin/tests/scenario/v2/test_pool.py b/octavia_tempest_plugin/tests/scenario/v2/test_pool.py
index 5e0622c..720e80a 100644
--- a/octavia_tempest_plugin/tests/scenario/v2/test_pool.py
+++ b/octavia_tempest_plugin/tests/scenario/v2/test_pool.py
@@ -167,8 +167,8 @@
}
if self.lb_feature_enabled.pool_algorithms_enabled:
- pool_update_kwargs[const.LB_ALGORITHM] = \
- const.LB_ALGORITHM_LEAST_CONNECTIONS
+ pool_update_kwargs[const.LB_ALGORITHM] = (
+ const.LB_ALGORITHM_LEAST_CONNECTIONS)
if self.protocol == const.HTTP and (
self.lb_feature_enabled.session_persistence_enabled):
diff --git a/octavia_tempest_plugin/tests/test_base.py b/octavia_tempest_plugin/tests/test_base.py
index aab78c1..741bb1c 100644
--- a/octavia_tempest_plugin/tests/test_base.py
+++ b/octavia_tempest_plugin/tests/test_base.py
@@ -302,8 +302,8 @@
network_kwargs = {
'name': data_utils.rand_name("lb_member_vip_network")}
if CONF.network_feature_enabled.port_security:
- # Note: Allowed Address Pairs requires port security
- network_kwargs['port_security_enabled'] = True
+ # Note: Allowed Address Pairs requires port security
+ network_kwargs['port_security_enabled'] = True
result = cls.lb_mem_net_client.create_network(**network_kwargs)
cls.lb_member_vip_net = result['network']
LOG.info('lb_member_vip_net: {}'.format(cls.lb_member_vip_net))
diff --git a/playbooks/Octavia-DSVM/pre.yaml b/playbooks/Octavia-DSVM/pre.yaml
deleted file mode 100644
index 9d6beb7..0000000
--- a/playbooks/Octavia-DSVM/pre.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-- hosts: all
- name: Octavia DSVM jobs pre-run playbook
- tasks:
- - shell:
- executable: /bin/bash
- cmd: |
- set -e
- set -x
- if $(egrep --quiet '(vmx|svm)' /proc/cpuinfo) && [[ ( ! $(hostname) =~ "ovh" && ! $(hostname) =~ "limestone" ) ]]; then
- export DEVSTACK_GATE_LIBVIRT_TYPE=kvm
- fi
-
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
index a346f01..8437073 100644
--- a/releasenotes/source/conf.py
+++ b/releasenotes/source/conf.py
@@ -43,8 +43,9 @@
]
# openstackdocstheme options
-repository_name = 'openstack/octavia-tempest-plugin'
-use_storyboard = True
+openstackdocs_repo_name = 'openstack/octavia-tempest-plugin'
+openstackdocs_auto_name = False
+openstackdocs_use_storyboard = True
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -102,7 +103,7 @@
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = 'native'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
diff --git a/requirements.txt b/requirements.txt
index 8020630..b30b450 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,6 @@
cryptography>=2.1 # BSD/Apache-2.0
python-dateutil>=2.5.3 # BSD
-ipaddress>=1.0.17;python_version<'3.3' # PSF
pbr!=2.1.0,>=2.0.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
oslo.log>=3.36.0 # Apache-2.0
diff --git a/setup.cfg b/setup.cfg
index 5da1d1d..d7d3196 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -6,6 +6,7 @@
author = OpenStack
author-email = openstack-discuss@lists.openstack.org
home-page = https://docs.openstack.org/octavia-tempest-plugin/latest/
+python-requires = >=3.6
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
@@ -13,10 +14,12 @@
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
- Programming Language :: Python :: 2
- Programming Language :: Python :: 2.7
+ Programming Language :: Python :: Implementation :: CPython
+ Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
+ Programming Language :: Python :: 3.6
+ Programming Language :: Python :: 3.7
+ Programming Language :: Python :: 3.8
[global]
setup-hooks =
@@ -26,14 +29,6 @@
packages =
octavia_tempest_plugin
-[build_sphinx]
-source-dir = doc/source
-build-dir = doc/build
-all_files = 1
-
-[upload_sphinx]
-upload-dir = doc/build/html
-
[compile_catalog]
directory = octavia_tempest_plugin/locale
domain = octavia_tempest_plugin
diff --git a/test-requirements.txt b/test-requirements.txt
index 47c128f..2125ea0 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -2,7 +2,7 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
+hacking>=3.0.1,<3.1.0;python_version>='3.5' # Apache-2.0
coverage!=4.4,>=4.0 # Apache-2.0
python-subunit>=1.0.0 # Apache-2.0/BSD
diff --git a/tox.ini b/tox.ini
index 4a61222..a419c62 100644
--- a/tox.ini
+++ b/tox.ini
@@ -43,6 +43,7 @@
deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
+ -r{toxinidir}/test-requirements.txt
-r{toxinidir}/doc/requirements.txt
whitelist_externals = rm
commands =
@@ -85,6 +86,24 @@
# [H904]: Delay string interpolations at logging calls
enable-extensions=H106,H203,H204,H205,H904
+[flake8:local-plugins]
+extension =
+ O316 = checks:assert_true_instance
+ O318 = checks:assert_equal_or_not_none
+ O323 = checks:assert_equal_true_or_false
+ O324 = checks:no_mutable_default_args
+ O338 = checks:assert_equal_in
+ O339 = checks:no_log_warn
+ O341 = checks:no_translate_logs
+ O342 = checks:check_raised_localized_exceptions
+ O345 = checks:check_no_eventlet_imports
+ O346 = checks:check_line_continuation_no_backslash
+ O347 = checks:revert_must_have_kwargs
+ O348 = checks:check_no_logging_imports
+ O349 = checks:check_no_import_mock
+paths =
+ ./octavia_tempest_plugin/hacking
+
[testenv:genconfig]
basepython = python3
whitelist_externals = mkdir
diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml
index 3e1c9f6..033dbae 100644
--- a/zuul.d/jobs.yaml
+++ b/zuul.d/jobs.yaml
@@ -36,11 +36,11 @@
parent: devstack-tempest
timeout: 7800
required-projects:
+ - openstack/devstack
- openstack/octavia
- openstack/octavia-lib
- openstack/octavia-tempest-plugin
- openstack/python-octaviaclient
- pre-run: playbooks/Octavia-DSVM/pre.yaml
irrelevant-files:
- ^.*\.rst$
- ^api-ref/.*$
@@ -51,6 +51,8 @@
devstack_localrc:
TEMPEST_PLUGINS: /opt/stack/octavia-tempest-plugin
USE_PYTHON3: true
+ LIBVIRT_TYPE: kvm
+ LIBVIRT_CPU_MODE: host-passthrough
devstack_local_conf:
post-config:
$OCTAVIA_CONF:
@@ -88,11 +90,11 @@
parent: devstack-tempest-ipv6
timeout: 7800
required-projects:
+ - openstack/devstack
- openstack/octavia
- openstack/octavia-lib
- openstack/octavia-tempest-plugin
- openstack/python-octaviaclient
- pre-run: playbooks/Octavia-DSVM/pre.yaml
irrelevant-files:
- ^.*\.rst$
- ^api-ref/.*$
@@ -103,6 +105,8 @@
devstack_localrc:
TEMPEST_PLUGINS: /opt/stack/octavia-tempest-plugin
USE_PYTHON3: true
+ LIBVIRT_TYPE: kvm
+ LIBVIRT_CPU_MODE: host-passthrough
devstack_local_conf:
post-config:
$OCTAVIA_CONF:
@@ -144,6 +148,8 @@
vars:
devstack_localrc:
DIB_LOCAL_ELEMENTS: openstack-ci-mirrors
+ LIBVIRT_TYPE: kvm
+ LIBVIRT_CPU_MODE: host-passthrough
devstack_local_conf:
post-config:
$OCTAVIA_CONF:
@@ -231,6 +237,8 @@
HOST_IP: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
TEMPEST_PLUGINS: /opt/stack/octavia-tempest-plugin
USE_PYTHON3: true
+ LIBVIRT_TYPE: kvm
+ LIBVIRT_CPU_MODE: host-passthrough
# Octavia specific settings
OCTAVIA_CONTROLLER_IP_PORT_LIST: 192.168.0.3:5555,192.168.0.4:5555
OCTAVIA_MGMT_PORT_IP: 192.168.0.3
@@ -271,6 +279,8 @@
RABBIT_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
GLANCE_HOSTPORT: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}:9292"
USE_PYTHON3: true
+ LIBVIRT_TYPE: kvm
+ LIBVIRT_CPU_MODE: host-passthrough
# Octavia specific settings
OCTAVIA_CONTROLLER_IP_PORT_LIST: 192.168.0.3:5555,192.168.0.4:5555
OCTAVIA_NODE: subnode
@@ -408,16 +418,6 @@
override-checkout: stable/stein
- job:
- name: octavia-v2-dsvm-noop-py2-api-stable-rocky
- parent: octavia-v2-dsvm-noop-py2-api
- override-checkout: stable/rocky
-
-- job:
- name: octavia-v2-dsvm-noop-py2-api-stable-queens
- parent: octavia-v2-dsvm-noop-py2-api
- override-checkout: stable/queens
-
-- job:
name: octavia-v2-dsvm-scenario
parent: octavia-dsvm-live-base
vars:
@@ -463,6 +463,9 @@
vars:
devstack_localrc:
USE_PYTHON3: False
+ required-projects:
+ - name: openstack/diskimage-builder
+ override-checkout: 2.30.0
- job:
name: octavia-v2-dsvm-scenario-stable-train
@@ -473,16 +476,9 @@
name: octavia-v2-dsvm-scenario-stable-stein
parent: octavia-v2-dsvm-scenario
override-checkout: stable/stein
-
-- job:
- name: octavia-v2-dsvm-py2-scenario-stable-rocky
- parent: octavia-v2-dsvm-py2-scenario
- override-checkout: stable/rocky
-
-- job:
- name: octavia-v2-dsvm-py2-scenario-stable-queens
- parent: octavia-v2-dsvm-py2-scenario
- override-checkout: stable/queens
+ required-projects:
+ - name: openstack/diskimage-builder
+ override-checkout: 2.30.0
# Legacy jobs for the transition to the act-stdby two node jobs
- job:
@@ -507,9 +503,16 @@
controller:
devstack_localrc:
USE_PYTHON3: False
+ LIBVIRT_TYPE: kvm
+ LIBVIRT_CPU_MODE: host-passthrough
controller2:
devstack_localrc:
USE_PYTHON3: False
+ LIBVIRT_TYPE: kvm
+ LIBVIRT_CPU_MODE: host-passthrough
+ required-projects:
+ - name: openstack/diskimage-builder
+ override-checkout: 2.30.0
- job:
name: octavia-v2-act-stdby-dsvm-scenario-two-node
@@ -560,6 +563,7 @@
OCTAVIA_AMP_BASE_OS: ubuntu
OCTAVIA_AMP_DISTRIBUTION_RELEASE_ID: xenial
USE_PYTHON3: false
+ TEMPEST_BRANCH: 23.0.0
- job:
name: octavia-v2-dsvm-tls-barbican
@@ -594,6 +598,9 @@
name: octavia-v2-dsvm-tls-barbican-stable-stein
parent: octavia-v2-dsvm-tls-barbican
override-checkout: stable/stein
+ required-projects:
+ - name: openstack/diskimage-builder
+ override-checkout: 2.30.0
- job:
name: octavia-v2-dsvm-tls-barbican-stable-rocky
@@ -626,6 +633,9 @@
vars:
devstack_localrc:
USE_PYTHON3: False
+ required-projects:
+ - name: openstack/diskimage-builder
+ override-checkout: 2.30.0
- job:
name: octavia-v2-dsvm-spare-pool-stable-train
@@ -636,22 +646,16 @@
name: octavia-v2-dsvm-spare-pool-stable-stein
parent: octavia-v2-dsvm-spare-pool
override-checkout: stable/stein
-
-- job:
- name: octavia-v2-dsvm-py2-spare-pool-stable-rocky
- parent: octavia-v2-dsvm-py2-spare-pool
- override-checkout: stable/rocky
-
-- job:
- name: octavia-v2-dsvm-py2-spare-pool-stable-queens
- parent: octavia-v2-dsvm-py2-spare-pool
- override-checkout: stable/queens
+ required-projects:
+ - name: openstack/diskimage-builder
+ override-checkout: 2.30.0
- job:
name: octavia-v2-dsvm-cinder-amphora
parent: octavia-v2-dsvm-scenario
required-projects:
- openstack/cinder
+ - openstack/devstack
- openstack/diskimage-builder
- openstack/octavia
- openstack/octavia-lib
@@ -737,6 +741,9 @@
vars:
devstack_localrc:
USE_PYTHON3: False
+ required-projects:
+ - name: openstack/diskimage-builder
+ override-checkout: 2.30.0
- job:
name: octavia-v2-act-stdby-iptables-dsvm-py2-scenario-centos-7
@@ -755,16 +762,6 @@
amphora_ssh_user: centos
- job:
- name: octavia-v2-act-stdby-iptables-dsvm-py2-scenario-stable-rocky
- parent: octavia-v2-act-stdby-iptables-dsvm-py2-scenario
- override-checkout: stable/rocky
-
-- job:
- name: octavia-v2-act-stdby-iptables-dsvm-py2-scenario-stable-queens
- parent: octavia-v2-act-stdby-iptables-dsvm-py2-scenario
- override-checkout: stable/queens
-
-- job:
name: octavia-v2-act-stdby-dsvm-scenario
parent: octavia-dsvm-live-base
vars:
@@ -790,3 +787,6 @@
name: octavia-v2-act-stdby-dsvm-scenario-stable-stein
parent: octavia-v2-act-stdby-dsvm-scenario
override-checkout: stable/stein
+ required-projects:
+ - name: openstack/diskimage-builder
+ override-checkout: 2.30.0
diff --git a/zuul.d/projects.yaml b/zuul.d/projects.yaml
index be12bba..6b1fcc0 100644
--- a/zuul.d/projects.yaml
+++ b/zuul.d/projects.yaml
@@ -11,23 +11,15 @@
- octavia-v2-dsvm-noop-api
- octavia-v2-dsvm-noop-api-stable-train
- octavia-v2-dsvm-noop-api-stable-stein
- - octavia-v2-dsvm-noop-py2-api-stable-rocky
- - octavia-v2-dsvm-noop-py2-api-stable-queens
- octavia-v2-dsvm-scenario
- octavia-v2-dsvm-scenario-stable-train
- octavia-v2-dsvm-scenario-stable-stein
- - octavia-v2-dsvm-py2-scenario-stable-rocky
- - octavia-v2-dsvm-py2-scenario-stable-queens
- octavia-v2-dsvm-scenario-ipv6-only:
voting: false
- octavia-v2-dsvm-scenario-centos-8:
voting: false
- octavia-v2-act-stdby-dsvm-scenario-two-node:
voting: false
- - octavia-v2-act-stdby-iptables-dsvm-py2-scenario-stable-rocky:
- voting: false
- - octavia-v2-act-stdby-iptables-dsvm-py2-scenario-stable-queens:
- voting: false
- octavia-v2-act-stdby-dsvm-scenario:
voting: false
- octavia-v2-act-stdby-dsvm-scenario-stable-train:
@@ -40,20 +32,12 @@
voting: false
- octavia-v2-dsvm-tls-barbican-stable-stein:
voting: false
- - octavia-v2-dsvm-tls-barbican-stable-rocky:
- voting: false
- - octavia-v2-dsvm-tls-barbican-stable-queens:
- voting: false
- octavia-v2-dsvm-spare-pool:
voting: false
- octavia-v2-dsvm-spare-pool-stable-train:
voting: false
- octavia-v2-dsvm-spare-pool-stable-stein:
voting: false
- - octavia-v2-dsvm-py2-spare-pool-stable-rocky:
- voting: false
- - octavia-v2-dsvm-py2-spare-pool-stable-queens:
- voting: false
- octavia-v2-dsvm-cinder-amphora:
voting: false
gate:
@@ -63,10 +47,6 @@
- octavia-v2-dsvm-noop-api
- octavia-v2-dsvm-noop-api-stable-train
- octavia-v2-dsvm-noop-api-stable-stein
- - octavia-v2-dsvm-noop-py2-api-stable-rocky
- - octavia-v2-dsvm-noop-py2-api-stable-queens
- octavia-v2-dsvm-scenario
- octavia-v2-dsvm-scenario-stable-train
- octavia-v2-dsvm-scenario-stable-stein
- - octavia-v2-dsvm-py2-scenario-stable-rocky
- - octavia-v2-dsvm-py2-scenario-stable-queens