Merge "Gate on octavia-v2-dsvm-tls-barbican jobs"
diff --git a/octavia_tempest_plugin/config.py b/octavia_tempest_plugin/config.py
index 8573d89..fc04c33 100644
--- a/octavia_tempest_plugin/config.py
+++ b/octavia_tempest_plugin/config.py
@@ -195,6 +195,12 @@
cfg.StrOpt('availability_zone',
default=None,
help='Availability zone to use for creating servers.'),
+ cfg.StrOpt('availability_zone2',
+ default=None,
+ help='A second availability zone to use for creating servers.'),
+ cfg.StrOpt('availability_zone3',
+ default=None,
+ help='A third availability zone to use for creating servers.'),
cfg.BoolOpt('test_reuse_connection', default=True,
help='Reuse TCP connections while testing LB with '
'HTTP members (keep-alive).'),
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/tests/api/v2/test_availability_zone.py b/octavia_tempest_plugin/tests/api/v2/test_availability_zone.py
index 023d5f5..816e00e 100644
--- a/octavia_tempest_plugin/tests/api/v2/test_availability_zone.py
+++ b/octavia_tempest_plugin/tests/api/v2/test_availability_zone.py
@@ -32,6 +32,15 @@
"""Test the availability zone object API."""
@classmethod
+ def skip_checks(cls):
+ super(AvailabilityZoneAPITest, cls).skip_checks()
+ if (CONF.load_balancer.availability_zone is None and
+ not CONF.load_balancer.test_with_noop):
+ raise cls.skipException(
+ 'Availability Zone API tests require an availability zone '
+ 'configured in the [load_balancer] availability_zone setting.')
+
+ @classmethod
def resource_setup(cls):
"""Setup resources needed by the tests."""
super(AvailabilityZoneAPITest, cls).resource_setup()
@@ -46,7 +55,7 @@
availability_zone_profile_name = data_utils.rand_name(
"lb_admin_availabilityzoneprofile-setup")
availability_zone_data = {
- const.COMPUTE_ZONE: 'my_compute_zone',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data_json = jsonutils.dumps(availability_zone_data)
diff --git a/octavia_tempest_plugin/tests/api/v2/test_availability_zone_profile.py b/octavia_tempest_plugin/tests/api/v2/test_availability_zone_profile.py
index 86ae066..c062dbe 100644
--- a/octavia_tempest_plugin/tests/api/v2/test_availability_zone_profile.py
+++ b/octavia_tempest_plugin/tests/api/v2/test_availability_zone_profile.py
@@ -32,6 +32,16 @@
class AvailabilityZoneProfileAPITest(test_base.LoadBalancerBaseTest):
"""Test the availability zone profile object API."""
+ @classmethod
+ def skip_checks(cls):
+ super(AvailabilityZoneProfileAPITest, cls).skip_checks()
+ if (CONF.load_balancer.availability_zone is None and
+ not CONF.load_balancer.test_with_noop):
+ raise cls.skipException(
+ 'Availability zone profile API tests require an availability '
+ 'zone configured in the [load_balancer] availability_zone '
+ 'setting in the tempest configuration file.')
+
@decorators.idempotent_id('e512b580-ef32-44c3-bbd2-efdc27ba2ea6')
def test_availability_zone_profile_create(self):
"""Tests availability zone profile create and basic show APIs.
@@ -53,7 +63,7 @@
availability_zone_profile_name = data_utils.rand_name(
"lb_admin_availabilityzoneprofile1-create")
availability_zone_data = {
- const.COMPUTE_ZONE: 'my_compute_zone',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data_json = jsonutils.dumps(availability_zone_data)
@@ -116,12 +126,20 @@
raise self.skipException(
'Availability zone profiles are only available on '
'Octavia API version 2.14 or newer.')
+ if ((CONF.load_balancer.availability_zone2 is None or
+ CONF.load_balancer.availability_zone3 is None) and
+ not CONF.load_balancer.test_with_noop):
+ raise self.skipException(
+ 'Availability zone profile list API test requires the '
+ '[load_balancer] availability_zone, availability_zone2, and '
+ 'availability_zone3 settings be defined in the tempest '
+ 'configuration file.')
# Create availability zone profile 1
availability_zone_profile1_name = data_utils.rand_name(
"lb_admin_availabilityzoneprofile-list-1")
availability_zone_data1 = {
- const.COMPUTE_ZONE: 'my_compute_zone1',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data1_json = jsonutils.dumps(availability_zone_data1)
@@ -144,7 +162,7 @@
availability_zone_profile2_name = data_utils.rand_name(
"lb_admin_availabilityzoneprofile-list-2")
availability_zone_data2 = {
- const.COMPUTE_ZONE: 'my_compute_zone2',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone2,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data2_json = jsonutils.dumps(availability_zone_data2)
@@ -167,7 +185,7 @@
availability_zone_profile3_name = data_utils.rand_name(
"lb_admin_availabilityzoneprofile-list-3")
availability_zone_data3 = {
- const.COMPUTE_ZONE: 'my_compute_zone3',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone3,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data3_json = jsonutils.dumps(availability_zone_data3)
@@ -329,7 +347,7 @@
availability_zone_profile_name = data_utils.rand_name(
"lb_admin_availabilityzoneprofile1-show")
availability_zone_data = {
- const.COMPUTE_ZONE: 'my_compute_zone',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data_json = jsonutils.dumps(availability_zone_data)
@@ -390,11 +408,17 @@
raise self.skipException(
'Availability zone profiles are only available on '
'Octavia API version 2.14 or newer.')
+ if (CONF.load_balancer.availability_zone2 is None and
+ not CONF.load_balancer.test_with_noop):
+ raise self.skipException(
+ 'Availability zone profile update API tests requires '
+ '[load_balancer] availability_zone2 to be defined in the '
+ 'tempest configuration file.')
availability_zone_profile_name = data_utils.rand_name(
"lb_admin_availabilityzoneprofile1-update")
availability_zone_data = {
- const.COMPUTE_ZONE: 'my_compute_zone1',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data_json = jsonutils.dumps(availability_zone_data)
@@ -427,7 +451,7 @@
availability_zone_profile_name2 = data_utils.rand_name(
"lb_admin_availabilityzoneprofile1-update2")
availability_zone_data2 = {
- const.COMPUTE_ZONE: 'my_compute_zone2',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone2,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data2_json = jsonutils.dumps(availability_zone_data2)
@@ -495,7 +519,7 @@
availability_zone_profile_name = data_utils.rand_name(
"lb_admin_availabilityzoneprofile1-delete")
availability_zone_data = {
- const.COMPUTE_ZONE: 'my_compute_zone',
+ const.COMPUTE_ZONE: CONF.load_balancer.availability_zone,
const.MANAGEMENT_NETWORK: uuidutils.generate_uuid(),
}
availability_zone_data_json = jsonutils.dumps(availability_zone_data)
diff --git a/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py b/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py
index 0d49d67..83049c7 100644
--- a/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py
+++ b/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py
@@ -198,6 +198,7 @@
protocol_port=protocol_port,
protocol=protocol)
+ @decorators.attr(type=['smoke', 'slow'])
@testtools.skipIf(CONF.load_balancer.test_with_noop,
'Traffic tests will not work in noop mode.')
@decorators.idempotent_id('6751135d-e15a-4e22-89f4-bfcc3408d424')
diff --git a/releasenotes/notes/skip-az-api-tests-if-azs-not-configured-c5d06cdcf29beeb5.yaml b/releasenotes/notes/skip-az-api-tests-if-azs-not-configured-c5d06cdcf29beeb5.yaml
new file mode 100644
index 0000000..84b1480
--- /dev/null
+++ b/releasenotes/notes/skip-az-api-tests-if-azs-not-configured-c5d06cdcf29beeb5.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Fixed availability zone API tests to skip if the required availability
+ zones are not defined in the tempest configuration file and the test run
+ is not using no-op drivers.
diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml
index d5fe9d2..2f94ada 100644
--- a/zuul.d/jobs.yaml
+++ b/zuul.d/jobs.yaml
@@ -1,10 +1,40 @@
- nodeset:
+ name: octavia-single-node-ubuntu-bionic
+ nodes:
+ - name: controller
+ label: nested-virt-ubuntu-bionic
+ groups:
+ - name: tempest
+ nodes:
+ - controller
+
+- nodeset:
+ name: octavia-single-node-centos-7
+ nodes:
+ - name: controller
+ label: nested-virt-centos-7
+ groups:
+ - name: tempest
+ nodes:
+ - controller
+
+- nodeset:
+ name: octavia-single-node-centos-8
+ nodes:
+ - name: controller
+ label: nested-virt-centos-8
+ groups:
+ - name: tempest
+ nodes:
+ - controller
+
+- nodeset:
name: octavia-two-node
nodes:
- name: controller
- label: ubuntu-bionic
+ label: nested-virt-ubuntu-bionic
- name: controller2
- label: ubuntu-bionic
+ label: nested-virt-ubuntu-bionic
groups:
- name: controller
nodes:
@@ -142,6 +172,7 @@
- job:
name: octavia-dsvm-live-base
parent: octavia-dsvm-base
+ nodeset: octavia-single-node-ubuntu-bionic
timeout: 9000
required-projects:
- openstack/diskimage-builder
@@ -176,6 +207,7 @@
- job:
name: octavia-dsvm-live-base-ipv6-only
parent: octavia-dsvm-base-ipv6-only
+ nodeset: octavia-single-node-ubuntu-bionic
timeout: 9000
required-projects:
- openstack/diskimage-builder
@@ -309,6 +341,7 @@
g-api: true
g-reg: true
key: true
+ memory_tracker: false
mysql: true
n-api: true
n-api-meta: true
@@ -324,7 +357,6 @@
o-cw: true
o-hm: true
o-hk: true
- peakmem_tracker: true
placement-api: true
q-agt: true
q-dhcp: true
@@ -365,12 +397,18 @@
"$TEMPEST_CONFIG":
load_balancer:
test_with_noop: True
+ # AZ API tests with no-op need AZs configured but they do not
+ # need to actually exist in Nova due to the no-op driver.
+ availability_zone: bogus-az-1
+ availability_zone2: bogus-az-2
+ availability_zone3: bogus-az-3
post-config:
$OCTAVIA_CONF:
controller_worker:
amphora_driver: amphora_noop_driver
compute_driver: compute_noop_driver
network_driver: network_noop_driver
+ image_driver: image_noop_driver
certificates:
cert_manager: local_cert_manager
devstack_services:
@@ -540,7 +578,7 @@
- job:
name: octavia-v2-dsvm-py2-scenario-centos-7
parent: octavia-v2-dsvm-py2-scenario
- nodeset: devstack-single-node-centos-7
+ nodeset: octavia-single-node-centos-7
vars:
devstack_localrc:
OCTAVIA_AMP_BASE_OS: centos
@@ -550,6 +588,7 @@
- job:
name: octavia-v2-dsvm-scenario-centos-8
parent: octavia-v2-dsvm-scenario
+ nodeset: octavia-single-node-centos-8
vars:
devstack_localrc:
OCTAVIA_AMP_BASE_OS: centos
@@ -620,11 +659,13 @@
- job:
name: octavia-v2-dsvm-tls-barbican-stable-rocky
parent: octavia-v2-dsvm-tls-barbican
+ nodeset: openstack-single-node-xenial
override-checkout: stable/rocky
- job:
name: octavia-v2-dsvm-tls-barbican-stable-queens
parent: octavia-v2-dsvm-tls-barbican
+ nodeset: openstack-single-node-xenial
override-checkout: stable/queens
- job:
@@ -727,6 +768,7 @@
- job:
name: octavia-v2-dsvm-scenario-centos-7
parent: octavia-v2-dsvm-py2-scenario-centos-7
+ nodeset: octavia-single-node-centos-7
- job:
name: octavia-v2-act-stdby-iptables-dsvm-scenario
@@ -768,7 +810,7 @@
- job:
name: octavia-v2-act-stdby-iptables-dsvm-py2-scenario-centos-7
parent: octavia-v2-act-stdby-iptables-dsvm-py2-scenario
- nodeset: devstack-single-node-centos-7
+ nodeset: octavia-single-node-centos-7
vars:
devstack_localrc:
USE_PYTHON3: False