aboutsummaryrefslogtreecommitdiffstats
path: root/functest
diff options
context:
space:
mode:
Diffstat (limited to 'functest')
-rw-r--r--functest/ci/add_proxy.sh138
-rw-r--r--functest/ci/check_deployment.py188
-rw-r--r--functest/ci/config_aarch64_patch.yaml281
-rw-r--r--functest/ci/config_functest.yaml75
-rw-r--r--functest/ci/config_patch.yaml553
-rw-r--r--functest/ci/convert_images.sh13
-rw-r--r--functest/ci/download_images.sh24
-rw-r--r--functest/ci/logging.debug.ini110
-rw-r--r--functest/ci/logging.ini30
-rw-r--r--functest/ci/rally_aarch64_patch.conf2
-rw-r--r--functest/ci/testcases.yaml939
-rw-r--r--functest/core/cloudify.py164
-rw-r--r--functest/core/singlevm.py272
-rw-r--r--functest/core/tenantnetwork.py149
-rw-r--r--functest/core/vnf.py187
-rw-r--r--functest/opnfv_tests/openstack/api/connection_check.py33
-rw-r--r--functest/opnfv_tests/openstack/barbican/__init__.py (renamed from functest/ci/__init__.py)0
-rw-r--r--functest/opnfv_tests/openstack/barbican/barbican.py37
-rw-r--r--functest/opnfv_tests/openstack/cinder/cinder_test.py35
-rw-r--r--functest/opnfv_tests/openstack/cinder/write_data.sh2
-rw-r--r--functest/opnfv_tests/openstack/patrole/patrole.py22
-rw-r--r--functest/opnfv_tests/openstack/rally/blacklist.txt28
-rw-r--r--functest/opnfv_tests/openstack/rally/blacklist.yaml40
-rw-r--r--functest/opnfv_tests/openstack/rally/macro/macro.yaml6
-rw-r--r--functest/opnfv_tests/openstack/rally/rally.py672
-rw-r--r--functest/opnfv_tests/openstack/rally/rally_jobs.yaml3
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml71
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml5
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml22
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml82
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/opnfv-barbican.yaml98
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml15
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/opnfv-swift.yaml71
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/opnfv-vm.yaml41
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-cinder.yaml20
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml5
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-neutron.yaml12
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml48
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/support/instance_dd_test.sh13
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template2
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template2
-rw-r--r--functest/opnfv_tests/openstack/rally/task.yaml10
-rw-r--r--functest/opnfv_tests/openstack/refstack/refstack.py65
-rw-r--r--functest/opnfv_tests/openstack/shaker/shaker.py95
-rw-r--r--functest/opnfv_tests/openstack/snaps/api_check.py50
-rw-r--r--functest/opnfv_tests/openstack/snaps/health_check.py49
-rw-r--r--functest/opnfv_tests/openstack/snaps/smoke.py48
-rw-r--r--functest/opnfv_tests/openstack/snaps/snaps_suite_builder.py451
-rw-r--r--functest/opnfv_tests/openstack/snaps/snaps_test_runner.py53
-rw-r--r--functest/opnfv_tests/openstack/snaps/snaps_utils.py62
-rw-r--r--functest/opnfv_tests/openstack/tempest/conf_utils.py261
-rw-r--r--functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt2
-rw-r--r--functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml19
-rw-r--r--functest/opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml15
-rw-r--r--functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml117
-rw-r--r--functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf_ovn.yaml104
-rw-r--r--functest/opnfv_tests/openstack/tempest/tempest.py652
-rw-r--r--functest/opnfv_tests/openstack/vmtp/vmtp.py117
-rw-r--r--functest/opnfv_tests/openstack/vping/vping_ssh.py18
-rw-r--r--functest/opnfv_tests/openstack/vping/vping_userdata.py34
-rw-r--r--functest/opnfv_tests/sdn/odl/odl.py31
-rw-r--r--functest/opnfv_tests/vnf/epc/juju_epc.py704
-rw-r--r--functest/opnfv_tests/vnf/ims/clearwater.py190
-rw-r--r--functest/opnfv_tests/vnf/ims/clearwater_ims_base.py183
-rw-r--r--functest/opnfv_tests/vnf/ims/cloudify_ims.py579
-rw-r--r--functest/opnfv_tests/vnf/ims/cloudify_ims.yaml29
-rw-r--r--functest/opnfv_tests/vnf/ims/heat_ims.py253
-rw-r--r--functest/opnfv_tests/vnf/ims/heat_ims.yaml22
-rw-r--r--functest/opnfv_tests/vnf/router/cloudify_vrouter.py440
-rw-r--r--functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml3
-rw-r--r--functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py20
-rw-r--r--functest/opnfv_tests/vnf/router/utilvnf.py129
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/checker.py2
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py2
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py8
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py28
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py24
-rw-r--r--functest/opnfv_tests/vnf/router/vrouter_base.py34
-rw-r--r--functest/tests/unit/ci/__init__.py0
-rw-r--r--functest/tests/unit/ci/test_check_deployment.py286
-rw-r--r--functest/tests/unit/core/test_vnf.py196
-rw-r--r--functest/tests/unit/odl/test_odl.py139
-rw-r--r--functest/tests/unit/openstack/cinder/__init__.py (renamed from functest/opnfv_tests/openstack/snaps/__init__.py)0
-rw-r--r--functest/tests/unit/openstack/cinder/test_cinder.py270
-rw-r--r--functest/tests/unit/openstack/rally/test_rally.py268
-rw-r--r--functest/tests/unit/openstack/snaps/__init__.py0
-rw-r--r--functest/tests/unit/openstack/snaps/test_snaps.py233
-rw-r--r--functest/tests/unit/openstack/tempest/test_conf_utils.py197
-rw-r--r--functest/tests/unit/openstack/tempest/test_tempest.py221
-rw-r--r--functest/tests/unit/openstack/vmtp/test_vmtp.py12
-rw-r--r--functest/tests/unit/openstack/vping/test_vping_ssh.py34
-rw-r--r--functest/tests/unit/utils/test_functest_utils.py337
-rw-r--r--functest/tests/unit/vnf/epc/test_juju_epc.py1
-rw-r--r--functest/tests/unit/vnf/ims/test_clearwater.py (renamed from functest/tests/unit/vnf/ims/test_ims_base.py)8
-rw-r--r--functest/tests/unit/vnf/ims/test_cloudify_ims.py49
-rw-r--r--functest/tests/unit/vnf/router/test_cloudify_vrouter.py53
-rw-r--r--functest/tests/unit/vnf/router/test_vrouter_base.py10
-rw-r--r--functest/utils/config.py16
-rw-r--r--functest/utils/env.py17
-rw-r--r--functest/utils/functest_utils.py189
100 files changed, 6252 insertions, 5697 deletions
diff --git a/functest/ci/add_proxy.sh b/functest/ci/add_proxy.sh
new file mode 100644
index 000000000..9d7db22e4
--- /dev/null
+++ b/functest/ci/add_proxy.sh
@@ -0,0 +1,138 @@
+#!/bin/sh
+
+set -e
+
+initdir=$(pwd)
+cd "${1:-/home/opnfv/functest/images}"
+
+http_proxy_host=${http_proxy_host:-proxy}
+http_proxy_port=${http_proxy_port:-8080}
+
+http_proxy=http://${http_proxy_host}:${http_proxy_port}
+https_proxy=${https_proxy:-${http_proxy:-http://proxy:8080}}
+ftp_proxy=${ftp_proxy:-${http_proxy:-http://proxy:8080}}
+no_proxy=${no_proxy:-"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"}
+
+images=${images-"\
+ubuntu-14.04-server-cloudimg-amd64-disk1.img \
+ubuntu-16.04-server-cloudimg-amd64-disk1.img"}
+
+add_proxy () {
+ cat << EOF >> "$1"
+http_proxy=${http_proxy}
+HTTP_PROXY=${http_proxy}
+https_proxy=${https_proxy}
+HTTPS_PROXY=${https_proxy}
+ftp_proxy=${ftp_proxy}
+FTP_PROXY=${ftp_proxy}
+no_proxy=${no_proxy}
+NO_PROXY=${no_proxy}
+EOF
+}
+
+add_proxy_apt () {
+ cat << EOF >> "$1"
+Acquire::http::Proxy "${http_proxy}";
+Acquire::https::Proxy "${https_proxy}";
+EOF
+}
+
+add_proxy_juju_env () {
+ cat << EOF >> "$1"
+export no_proxy="${no_proxy}";
+export NO_PROXY="${no_proxy}";
+EOF
+}
+
+add_proxy_juju_systemd () {
+ cat << EOF >> "$1"
+[Manager]
+DefaultEnvironment="no_proxy='${no_proxy}'" "NO_PROXY='${no_proxy}'"
+EOF
+}
+
+add_proxy_maven () {
+ cat << EOF >> "$1"
+<settings>
+ <proxies>
+ <proxy>
+ <id>example-proxy</id>
+ <active>true</active>
+ <protocol>http</protocol>
+ <host>"${http_proxy_host}"</host>
+ <port>"${http_proxy_port}"</port>
+ </proxy>
+ </proxies>
+</settings>
+EOF
+}
+
+add_proxy_svn () {
+ cat << EOF >> "$1"
+[global]
+http-proxy-host = "${http_proxy_host}"
+http-proxy-port = "${http_proxy_port}"
+EOF
+}
+
+add_proxy_pip () {
+ cat << EOF >> "$1"
+[global]
+proxy="${http_proxy}"
+EOF
+}
+
+tmpdir=$(mktemp -d)
+for image in $images; do
+ if [ ! -f "$image" ]; then
+ echo "skip ${image} ($(pwd)/${image} not found)"
+ continue
+ fi
+ guestmount -a "${image}" -i --rw "${tmpdir}"
+ add_proxy "${tmpdir}/etc/environment"
+ if expr "$image" : 'ubuntu' ; then
+ add_proxy_apt "${tmpdir}/etc/apt/apt.conf"
+ add_proxy_juju_env "${tmpdir}/etc/juju-proxy.conf"
+ add_proxy_juju_systemd "${tmpdir}/etc/juju-proxy-systemd.conf"
+ mkdir -p ${tmpdir}/root/.m2
+ mkdir -p ${tmpdir}/root/.subversion
+ add_proxy_maven "${tmpdir}/root/.m2/settings.xml"
+ add_proxy_svn "${tmpdir}/root/.subversion/servers"
+ add_proxy_pip "${tmpdir}/etc/pip.conf"
+ fi
+ guestunmount "${tmpdir}"
+done
+
+if [ -f cloudify-docker-manager-community-19.01.24.tar ]; then
+ sudo docker load -i cloudify-docker-manager-community-19.01.24.tar
+ dockerfile=${tmpdir}/Dockerfile
+ cat << EOF > $dockerfile
+FROM docker-cfy-manager:latest
+ENV HTTP_PROXY "${http_proxy}"
+ENV HTTPS_PROXY "${https_proxy}"
+ENV NO_PROXY "${no_proxy}"
+EOF
+ for f in /etc/sysconfig/cloudify-mgmtworker /etc/sysconfig/cloudify-restservice; do \
+ cat << EOF >> $dockerfile
+RUN echo >> $f
+RUN echo "http_proxy=${http_proxy}" >> $f
+RUN echo "https_proxy=${https_proxy}" >> $f
+RUN echo "HTTP_PROXY=${http_proxy}" >> $f
+RUN echo "HTTPS_PROXY=${https_proxy}" >> $f
+RUN echo "no_proxy=${no_proxy}" >> $f
+EOF
+ done
+ sudo docker build -t docker-cfy-manager -f $dockerfile ${tmpdir}
+ sudo docker save \
+ docker-cfy-manager > cloudify-docker-manager-community-19.01.24.tar
+ sudo docker rmi docker-cfy-manager
+
+ rm "${dockerfile}"
+else
+ echo "skip cloudify-docker-manager-community-19.01.24.tar \
+ ($(pwd)/cloudify-docker-manager-community-19.01.24.tar not found)"
+fi
+
+rmdir "${tmpdir}"
+cd initdir
+
diff --git a/functest/ci/check_deployment.py b/functest/ci/check_deployment.py
deleted file mode 100644
index a475491a1..000000000
--- a/functest/ci/check_deployment.py
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Ericsson and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-OpenStack deployment checker
-
-Verifies that:
- - Credentials file is given and contains the right information
- - OpenStack endpoints are reachable
-"""
-
-import logging
-import logging.config
-import os
-import socket
-
-import pkg_resources
-from six.moves import urllib
-from snaps.openstack.tests import openstack_tests
-from snaps.openstack.utils import glance_utils
-from snaps.openstack.utils import keystone_utils
-from snaps.openstack.utils import neutron_utils
-from snaps.openstack.utils import nova_utils
-
-from functest.utils import constants
-from functest.opnfv_tests.openstack.snaps import snaps_utils
-
-__author__ = "Jose Lausuch <jose.lausuch@ericsson.com>"
-
-LOGGER = logging.getLogger(__name__)
-
-
-def verify_connectivity(endpoint):
- """ Returns true if an hostname/port is reachable"""
- try:
- connection = socket.socket()
- connection.settimeout(10)
- url = urllib.parse.urlparse(endpoint)
- port = url.port
- if not port:
- port = 443 if url.scheme == "https" else 80
- connection.connect((url.hostname, port))
- LOGGER.debug('%s:%s is reachable!', url.hostname, port)
- return True
- except socket.error:
- LOGGER.error('%s:%s is not reachable.', url.hostname, port)
- except Exception: # pylint: disable=broad-except
- LOGGER.exception(
- 'Errors when verifying connectivity to %s:%s', url.hostname, port)
- return False
-
-
-def get_auth_token(os_creds):
- """ Get auth token """
- sess = keystone_utils.keystone_session(os_creds)
- try:
- return sess.get_token()
- except Exception as error:
- LOGGER.error("Got token ...FAILED")
- raise error
-
-
-class CheckDeployment(object):
- """ Check deployment class."""
-
- def __init__(self, rc_file=constants.ENV_FILE):
- self.rc_file = rc_file
- self.services = ('compute', 'network', 'image')
- self.os_creds = None
-
- def check_rc(self):
- """ Check if RC file exists and contains OS_AUTH_URL """
- if not os.path.isfile(self.rc_file):
- raise IOError('RC file {} does not exist!'.format(self.rc_file))
- if 'OS_AUTH_URL' not in open(self.rc_file).read():
- raise SyntaxError('OS_AUTH_URL not defined in {}.'.
- format(self.rc_file))
-
- def check_auth_endpoint(self):
- """ Verifies connectivity to the OS_AUTH_URL given in the RC file
- and get auth token"""
- rc_endpoint = self.os_creds.auth_url
- if not verify_connectivity(rc_endpoint):
- raise Exception("OS_AUTH_URL {} is not reachable.".
- format(rc_endpoint))
- LOGGER.info("Connectivity to OS_AUTH_URL %s ...OK", rc_endpoint)
- if get_auth_token(self.os_creds):
- LOGGER.info("Got token ...OK")
-
- def check_public_endpoint(self):
- """ Gets the public endpoint and verifies connectivity to it """
- public_endpoint = keystone_utils.get_endpoint(self.os_creds,
- 'identity',
- interface='public')
- if not verify_connectivity(public_endpoint):
- raise Exception("Public endpoint {} is not reachable.".
- format(public_endpoint))
- LOGGER.info("Connectivity to the public endpoint %s ...OK",
- public_endpoint)
-
- def check_service_endpoint(self, service):
- """ Verifies connectivity to a given openstack service """
- endpoint = keystone_utils.get_endpoint(self.os_creds,
- service,
- interface='public')
- if not verify_connectivity(endpoint):
- raise Exception("{} endpoint {} is not reachable.".
- format(service, endpoint))
- LOGGER.info("Connectivity to endpoint '%s' %s ...OK",
- service, endpoint)
-
- def check_nova(self):
- """ checks that a simple nova operation works """
- try:
- client = nova_utils.nova_client(self.os_creds)
- client.servers.list()
- LOGGER.info("Nova service ...OK")
- except Exception as error:
- LOGGER.error("Nova service ...FAILED")
- raise error
-
- def check_neutron(self):
- """ checks that a simple neutron operation works """
- try:
- client = neutron_utils.neutron_client(self.os_creds)
- client.list_networks()
- LOGGER.info("Neutron service ...OK")
- except Exception as error:
- LOGGER.error("Neutron service ...FAILED")
- raise error
-
- def check_glance(self):
- """ checks that a simple glance operation works """
- try:
- client = glance_utils.glance_client(self.os_creds)
- client.images.list()
- LOGGER.info("Glance service ...OK")
- except Exception as error:
- LOGGER.error("Glance service ...FAILED")
- raise error
-
- def check_ext_net(self):
- """ checks if external network exists """
- ext_net = snaps_utils.get_ext_net_name(self.os_creds)
- if ext_net:
- LOGGER.info("External network found: %s", ext_net)
- else:
- raise Exception("ERROR: No external networks in the deployment.")
-
- def check_all(self):
- """
- Calls all the class functions and returns 0 if all of them succeed.
- This is the method called by CLI
- """
- self.check_rc()
- try:
- self.os_creds = openstack_tests.get_credentials(
- os_env_file=self.rc_file,
- proxy_settings_str=None,
- ssh_proxy_cmd=None)
- except:
- raise Exception("Problem while getting credentials object.")
- if self.os_creds is None:
- raise Exception("Credentials is None.")
- self.check_auth_endpoint()
- self.check_public_endpoint()
- for service in self.services:
- self.check_service_endpoint(service)
- self.check_nova()
- self.check_neutron()
- self.check_glance()
- self.check_ext_net()
- return 0
-
-
-def main():
- """Entry point"""
- logging.config.fileConfig(pkg_resources.resource_filename(
- 'functest', 'ci/logging.ini'))
- logging.captureWarnings(True)
- deployment = CheckDeployment()
- return deployment.check_all()
diff --git a/functest/ci/config_aarch64_patch.yaml b/functest/ci/config_aarch64_patch.yaml
index 00020af6a..278265620 100644
--- a/functest/ci/config_aarch64_patch.yaml
+++ b/functest/ci/config_aarch64_patch.yaml
@@ -1,204 +1,99 @@
---
os:
- general:
- openstack:
- image_name: TestVM
- image_file_name: cirros-0.4.0-aarch64-disk.img
- image_password: gocubsgo
- image_url:
- /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- short_id: 'ubuntu16.04'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
vmready1:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
vmready2:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
singlevm1:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
singlevm2:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
vping_ssh:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
vping_userdata:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
cinder_test:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- functest_smoke_serial:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- refstack_defcore:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- patrole:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- vmtp:
- image:
- /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-arm64-uefi1.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- shaker:
- image: /home/opnfv/functest/images/shaker-image-arm64.qcow2
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- neutron_trunk:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- barbican:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- tempest_full_parallel:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_smoke:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_horizon:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_neutron:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_cinder:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_keystone:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_heat:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt:
+ /home/opnfv/functest/images/Fedora-Cloud-Base-30-1.2.aarch64.qcow2
+ tempest_telemetry:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
rally_sanity:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ refstack_compute:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ refstack_object:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ refstack_platform:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_full:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_scenario:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_slow:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ patrole:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_barbican:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_octavia:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_neutron_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_cinder_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_keystone_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_heat_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt:
+ /home/opnfv/functest/images/Fedora-Cloud-Base-30-1.2.aarch64.qcow2
+ rally_sanity_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_full_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_scenario_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ tempest_slow_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
rally_full:
- image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
-
- snaps:
- images:
- glance_tests:
- disk_file:
- /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- short_id: 'ubuntu16.04'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
- cirros:
- disk_file:
- /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img
- extra_properties:
- hw_firmware_type: 'uefi'
- short_id: 'ubuntu16.04'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
- ubuntu:
- disk_file:
- /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-arm64-uefi1.img
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
- hw_disk_bus: 'scsi'
- hw_scsi_model: 'virtio-scsi'
- centos:
- disk_file:
- /home/opnfv/functest/images/CentOS-7-aarch64-GenericCloud.qcow2
- extra_properties:
- hw_firmware_type: 'uefi'
- hw_video_model: 'vga'
-
- vping:
- image_name: TestVM
-
- tempest:
- use_custom_flavors: 'True'
-
- odl_sfc:
- image_base_url: "http://artifacts.opnfv.org/sfc/demo"
- image_name: sfc_nsh_danube
- image_file_name: sf_nsh_danube_arm64.img
- image_initrd: sf_nsh_danube_arm64-initrd
- image_kernel: sf_nsh_danube_arm64-kernel
- image_format: ami
- os_cmd_line: 'root=LABEL=cloudimg-rootfs ro'
- doctor:
- image_name: TestVM
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ rally_jobs:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ rally_full_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
+ rally_jobs_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img
diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml
index 5aa02be68..647301ab4 100644
--- a/functest/ci/config_functest.yaml
+++ b/functest/ci/config_functest.yaml
@@ -11,16 +11,17 @@ general:
functest_conf: /home/opnfv/functest/conf
functest_data: /home/opnfv/functest/data
ims_data: /home/opnfv/functest/data/ims/
+ rally_data: /home/opnfv/functest/data/rally
refstack_data: /home/opnfv/functest/data/refstack
- router_data: /home/opnfv/functest/data/router/
+ router_data: /home/opnfv/functest/data/router/opnfv-vnf-data
functest_images: /home/opnfv/functest/images
rally_inst: /root/.rally
openstack:
- image_name: Cirros-0.4.0
- image_name_alt: Cirros-0.4.0-1
- image_file_name: cirros-0.4.0-x86_64-disk.img
- image_url: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img
+ image_name: Cirros-0.5.1
+ image_name_alt: Cirros-0.5.1-1
+ image_file_name: cirros-0.5.1-x86_64-disk.img
+ image_url: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.img
image_user: cirros
image_disk_format: qcow2
image_username: cirros
@@ -41,47 +42,6 @@ general:
neutron_private_subnet_gateway: 192.168.120.254
neutron_router_name: functest-router
-snaps:
- use_keystone: 'True'
- use_floating_ips: 'True'
- flavor_extra_specs: {}
- images:
- glance_tests:
- disk_file: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img
- cirros:
- disk_file: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img
- ubuntu:
- disk_file:
- /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.img
- centos:
- disk_file:
- /home/opnfv/functest/images/CentOS-7-x86_64-GenericCloud.qcow2
-# netconf_override:
-# network_type: vlan
-# physical_network: physnet2
-# segmentation_id: 2366
-
-# All of these values are optional and will override the values retrieved
-# by the RC file
-# os_creds_override:
-# username: {user}
-# password: {password}
-# auth_url: {auth_url}
-# project_name: {project_name}
-# identity_api_version: {2|3}
-# network_api_version: {2}
-# compute_api_version: {2}
-# image_api_version: {1|2}
-# user_domain_id: {user_domain_id}
-# project_domain_id: {projects_domain_id}
-# interface: {interface}
-# cacert: {True|False}
-# proxy_settings:
-# host: {proxy_host}
-# port: {proxy_port}
-# ssh_proxy_cmd: {OpenSSH -o ProxyCommand value}
-
-
vping:
ping_timeout: 200
vm_flavor: m1.tiny # adapt to your environment
@@ -131,26 +91,9 @@ odl_sfc:
tempest:
verifier_name: opnfv-tempest
- identity:
- tenant_name: tempest
- tenant_description: Tenant for Tempest test suite
- user_name: tempest
- user_password: Tempest123!
- validation:
- ssh_timeout: 130
- object_storage:
- operator_role: SwiftOperator
- # network_type: vlan
- # physical_network: physnet2
- # segmentation_id: 2366
- private_net_name: tempest-net
- private_subnet_name: tempest-subnet
- private_subnet_cidr: 192.168.150.0/24
- router_name: tempest-router
rally:
deployment_name: opnfv-rally
- network_name: rally-net
vnf:
juju_epc:
@@ -165,10 +108,8 @@ vnf:
tenant_name: cloudify_ims
tenant_description: vIMS
config: cloudify_ims.yaml
- cloudify_ims_perf:
- tenant_name: cloudify_ims_perf
- tenant_description: vIMS
- config: cloudify_ims_perf.yaml
+ heat_ims:
+ config: heat_ims.yaml
orchestra_openims:
tenant_name: orchestra_openims
tenant_description: OpenIMS deployed with Open Baton
diff --git a/functest/ci/config_patch.yaml b/functest/ci/config_patch.yaml
index c2bfe33e7..d5335c3ab 100644
--- a/functest/ci/config_patch.yaml
+++ b/functest/ci/config_patch.yaml
@@ -1,161 +1,504 @@
---
-lxd:
- general:
- openstack:
- image_name: Cirros-0.4.0
- image_file_name: cirros-0.4.0-x86_64-lxc.tar.gz
- image_disk_format: raw
+gsma:
+ tempest_smoke:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_horizon:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_neutron:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_cinder:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_keystone:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_heat:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_telemetry:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ rally_sanity:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ refstack_compute:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ refstack_object:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ refstack_platform:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_full:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_scenario:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_slow:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ patrole:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_barbican:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_octavia:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_neutron_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_cinder_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_keystone_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_heat_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ rally_sanity_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_full_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_scenario_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ tempest_slow_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ rally_full:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ rally_jobs:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ vmtp:
+ flavor_ram: 2048
+ flavor_vcpus: 1
+ flavor_disk: 40
+ shaker:
+ flavor_ram: 2048
+ flavor_vcpus: 1
+ flavor_disk: 40
+ rally_full_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ rally_jobs_cntt:
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ cloudify:
+ flavor_ram: 4096
+ flavor_vcpus: 2
+ flavor_disk: 40
+ cloudify_ims:
+ flavor_ram: 4096
+ flavor_vcpus: 2
+ flavor_disk: 40
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ heat_ims:
+ flavor_ram: 2048
+ flavor_vcpus: 1
+ flavor_disk: 40
+ vyos_vrouter:
+ flavor_ram: 4096
+ flavor_vcpus: 2
+ flavor_disk: 40
+ flavor_alt_ram: 2048
+ flavor_alt_vcpus: 1
+ flavor_alt_disk: 40
+ juju_epc:
+ flavor_ram: 2048
+ flavor_vcpus: 1
+ flavor_disk: 40
+ flavor_alt_ram: 4096
+ flavor_alt_vcpus: 2
+ flavor_alt_disk: 40
fdio:
- general:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- image_properties: {'hw_mem_page_size':'large'}
- openstack:
- flavor_ram: 1024
- snaps:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
vmready1:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
vmready2:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
singlevm1:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
singlevm2:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
vping_ssh:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
vping_userdata:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
cinder_test:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
- tempest_smoke_serial:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_smoke:
flavor_ram: 1024
- refstack_defcore:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_horizon:
flavor_ram: 1024
- patrole:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_neutron:
flavor_ram: 1024
- vmtp:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
- flavor_ram: 2048
- shaker:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_cinder:
flavor_ram: 1024
- neutron_trunk:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_keystone:
flavor_ram: 1024
- barbican:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_heat:
flavor_ram: 1024
- tempest_full_parallel:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_telemetry:
flavor_ram: 1024
rally_sanity:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ flavor_ram: 1024
+ refstack_compute:
+ flavor_ram: 1024
+ refstack_object:
+ flavor_ram: 1024
+ refstack_platform:
+ flavor_ram: 1024
+ tempest_full:
+ flavor_ram: 1024
+ tempest_scenario:
+ flavor_ram: 1024
+ tempest_slow:
+ flavor_ram: 1024
+ patrole:
+ flavor_ram: 1024
+ tempest_barbican:
+ flavor_ram: 1024
+ tempest_octavia:
+ flavor_ram: 1024
+ tempest_neutron_cntt:
+ flavor_ram: 1024
+ tempest_cinder_cntt:
+ flavor_ram: 1024
+ tempest_keystone_cntt:
+ flavor_ram: 1024
+ tempest_heat_cntt:
+ flavor_ram: 1024
+ rally_sanity_cntt:
+ flavor_ram: 1024
+ tempest_full_cntt:
+ flavor_ram: 1024
+ tempest_scenario_cntt:
+ flavor_ram: 1024
+ tempest_slow_cntt:
flavor_ram: 1024
rally_full:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ flavor_ram: 1024
+ rally_jobs:
+ flavor_ram: 1024
+ vmtp:
+ flavor_ram: 2048
+ shaker:
+ flavor_ram: 1024
+ rally_full_cntt:
+ flavor_ram: 1024
+ rally_jobs_cntt:
flavor_ram: 1024
ovs:
- general:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- image_properties: {'hw_mem_page_size':'large'}
- openstack:
- flavor_ram: 1024
- snaps:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
vmready1:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
vmready2:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
singlevm1:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
singlevm2:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
vping_ssh:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
vping_userdata:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
cinder_test:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
- tempest_smoke_serial:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_smoke:
+ flavor_ram: 1024
+ tempest_horizon:
flavor_ram: 1024
- refstack_defcore:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ tempest_neutron:
+ flavor_ram: 1024
+ tempest_cinder:
+ flavor_ram: 1024
+ tempest_keystone:
+ flavor_ram: 1024
+ tempest_heat:
+ flavor_ram: 1024
+ tempest_telemetry:
+ flavor_ram: 1024
+ rally_sanity:
+ flavor_ram: 1024
+ refstack_compute:
+ flavor_ram: 1024
+ refstack_object:
+ flavor_ram: 1024
+ refstack_platform:
+ flavor_ram: 1024
+ tempest_full:
+ flavor_ram: 1024
+ tempest_scenario:
+ flavor_ram: 1024
+ tempest_slow:
flavor_ram: 1024
patrole:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ flavor_ram: 1024
+ tempest_barbican:
+ flavor_ram: 1024
+ tempest_octavia:
+ flavor_ram: 1024
+ tempest_neutron_cntt:
+ flavor_ram: 1024
+ tempest_cinder_cntt:
+ flavor_ram: 1024
+ tempest_keystone_cntt:
+ flavor_ram: 1024
+ tempest_heat_cntt:
+ flavor_ram: 1024
+ rally_sanity_cntt:
+ flavor_ram: 1024
+ tempest_full_cntt:
+ flavor_ram: 1024
+ tempest_scenario_cntt:
+ flavor_ram: 1024
+ tempest_slow_cntt:
+ flavor_ram: 1024
+ rally_full:
+ flavor_ram: 1024
+ rally_jobs:
flavor_ram: 1024
vmtp:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 2048
shaker:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
flavor_ram: 1024
- neutron_trunk:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ rally_full_cntt:
flavor_ram: 1024
- barbican:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
- flavor_ram: 1024
- tempest_full_parallel:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
+ rally_jobs_cntt:
flavor_ram: 1024
+
+vio:
+ vmready1:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ vmready2:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ singlevm1:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ singlevm2:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ vping_ssh:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ vping_userdata:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ cinder_test:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ tempest_smoke:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_horizon:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_neutron:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_cinder:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_keystone:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_heat:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt:
+ /home/opnfv/functest/images/Fedora-Cloud-Base-30-1.2.x86_64.vmdk
+ image_alt_format: vmdk
+ tempest_telemetry:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
rally_sanity:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
- flavor_ram: 1024
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ refstack_compute:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ refstack_object:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ refstack_platform:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_full:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_scenario:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_slow:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ patrole:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_barbican:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_octavia:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_neutron_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_cinder_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_keystone_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_heat_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt:
+ /home/opnfv/functest/images/Fedora-Cloud-Base-30-1.2.x86_64.vmdk
+ image_alt_format: vmdk
+ rally_sanity_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ tempest_full_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_scenario_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
+ tempest_slow_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_alt_format: vmdk
rally_full:
- flavor_extra_specs: {'hw:mem_page_size':'large'}
- extra_properties: {'hw_mem_page_size':'large'}
- flavor_ram: 1024
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ rally_jobs:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ vmtp:
+ image:
+ /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.vmdk
+ image_format: vmdk
+ shaker:
+ image: /home/opnfv/functest/images/shaker-image.vmdk
+ image_format: vmdk
+ rally_full_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ rally_jobs_cntt:
+ image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk
+ image_format: vmdk
+ cloudify:
+ image:
+ /home/opnfv/functest/images/ubuntu-16.04-server-cloudimg-amd64-disk1.vmdk
+ image_format: vmdk
+ cloudify_ims:
+ image:
+ /home/opnfv/functest/images/ubuntu-16.04-server-cloudimg-amd64-disk1.vmdk
+ image_format: vmdk
+ image_alt:
+ /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.vmdk
+ image_alt_format: vmdk
+ heat_ims:
+ image:
+ /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.vmdk
+ image_format: vmdk
+ vyos_vrouter:
+ image:
+ /home/opnfv/functest/images/ubuntu-16.04-server-cloudimg-amd64-disk1.vmdk
+ image_format: vmdk
+ image_alt: /home/opnfv/functest/images/vyos-1.1.7.vmdk
+ image_alt_format: vmdk
+ juju_epc:
+ image:
+ /home/opnfv/functest/images/ubuntu-16.04-server-cloudimg-amd64-disk1.vmdk
+ image_format: vmdk
+ image_alt:
+ /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.vmdk
+ image_alt_format: vmdk
diff --git a/functest/ci/convert_images.sh b/functest/ci/convert_images.sh
new file mode 100644
index 000000000..2159d2a60
--- /dev/null
+++ b/functest/ci/convert_images.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -ex
+
+initdir=$(pwd)
+
+cd "${1:-/home/opnfv/functest/images}"
+
+for i in *.img *.qcow2; do
+ qemu-img convert -f qcow2 -O vmdk "$i" "${i%.*}.vmdk"
+done
+
+cd $initdir
diff --git a/functest/ci/download_images.sh b/functest/ci/download_images.sh
index a23d8f707..a56c02b60 100644
--- a/functest/ci/download_images.sh
+++ b/functest/ci/download_images.sh
@@ -1,23 +1,19 @@
-#!/bin/bash
+#!/bin/sh
set -ex
wget_opts="-N --tries=1 --connect-timeout=30"
+[ -t 1 ] || wget_opts="${wget_opts} --progress=dot:giga"
cat << EOF | wget ${wget_opts} -i - -P ${1:-/home/opnfv/functest/images}
-http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img
+http://download.cirros-cloud.net/0.6.1/cirros-0.6.1-x86_64-disk.img
https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloudimg-amd64-disk1.img
-https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2
https://cloud-images.ubuntu.com/releases/16.04/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img
-http://repository.cloudifysource.org/cloudify/4.0.1/sp-release/cloudify-manager-premium-4.0.1.qcow2
-http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-lxc.tar.gz
-http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-aarch64-disk.img
-https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloudimg-arm64-uefi1.img
-http://cloud.centos.org/altarch/7/images/aarch64/CentOS-7-aarch64-GenericCloud.qcow2.xz
-https://sourceforge.net/projects/ool-opnfv/files/vyos-1.1.7.img
-http://testresults.opnfv.org/functest/shaker-image.qcow2
-http://testresults.opnfv.org/functest/shaker-image-arm64.qcow2
+https://cloud-images.ubuntu.com/releases/18.04/release/ubuntu-18.04-server-cloudimg-amd64.img
+http://download.cirros-cloud.net/0.6.1/cirros-0.6.1-aarch64-disk.img
+http://repository.cloudifysource.org/cloudify/19.01.24/community-release/cloudify-docker-manager-community-19.01.24.tar
+http://testresults.opnfv.org/functest/vyos-1.1.8-amd64.qcow2
+http://testresults.opnfv.org/functest/shaker-image-1.3.4+stretch.qcow2
+https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-Base-30-1.2.x86_64.qcow2
+https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/30/Cloud/aarch64/images/Fedora-Cloud-Base-30-1.2.aarch64.qcow2
EOF
-
-xz --decompress --force --keep \
- ${1:-/home/opnfv/functest/images}/CentOS-7-aarch64-GenericCloud.qcow2.xz
diff --git a/functest/ci/logging.debug.ini b/functest/ci/logging.debug.ini
new file mode 100644
index 000000000..c926a5055
--- /dev/null
+++ b/functest/ci/logging.debug.ini
@@ -0,0 +1,110 @@
+[loggers]
+keys=root,functest,api,ci,core,cli,opnfv_tests,utils,xtesting,xci,xcore,xutils,sfc,baro,warnings
+
+[handlers]
+keys=console,wconsole,file,dfile
+
+[formatters]
+keys=standard
+
+[logger_root]
+level=NOTSET
+handlers=dfile
+
+[logger_functest]
+level=NOTSET
+handlers=file
+qualname=functest
+
+[logger_api]
+level=NOTSET
+handlers=wconsole
+qualname=functest.api
+
+[logger_ci]
+level=NOTSET
+handlers=console
+qualname=functest.ci
+
+[logger_core]
+level=NOTSET
+handlers=console
+qualname=functest.core
+
+[logger_cli]
+level=NOTSET
+handlers=wconsole
+qualname=functest.cli
+
+[logger_opnfv_tests]
+level=NOTSET
+handlers=wconsole
+qualname=functest.opnfv_tests
+
+[logger_utils]
+level=NOTSET
+handlers=wconsole
+qualname=functest.utils
+
+[logger_xtesting]
+level=NOTSET
+handlers=file
+qualname=xtesting
+
+[logger_xci]
+level=NOTSET
+handlers=console
+qualname=xtesting.ci
+
+[logger_xcore]
+level=NOTSET
+handlers=console
+qualname=xtesting.core
+
+[logger_xutils]
+level=NOTSET
+handlers=wconsole
+qualname=xtesting.utils
+
+[logger_sfc]
+level=NOTSET
+handlers=file,wconsole
+qualname=sfc
+
+[logger_baro]
+level=NOTSET
+handlers=file,wconsole
+qualname=baro_tests
+
+[logger_warnings]
+level=NOTSET
+handlers=file,console
+qualname=py.warnings
+
+[handler_console]
+class=StreamHandler
+level=INFO
+formatter=standard
+args=(sys.stdout,)
+
+[handler_wconsole]
+class=StreamHandler
+level=WARN
+formatter=standard
+args=(sys.stdout,)
+
+[handler_file]
+class=FileHandler
+level=INFO
+formatter=standard
+args=("/home/opnfv/functest/results/functest.log",)
+
+[handler_dfile]
+class=FileHandler
+level=DEBUG
+formatter=standard
+args=("/home/opnfv/functest/results/functest.debug.log",)
+
+[formatter_standard]
+format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
+datefmt=
diff --git a/functest/ci/logging.ini b/functest/ci/logging.ini
index f14014354..dde079493 100644
--- a/functest/ci/logging.ini
+++ b/functest/ci/logging.ini
@@ -1,15 +1,15 @@
[loggers]
-keys=root,functest,api,ci,core,cli,opnfv_tests,utils,xtesting,xci,xcore,energy,xutils,sfc,sdnvpn,baro,warnings
+keys=root,functest,api,ci,core,cli,opnfv_tests,utils,xtesting,xci,xcore,xutils,sfc,baro,warnings
[handlers]
-keys=console,wconsole,file,dfile
+keys=console,wconsole,file,null
[formatters]
keys=standard
[logger_root]
level=NOTSET
-handlers=dfile
+handlers=null
[logger_functest]
level=NOTSET
@@ -61,11 +61,6 @@ level=NOTSET
handlers=console
qualname=xtesting.core
-[logger_energy]
-level=NOTSET
-handlers=wconsole
-qualname=xtesting.energy
-
[logger_xutils]
level=NOTSET
handlers=wconsole
@@ -76,11 +71,6 @@ level=NOTSET
handlers=file,wconsole
qualname=sfc
-[logger_sdnvpn]
-level=NOTSET
-handlers=file,wconsole
-qualname=sdnvpn
-
[logger_baro]
level=NOTSET
handlers=file,wconsole
@@ -91,6 +81,12 @@ level=NOTSET
handlers=file,console
qualname=py.warnings
+[handler_null]
+class=NullHandler
+level=NOTSET
+formatter=standard
+args=()
+
[handler_console]
class=StreamHandler
level=INFO
@@ -105,16 +101,10 @@ args=(sys.stdout,)
[handler_file]
class=FileHandler
-level=DEBUG
+level=INFO
formatter=standard
args=("/home/opnfv/functest/results/functest.log",)
-[handler_dfile]
-class=FileHandler
-level=DEBUG
-formatter=standard
-args=("/home/opnfv/functest/results/functest.debug.log",)
-
[formatter_standard]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
diff --git a/functest/ci/rally_aarch64_patch.conf b/functest/ci/rally_aarch64_patch.conf
index baeceac76..4ea0d7605 100644
--- a/functest/ci/rally_aarch64_patch.conf
+++ b/functest/ci/rally_aarch64_patch.conf
@@ -1,5 +1,5 @@
img_name_regex = ^TestVM$
-img_url = http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-aarch64-disk.img
+img_url = http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-aarch64-disk.img
flavor_ref_ram = 256
flavor_ref_alt_ram = 256
heat_instance_type_ram = 256
diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml
index a9e023e4c..acf5a7199 100644
--- a/functest/ci/testcases.yaml
+++ b/functest/ci/testcases.yaml
@@ -2,7 +2,6 @@
tiers:
-
name: healthcheck
- order: 0
description: >-
First tier to be executed to verify the basic
operations in the VIM.
@@ -17,9 +16,7 @@ tiers:
Keystone, Glance, Neutron and Nova and may perform some
simple queries.
run:
- module:
- 'functest.opnfv_tests.openstack.api.connection_check'
- class: 'ConnectionCheck'
+ name: connection_check
-
case_name: tenantnetwork1
@@ -30,9 +27,10 @@ tiers:
It creates and configures all tenant network ressources
required by advanced testcases (subnet, network and
router).
+ dependencies:
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
run:
- module: 'functest.core.tenantnetwork'
- class: 'TenantNetwork1'
+ name: tenantnetwork1
-
case_name: tenantnetwork2
@@ -43,9 +41,10 @@ tiers:
It creates new user/project before creating and configuring
all tenant network ressources required by a testcase
(subnet, network and router).
+ dependencies:
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
run:
- module: 'functest.core.tenantnetwork'
- class: 'TenantNetwork2'
+ name: tenantnetwork2
-
case_name: vmready1
@@ -57,8 +56,7 @@ tiers:
resources and prepares a future VM attached to that
network.
run:
- module: 'functest.core.singlevm'
- class: 'VmReady1'
+ name: vmready1
-
case_name: vmready2
@@ -70,8 +68,7 @@ tiers:
all tenant network ressources, flavors, images, etc.
required by advanced testcases.
run:
- module: 'functest.core.singlevm'
- class: 'VmReady2'
+ name: vmready2
-
case_name: singlevm1
@@ -83,8 +80,7 @@ tiers:
resources and completes it by booting a VM attached to that
network.
run:
- module: 'functest.core.singlevm'
- class: 'SingleVm1'
+ name: singlevm1
-
case_name: singlevm2
@@ -96,8 +92,7 @@ tiers:
all tenant network ressources and vms required by advanced
testcases.
run:
- module: 'functest.core.singlevm'
- class: 'SingleVm2'
+ name: singlevm2
-
case_name: vping_ssh
@@ -109,8 +104,7 @@ tiers:
floating IPs over the public network. 2) Connectivity
between 2 instances over a private network.
run:
- module: 'functest.opnfv_tests.openstack.vping.vping_ssh'
- class: 'VPingSSH'
+ name: vping_ssh
-
case_name: vping_userdata
@@ -121,9 +115,7 @@ tiers:
This test case verifies: 1) Boot a VM with given userdata.
2) Connectivity between 2 instances over a private network.
run:
- module:
- 'functest.opnfv_tests.openstack.vping.vping_userdata'
- class: 'VPingUserdata'
+ name: vping_userdata
-
case_name: cinder_test
@@ -136,8 +128,7 @@ tiers:
from instance 1, attach it on instance 2 3) Read volume
data
run:
- module: 'functest.opnfv_tests.openstack.cinder.cinder_test'
- class: 'CinderCheck'
+ name: cinder_test
-
case_name: odl
@@ -151,68 +142,134 @@ tiers:
dependencies:
- DEPLOY_SCENARIO: 'odl'
run:
- module: 'functest.opnfv_tests.sdn.odl.odl'
- class: 'ODLTests'
+ name: odl
args:
suites:
- /src/odl_test/csit/suites/integration/basic
- /src/odl_test/csit/suites/openstack/neutron
-
- case_name: api_check
+ case_name: tempest_smoke
project_name: functest
criteria: 100
- blocking: true
+ blocking: false
description: >-
- This test case verifies the retrieval of OpenStack clients:
- Keystone, Glance, Neutron and Nova and may perform some
- simple queries. When the config value of
- snaps.use_keystone is True, functest must have access to
- the cloud's private network.
- dependencies:
- - DEPLOY_SCENARIO: '^((?!lxd).)*$'
+ This test case runs the smoke subset of the OpenStack
+ Tempest suite. The list of test cases is generated by
+ Tempest automatically and depends on the parameters of
+ the OpenStack deplopyment.
+ https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L114
run:
- module: 'functest.opnfv_tests.openstack.snaps.api_check'
- class: 'ApiCheck'
+ name: tempest_common
+ args:
+ mode: '(?=.*\[.*\bsmoke\b.*\])(^tempest\.api)'
+ option:
+ - '--concurrency=4'
-
- case_name: snaps_health_check
+ case_name: tempest_horizon
project_name: functest
criteria: 100
- blocking: true
+ blocking: false
description: >-
- This test case creates executes the SimpleHealthCheck
- Python test class which creates an, image, flavor, network,
- and Cirros VM instance and observes the console output to
- validate the single port obtains the correct IP address.
+ This test case runs the Tempest suite proposed by the
+ Horizon project.
dependencies:
- - DEPLOY_SCENARIO: '^((?!lxd).)*$'
+ - DASHBOARD_URL: '^(?!\s*$).+'
run:
- module: 'functest.opnfv_tests.openstack.snaps.health_check'
- class: 'HealthCheck'
+ name: tempest_common
+ args:
+ mode: '^tempest.scenario.test_dashboard_basic_ops.'
-
name: smoke
- order: 1
description: >-
Set of basic Functional tests to validate the OPNFV scenarios.
testcases:
-
- case_name: tempest_smoke
+ case_name: tempest_neutron
project_name: functest
criteria: 100
blocking: false
description: >-
- This test case runs the smoke subset of the OpenStack
- Tempest suite. The list of test cases is generated by
+ This test case runs the Tempest suite proposed by the
+ Neutron project. The list of test cases is generated by
Tempest automatically and depends on the parameters of
- the OpenStack deplopyment.
+ the OpenStack deployment.
run:
- module: 'functest.opnfv_tests.openstack.tempest.tempest'
- class: 'TempestCommon'
+ name: tempest_common
args:
- mode:
- '^(tempest|neutron_tempest_plugin)\.(api|scenario).*\[.*\bsmoke\b.*\]$'
+ mode: '^neutron_tempest_plugin\.api'
+ option:
+ - '--concurrency=4'
+
+ -
+ case_name: tempest_cinder
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ This test case runs the Tempest suite proposed by the
+ Cinder project.
+ run:
+ name: tempest_common
+ args:
+ mode: "(?!.*test_incremental_backup)\
+ (?!.*test_backup_crossproject_admin_negative)\
+ (?!.*test_backup_crossproject_user_negative)\
+ (^cinder_tempest_plugin.)"
+ option:
+ - '--concurrency=4'
+
+ -
+ case_name: tempest_keystone
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ This test case runs the Tempest suite proposed by the
+ Keystone project.
+ run:
+ name: tempest_common
+ args:
+ mode: 'keystone_tempest_plugin.'
+ option:
+ - '--concurrency=4'
+
+ -
+ case_name: tempest_heat
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ This test case runs the Tempest suite proposed by the
+ Heat project.
+ run:
+ name: tempest_heat
+ args:
+ mode: '^heat_tempest_plugin.tests'
+ option:
+ - '--concurrency=1'
+
+ -
+ case_name: tempest_telemetry
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ This test case runs the Tempest suite proposed by the
+ Telemetry project.
+ run:
+ name: tempest_common
+ args:
+ mode: "(?!.*test_autoscaling)(?!.*test_live)\
+ (^telemetry_tempest_plugin)"
+ services:
+ - aodh
+ - gnocchi
+ - panko
+ option:
+ - '--concurrency=4'
-
case_name: rally_sanity
@@ -223,110 +280,252 @@ tiers:
This test case runs a sub group of tests of the OpenStack
Rally suite in smoke mode.
run:
- module: 'functest.opnfv_tests.openstack.rally.rally'
- class: 'RallySanity'
+ name: rally_sanity
+ args:
+ optional:
+ - 'gnocchi'
+ - 'barbican'
-
- case_name: refstack_defcore
+ case_name: refstack_compute
project_name: functest
- enabled: false
criteria: 100
blocking: false
description: >-
This test case runs a sub group of tests of the OpenStack
- Defcore testcases.
+ Compute testcases.
+ dependencies:
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
run:
- module:
- 'functest.opnfv_tests.openstack.refstack.refstack'
- class: 'Refstack'
+ name: refstack
+ args:
+ target: compute
+ option:
+ - '--concurrency=4'
-
- case_name: patrole
+ case_name: refstack_object
project_name: functest
criteria: 100
blocking: false
description: >-
- Test suite from Patrole project.
+ This test case runs a sub group of tests of the OpenStack
+ Object testcases.
run:
- module: 'functest.opnfv_tests.openstack.patrole.patrole'
- class: 'Patrole'
+ name: refstack
args:
- role: 'admin'
- services:
- - 'image'
- - 'network'
- exclude:
- - 'test_networks_multiprovider_rbac'
+ target: object
+ option:
+ - '--concurrency=4'
-
- case_name: vmtp
+ case_name: refstack_platform
project_name: functest
criteria: 100
blocking: false
description: >-
- VMTP is a small python application that will automatically
- perform ping connectivity, round trip time measurement
- (latency) and TCP/UDP throughput
+ This test case runs a sub group of tests of the OpenStack
+ Platform testcases.
+ dependencies:
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
run:
- module:
- 'functest.opnfv_tests.openstack.vmtp.vmtp'
- class: 'Vmtp'
+ name: refstack
+ args:
+ target: platform
+ option:
+ - '--concurrency=4'
-
- case_name: shaker
+ case_name: tempest_full
project_name: functest
criteria: 100
blocking: false
description: >-
- Shaker wraps around popular system network testing tools
- like iperf, iperf3 and netperf (with help of flent). Shaker
- is able to deploy OpenStack instances and networks in
- different topologies.
+ The list of test cases is generated by
+ Tempest automatically and depends on the parameters of
+ the OpenStack deployment.
+ https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L83
run:
- module:
- 'functest.opnfv_tests.openstack.shaker.shaker'
- class: 'Shaker'
+ name: tempest_common
+ args:
+ mode: '(?!.*\[.*\bslow\b.*\])(^tempest\.api)'
+ option:
+ - '--concurrency=4'
-
- case_name: snaps_smoke
+ case_name: tempest_scenario
project_name: functest
criteria: 100
blocking: false
description: >-
- This test case contains tests that setup and destroy
- environments with VMs with and without Floating IPs
- with a newly created user and project. Set the config
- value snaps.use_floating_ips (True|False) to toggle
- this functionality. When the config value of
- snaps.use_keystone is True, functest must have access to
- the cloud's private network.
- dependencies:
- - DEPLOY_SCENARIO: '^((?!lxd).)*$'
+ The list of test cases is generated by
+ Tempest automatically and depends on the parameters of
+ the OpenStack deployment.
+ https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L84
run:
- module: 'functest.opnfv_tests.openstack.snaps.smoke'
- class: 'SnapsSmoke'
+ name: tempest_common
+ args:
+ mode: '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)'
+ option:
+ - '--concurrency=1'
-
- case_name: neutron_trunk
+ case_name: tempest_slow
project_name: functest
criteria: 100
blocking: false
description: >-
- This test case runs the neutron trunk subtest of the
- OpenStack Tempest suite. The list of test cases is
- generated by Tempest having as input the relevant
- testcase list file.
+ The list of test cases is generated by
+ Tempest automatically and depends on the parameters of
+ the OpenStack deployment.
+ https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L84
run:
- module: 'functest.opnfv_tests.openstack.tempest.tempest'
- class: 'TempestCommon'
+ name: tempest_common
args:
- mode: 'neutron_tempest_plugin.(api|scenario).test_trunk'
- neutron_extensions:
- - trunk
- - trunk_details
+ mode: '(?=.*\[.*\bslow\b.*\])(^tempest\.)'
+ option:
+ - '--concurrency=1'
-
- case_name: barbican
+ case_name: patrole_admin
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ Test suite from Patrole project.
+ run:
+ name: patrole
+ args:
+ roles: 'admin'
+ mode: "(?!.*test_unmanage_snapshot_rbac)\
+ (?!.*test_show_auto_allocated_topology)\
+ (?!.*test_delete_auto_allocated_topology)\
+ (?!.*test_create_network_provider_segmentation_id)\
+ (?!.*compute.test_floating_ips_rbac)\
+ (?!.*test_reset_network)\
+ (?!.*test_create_image_from_volume_backed_server)\
+ (?!.*test_network_ip_availability_rbac.NetworkIpAvailabilityExtRbacTest.test_get_network_ip_availabilities)\
+ (?!.*test_policy_bandwidth_limit_rule_rbac)\
+ (?!.*test_policy_minimum_bandwidth_rule_rbac)\
+ (?!.*test_group_type_specs)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_create_group_type)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_delete_group_type)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_update_group_type)\
+ (?!.*test_group_snapshots_rbac)\
+ (?!.*test_groups_rbac)\
+ (?!.*test_quota_classes_rbac)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_create_interface)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_delete_interface)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_show_interface)\
+ (?!.*test_user_messages_rbac)\
+ (?!.*test_volume_actions_rbac.VolumesActionsV310RbacTest)\
+ (?!.*test_volume_actions_rbac.VolumesActionsV312RbacTest)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_delete_volume_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_list_volumes_details_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_show_volume_details_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_update_volume_image_metadata)\
+ (?!.*test_volumes_backup_rbac.VolumesBackupsV318RbacTest)\
+ (?!.*test_volumes_backup_rbac.VolumesBackupsV39RbacTest)\
+ (?!.*test_volume_types_rbac)\
+ (?=.*[.*\bslow\b.*])\
+ (^patrole_tempest_plugin.tests.api.(compute|image|network|volume))"
+ option:
+ - '--concurrency=4'
+
+ -
+ case_name: patrole_member
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ Test suite from Patrole project.
+ run:
+ name: patrole
+ args:
+ roles: 'member'
+ mode: "(?!.*test_unmanage_snapshot_rbac)\
+ (?!.*test_show_auto_allocated_topology)\
+ (?!.*test_delete_auto_allocated_topology)\
+ (?!.*test_create_network_provider_segmentation_id)\
+ (?!.*compute.test_floating_ips_rbac)\
+ (?!.*test_reset_network)\
+ (?!.*test_create_image_from_volume_backed_server)\
+ (?!.*test_network_ip_availability_rbac.NetworkIpAvailabilityExtRbacTest.test_get_network_ip_availabilities)\
+ (?!.*test_policy_bandwidth_limit_rule_rbac)\
+ (?!.*test_policy_minimum_bandwidth_rule_rbac)\
+ (?!.*test_group_type_specs)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_create_group_type)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_delete_group_type)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_update_group_type)\
+ (?!.*test_group_snapshots_rbac)\
+ (?!.*test_groups_rbac)\
+ (?!.*test_quota_classes_rbac)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_create_interface)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_delete_interface)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_show_interface)\
+ (?!.*test_user_messages_rbac)\
+ (?!.*test_volume_actions_rbac.VolumesActionsV310RbacTest)\
+ (?!.*test_volume_actions_rbac.VolumesActionsV312RbacTest)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_delete_volume_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_list_volumes_details_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_show_volume_details_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_update_volume_image_metadata)\
+ (?!.*test_volumes_backup_rbac.VolumesBackupsV318RbacTest)\
+ (?!.*test_volumes_backup_rbac.VolumesBackupsV39RbacTest)\
+ (?!.*test_volume_types_rbac)\
+ (?=.*[.*\bslow\b.*])\
+ (^patrole_tempest_plugin.tests.api.(compute|image|network|volume))"
+ option:
+ - '--concurrency=4'
+
+ -
+ case_name: patrole_reader
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ Test suite from Patrole project.
+ run:
+ name: patrole
+ args:
+ roles: 'reader'
+ mode: "(?!.*test_unmanage_snapshot_rbac)\
+ (?!.*test_show_auto_allocated_topology)\
+ (?!.*test_delete_auto_allocated_topology)\
+ (?!.*test_create_network_provider_segmentation_id)\
+ (?!.*compute.test_floating_ips_rbac)\
+ (?!.*test_reset_network)\
+ (?!.*test_create_image_from_volume_backed_server)\
+ (?!.*test_network_ip_availability_rbac.NetworkIpAvailabilityExtRbacTest.test_get_network_ip_availabilities)\
+ (?!.*test_policy_bandwidth_limit_rule_rbac)\
+ (?!.*test_policy_minimum_bandwidth_rule_rbac)\
+ (?!.*test_group_type_specs)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_create_group_type)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_delete_group_type)\
+ (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_update_group_type)\
+ (?!.*test_group_snapshots_rbac)\
+ (?!.*test_groups_rbac)\
+ (?!.*test_quota_classes_rbac)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_create_interface)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_delete_interface)\
+ (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_show_interface)\
+ (?!.*test_user_messages_rbac)\
+ (?!.*test_volume_actions_rbac.VolumesActionsV310RbacTest)\
+ (?!.*test_volume_actions_rbac.VolumesActionsV312RbacTest)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_delete_volume_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_list_volumes_details_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_show_volume_details_image_metadata)\
+ (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_update_volume_image_metadata)\
+ (?!.*test_volumes_backup_rbac.VolumesBackupsV318RbacTest)\
+ (?!.*test_volumes_backup_rbac.VolumesBackupsV39RbacTest)\
+ (?!.*test_volume_types_rbac)\
+ (?=.*[.*\bslow\b.*])\
+ (^patrole_tempest_plugin.tests.api.(compute|image|network|volume))"
+ option:
+ - '--concurrency=4'
+
+ -
+ case_name: tempest_barbican
project_name: functest
criteria: 100
blocking: false
@@ -334,117 +533,378 @@ tiers:
It leverages on the tempest plugin containing tests used to
verify the functionality of a barbican installation.
run:
- module: 'functest.opnfv_tests.openstack.tempest.tempest'
- class: 'TempestCommon'
+ name: barbican
args:
- mode: 'barbican_tempest_plugin.tests.(api|scenario)'
+ mode:
+ '^barbican_tempest_plugin.((?!test_signed_image_upload_boot_failure).)*$'
services:
- barbican
+ option:
+ - '--concurrency=4'
+
+ -
+ case_name: tempest_octavia
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ It leverages on the tempest plugin containing tests used to
+ verify the functionality of an octavia installation.
+ run:
+ name: tempest_common
+ args:
+ mode: "(?!.*api.v2.test_availability_zone)\
+ (?!.*api.v2.test_availability_zone_profile)\
+ (?!.*api.v2.test_member.MemberAPITest.test_member_ipv4_create)\
+ (?!.*api.v2.test_member.MemberAPITest.test_member_ipv6_create)\
+ (^octavia_tempest_plugin.tests.(api|scenario))"
+ services:
+ - octavia
+ option:
+ - '--concurrency=2'
+
+ -
+ case_name: tempest_cyborg
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ It leverages on the tempest plugin containing tests used to
+ verify the functionality of a cyborg installation.
+ run:
+ name: tempest_common
+ args:
+ mode: '^cyborg_tempest_plugin'
+ services:
+ - cyborg
+ option:
+ - '--concurrency=4'
-
- name: features
- order: 2
+ name: smoke_cntt
description: >-
- Test suites from feature projects
- integrated in functest
+ Set of basic Functional tests to validate the OPNFV scenarios.
testcases:
-
- case_name: doctor-notification
- project_name: doctor
+ case_name: tempest_neutron_cntt
+ project_name: functest
criteria: 100
blocking: false
+ deny_skipping: true
+ tests_count: 564
description: >-
- Test suite from Doctor project.
- dependencies:
- - INSTALLER_TYPE: '(apex)|(fuel)|(daisy)'
- - DEPLOY_SCENARIO: '^((?!fdio|nofeature).)*$'
+ This test case runs the Tempest suite proposed by the
+ Neutron project. The list of test cases is generated by
+ Tempest automatically and depends on the parameters of
+ the OpenStack deployment.
run:
- module: 'xtesting.core.feature'
- class: 'BashFeature'
+ name: tempest_common
args:
- cmd: 'doctor-test'
+ mode: "(?!.*admin.test_agent_availability_zone)\
+ (?!.*admin.test_dhcp_agent_scheduler)\
+ (?!.*admin.test_l3_agent_scheduler)\
+ (?!.*admin.test_logging)\
+ (?!.*admin.test_logging_negative)\
+ (?!.*admin.test_network_segment_range)\
+ (?!.*admin.test_ports.PortTestCasesAdmin.test_regenerate_mac_address)\
+ (?!.*admin.test_ports.PortTestCasesResourceRequest)\
+ (?!.*admin.test_routers_dvr)\
+ (?!.*admin.test_routers_flavors)\
+ (?!.*admin.test_routers_ha)\
+ (?!.*test_conntrack_helper)\
+ (?!.*test_floating_ips.FloatingIPPoolTestJSON)\
+ (?!.*test_floating_ips.FloatingIPTestJSON.test_create_update_floatingip_port_details)\
+ (?!.*test_local_ip)\
+ (?!.*test_metering_extensions)\
+ (?!.*test_metering_negative)\
+ (?!.*test_networks.NetworksSearchCriteriaTest.test_list_validation_filters)\
+ (?!.*test_networks.NetworksTestAdmin.test_create_tenant_network_vxlan)\
+ (?!.*test_networks.NetworksTestJSON.test_create_update_network_dns_domain)\
+ (?!.*test_port_forwardings)\
+ (?!.*test_ports.PortsTaggingOnCreation)\
+ (?!.*test_ports.PortsTestJSON.test_create_port_with_propagate_uplink_status)\
+ (?!.*test_ports.PortsTestJSON.test_create_port_without_propagate_uplink_status)\
+ (?!.*test_ports.PortsTestJSON.test_create_update_port_with_dns_domain)\
+ (?!.*test_ports.PortsTestJSON.test_create_update_port_with_dns_name)\
+ (?!.*test_ports.PortsTestJSON.test_create_update_port_with_no_dns_name)\
+ (?!.*test_qos.QosMinimumBandwidthRuleTestJSON)\
+ (?!.*test_revisions.TestRevisions.test_update_dns_domain_bumps_revision)\
+ (?!.*test_revisions.TestRevisions.test_update_router_extra_attributes_bumps_revision)\
+ (?!.*test_router_interface_fip)\
+ (?!.*test_routers.DvrRoutersTest)\
+ (?!.*test_routers.HaRoutersTest)\
+ (?!.*test_routers.RoutersIpV6Test.test_extra_routes_atomic)\
+ (?!.*test_routers.RoutersTest.test_extra_routes_atomic)\
+ (?!.*test_routers_negative.DvrRoutersNegativeTest)\
+ (?!.*test_routers_negative.DvrRoutersNegativeTestExtended)\
+ (?!.*test_routers_negative.HaRoutersNegativeTest)\
+ (?!.*test_security_groups.RbacSharedSecurityGroupTest)\
+ (?!.*test_subnetpool_prefix_ops)\
+ (?!.*test_subnetpools.RbacSubnetPoolTest)\
+ (?!.*test_subnetpools.SubnetPoolsSearchCriteriaTest.test_list_validation_filters)\
+ (?!.*test_subnetpools_negative.SubnetPoolsNegativeTestJSON.test_tenant_create_subnetpool_associate_shared_address_scope)\
+ (?!.*test_subnets.SubnetsSearchCriteriaTest.test_list_validation_filters)\
+ (?!.*test_timestamp.TestTimeStamp.test_segment_with_timestamp)\
+ (?!.*test_trunk.TrunkTestInheritJSONBase.test_add_subport)\
+ (?!.*test_trunk.TrunkTestMtusJSON)\
+ (?!.*test_trunk_negative.TrunkTestJSON.test_create_subport_invalid_inherit_network_segmentation_type)\
+ (?!.*test_trunk_negative.TrunkTestMtusJSON)\
+ (^neutron_tempest_plugin.api)"
+ option:
+ - '--concurrency=4'
-
- case_name: bgpvpn
- project_name: sdnvpn
+ case_name: tempest_cinder_cntt
+ project_name: functest
criteria: 100
blocking: false
+ deny_skipping: true
+ tests_count: 10
description: >-
- Test suite from SDNVPN project.
- dependencies:
- - DEPLOY_SCENARIO: 'bgpvpn'
+ This test case runs the Tempest suite proposed by the
+ Cinder project.
run:
- module: 'sdnvpn.test.functest.run_sdnvpn_tests'
- class: 'SdnvpnFunctest'
+ name: tempest_common
+ args:
+ mode: "(?!.*test_incremental_backup)\
+ (?!.*test_consistencygroups)\
+ (?!.*test_backup_crossproject_admin_negative)\
+ (?!.*test_backup_crossproject_user_negative)\
+ (?!.*test_volume_encrypted.TestEncryptedCinderVolumes)\
+ (?!.*rbac)\
+ (^cinder_tempest_plugin.)"
+ option:
+ - '--concurrency=4'
-
- case_name: functest-odl-sfc
- project_name: sfc
+ case_name: tempest_keystone_cntt
+ project_name: functest
criteria: 100
blocking: false
+ deny_skipping: true
+ tests_count: 27
description: >-
- Test suite for odl-sfc to test two chains with one SF and
- one chain with two SFs
- dependencies:
- - DEPLOY_SCENARIO: 'odl.*sfc'
+ This test case runs the Tempest suite proposed by the
+ Keystone project.
run:
- module: 'sfc.tests.functest.run_sfc_tests'
- class: 'SfcFunctest'
+ name: tempest_common
+ args:
+ mode: "(?!.*api.identity.v3.test_oauth1_tokens)\
+ (?!.*rbac)\
+ (?!.*scenario.test_federated_authentication)\
+ keystone_tempest_plugin."
+ option:
+ - '--concurrency=4'
-
- case_name: barometercollectd
- project_name: barometer
+ case_name: tempest_heat_cntt
+ project_name: functest
criteria: 100
blocking: false
+ deny_skipping: true
+ tests_count: 124
description: >-
- Test suite for the Barometer project. Separate tests verify
- the proper configuration and basic functionality of all the
- collectd plugins as described in the Project Release Plan
- dependencies:
- - DEPLOY_SCENARIO: 'bar'
+ This test case runs the Tempest suite proposed by the
+ Heat project.
run:
- module: 'baro_tests.barometer'
- class: 'BarometerCollectd'
+ name: tempest_heat
+ args:
+ mode: "(?!.*functional.test_lbaasv2)\
+ (?!.*functional.test_encryption_vol_type)\
+ (?!.*functional.test_event_sinks)\
+ (?!.*functional.test_software_config.ZaqarSignalTransportTest)\
+ (?!.*functional.test_stack_events)\
+ (?!.*functional.test_waitcondition)\
+ (?!.*RemoteStackTest.test_stack_create_with_cloud_credential)\
+ (?!.*scenario.test_aodh_alarm)\
+ (?!.*tests.scenario.test_autoscaling_lb)\
+ (?!.*scenario.test_autoscaling_lbv2)\
+ (?!.*scenario.test_server_software_config)\
+ (?!.*test_volumes.VolumeBackupRestoreIntegrationTest)\
+ (?!.*scenario.test_octavia_lbaas)\
+ (?!.*scenario.test_server_cfn_init)\
+ ^heat_tempest_plugin.tests"
+ option:
+ - '--concurrency=1'
-
- case_name: fds
- project_name: fastdatastacks
+ case_name: rally_sanity_cntt
+ project_name: functest
criteria: 100
blocking: false
description: >-
- Test Suite for the OpenDaylight SDN Controller when GBP
- features are installed. It integrates some test suites from
- upstream using Robot as the test framework.
- dependencies:
- - DEPLOY_SCENARIO: 'odl.*-fdio'
+ This test case runs a sub group of tests of the OpenStack
+ Rally suite in smoke mode.
run:
- module: 'functest.opnfv_tests.sdn.odl.odl'
- class: 'ODLTests'
+ name: rally_sanity
args:
- suites:
- - /src/fds/testing/robot
+ tests:
+ - 'authenticate'
+ - 'glance'
+ - 'cinder'
+ - 'heat'
+ - 'keystone'
+ - 'neutron'
+ - 'nova'
+ - 'quotas'
+ - 'swift'
- -
- name: components
- order: 3
- description: >-
- Extensive testing of OpenStack API.
- testcases:
-
- case_name: tempest_full
+ case_name: tempest_full_cntt
project_name: functest
- criteria: 80
+ criteria: 100
blocking: false
+ deny_skipping: true
+ tests_count: 1271
description: >-
The list of test cases is generated by
Tempest automatically and depends on the parameters of
- the OpenStack deplopyment.
+ the OpenStack deployment.
+ https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L83
+ run:
+ name: tempest_common
+ args:
+ mode: "(?!.*admin.test_agents)(?!.*test_fixed_ips)\
+ (?!.*test_fixed_ips_negative)\
+ (?!.*test_auto_allocate_network)(?!.*test_floating_ips_bulk)\
+ (?!.*test_flavors_microversions.FlavorsV255TestJSON)\
+ (?!.*test_flavors_microversions.FlavorsV261TestJSON)\
+ (?!.*test_live_migration.LiveAutoBlockMigrationV225Test.test_iscsi_volume)\
+ (?!.*test_live_migration.LiveAutoBlockMigrationV225Test.test_live_block_migration)\
+ (?!.*test_live_migration.LiveAutoBlockMigrationV225Test.test_live_block_migration_paused)\
+ (?!.*test_live_migration.LiveAutoBlockMigrationV225Test.test_volume_backed_live_migration)\
+ (?!.*test_live_migration.LiveMigrationTest.test_iscsi_volume)\
+ (?!.*test_live_migration.LiveMigrationTest.test_live_block_migration)\
+ (?!.*test_live_migration.LiveMigrationTest.test_live_block_migration_paused)\
+ (?!.*test_live_migration.LiveMigrationTest.test_volume_backed_live_migration)\
+ (?!.*test_live_migration.LiveMigrationRemoteConsolesV26Test)\
+ (?!.*test_quotas.QuotasAdminTestV257)\
+ (?!.*test_servers.ServersAdminTestJSON.test_reset_network_inject_network_info)\
+ (?!.*certificates.test_certificates)\
+ (?!.*test_quotas_negative.QuotasSecurityGroupAdminNegativeTest)\
+ (?!.*test_novnc)(?!.*test_server_personality)\
+ (?!.*test_servers.ServerShowV263Test.test_show_update_rebuild_list_server)\
+ (?!.*test_servers_microversions.ServerShowV254Test)\
+ (?!.*test_servers_microversions.ServerShowV257Test)\
+ (?!.*test_servers_negative.ServersNegativeTestJSON.test_personality_file_contents_not_encoded)\
+ (?!.*servers.test_virtual_interfaces)\
+ (?!.*test_server_actions.ServerActionsTestJSON.test_change_server_password)\
+ (?!.*test_server_actions.ServerActionsTestJSON.test_get_vnc_console)\
+ (?!.*test_server_actions.ServerActionsTestJSON.test_reboot_server_soft)\
+ (?!.*test_server_rescue.ServerBootFromVolumeStableRescueTest)\
+ (?!.*test_server_rescue.ServerStableDeviceRescueTest)\
+ (?!.*test_security_group_default_rules)\
+ (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_security_group_create_with_duplicate_name)\
+ (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_security_group_create_with_invalid_group_description)\
+ (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_security_group_create_with_invalid_group_name)\
+ (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_update_security_group_with_invalid_sg_des)\
+ (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_update_security_group_with_invalid_sg_id)\
+ (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_update_security_group_with_invalid_sg_name)\
+ (?!.*test_create_server.ServersTestFqdnHostnames.test_create_server_with_fqdn_name)\
+ (?!.*test_server_metadata.ServerMetadataTestJSON)\
+ (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_delete_metadata_non_existent_server)\
+ (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_metadata_items_limit)\
+ (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_set_metadata_invalid_key)\
+ (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_set_metadata_non_existent_server)\
+ (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_set_server_metadata_blank_key)\
+ (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_set_server_metadata_missing_metadata)\
+ (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_update_metadata_non_existent_server)\
+ (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_update_metadata_with_blank_key)\
+ (?!.*test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filtered_by_ip_regex)\
+ (?!.*compute.test_virtual_interfaces)(?!.*compute.test_virtual_interfaces_negative)\
+ (?!.*compute.test_networks)\
+ (?!.*test_attach_volume.AttachVolumeMultiAttach)\
+ (?!.*identity.admin.v2)(?!.*identity.v2)\
+ (?!.*identity.v3.test_access_rules)\
+ (?!.*identity.v3.test_application_credentials.ApplicationCredentialsV3Test.test_create_application_credential_access_rules)\
+ (?!.*image.v1)\
+ (?!.*image.v2.admin.test_images.ImportCopyImagesTest)\
+ (?!.*image.v2.test_images_negative.ImagesNegativeTest.test_create_image_reserved_property)\
+ (?!.*image.v2.test_images_negative.ImagesNegativeTest.test_update_image_reserved_property)\
+ (?!.*image.v2.test_images_negative.ImportImagesNegativeTest.test_image_web_download_import_with_bad_url)\
+ (?!.*image.v2.test_images.ImportImagesTest)\
+ (?!.*image.v2.test_images.MultiStoresImportImages)\
+ (?!.*admin.test_dhcp_agent_scheduler)\
+ (?!.*admin.test_routers_dvr)\
+ (?!.*test_metering_extensions)(?!.*network.test_tags)\
+ (?!.*test_routers_negative.DvrRoutersNegativeTest)\
+ (?!.*test_routers.RoutersIpV6Test.test_create_router_set_gateway_with_fixed_ip)\
+ (?!.*test_routers.RoutersTest.test_create_router_set_gateway_with_fixed_ip)\
+ (?!.*test_object_services.ObjectTest.test_create_object_with_transfer_encoding)\
+ (?!.*test_encrypted_volumes_extend)\
+ (?!.*test_group_snapshots.GroupSnapshotsV319Test.test_reset_group_snapshot_status)\
+ (?!.*test_multi_backend)\
+ (?!.*test_volume_retype.VolumeRetypeWithMigrationTest)\
+ (?!.*test_volume_delete_cascade.VolumesDeleteCascade.test_volume_from_snapshot_cascade_delete)\
+ (?!.*test_volumes_backup.VolumesBackupsTest.test_volume_backup_create_get_detailed_list_restore_delete)\
+ (?!.*test_volumes_negative.UpdateMultiattachVolumeNegativeTest.test_multiattach_rw_volume_update_failure)\
+ (?!.*test_volumes_extend.VolumesExtendAttachedTest.test_extend_attached_volume)\
+ (?!.*\\[.*\\bslow\\b.*\\])(^tempest.api)"
+ option:
+ - '--concurrency=4'
+
+ -
+ case_name: tempest_scenario_cntt
+ project_name: functest
+ criteria: 100
+ blocking: false
+ deny_skipping: true
+ tests_count: 13
+ description: >-
+ The list of test cases is generated by
+ Tempest automatically and depends on the parameters of
+ the OpenStack deployment.
+ https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L84
+ run:
+ name: tempest_scenario
+ args:
+ mode: "\
+ (?!.*test_compute_unified_limits)\
+ (?!.*test_minbw_allocation_placement)\
+ (?!.*test_network_qos_placement)\
+ (?!.*test_unified_limits.ImageQuotaTest.test_image_count_uploading_quota)\
+ (?!.*test_unified_limits.ImageQuotaTest.test_image_stage_quota)\
+ (?!.*test_volume_boot_pattern.TestVolumeBootPattern.test_boot_server_from_encrypted_volume_luks)\
+ (?!.*\\[.*\\bslow\\b.*\\])(^tempest.scenario)"
+ option:
+ - '--concurrency=1'
+
+ -
+ case_name: tempest_slow_cntt
+ project_name: functest
+ criteria: 100
+ blocking: false
+ deny_skipping: true
+ tests_count: 43
+ description: >-
+ The list of test cases is generated by
+ Tempest automatically and depends on the parameters of
+ the OpenStack deployment.
+ https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L84
run:
- module: 'functest.opnfv_tests.openstack.tempest.tempest'
- class: 'TempestCommon'
+ name: tempest_common
args:
- mode: '^(tempest|neutron_tempest_plugin)\.'
+ mode: "(?!.*test_volume_swap)\
+ (?!.*test_server_personality)\
+ (?!.*test_server_rescue.ServerBootFromVolumeStableRescueTest)\
+ (?!.*test_container_sync.ContainerSyncTest.test_container_synchronization)\
+ (?!.*test_container_sync_middleware.ContainerSyncMiddlewareTest.test_container_synchronization)\
+ (?!.*test_encrypted_cinder_volumes)\
+ (?!.*test_minbw_allocation_placement)\
+ (?!.*test_network_basic_ops.TestNetworkBasicOps.test_router_rescheduling)\
+ (?!.*test_shelve_instance.TestShelveInstance.test_cold_migrate_unshelved_instance)\
+ (?!.*test_volume_migrate_attached)\
+ (?!.*test_network_advanced_server_ops.TestNetworkAdvancedServerOps.test_server_connectivity_cold_migration_revert)\
+ (?=.*\\[.*\\bslow\\b.*\\])(^tempest.)"
+ option:
+ - '--concurrency=1'
+ -
+ name: benchmarking
+ description: >-
+ Run several OpenStack performance tools
+ https://docs.openstack.org/performance-docs/latest/methodologies/tools.html
+ testcases:
-
case_name: rally_full
project_name: functest
@@ -454,12 +914,101 @@ tiers:
This test case runs the full suite of scenarios of the
OpenStack Rally suite using several threads and iterations.
run:
- module: 'functest.opnfv_tests.openstack.rally.rally'
- class: 'RallyFull'
+ name: rally_full
+ args:
+ optional:
+ - 'gnocchi'
+ - 'barbican'
+
+ -
+ case_name: rally_jobs
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ This test case runs a group of Rally jobs used in
+ OpenStack gating
+ dependencies:
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
+ run:
+ name: rally_jobs
+ args:
+ optional:
+ - 'gnocchi'
+
+ -
+ case_name: vmtp
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ VMTP is a small python application that will automatically
+ perform ping connectivity, round trip time measurement
+ (latency) and TCP/UDP throughput
+ dependencies:
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
+ run:
+ name: vmtp
+
+ -
+ case_name: shaker
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ Shaker wraps around popular system network testing tools
+ like iperf, iperf3 and netperf (with help of flent). Shaker
+ is able to deploy OpenStack instances and networks in
+ different topologies.
+ dependencies:
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
+ run:
+ name: shaker
+
+ -
+ name: benchmarking_cntt
+ description: >-
+ Run several OpenStack performance tools
+ https://docs.openstack.org/performance-docs/latest/methodologies/tools.html
+ testcases:
+ -
+ case_name: rally_full_cntt
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ This test case runs the full suite of scenarios of the
+ OpenStack Rally suite using several threads and iterations.
+ run:
+ name: rally_full
+ args:
+ tests:
+ - 'authenticate'
+ - 'glance'
+ - 'cinder'
+ - 'heat'
+ - 'keystone'
+ - 'neutron'
+ - 'nova'
+ - 'quotas'
+ - 'swift'
+
+ -
+ case_name: rally_jobs_cntt
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ This test case runs a group of Rally jobs used in
+ OpenStack gating
+ run:
+ name: rally_jobs
+ args:
+ tests:
+ - 'neutron'
-
name: vnf
- order: 4
description: >-
Collection of VNF test cases.
testcases:
@@ -470,25 +1019,35 @@ tiers:
blocking: false
description: >-
This test case deploys the Cloudify orchestrator.
- dependencies:
- - DEPLOY_SCENARIO: 'os-.*-nofeature-.*ha'
run:
- module: 'functest.core.cloudify'
- class: 'Cloudify'
+ name: cloudify
-
case_name: cloudify_ims
project_name: functest
- criteria: 80
+ criteria: 100
blocking: false
description: >-
This test case deploys an OpenSource vIMS solution from
Clearwater using the Cloudify orchestrator. It also runs
some signaling traffic.
dependencies:
- - DEPLOY_SCENARIO: 'os-.*-nofeature-.*ha'
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
+ run:
+ name: cloudify_ims
+
+ -
+ case_name: heat_ims
+ project_name: functest
+ criteria: 100
+ blocking: false
+ description: >-
+ This test case deploys an OpenSource vIMS solution from
+ Clearwater using the OpenStack Heat orchestrator.
+ It also runs some signaling traffic.
+ dependencies:
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
run:
- module: 'functest.opnfv_tests.vnf.ims.cloudify_ims'
- class: 'CloudifyIms'
+ name: heat_ims
-
case_name: vyos_vrouter
@@ -498,10 +1057,9 @@ tiers:
description: >-
This test case is vRouter testing.
dependencies:
- - DEPLOY_SCENARIO: 'os-.*-nofeature-.*ha'
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
run:
- module: 'functest.opnfv_tests.vnf.router.cloudify_vrouter'
- class: 'CloudifyVrouter'
+ name: vyos_vrouter
-
case_name: juju_epc
@@ -512,7 +1070,6 @@ tiers:
vEPC validation with Juju as VNF manager and ABoT as test
executor.
dependencies:
- - DEPLOY_SCENARIO: 'os-.*-nofeature-.*ha'
+ - NO_TENANT_NETWORK: '^(?![tT]rue$)'
run:
- module: 'functest.opnfv_tests.vnf.epc.juju_epc'
- class: 'JujuEpc'
+ name: juju_epc
diff --git a/functest/core/cloudify.py b/functest/core/cloudify.py
index 954491f6c..966d33645 100644
--- a/functest/core/cloudify.py
+++ b/functest/core/cloudify.py
@@ -12,9 +12,13 @@
from __future__ import division
import logging
+import os
import time
+import traceback
from cloudify_rest_client import CloudifyClient
+from cloudify_rest_client.executions import Execution
+import scp
from functest.core import singlevm
@@ -25,23 +29,28 @@ class Cloudify(singlevm.SingleVm2):
__logger = logging.getLogger(__name__)
filename = ('/home/opnfv/functest/images/'
- 'cloudify-manager-premium-4.0.1.qcow2')
+ 'ubuntu-18.04-server-cloudimg-amd64.img')
flavor_ram = 4096
flavor_vcpus = 2
- flavor_disk = 50
- username = 'centos'
+ flavor_disk = 40
+ username = 'ubuntu'
ssh_connect_loops = 12
+ create_server_timeout = 600
ports = [80, 443, 5671, 53333]
+ cloudify_archive = ('/home/opnfv/functest/images/'
+ 'cloudify-docker-manager-community-19.01.24.tar')
+ cloudify_container = "docker-cfy-manager:latest"
+
def __init__(self, **kwargs):
"""Initialize Cloudify testcase object."""
if "case_name" not in kwargs:
kwargs["case_name"] = "cloudify"
- super(Cloudify, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.cfy_client = None
def prepare(self):
- super(Cloudify, self).prepare()
+ super().prepare()
for port in self.ports:
self.cloud.create_security_group_rule(
self.sec.id, port_range_min=port, port_range_max=port,
@@ -51,12 +60,28 @@ class Cloudify(singlevm.SingleVm2):
"""
Deploy Cloudify Manager.
"""
+ scpc = scp.SCPClient(self.ssh.get_transport())
+ scpc.put(self.cloudify_archive,
+ remote_path=os.path.basename(self.cloudify_archive))
+ (_, stdout, stderr) = self.ssh.exec_command(
+ "sudo apt-get update && "
+ "sudo apt-get install -y docker.io && "
+ "sudo docker load -i "
+ f"~/{os.path.basename(self.cloudify_archive)} && "
+ "sudo docker run --name cfy_manager_local -d "
+ "--restart unless-stopped -v /sys/fs/cgroup:/sys/fs/cgroup:ro "
+ "--tmpfs /run --tmpfs /run/lock --security-opt seccomp:unconfined "
+ f"--cap-add SYS_ADMIN --network=host {self.cloudify_container}")
+ self.__logger.debug("output:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("error:\n%s", stderr.read().decode("utf-8"))
self.cfy_client = CloudifyClient(
- host=self.fip.floating_ip_address,
- username='admin', password='admin', tenant='default_tenant',
- api_version='v3')
+ host=self.fip.floating_ip_address if self.fip else (
+ self.sshvm.public_v4),
+ username='admin', password='admin', tenant='default_tenant')
self.__logger.info("Attemps running status of the Manager")
- for loop in range(10):
+ secret_key = "foo"
+ secret_value = "bar"
+ for loop in range(20):
try:
self.__logger.debug(
"status %s", self.cfy_client.manager.get_status())
@@ -65,13 +90,130 @@ class Cloudify(singlevm.SingleVm2):
"The current manager status is %s", cfy_status)
if str(cfy_status) != 'running':
raise Exception("Cloudify Manager isn't up and running")
+ for secret in iter(self.cfy_client.secrets.list()):
+ if secret_key == secret["key"]:
+ self.__logger.debug("Updating secrets: %s", secret_key)
+ self.cfy_client.secrets.update(
+ secret_key, secret_value)
+ break
+ else:
+ self.__logger.debug("Creating secrets: %s", secret_key)
+ self.cfy_client.secrets.create(secret_key, secret_value)
+ self.cfy_client.secrets.delete(secret_key)
+ self.__logger.info("Secrets API successfully reached")
break
except Exception: # pylint: disable=broad-except
- self.__logger.info(
- "try %s: Cloudify Manager isn't up and running", loop + 1)
+ self.__logger.debug(
+ "try %s: Cloudify Manager isn't up and running \n%s",
+ loop + 1, traceback.format_exc())
time.sleep(30)
else:
self.__logger.error("Cloudify Manager isn't up and running")
return 1
self.__logger.info("Cloudify Manager is up and running")
return 0
+
+ def put_private_key(self):
+ """Put private keypair in manager"""
+ self.__logger.info("Put private keypair in manager")
+ scpc = scp.SCPClient(self.ssh.get_transport())
+ scpc.put(self.key_filename, remote_path='~/cloudify_ims.pem')
+ (_, stdout, stderr) = self.ssh.exec_command(
+ "sudo docker cp ~/cloudify_ims.pem "
+ "cfy_manager_local:/etc/cloudify/ && "
+ "sudo docker exec cfy_manager_local "
+ "chmod 444 /etc/cloudify/cloudify_ims.pem")
+ self.__logger.debug("output:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("error:\n%s", stderr.read().decode("utf-8"))
+
+ def upload_cfy_plugins(self, yaml, wgn):
+ """Upload Cloudify plugins"""
+ (_, stdout, stderr) = self.ssh.exec_command(
+ "sudo docker exec cfy_manager_local "
+ f"cfy plugins upload -y {yaml} {wgn} && "
+ "sudo docker exec cfy_manager_local cfy status")
+ self.__logger.debug("output:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("error:\n%s", stderr.read().decode("utf-8"))
+
+ def kill_existing_execution(self, dep_name):
+ """kill existing execution"""
+ try:
+ self.__logger.info('Deleting the current deployment')
+ exec_list = self.cfy_client.executions.list()
+ for execution in exec_list:
+ if execution['status'] == "started":
+ try:
+ self.cfy_client.executions.cancel(
+ execution['id'], force=True)
+ except Exception: # pylint: disable=broad-except
+ self.__logger.warning("Can't cancel the current exec")
+ execution = self.cfy_client.executions.start(
+ dep_name, 'uninstall', parameters=dict(ignore_failure=True))
+ wait_for_execution(self.cfy_client, execution, self.__logger)
+ self.cfy_client.deployments.delete(dep_name)
+ time.sleep(10)
+ self.cfy_client.blueprints.delete(dep_name)
+ except Exception: # pylint: disable=broad-except
+ self.__logger.exception("Some issue during the undeployment ..")
+
+
+def wait_for_execution(client, execution, logger, timeout=3600, ):
+ """Wait for a workflow execution on Cloudify Manager."""
+ # if execution already ended - return without waiting
+ if execution.status in Execution.END_STATES:
+ return execution
+
+ if timeout is not None:
+ deadline = time.time() + timeout
+
+ # Poll for execution status and execution logs, until execution ends
+ # and we receive an event of type in WORKFLOW_END_TYPES
+ offset = 0
+ batch_size = 50
+ event_list = []
+ execution_ended = False
+ while True:
+ event_list = client.events.list(
+ execution_id=execution.id,
+ _offset=offset,
+ _size=batch_size,
+ include_logs=True,
+ sort='@timestamp').items
+
+ offset = offset + len(event_list)
+ for event in event_list:
+ logger.debug(event.get('message'))
+
+ if timeout is not None:
+ if time.time() > deadline:
+ raise RuntimeError(
+ 'execution of operation {execution.workflow_id} for '
+ 'deployment {execution.deployment_id} timed out')
+ # update the remaining timeout
+ timeout = deadline - time.time()
+
+ if not execution_ended:
+ execution = client.executions.get(execution.id)
+ execution_ended = execution.status in Execution.END_STATES
+
+ if execution_ended:
+ break
+
+ time.sleep(5)
+
+ return execution
+
+
+def get_execution_id(client, deployment_id):
+ """
+ Get the execution id of a env preparation.
+
+ network, security group, fip, VM creation
+ """
+ executions = client.executions.list(deployment_id=deployment_id)
+ for execution in executions:
+ if execution.workflow_id == 'create_deployment_environment':
+ return execution
+ raise RuntimeError('Failed to get create_deployment_environment '
+ 'workflow execution.'
+ f'Available executions: {executions}')
diff --git a/functest/core/singlevm.py b/functest/core/singlevm.py
index ad79a8e14..4bce516d3 100644
--- a/functest/core/singlevm.py
+++ b/functest/core/singlevm.py
@@ -9,11 +9,12 @@
"""Ease deploying a single VM reachable via ssh
-It offers a simple way to create all tenant network ressources + a VM for
+It offers a simple way to create all tenant network resources + a VM for
advanced testcases (e.g. deploying an orchestrator).
"""
import logging
+import re
import tempfile
import time
@@ -22,6 +23,8 @@ from xtesting.core import testcase
from functest.core import tenantnetwork
from functest.utils import config
+from functest.utils import env
+from functest.utils import functest_utils
class VmReady1(tenantnetwork.TenantNetwork1):
@@ -36,23 +39,27 @@ class VmReady1(tenantnetwork.TenantNetwork1):
# pylint: disable=too-many-instance-attributes
__logger = logging.getLogger(__name__)
- filename = '/home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img'
+ filename = '/home/opnfv/functest/images/cirros-0.6.1-x86_64-disk.img'
+ image_format = 'qcow2'
+ extra_properties = {}
+ filename_alt = filename
+ image_alt_format = image_format
+ extra_alt_properties = extra_properties
visibility = 'private'
- extra_properties = None
flavor_ram = 512
flavor_vcpus = 1
flavor_disk = 1
+ flavor_extra_specs = {}
flavor_alt_ram = 1024
flavor_alt_vcpus = 1
flavor_alt_disk = 1
-
- image_format = 'qcow2'
+ flavor_alt_extra_specs = flavor_extra_specs
+ create_server_timeout = 180
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'vmready1'
- super(VmReady1, self).__init__(**kwargs)
- self.orig_cloud = self.cloud
+ super().__init__(**kwargs)
self.image = None
self.flavor = None
@@ -67,20 +74,60 @@ class VmReady1(tenantnetwork.TenantNetwork1):
Raises: expection on error
"""
assert self.cloud
+ extra_properties = self.extra_properties.copy()
+ if env.get('IMAGE_PROPERTIES'):
+ extra_properties.update(
+ functest_utils.convert_ini_to_dict(
+ env.get('IMAGE_PROPERTIES')))
+ extra_properties.update(
+ getattr(config.CONF, f'{self.case_name}_extra_properties', {}))
image = self.cloud.create_image(
- name if name else '{}-img_{}'.format(self.case_name, self.guid),
+ name if name else f'{self.case_name}-img_{self.guid}',
filename=getattr(
- config.CONF, '{}_image'.format(self.case_name),
+ config.CONF, f'{self.case_name}_image',
self.filename),
- meta=getattr(
- config.CONF, '{}_extra_properties'.format(self.case_name),
- self.extra_properties),
+ meta=extra_properties,
disk_format=getattr(
- config.CONF, '{}_image_format'.format(self.case_name),
+ config.CONF, f'{self.case_name}_image_format',
self.image_format),
visibility=getattr(
- config.CONF, '{}_visibility'.format(self.case_name),
- self.visibility))
+ config.CONF, f'{self.case_name}_visibility',
+ self.visibility),
+ wait=True)
+ self.__logger.debug("image: %s", image)
+ return image
+
+ def publish_image_alt(self, name=None):
+ """Publish alternative image
+
+ It allows publishing multiple images for the child testcases. It forces
+ the same configuration for all subtestcases.
+
+ Returns: image
+
+ Raises: expection on error
+ """
+ assert self.cloud
+ extra_alt_properties = self.extra_alt_properties.copy()
+ if env.get('IMAGE_PROPERTIES'):
+ extra_alt_properties.update(
+ functest_utils.convert_ini_to_dict(
+ env.get('IMAGE_PROPERTIES')))
+ extra_alt_properties.update(
+ getattr(config.CONF, f'{self.case_name}_extra_alt_properties', {}))
+ image = self.cloud.create_image(
+ name if name else f'{self.case_name}-img_alt_{self.guid}',
+ filename=getattr(
+ config.CONF, f'{self.case_name}_image_alt',
+ self.filename_alt),
+ meta=extra_alt_properties,
+ disk_format=getattr(
+ config.CONF, f'{self.case_name}_image_alt_format',
+ self.image_format),
+ visibility=getattr(
+ config.CONF, f'{self.case_name}_visibility',
+ self.visibility),
+ wait=True)
self.__logger.debug("image: %s", image)
return image
@@ -96,16 +143,23 @@ class VmReady1(tenantnetwork.TenantNetwork1):
"""
assert self.orig_cloud
flavor = self.orig_cloud.create_flavor(
- name if name else '{}-flavor_{}'.format(self.case_name, self.guid),
- getattr(config.CONF, '{}_flavor_ram'.format(self.case_name),
+ name if name else f'{self.case_name}-flavor_{self.guid}',
+ getattr(config.CONF, f'{self.case_name}_flavor_ram',
self.flavor_ram),
- getattr(config.CONF, '{}_flavor_vcpus'.format(self.case_name),
+ getattr(config.CONF, f'{self.case_name}_flavor_vcpus',
self.flavor_vcpus),
- getattr(config.CONF, '{}_flavor_disk'.format(self.case_name),
+ getattr(config.CONF, f'{self.case_name}_flavor_disk',
self.flavor_disk))
self.__logger.debug("flavor: %s", flavor)
- self.orig_cloud.set_flavor_specs(
- flavor.id, getattr(config.CONF, 'flavor_extra_specs', {}))
+ flavor_extra_specs = self.flavor_extra_specs.copy()
+ if env.get('FLAVOR_EXTRA_SPECS'):
+ flavor_extra_specs.update(
+ functest_utils.convert_ini_to_dict(
+ env.get('FLAVOR_EXTRA_SPECS')))
+ flavor_extra_specs.update(
+ getattr(config.CONF,
+ f'{self.case_name}_flavor_extra_specs', {}))
+ self.orig_cloud.set_flavor_specs(flavor.id, flavor_extra_specs)
return flavor
def create_flavor_alt(self, name=None):
@@ -120,17 +174,24 @@ class VmReady1(tenantnetwork.TenantNetwork1):
"""
assert self.orig_cloud
flavor = self.orig_cloud.create_flavor(
- name if name else '{}-flavor_alt_{}'.format(
- self.case_name, self.guid),
- getattr(config.CONF, '{}_flavor_alt_ram'.format(self.case_name),
+ name if name else f'{self.case_name}-flavor_alt_{self.guid}',
+ getattr(config.CONF, f'{self.case_name}_flavor_alt_ram',
self.flavor_alt_ram),
- getattr(config.CONF, '{}_flavor_alt_vcpus'.format(self.case_name),
+ getattr(config.CONF, f'{self.case_name}_flavor_alt_vcpus',
self.flavor_alt_vcpus),
- getattr(config.CONF, '{}_flavor_alt_disk'.format(self.case_name),
+ getattr(config.CONF, f'{self.case_name}_flavor_alt_disk',
self.flavor_alt_disk))
self.__logger.debug("flavor: %s", flavor)
+ flavor_alt_extra_specs = self.flavor_alt_extra_specs.copy()
+ if env.get('FLAVOR_EXTRA_SPECS'):
+ flavor_alt_extra_specs.update(
+ functest_utils.convert_ini_to_dict(
+ env.get('FLAVOR_EXTRA_SPECS')))
+ flavor_alt_extra_specs.update(
+ getattr(config.CONF,
+ f'{self.case_name}_flavor_alt_extra_specs', {}))
self.orig_cloud.set_flavor_specs(
- flavor.id, getattr(config.CONF, 'flavor_extra_specs', {}))
+ flavor.id, flavor_alt_extra_specs)
return flavor
def boot_vm(self, name=None, **kwargs):
@@ -145,15 +206,71 @@ class VmReady1(tenantnetwork.TenantNetwork1):
"""
assert self.cloud
vm1 = self.cloud.create_server(
- name if name else '{}-vm_{}'.format(self.case_name, self.guid),
+ name if name else f'{self.case_name}-vm_{self.guid}',
image=self.image.id, flavor=self.flavor.id,
- auto_ip=False, wait=True,
- network=self.network.id,
- **kwargs)
- vm1 = self.cloud.wait_for_server(vm1, auto_ip=False)
+ auto_ip=False,
+ network=self.network.id if self.network else env.get(
+ "EXTERNAL_NETWORK"),
+ timeout=self.create_server_timeout, wait=True, **kwargs)
self.__logger.debug("vm: %s", vm1)
return vm1
+ def check_regex_in_console(self, name, regex=' login: ', loop=6):
+ """Wait for specific message in console
+
+ Returns: True or False on errors
+ """
+ assert self.cloud
+ for iloop in range(loop):
+ console = self.cloud.get_server_console(name)
+ self.__logger.debug("console: \n%s", console)
+ if re.search(regex, console):
+ self.__logger.debug(
+ "regex found: '%s' in console\n%s", regex, console)
+ return True
+ self.__logger.debug(
+ "try %s: cannot find regex '%s' in console\n%s",
+ iloop + 1, regex, console)
+ time.sleep(10)
+ self.__logger.error("cannot find regex '%s' in console", regex)
+ return False
+
+ def clean_orphan_security_groups(self):
+ """Clean all security groups which are not owned by an existing tenant
+
+ It lists all orphan security groups in use as debug to avoid
+ misunderstanding the testcase results (it could happen if cloud admin
+ removes accounts without cleaning the virtual machines)
+ """
+ sec_groups = self.orig_cloud.list_security_groups()
+ for sec_group in sec_groups:
+ if not sec_group.tenant_id:
+ continue
+ if not self.orig_cloud.get_project(sec_group.tenant_id):
+ self.__logger.debug("Cleaning security group %s", sec_group.id)
+ try:
+ self.orig_cloud.delete_security_group(sec_group.id)
+ except Exception: # pylint: disable=broad-except
+ self.__logger.debug(
+ "Orphan security group %s in use", sec_group.id)
+
+ def count_hypervisors(self):
+ """Count hypervisors."""
+ if env.get('SKIP_DOWN_HYPERVISORS').lower() == 'false':
+ return len(self.orig_cloud.list_hypervisors())
+ return self.count_active_hypervisors()
+
+ def count_active_hypervisors(self):
+ """Count all hypervisors which are up."""
+ compute_cnt = 0
+ for hypervisor in self.orig_cloud.list_hypervisors():
+ if hypervisor['state'] == 'up':
+ compute_cnt += 1
+ else:
+ self.__logger.warning(
+ "%s is down", hypervisor['hypervisor_hostname'])
+ return compute_cnt
+
def run(self, **kwargs):
"""Boot the new VM
@@ -168,7 +285,7 @@ class VmReady1(tenantnetwork.TenantNetwork1):
status = testcase.TestCase.EX_RUN_ERROR
try:
assert self.cloud
- assert super(VmReady1, self).run(
+ assert super().run(
**kwargs) == testcase.TestCase.EX_OK
self.image = self.publish_image()
self.flavor = self.create_flavor()
@@ -185,20 +302,22 @@ class VmReady1(tenantnetwork.TenantNetwork1):
try:
assert self.orig_cloud
assert self.cloud
- super(VmReady1, self).clean()
+ super().clean()
if self.image:
self.cloud.delete_image(self.image.id)
if self.flavor:
self.orig_cloud.delete_flavor(self.flavor.id)
+ if env.get('CLEAN_ORPHAN_SECURITY_GROUPS').lower() == 'true':
+ self.clean_orphan_security_groups()
except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot clean all ressources")
+ self.__logger.exception("Cannot clean all resources")
class VmReady2(VmReady1):
"""Deploy a single VM reachable via ssh (scenario2)
It creates new user/project before creating and configuring all tenant
- network ressources, flavors, images, etc. required by advanced testcases.
+ network resources, flavors, images, etc. required by advanced testcases.
It ensures that all testcases inheriting from SingleVm2 could work
without specific configurations (or at least read the same config data).
@@ -209,7 +328,7 @@ class VmReady2(VmReady1):
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'vmready2'
- super(VmReady2, self).__init__(**kwargs)
+ super().__init__(**kwargs)
try:
assert self.orig_cloud
self.project = tenantnetwork.NewProject(
@@ -223,11 +342,11 @@ class VmReady2(VmReady1):
def clean(self):
try:
- super(VmReady2, self).clean()
+ super().clean()
assert self.project
self.project.clean()
except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot clean all ressources")
+ self.__logger.exception("Cannot clean all resources")
class SingleVm1(VmReady1):
@@ -243,13 +362,16 @@ class SingleVm1(VmReady1):
__logger = logging.getLogger(__name__)
username = 'cirros'
- ssh_connect_timeout = 60
+ ssh_connect_timeout = 1
ssh_connect_loops = 6
+ create_floating_ip_timeout = 120
+ check_console_loop = 6
+ check_console_regex = ' login: '
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'singlevm1'
- super(SingleVm1, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.sshvm = None
self.sec = None
self.fip = None
@@ -267,14 +389,15 @@ class SingleVm1(VmReady1):
"""
assert self.cloud
self.keypair = self.cloud.create_keypair(
- '{}-kp_{}'.format(self.case_name, self.guid))
+ f'{self.case_name}-kp_{self.guid}')
self.__logger.debug("keypair: %s", self.keypair)
- self.__logger.debug("private_key: %s", self.keypair.private_key)
- with open(self.key_filename, 'w') as private_key_file:
+ self.__logger.debug("private_key:\n%s", self.keypair.private_key)
+ with open(
+ self.key_filename, 'w', encoding='utf-8') as private_key_file:
private_key_file.write(self.keypair.private_key)
self.sec = self.cloud.create_security_group(
- '{}-sg_{}'.format(self.case_name, self.guid),
- 'created by OPNFV Functest ({})'.format(self.case_name))
+ f'{self.case_name}-sg_{self.guid}',
+ f'created by OPNFV Functest ({self.case_name})')
self.cloud.create_security_group_rule(
self.sec.id, port_range_min='22', port_range_max='22',
protocol='tcp', direction='ingress')
@@ -292,31 +415,34 @@ class SingleVm1(VmReady1):
- None on error
"""
assert vm1
- fip = self.cloud.create_floating_ip(
- network=self.ext_net.id, server=vm1)
- self.__logger.debug("floating_ip: %s", fip)
- p_console = self.cloud.get_server_console(vm1)
- self.__logger.debug("vm console: \n%s", p_console)
+ fip = None
+ if env.get('NO_TENANT_NETWORK').lower() != 'true':
+ fip = self.cloud.create_floating_ip(
+ network=self.ext_net.id, server=vm1, wait=True,
+ timeout=self.create_floating_ip_timeout)
+ self.__logger.debug("floating_ip: %s", fip)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
for loop in range(self.ssh_connect_loops):
try:
+ p_console = self.cloud.get_server_console(vm1)
+ self.__logger.debug("vm console: \n%s", p_console)
ssh.connect(
- fip.floating_ip_address,
+ fip.floating_ip_address if fip else vm1.public_v4,
username=getattr(
config.CONF,
- '{}_image_user'.format(self.case_name), self.username),
+ f'{self.case_name}_image_user', self.username),
key_filename=self.key_filename,
timeout=getattr(
config.CONF,
- '{}_vm_ssh_connect_timeout'.format(self.case_name),
+ f'{self.case_name}_vm_ssh_connect_timeout',
self.ssh_connect_timeout))
break
- except Exception: # pylint: disable=broad-except
+ except Exception as exc: # pylint: disable=broad-except
self.__logger.debug(
- "try %s: cannot connect to %s", loop + 1,
- fip.floating_ip_address)
- time.sleep(10)
+ "try %s: cannot connect to %s: %s", loop + 1,
+ fip.floating_ip_address if fip else vm1.public_v4, exc)
+ time.sleep(9)
else:
self.__logger.error(
"cannot connect to %s", fip.floating_ip_address)
@@ -330,8 +456,9 @@ class SingleVm1(VmReady1):
Returns: echo exit codes
"""
- (_, stdout, _) = self.ssh.exec_command('echo Hello World')
- self.__logger.debug("output:\n%s", stdout.read())
+ (_, stdout, stderr) = self.ssh.exec_command('echo Hello World')
+ self.__logger.debug("output:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("error:\n%s", stderr.read().decode("utf-8"))
return stdout.channel.recv_exit_status()
def run(self, **kwargs):
@@ -350,16 +477,19 @@ class SingleVm1(VmReady1):
status = testcase.TestCase.EX_RUN_ERROR
try:
assert self.cloud
- assert super(SingleVm1, self).run(
+ assert super().run(
**kwargs) == testcase.TestCase.EX_OK
self.result = 0
self.prepare()
self.sshvm = self.boot_vm(
key_name=self.keypair.id, security_groups=[self.sec.id])
- (self.fip, self.ssh) = self.connect(self.sshvm)
- if not self.execute():
- self.result = 100
- status = testcase.TestCase.EX_OK
+ if self.check_regex_in_console(
+ self.sshvm.name, regex=self.check_console_regex,
+ loop=self.check_console_loop):
+ (self.fip, self.ssh) = self.connect(self.sshvm)
+ if not self.execute():
+ self.result = 100
+ status = testcase.TestCase.EX_OK
except Exception: # pylint: disable=broad-except
self.__logger.exception('Cannot run %s', self.case_name)
finally:
@@ -378,16 +508,16 @@ class SingleVm1(VmReady1):
self.cloud.delete_security_group(self.sec.id)
if self.keypair:
self.cloud.delete_keypair(self.keypair.name)
- super(SingleVm1, self).clean()
+ super().clean()
except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot clean all ressources")
+ self.__logger.exception("Cannot clean all resources")
class SingleVm2(SingleVm1):
"""Deploy a single VM reachable via ssh (scenario2)
It creates new user/project before creating and configuring all tenant
- network ressources and vms required by advanced testcases.
+ network resources and vms required by advanced testcases.
It ensures that all testcases inheriting from SingleVm2 could work
without specific configurations (or at least read the same config data).
@@ -398,7 +528,7 @@ class SingleVm2(SingleVm1):
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'singlevm2'
- super(SingleVm2, self).__init__(**kwargs)
+ super().__init__(**kwargs)
try:
assert self.orig_cloud
self.project = tenantnetwork.NewProject(
@@ -412,8 +542,8 @@ class SingleVm2(SingleVm1):
def clean(self):
try:
- super(SingleVm2, self).clean()
+ super().clean()
assert self.project
self.project.clean()
except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot clean all ressources")
+ self.__logger.exception("Cannot clean all resources")
diff --git a/functest/core/tenantnetwork.py b/functest/core/tenantnetwork.py
index 286aef67e..3670dbe8a 100644
--- a/functest/core/tenantnetwork.py
+++ b/functest/core/tenantnetwork.py
@@ -9,10 +9,11 @@
"""Ease deploying tenant networks
-It offers a simple way to create all tenant network ressources required by a
+It offers a simple way to create all tenant network resources required by a
testcase (including all Functest ones):
+
- TenantNetwork1 selects the user and the project set as env vars
- - TenantNetwork2 creates a user and project to isolate the same ressources
+ - TenantNetwork2 creates a user and project to isolate the same resources
This classes could be reused by more complexed scenarios (Single VM)
"""
@@ -24,18 +25,19 @@ import uuid
import os_client_config
import shade
+from tempest.lib.common.utils import data_utils
from xtesting.core import testcase
from functest.utils import config
from functest.utils import env
+from functest.utils import functest_utils
-class NewProject(object):
+class NewProject():
"""Ease creating new projects/users"""
# pylint: disable=too-many-instance-attributes
__logger = logging.getLogger(__name__)
- default_member = "Member"
def __init__(self, cloud, case_name, guid):
self.cloud = None
@@ -46,25 +48,25 @@ class NewProject(object):
self.user = None
self.password = None
self.domain = None
- self.role = None
self.role_name = None
+ self.default_member = env.get('NEW_USER_ROLE')
def create(self):
"""Create projects/users"""
assert self.orig_cloud
assert self.case_name
- self.password = str(uuid.uuid4())
+ self.password = data_utils.rand_password().replace('%', '!')
+ self.__logger.debug("password: %s", self.password)
self.domain = self.orig_cloud.get_domain(
name_or_id=self.orig_cloud.auth.get(
"project_domain_name", "Default"))
self.project = self.orig_cloud.create_project(
- name='{}-project_{}'.format(self.case_name, self.guid),
- description="Created by OPNFV Functest: {}".format(
- self.case_name),
+ name=f'{self.case_name[:18]}-project_{self.guid}',
+ description=f"Created by OPNFV Functest: {self.case_name}",
domain_id=self.domain.id)
self.__logger.debug("project: %s", self.project)
self.user = self.orig_cloud.create_user(
- name='{}-user_{}'.format(self.case_name, self.guid),
+ name=f'{self.case_name}-user_{self.guid}',
password=self.password,
domain_id=self.domain.id)
self.__logger.debug("user: %s", self.user)
@@ -74,12 +76,12 @@ class NewProject(object):
elif self.orig_cloud.get_role(self.default_member.lower()):
self.role_name = self.default_member.lower()
else:
- raise Exception("Cannot detect {}".format(self.default_member))
+ raise Exception(f"Cannot detect {self.default_member}")
except Exception: # pylint: disable=broad-except
self.__logger.info("Creating default role %s", self.default_member)
- self.role = self.orig_cloud.create_role(self.default_member)
- self.role_name = self.role.name
- self.__logger.debug("role: %s", self.role)
+ role = self.orig_cloud.create_role(self.default_member)
+ self.role_name = role.name
+ self.__logger.debug("role: %s", role)
self.orig_cloud.grant_role(
self.role_name, user=self.user.id, project=self.project.id,
domain=self.domain.id)
@@ -95,6 +97,21 @@ class NewProject(object):
cloud_config=osconfig.get_one_cloud())
self.__logger.debug("new cloud %s", self.cloud.auth)
+ def get_environ(self):
+ "Get new environ"
+ environ = dict(
+ os.environ,
+ OS_USERNAME=self.user.name,
+ OS_PROJECT_NAME=self.project.name,
+ OS_PROJECT_ID=self.project.id,
+ OS_PASSWORD=self.password)
+ try:
+ del environ['OS_TENANT_NAME']
+ del environ['OS_TENANT_ID']
+ except Exception: # pylint: disable=broad-except
+ pass
+ return environ
+
def clean(self):
"""Remove projects/users"""
try:
@@ -103,17 +120,21 @@ class NewProject(object):
self.orig_cloud.delete_user(self.user.id)
if self.project:
self.orig_cloud.delete_project(self.project.id)
- if self.role:
- self.orig_cloud.delete_role(self.role.id)
+ secgroups = self.orig_cloud.list_security_groups(
+ filters={'name': 'default',
+ 'project_id': self.project.id})
+ if secgroups:
+ sec_id = secgroups[0].id
+ self.orig_cloud.delete_security_group(sec_id)
except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot clean all ressources")
+ self.__logger.exception("Cannot clean all resources")
class TenantNetwork1(testcase.TestCase):
# pylint: disable=too-many-instance-attributes
"""Create a tenant network (scenario1)
- It creates and configures all tenant network ressources required by
+ It creates and configures all tenant network resources required by
advanced testcases (subnet, network and router).
It ensures that all testcases inheriting from TenantNetwork1 could work
@@ -122,26 +143,30 @@ class TenantNetwork1(testcase.TestCase):
"""
__logger = logging.getLogger(__name__)
- cidr = '192.168.0.0/24'
+ cidr = '192.168.120.0/24'
shared_network = False
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'tenantnetwork1'
- super(TenantNetwork1, self).__init__(**kwargs)
- self.res_dir = os.path.join(
- getattr(config.CONF, 'dir_results'), self.case_name)
+ super().__init__(**kwargs)
+ self.dir_results = os.path.join(getattr(config.CONF, 'dir_results'))
+ self.res_dir = os.path.join(self.dir_results, self.case_name)
+ self.output_log_name = 'functest.log'
+ self.output_debug_log_name = 'functest.debug.log'
+ self.ext_net = None
try:
cloud_config = os_client_config.get_config()
- self.cloud = shade.OpenStackCloud(cloud_config=cloud_config)
+ self.cloud = self.orig_cloud = shade.OpenStackCloud(
+ cloud_config=cloud_config)
except Exception: # pylint: disable=broad-except
- self.cloud = None
- self.ext_net = None
+ self.cloud = self.orig_cloud = None
self.__logger.exception("Cannot connect to Cloud")
- try:
- self.ext_net = self.get_external_network(self.cloud)
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot get the external network")
+ if env.get('NO_TENANT_NETWORK').lower() != 'true':
+ try:
+ self.ext_net = self.get_external_network(self.cloud)
+ except Exception: # pylint: disable=broad-except
+ self.__logger.exception("Cannot get the external network")
self.guid = str(uuid.uuid4())
self.network = None
self.subnet = None
@@ -175,38 +200,61 @@ class TenantNetwork1(testcase.TestCase):
role = cloud.get_role(member.lower())
return role
- def _create_network_ressources(self):
+ @staticmethod
+ def get_public_auth_url(cloud):
+ """Get Keystone public endpoint"""
+ keystone_id = functest_utils.search_services(cloud, 'keystone')[0].id
+ endpoint = cloud.search_endpoints(
+ filters={'interface': 'public',
+ 'service_id': keystone_id})[0].url
+ return endpoint
+
+ def create_network_resources(self):
+ """Create all tenant network resources
+
+ It creates a router which gateway is the external network detected.
+ The new subnet is attached to that router.
+
+ Raises: expection on error
+ """
assert self.cloud
- assert self.ext_net
+ if env.get('NO_TENANT_NETWORK').lower() != 'true':
+ assert self.ext_net
provider = {}
- if hasattr(config.CONF, '{}_network_type'.format(self.case_name)):
+ if hasattr(config.CONF, f'{self.case_name}_network_type'):
provider["network_type"] = getattr(
- config.CONF, '{}_network_type'.format(self.case_name))
- if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)):
+ config.CONF, f'{self.case_name}_network_type')
+ if hasattr(config.CONF, f'{self.case_name}_physical_network'):
provider["physical_network"] = getattr(
- config.CONF, '{}_physical_network'.format(self.case_name))
- if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)):
+ config.CONF, f'{self.case_name}_physical_network')
+ if hasattr(config.CONF, f'{self.case_name}_segmentation_id'):
provider["segmentation_id"] = getattr(
- config.CONF, '{}_segmentation_id'.format(self.case_name))
- self.network = self.cloud.create_network(
- '{}-net_{}'.format(self.case_name, self.guid),
- provider=provider,
+ config.CONF, f'{self.case_name}_segmentation_id')
+ domain = self.orig_cloud.get_domain(
+ name_or_id=self.orig_cloud.auth.get(
+ "project_domain_name", "Default"))
+ project = self.orig_cloud.get_project(
+ self.cloud.auth['project_name'],
+ domain_id=domain.id)
+ self.network = self.orig_cloud.create_network(
+ f'{self.case_name}-net_{self.guid}',
+ provider=provider, project_id=project.id,
shared=self.shared_network)
self.__logger.debug("network: %s", self.network)
self.subnet = self.cloud.create_subnet(
self.network.id,
- subnet_name='{}-subnet_{}'.format(self.case_name, self.guid),
+ subnet_name=f'{self.case_name}-subnet_{self.guid}',
cidr=getattr(
- config.CONF, '{}_private_subnet_cidr'.format(self.case_name),
+ config.CONF, f'{self.case_name}_private_subnet_cidr',
self.cidr),
enable_dhcp=True,
dns_nameservers=[env.get('NAMESERVER')])
self.__logger.debug("subnet: %s", self.subnet)
self.router = self.cloud.create_router(
- name='{}-router_{}'.format(self.case_name, self.guid),
- ext_gateway_net_id=self.ext_net.id)
+ name=f'{self.case_name}-router_{self.guid}',
+ ext_gateway_net_id=self.ext_net.id if self.ext_net else None)
self.__logger.debug("router: %s", self.router)
self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id)
@@ -215,7 +263,8 @@ class TenantNetwork1(testcase.TestCase):
try:
assert self.cloud
self.start_time = time.time()
- self._create_network_ressources()
+ if env.get('NO_TENANT_NETWORK').lower() != 'true':
+ self.create_network_resources()
self.result = 100
status = testcase.TestCase.EX_OK
except Exception: # pylint: disable=broad-except
@@ -237,14 +286,14 @@ class TenantNetwork1(testcase.TestCase):
if self.network:
self.cloud.delete_network(self.network.id)
except Exception: # pylint: disable=broad-except
- self.__logger.exception("cannot clean all ressources")
+ self.__logger.exception("cannot clean all resources")
class TenantNetwork2(TenantNetwork1):
"""Create a tenant network (scenario2)
It creates new user/project before creating and configuring all tenant
- network ressources required by a testcase (subnet, network and router).
+ network resources required by a testcase (subnet, network and router).
It ensures that all testcases inheriting from TenantNetwork2 could work
without network specific configurations (or at least read the same config
@@ -256,7 +305,7 @@ class TenantNetwork2(TenantNetwork1):
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'tenantnetwork2'
- super(TenantNetwork2, self).__init__(**kwargs)
+ super().__init__(**kwargs)
try:
assert self.cloud
self.project = NewProject(
@@ -270,8 +319,8 @@ class TenantNetwork2(TenantNetwork1):
def clean(self):
try:
- super(TenantNetwork2, self).clean()
+ super().clean()
assert self.project
self.project.clean()
except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot clean all ressources")
+ self.__logger.exception("Cannot clean all resources")
diff --git a/functest/core/vnf.py b/functest/core/vnf.py
deleted file mode 100644
index a6afd4e6b..000000000
--- a/functest/core/vnf.py
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2016 Orange and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""Define the parent class of all VNF TestCases."""
-
-import logging
-import uuid
-
-from snaps.config.user import UserConfig
-from snaps.config.project import ProjectConfig
-from snaps.openstack.create_user import OpenStackUser
-from snaps.openstack.create_project import OpenStackProject
-from snaps.openstack.utils import keystone_utils
-from snaps.openstack.tests import openstack_tests
-
-from xtesting.core import vnf
-from functest.utils import constants
-
-__author__ = ("Morgan Richomme <morgan.richomme@orange.com>, "
- "Valentin Boucher <valentin.boucher@orange.com>")
-
-
-class VnfPreparationException(vnf.VnfPreparationException):
- """Raise when VNF preparation cannot be executed."""
-
-
-class OrchestratorDeploymentException(vnf.OrchestratorDeploymentException):
- """Raise when orchestrator cannot be deployed."""
-
-
-class VnfDeploymentException(vnf.VnfDeploymentException):
- """Raise when VNF cannot be deployed."""
-
-
-class VnfTestException(vnf.VnfTestException):
- """Raise when VNF cannot be tested."""
-
-
-class VnfOnBoarding(vnf.VnfOnBoarding):
- # pylint: disable=too-many-instance-attributes
- """Base model for OpenStack VNF test cases."""
-
- __logger = logging.getLogger(__name__)
-
- def __init__(self, **kwargs):
- super(VnfOnBoarding, self).__init__(**kwargs)
- self.uuid = uuid.uuid4()
- self.user_name = "{}-{}".format(self.case_name, self.uuid)
- self.tenant_name = "{}-{}".format(self.case_name, self.uuid)
- self.snaps_creds = {}
- self.created_object = []
- self.os_project = None
- self.tenant_description = "Created by OPNFV Functest: {}".format(
- self.case_name)
-
- def prepare(self):
- """
- Prepare the environment for VNF testing:
-
- * Creation of a user,
- * Creation of a tenant,
- * Allocation admin role to the user on this tenant
-
- Returns base.TestCase.EX_OK if preparation is successfull
-
- Raise VnfPreparationException in case of problem
- """
- try:
- self.__logger.info(
- "Prepare VNF: %s, description: %s", self.case_name,
- self.tenant_description)
- snaps_creds = openstack_tests.get_credentials(
- os_env_file=constants.ENV_FILE)
-
- self.os_project = OpenStackProject(
- snaps_creds,
- ProjectConfig(
- name=self.tenant_name,
- description=self.tenant_description,
- domain=snaps_creds.project_domain_name
- ))
- self.os_project.create()
- self.created_object.append(self.os_project)
-
- snaps_creds.project_domain_id = \
- self.os_project.get_project().domain_id
- snaps_creds.user_domain_id = \
- self.os_project.get_project().domain_id
-
- for role in ['admin', 'Admin']:
- if keystone_utils.get_role_by_name(
- keystone_utils.keystone_client(snaps_creds), role):
- admin_role = role
- break
-
- user_creator = OpenStackUser(
- snaps_creds,
- UserConfig(
- name=self.user_name,
- password=str(uuid.uuid4()),
- project_name=self.tenant_name,
- domain_name=snaps_creds.user_domain_name,
- roles={admin_role: self.tenant_name}))
- user_creator.create()
- self.created_object.append(user_creator)
- self.snaps_creds = user_creator.get_os_creds(self.tenant_name)
- self.__logger.debug("snaps creds: %s", self.snaps_creds)
-
- return vnf.VnfOnBoarding.EX_OK
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Exception raised during VNF preparation")
- raise VnfPreparationException
-
- def deploy_orchestrator(self):
- """
- Deploy an orchestrator (optional).
-
- If this method is overriden then raise orchestratorDeploymentException
- if error during orchestrator deployment
- """
- self.__logger.info("Deploy orchestrator (if necessary)")
- return True
-
- def deploy_vnf(self):
- """
- Deploy the VNF
-
- This function MUST be implemented by vnf test cases.
- The details section MAY be updated in the vnf test cases.
-
- The deployment can be executed via a specific orchestrator
- or using build-in orchestrators such as heat, OpenBaton, cloudify,
- juju, onap, ...
-
- Returns:
- True if the VNF is properly deployed
- False if the VNF is not deployed
-
- Raise VnfDeploymentException if error during VNF deployment
- """
- self.__logger.error("VNF must be deployed")
- raise VnfDeploymentException
-
- def test_vnf(self):
- """
- Test the VNF
-
- This function MUST be implemented by vnf test cases.
- The details section MAY be updated in the vnf test cases.
-
- Once a VNF is deployed, it is assumed that specific test suite can be
- run to validate the VNF.
- Please note that the same test suite can be used on several test case
- (e.g. clearwater test suite can be used whatever the orchestrator used
- for the deployment)
-
- Returns:
- True if VNF tests are PASS
- False if test suite is FAIL
-
- Raise VnfTestException if error during VNF test
- """
- self.__logger.error("VNF must be tested")
- raise VnfTestException
-
- def clean(self):
- """
- Clean VNF test case.
-
- It is up to the test providers to delete resources used for the tests.
- By default we clean:
-
- * the user,
- * the tenant
- """
- self.__logger.info('Removing the VNF resources ..')
- for creator in reversed(self.created_object):
- try:
- creator.clean()
- except Exception as exc: # pylint: disable=broad-except
- self.__logger.error('Unexpected error cleaning - %s', exc)
diff --git a/functest/opnfv_tests/openstack/api/connection_check.py b/functest/opnfv_tests/openstack/api/connection_check.py
index a7a780f67..eaf9767c0 100644
--- a/functest/opnfv_tests/openstack/api/connection_check.py
+++ b/functest/opnfv_tests/openstack/api/connection_check.py
@@ -16,15 +16,27 @@ import os_client_config
import shade
from xtesting.core import testcase
+from functest.utils import env
+from functest.utils import functest_utils
+
class ConnectionCheck(testcase.TestCase):
"""Perform simplest queries"""
__logger = logging.getLogger(__name__)
+ func_list = [
+ "get_network_extensions", "list_aggregates", "list_domains",
+ "list_endpoints", "list_floating_ip_pools", "list_floating_ips",
+ "list_hypervisors", "list_keypairs", "list_networks", "list_ports",
+ "list_role_assignments", "list_roles", "list_routers", "list_servers",
+ "list_subnets"]
+
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'connection_check'
- super(ConnectionCheck, self).__init__(**kwargs)
+ super().__init__(**kwargs)
+ self.output_log_name = 'functest.log'
+ self.output_debug_log_name = 'functest.debug.log'
try:
cloud_config = os_client_config.get_config()
self.cloud = shade.OpenStackCloud(cloud_config=cloud_config)
@@ -32,19 +44,26 @@ class ConnectionCheck(testcase.TestCase):
self.cloud = None
def run(self, **kwargs):
+ # pylint: disable=protected-access
"""Run all read operations to check connections"""
status = testcase.TestCase.EX_RUN_ERROR
try:
assert self.cloud
self.start_time = time.time()
- for func in ["list_aggregates", "list_domains", "list_endpoints",
- "list_floating_ip_pools", "list_floating_ips",
- "list_hypervisors", "list_keypairs", "list_networks",
- "list_ports", "list_role_assignments", "list_roles",
- "list_routers", "list_servers", "list_services",
- "list_subnets"]:
+ self.__logger.debug(
+ "list_services: %s", functest_utils.list_services(self.cloud))
+ if env.get('NO_TENANT_NETWORK').lower() == 'true':
+ self.func_list.remove("list_floating_ip_pools")
+ self.func_list.remove("list_floating_ips")
+ self.func_list.remove("list_routers")
+ for func in self.func_list:
self.__logger.debug(
"%s: %s", func, getattr(self.cloud, func)())
+ data = self.cloud._network_client.get("/service-providers.json")
+ self.__logger.debug(
+ "list_service_providers: %s",
+ self.cloud._get_and_munchify('service_providers', data))
+ functest_utils.get_openstack_version(self.cloud)
self.result = 100
status = testcase.TestCase.EX_OK
except Exception: # pylint: disable=broad-except
diff --git a/functest/ci/__init__.py b/functest/opnfv_tests/openstack/barbican/__init__.py
index e69de29bb..e69de29bb 100644
--- a/functest/ci/__init__.py
+++ b/functest/opnfv_tests/openstack/barbican/__init__.py
diff --git a/functest/opnfv_tests/openstack/barbican/barbican.py b/functest/opnfv_tests/openstack/barbican/barbican.py
new file mode 100644
index 000000000..706304bbf
--- /dev/null
+++ b/functest/opnfv_tests/openstack/barbican/barbican.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2018 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+from six.moves import configparser
+
+from functest.opnfv_tests.openstack.tempest import tempest
+
+
+class Barbican(tempest.TempestCommon):
+
+ def configure(self, **kwargs):
+ super().configure(**kwargs)
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if not rconfig.has_section('auth'):
+ rconfig.add_section('auth')
+ rconfig.set('auth', 'tempest_roles', 'creator')
+ if not rconfig.has_section('glance'):
+ rconfig.add_section('glance')
+ rconfig.set('glance', 'verify_glance_signatures', True)
+ if not rconfig.has_section('ephemeral_storage_encryption'):
+ rconfig.add_section('ephemeral_storage_encryption')
+ rconfig.set('ephemeral_storage_encryption', 'enabled', True)
+ if not rconfig.has_section('image-feature-enabled'):
+ rconfig.add_section('image-feature-enabled')
+ rconfig.set('image-feature-enabled', 'api_v1', False)
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+ self.backup_tempest_config(self.conf_file, self.res_dir)
diff --git a/functest/opnfv_tests/openstack/cinder/cinder_test.py b/functest/opnfv_tests/openstack/cinder/cinder_test.py
index 5354291e6..7d8c0a0bd 100644
--- a/functest/opnfv_tests/openstack/cinder/cinder_test.py
+++ b/functest/opnfv_tests/openstack/cinder/cinder_test.py
@@ -35,7 +35,7 @@ class CinderCheck(singlevm.SingleVm2):
"""Initialize testcase."""
if "case_name" not in kwargs:
kwargs["case_name"] = "cinder_test"
- super(CinderCheck, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.logger = logging.getLogger(__name__)
self.vm2 = None
self.fip2 = None
@@ -52,15 +52,15 @@ class CinderCheck(singlevm.SingleVm2):
return self._write_data() or self._read_data()
def prepare(self):
- super(CinderCheck, self).prepare()
+ super().prepare()
self.vm2 = self.boot_vm(
- '{}-vm2_{}'.format(self.case_name, self.guid),
+ f'{self.case_name}-vm2_{self.guid}',
key_name=self.keypair.id,
security_groups=[self.sec.id])
(self.fip2, self.ssh2) = self.connect(self.vm2)
self.volume = self.cloud.create_volume(
- name='{}-volume_{}'.format(self.case_name, self.guid), size='2',
- timeout=self.volume_timeout)
+ name=f'{self.case_name}-volume_{self.guid}', size='2',
+ timeout=self.volume_timeout, wait=True)
def _write_data(self):
assert self.cloud
@@ -76,12 +76,15 @@ class CinderCheck(singlevm.SingleVm2):
return testcase.TestCase.EX_RUN_ERROR
self.logger.debug("ssh: %s", self.ssh)
(_, stdout, stderr) = self.ssh.exec_command(
- "sh ~/write_data.sh {}".format(env.get('VOLUME_DEVICE_NAME')))
- self.logger.debug("volume_write stdout: %s", stdout.read())
- self.logger.debug("volume_write stderr: %s", stderr.read())
+ f"sh ~/write_data.sh {env.get('VOLUME_DEVICE_NAME')}")
+ self.logger.debug(
+ "volume_write stdout: %s", stdout.read().decode("utf-8"))
+ self.logger.debug(
+ "volume_write stderr: %s", stderr.read().decode("utf-8"))
# Detach volume from VM 1
self.logger.info("Detach volume from VM 1")
- self.cloud.detach_volume(self.sshvm, self.volume)
+ self.cloud.detach_volume(
+ self.sshvm, self.volume, timeout=self.volume_timeout)
return stdout.channel.recv_exit_status()
def _read_data(self):
@@ -101,12 +104,14 @@ class CinderCheck(singlevm.SingleVm2):
return testcase.TestCase.EX_RUN_ERROR
self.logger.debug("ssh: %s", self.ssh2)
(_, stdout, stderr) = self.ssh2.exec_command(
- "sh ~/read_data.sh {}".format(env.get('VOLUME_DEVICE_NAME')))
- self.logger.debug("read volume stdout: %s", stdout.read())
- self.logger.debug("read volume stderr: %s", stderr.read())
+ f"sh ~/read_data.sh {env.get('VOLUME_DEVICE_NAME')}")
+ self.logger.debug(
+ "read volume stdout: %s", stdout.read().decode("utf-8"))
+ self.logger.debug(
+ "read volume stderr: %s", stderr.read().decode("utf-8"))
self.logger.info("Detach volume from VM 2")
- self.cloud.detach_volume(self.vm2, self.volume,
- timeout=self.volume_timeout)
+ self.cloud.detach_volume(
+ self.vm2, self.volume, timeout=self.volume_timeout)
return stdout.channel.recv_exit_status()
def clean(self):
@@ -119,4 +124,4 @@ class CinderCheck(singlevm.SingleVm2):
self.cloud.delete_floating_ip(self.fip2.id)
if self.volume:
self.cloud.delete_volume(self.volume.id)
- super(CinderCheck, self).clean()
+ super().clean()
diff --git a/functest/opnfv_tests/openstack/cinder/write_data.sh b/functest/opnfv_tests/openstack/cinder/write_data.sh
index 6689309b9..16845ba31 100644
--- a/functest/opnfv_tests/openstack/cinder/write_data.sh
+++ b/functest/opnfv_tests/openstack/cinder/write_data.sh
@@ -15,7 +15,7 @@ echo "VOL_DEV_NAME: $VOL_DEV_NAME"
echo "$(lsblk -l -o NAME)"
if [ ! -z $(lsblk -l -o NAME | grep $VOL_DEV_NAME) ]; then
- sudo /usr/sbin/mkfs.ext4 -F /dev/$VOL_DEV_NAME
+ sudo mkfs.ext4 -F /dev/$VOL_DEV_NAME
sudo mount /dev/$VOL_DEV_NAME $DEST
sudo touch $DEST/new_data
if [ -f $DEST/new_data ]; then
diff --git a/functest/opnfv_tests/openstack/patrole/patrole.py b/functest/opnfv_tests/openstack/patrole/patrole.py
index efc513cdb..88c42f269 100644
--- a/functest/opnfv_tests/openstack/patrole/patrole.py
+++ b/functest/opnfv_tests/openstack/patrole/patrole.py
@@ -9,8 +9,6 @@
# pylint: disable=missing-docstring
-import logging
-
from six.moves import configparser
from functest.opnfv_tests.openstack.tempest import tempest
@@ -18,23 +16,13 @@ from functest.opnfv_tests.openstack.tempest import tempest
class Patrole(tempest.TempestCommon):
- __logger = logging.getLogger(__name__)
-
def configure(self, **kwargs):
- super(Patrole, self).configure(**kwargs)
+ super().configure(**kwargs)
rconfig = configparser.RawConfigParser()
rconfig.read(self.conf_file)
- rconfig.add_section('rbac')
- rconfig.set('rbac', 'enable_rbac', True)
- rconfig.set('rbac', 'rbac_test_role', kwargs.get('role', 'admin'))
- with open(self.conf_file, 'wb') as config_file:
+ if not rconfig.has_section('rbac'):
+ rconfig.add_section('rbac')
+ rconfig.set('rbac', 'rbac_test_roles', kwargs.get('roles', 'admin'))
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
self.backup_tempest_config(self.conf_file, self.res_dir)
-
- def run(self, **kwargs):
- for exclude in kwargs.get('exclude', []):
- kwargs['mode'] = "{}(?!.*{})".format(
- kwargs.get('mode', ''), exclude)
- kwargs['mode'] = '{}(?=patrole_tempest_plugin.tests.api.({}))'.format(
- kwargs['mode'], '|'.join(kwargs.get('services', [])))
- return super(Patrole, self).run(**kwargs)
diff --git a/functest/opnfv_tests/openstack/rally/blacklist.txt b/functest/opnfv_tests/openstack/rally/blacklist.txt
deleted file mode 100644
index c9d7c6007..000000000
--- a/functest/opnfv_tests/openstack/rally/blacklist.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-scenario:
- -
- scenarios:
- - '^os-nosdn-lxd-(no)?ha$'
- installers:
- - '.+' # all installers
- tests:
- - NovaServers.boot_server_from_volume_and_delete
- -
- scenarios:
- - '^os-' # all scenarios
- installers:
- - '.+' # all installers
- tests:
- # Following test occasionally fails due to race condition issue on
- # quota manipulation in nova.
- # Ref: https://bugs.launchpad.net/nova/+bug/1552622
- - 'Quotas.nova_update_and_delete'
-
-functionality:
- -
- functions:
- - no_migration
- tests:
- - NovaServers.boot_and_live_migrate_server
- - NovaServers.boot_server_attach_created_volume_and_live_migrate
- - NovaServers.boot_server_from_volume_and_live_migrate
- - NovaServers.boot_and_migrate_server
diff --git a/functest/opnfv_tests/openstack/rally/blacklist.yaml b/functest/opnfv_tests/openstack/rally/blacklist.yaml
new file mode 100644
index 000000000..e16b83ba6
--- /dev/null
+++ b/functest/opnfv_tests/openstack/rally/blacklist.yaml
@@ -0,0 +1,40 @@
+---
+scenario:
+
+functionality:
+ -
+ functions:
+ - block_migration
+ tests:
+ - NovaServers.boot_server_from_volume_and_live_migrate
+ -
+ functions:
+ - no_migration
+ tests:
+ - NovaServers.boot_and_live_migrate_server
+ - NovaServers.boot_server_attach_created_volume_and_live_migrate
+ - NovaServers.boot_server_from_volume_and_live_migrate
+ - NovaServers.boot_and_migrate_server
+ -
+ functions:
+ - no_net_trunk_service
+ tests:
+ - '^NeutronTrunk'
+ -
+ functions:
+ - no_floating_ip
+ tests:
+ - HeatStacks.create_and_delete_stack
+ - NovaServers.boot_and_associate_floating_ip
+ - NovaServers.boot_server_and_list_interfaces
+ - NovaServers.boot_server_associate_and_dissociate_floating_ip
+ - NeutronNetworks.create_and_delete_floating_ips
+ - NeutronNetworks.create_and_list_floating_ips
+ - NeutronNetworks.associate_and_dissociate_floating_ips
+ - VMTasks.dd_load_test
+ - NeutronNetworks.create_and_delete_routers
+ - NeutronNetworks.create_and_list_routers
+ - NeutronNetworks.create_and_show_routers
+ - NeutronNetworks.create_and_update_routers
+ - NeutronNetworks.set_and_clear_router_gateway
+ - Quotas.neutron_update
diff --git a/functest/opnfv_tests/openstack/rally/macro/macro.yaml b/functest/opnfv_tests/openstack/rally/macro/macro.yaml
index 48c0333e9..2536c92f0 100644
--- a/functest/opnfv_tests/openstack/rally/macro/macro.yaml
+++ b/functest/opnfv_tests/openstack/rally/macro/macro.yaml
@@ -95,3 +95,9 @@
disk_format: {{ type }}
image_location: {{ location }}
{%- endmacro %}
+
+{%- macro volume_service(version, service_type) %}
+ cinder:
+ version: {{ version }}
+ service_type: {{ service_type }}
+{%- endmacro %}
diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py
index 2cdb03cb3..3d897e25d 100644
--- a/functest/opnfv_tests/openstack/rally/rally.py
+++ b/functest/opnfv_tests/openstack/rally/rally.py
@@ -11,85 +11,118 @@
"""Rally testcases implementation."""
from __future__ import division
+from __future__ import print_function
+import fileinput
import json
import logging
import os
import re
+import shutil
import subprocess
import time
import pkg_resources
import prettytable
+from ruamel.yaml import YAML
+import six
+from six.moves import configparser
from xtesting.core import testcase
-from xtesting.energy import energy
import yaml
from functest.core import singlevm
-from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils import config
from functest.utils import env
+from functest.utils import functest_utils
LOGGER = logging.getLogger(__name__)
-class RallyBase(singlevm.VmReady1):
+class RallyBase(singlevm.VmReady2):
"""Base class form Rally testcases implementation."""
- # pylint: disable=too-many-instance-attributes
- TESTS = ['authenticate', 'glance', 'cinder', 'gnocchi', 'heat',
- 'keystone', 'neutron', 'nova', 'quotas', 'vm', 'all']
+ # pylint: disable=too-many-instance-attributes, too-many-public-methods
+ stests = ['authenticate', 'glance', 'cinder', 'gnocchi', 'heat',
+ 'keystone', 'neutron', 'nova', 'quotas', 'swift', 'barbican',
+ 'vm']
- RALLY_DIR = pkg_resources.resource_filename(
+ rally_conf_path = "/etc/rally/rally.conf"
+ rally_aar4_patch_path = pkg_resources.resource_filename(
+ 'functest', 'ci/rally_aarch64_patch.conf')
+ rally_dir = pkg_resources.resource_filename(
'functest', 'opnfv_tests/openstack/rally')
- RALLY_SCENARIO_DIR = pkg_resources.resource_filename(
+ rally_scenario_dir = pkg_resources.resource_filename(
'functest', 'opnfv_tests/openstack/rally/scenario')
- TEMPLATE_DIR = pkg_resources.resource_filename(
+ template_dir = pkg_resources.resource_filename(
'functest', 'opnfv_tests/openstack/rally/scenario/templates')
- SUPPORT_DIR = pkg_resources.resource_filename(
+ support_dir = pkg_resources.resource_filename(
'functest', 'opnfv_tests/openstack/rally/scenario/support')
- USERS_AMOUNT = 2
- TENANTS_AMOUNT = 3
- ITERATIONS_AMOUNT = 10
- CONCURRENCY = 4
- RESULTS_DIR = os.path.join(getattr(config.CONF, 'dir_results'), 'rally')
- BLACKLIST_FILE = os.path.join(RALLY_DIR, "blacklist.txt")
- TEMP_DIR = os.path.join(RALLY_DIR, "var")
+ users_amount = 2
+ tenants_amount = 3
+ iterations_amount = 10
+ concurrency = 4
+ volume_version = 3
+ volume_service_type = "volumev3"
+ blacklist_file = os.path.join(rally_dir, "blacklist.yaml")
+ task_dir = os.path.join(getattr(config.CONF, 'dir_rally_data'), 'task')
+ temp_dir = os.path.join(task_dir, 'var')
visibility = 'public'
shared_network = True
+ task_timeout = 3600
+ username = 'cirros'
def __init__(self, **kwargs):
"""Initialize RallyBase object."""
- super(RallyBase, self).__init__(**kwargs)
+ super().__init__(**kwargs)
+ assert self.orig_cloud
+ assert self.project
+ if self.orig_cloud.get_role("admin"):
+ role_name = "admin"
+ elif self.orig_cloud.get_role("Admin"):
+ role_name = "Admin"
+ else:
+ raise Exception("Cannot detect neither admin nor Admin")
+ self.orig_cloud.grant_role(
+ role_name, user=self.project.user.id,
+ project=self.project.project.id,
+ domain=self.project.domain.id)
+ self.results_dir = os.path.join(
+ getattr(config.CONF, 'dir_results'), self.case_name)
+ self.task_file = ''
self.creators = []
- self.mode = ''
self.summary = []
self.scenario_dir = ''
self.smoke = None
- self.test_name = None
self.start_time = None
self.result = None
- self.details = None
self.compute_cnt = 0
self.flavor_alt = None
+ self.tests = []
+ self.run_cmd = ''
+ self.network_extensions = []
+ self.services = []
- def _build_task_args(self, test_file_name):
+ def build_task_args(self, test_name):
"""Build arguments for the Rally task."""
- task_args = {'service_list': [test_file_name]}
+ task_args = {'service_list': [test_name]}
task_args['image_name'] = str(self.image.name)
task_args['flavor_name'] = str(self.flavor.name)
task_args['flavor_alt_name'] = str(self.flavor_alt.name)
task_args['glance_image_location'] = str(self.filename)
task_args['glance_image_format'] = str(self.image_format)
- task_args['tmpl_dir'] = str(self.TEMPLATE_DIR)
- task_args['sup_dir'] = str(self.SUPPORT_DIR)
- task_args['users_amount'] = self.USERS_AMOUNT
- task_args['tenants_amount'] = self.TENANTS_AMOUNT
+ task_args['tmpl_dir'] = str(self.template_dir)
+ task_args['sup_dir'] = str(self.support_dir)
+ task_args['users_amount'] = self.users_amount
+ task_args['tenants_amount'] = self.tenants_amount
task_args['use_existing_users'] = False
- task_args['iterations'] = self.ITERATIONS_AMOUNT
- task_args['concurrency'] = self.CONCURRENCY
+ task_args['iterations'] = self.iterations_amount
+ task_args['concurrency'] = self.concurrency
task_args['smoke'] = self.smoke
+ task_args['volume_version'] = self.volume_version
+ task_args['volume_service_type'] = self.volume_service_type
+ task_args['block_migration'] = env.get("BLOCK_MIGRATION").lower()
+ task_args['username'] = self.username
if self.ext_net:
task_args['floating_network'] = str(self.ext_net.name)
@@ -99,14 +132,21 @@ class RallyBase(singlevm.VmReady1):
if self.network:
task_args['netid'] = str(self.network.id)
else:
- task_args['netid'] = ''
+ LOGGER.warning(
+ 'No tenant network created. '
+ 'Trying EXTERNAL_NETWORK as a fallback')
+ if env.get("EXTERNAL_NETWORK"):
+ network = self.cloud.get_network(env.get("EXTERNAL_NETWORK"))
+ task_args['netid'] = str(network.id) if network else ''
+ else:
+ task_args['netid'] = ''
return task_args
def _prepare_test_list(self, test_name):
"""Build the list of test cases to be executed."""
- test_yaml_file_name = 'opnfv-{}.yaml'.format(test_name)
- scenario_file_name = os.path.join(self.RALLY_SCENARIO_DIR,
+ test_yaml_file_name = f'opnfv-{test_name}.yaml'
+ scenario_file_name = os.path.join(self.rally_scenario_dir,
test_yaml_file_name)
if not os.path.exists(scenario_file_name):
@@ -114,33 +154,108 @@ class RallyBase(singlevm.VmReady1):
test_yaml_file_name)
if not os.path.exists(scenario_file_name):
- raise Exception("The scenario '%s' does not exist."
- % scenario_file_name)
+ raise Exception(
+ f"The scenario '{scenario_file_name}' does not exist.")
LOGGER.debug('Scenario fetched from : %s', scenario_file_name)
- test_file_name = os.path.join(self.TEMP_DIR, test_yaml_file_name)
+ test_file_name = os.path.join(self.temp_dir, test_yaml_file_name)
- if not os.path.exists(self.TEMP_DIR):
- os.makedirs(self.TEMP_DIR)
+ if not os.path.exists(self.temp_dir):
+ os.makedirs(self.temp_dir)
- self._apply_blacklist(scenario_file_name, test_file_name)
+ self.apply_blacklist(scenario_file_name, test_file_name)
return test_file_name
@staticmethod
- def get_task_id(cmd_raw):
+ def get_verifier_deployment_id():
+ """
+ Returns deployment id for active Rally deployment
+ """
+ cmd = ("rally deployment list | awk '/" +
+ getattr(config.CONF, 'rally_deployment_name') +
+ "/ {print $2}'")
+ with subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT) as proc:
+ deployment_uuid = proc.stdout.readline().rstrip()
+ return deployment_uuid.decode("utf-8")
+
+ @staticmethod
+ def create_rally_deployment(environ=None):
+ # pylint: disable=unexpected-keyword-arg
+ """Create new rally deployment"""
+ # set the architecture to default
+ pod_arch = env.get("POD_ARCH")
+ arch_filter = ['aarch64']
+
+ if pod_arch and pod_arch in arch_filter:
+ LOGGER.info("Apply aarch64 specific to rally config...")
+ with open(
+ RallyBase.rally_aar4_patch_path, "r",
+ encoding='utf-8') as pfile:
+ rally_patch_conf = pfile.read()
+
+ for line in fileinput.input(RallyBase.rally_conf_path):
+ print(line, end=' ')
+ if "cirros|testvm" in line:
+ print(rally_patch_conf)
+
+ LOGGER.info("Creating Rally environment...")
+ try:
+ cmd = ['rally', 'deployment', 'destroy',
+ '--deployment',
+ str(getattr(config.CONF, 'rally_deployment_name'))]
+ output = subprocess.check_output(cmd)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+ except subprocess.CalledProcessError:
+ pass
+
+ cmd = ['rally', 'deployment', 'create', '--fromenv',
+ '--name', str(getattr(config.CONF, 'rally_deployment_name'))]
+ output = subprocess.check_output(cmd, env=environ)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+
+ cmd = ['rally', 'deployment', 'check']
+ output = subprocess.check_output(cmd)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+ return RallyBase.get_verifier_deployment_id()
+
+ @staticmethod
+ def update_keystone_default_role(rally_conf='/etc/rally/rally.conf'):
+ """Set keystone_default_role in rally.conf"""
+ if env.get("NEW_USER_ROLE").lower() != "member":
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(rally_conf)
+ if not rconfig.has_section('openstack'):
+ rconfig.add_section('openstack')
+ rconfig.set(
+ 'openstack', 'keystone_default_role', env.get("NEW_USER_ROLE"))
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ @staticmethod
+ def clean_rally_conf(rally_conf='/etc/rally/rally.conf'):
+ """Clean Rally config"""
+ if env.get("NEW_USER_ROLE").lower() != "member":
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(rally_conf)
+ if rconfig.has_option('openstack', 'keystone_default_role'):
+ rconfig.remove_option('openstack', 'keystone_default_role')
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ @staticmethod
+ def get_task_id(tag):
"""
Get task id from command rally result.
- :param cmd_raw:
+ :param tag:
:return: task_id as string
"""
- taskid_re = re.compile('^Task +(.*): started$')
- for line in cmd_raw.splitlines(True):
- line = line.strip()
- match = taskid_re.match(line)
- if match:
- return match.group(1)
- return None
+ cmd = ["rally", "task", "list", "--tag", tag, "--uuids-only"]
+ output = subprocess.check_output(cmd).decode("utf-8").rstrip()
+ LOGGER.info("%s: %s", " ".join(cmd), output)
+ return output
@staticmethod
def task_succeed(json_raw):
@@ -165,35 +280,31 @@ class RallyBase(singlevm.VmReady1):
"""Determine if migration is supported."""
if self.compute_cnt > 1:
return True
-
return False
- @staticmethod
- def get_cmd_output(proc):
- """Get command stdout."""
- result = ""
- for line in proc.stdout:
- result += line
- return result
+ def _network_trunk_supported(self):
+ """Determine if network trunk service is available"""
+ if 'trunk' in self.network_extensions:
+ return True
+ return False
@staticmethod
def excl_scenario():
"""Exclude scenario."""
black_tests = []
try:
- with open(RallyBase.BLACKLIST_FILE, 'r') as black_list_file:
+ with open(
+ RallyBase.blacklist_file, 'r',
+ encoding='utf-8') as black_list_file:
black_list_yaml = yaml.safe_load(black_list_file)
- installer_type = env.get('INSTALLER_TYPE')
deploy_scenario = env.get('DEPLOY_SCENARIO')
- if (bool(installer_type) and bool(deploy_scenario) and
+ if (bool(deploy_scenario) and
'scenario' in black_list_yaml.keys()):
for item in black_list_yaml['scenario']:
scenarios = item['scenarios']
- installers = item['installers']
in_it = RallyBase.in_iterable_re
- if (in_it(deploy_scenario, scenarios) and
- in_it(installer_type, installers)):
+ if in_it(deploy_scenario, scenarios):
tests = item['tests']
black_tests.extend(tests)
except Exception: # pylint: disable=broad-except
@@ -228,11 +339,19 @@ class RallyBase(singlevm.VmReady1):
func_list = []
try:
- with open(RallyBase.BLACKLIST_FILE, 'r') as black_list_file:
+ with open(
+ RallyBase.blacklist_file, 'r',
+ encoding='utf-8') as black_list_file:
black_list_yaml = yaml.safe_load(black_list_file)
+ if env.get('BLOCK_MIGRATION').lower() == 'true':
+ func_list.append("block_migration")
if not self._migration_supported():
func_list.append("no_migration")
+ if not self._network_trunk_supported():
+ func_list.append("no_net_trunk_service")
+ if not self.ext_net:
+ func_list.append("no_floating_ip")
if 'functionality' in black_list_yaml.keys():
for item in black_list_yaml['functionality']:
@@ -246,34 +365,28 @@ class RallyBase(singlevm.VmReady1):
return black_tests
- def _apply_blacklist(self, case_file_name, result_file_name):
+ def apply_blacklist(self, case_file_name, result_file_name):
"""Apply blacklist."""
LOGGER.debug("Applying blacklist...")
- cases_file = open(case_file_name, 'r')
- result_file = open(result_file_name, 'w')
-
- black_tests = list(set(self.excl_func() +
- self.excl_scenario()))
-
- if black_tests:
- LOGGER.debug("Blacklisted tests: %s", str(black_tests))
-
- include = True
- for cases_line in cases_file:
- if include:
- for black_tests_line in black_tests:
- if re.search(black_tests_line,
- cases_line.strip().rstrip(':')):
- include = False
- break
+ with open(case_file_name, 'r', encoding='utf-8') as cases_file, open(
+ result_file_name, 'w', encoding='utf-8') as result_file:
+ black_tests = list(set(self.excl_func() + self.excl_scenario()))
+ if black_tests:
+ LOGGER.debug("Blacklisted tests: %s", str(black_tests))
+
+ include = True
+ for cases_line in cases_file:
+ if include:
+ for black_tests_line in black_tests:
+ if re.search(black_tests_line,
+ cases_line.strip().rstrip(':')):
+ include = False
+ break
+ else:
+ result_file.write(str(cases_line))
else:
- result_file.write(str(cases_line))
- else:
- if cases_line.isspace():
- include = True
-
- cases_file.close()
- result_file.close()
+ if cases_line.isspace():
+ include = True
@staticmethod
def file_is_empty(file_name):
@@ -289,41 +402,28 @@ class RallyBase(singlevm.VmReady1):
def _save_results(self, test_name, task_id):
""" Generate and save task execution results"""
# check for result directory and create it otherwise
- if not os.path.exists(self.RESULTS_DIR):
+ if not os.path.exists(self.results_dir):
LOGGER.debug('%s does not exist, we create it.',
- self.RESULTS_DIR)
- os.makedirs(self.RESULTS_DIR)
+ self.results_dir)
+ os.makedirs(self.results_dir)
# put detailed result to log
cmd = (["rally", "task", "detailed", "--uuid", task_id])
LOGGER.debug('running command: %s', cmd)
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- json_detailed = self.get_cmd_output(proc)
- LOGGER.info('%s', json_detailed)
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
# save report as JSON
- cmd = (["rally", "task", "report", "--json", "--uuid", task_id])
+ report_json_name = f'{test_name}.json'
+ report_json_dir = os.path.join(self.results_dir, report_json_name)
+ cmd = (["rally", "task", "report", "--json", "--uuid", task_id,
+ "--out", report_json_dir])
LOGGER.debug('running command: %s', cmd)
- with open(os.devnull, 'w') as devnull:
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=devnull)
- json_results = self.get_cmd_output(proc)
- report_json_name = 'opnfv-{}.json'.format(test_name)
- report_json_dir = os.path.join(self.RESULTS_DIR, report_json_name)
- with open(report_json_dir, 'w') as r_file:
- LOGGER.debug('saving json file')
- r_file.write(json_results)
-
- # save report as HTML
- report_html_name = 'opnfv-{}.html'.format(test_name)
- report_html_dir = os.path.join(self.RESULTS_DIR, report_html_name)
- cmd = (["rally", "task", "report", "--html", "--uuid", task_id,
- "--out", report_html_dir])
- LOGGER.debug('running command: %s', cmd)
- with open(os.devnull, 'w') as devnull:
- subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=devnull)
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+ with open(report_json_dir, encoding='utf-8') as json_file:
+ json_results = json_file.read()
self._append_summary(json_results, test_name)
# parse JSON operation result
@@ -332,54 +432,37 @@ class RallyBase(singlevm.VmReady1):
else:
LOGGER.info('Test scenario: "%s" Failed.', test_name)
- def _run_task(self, test_name):
+ def run_task(self, test_name):
"""Run a task."""
LOGGER.info('Starting test scenario "%s" ...', test_name)
-
- task_file = os.path.join(self.RALLY_DIR, 'task.yaml')
- if not os.path.exists(task_file):
- LOGGER.error("Task file '%s' does not exist.", task_file)
- raise Exception("Task file '{}' does not exist.".format(task_file))
-
- file_name = self._prepare_test_list(test_name)
- if self.file_is_empty(file_name):
- LOGGER.info('No tests for scenario "%s"', test_name)
- return
-
- cmd = (["rally", "task", "start", "--abort-on-sla-failure", "--task",
- task_file, "--task-args",
- str(self._build_task_args(test_name))])
- LOGGER.debug('running command: %s', cmd)
-
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- output = self.get_cmd_output(proc)
- task_id = self.get_task_id(output)
-
+ LOGGER.debug('running command: %s', self.run_cmd)
+ if six.PY3:
+ subprocess.call(
+ self.run_cmd, timeout=self.task_timeout,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ else:
+ with open(os.devnull, 'wb') as devnull:
+ subprocess.call(self.run_cmd, stdout=devnull, stderr=devnull)
+ task_id = self.get_task_id(test_name)
LOGGER.debug('task_id : %s', task_id)
-
- if task_id is None:
- LOGGER.error('Failed to retrieve task_id, validating task...')
- cmd = (["rally", "task", "validate", "--task", task_file,
- "--task-args", str(self._build_task_args(test_name))])
- LOGGER.debug('running command: %s', cmd)
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- output = self.get_cmd_output(proc)
- LOGGER.error("Task validation result:" + "\n" + output)
+ if not task_id:
+ LOGGER.error("Failed to retrieve task_id")
raise Exception("Failed to retrieve task id")
-
self._save_results(test_name, task_id)
def _append_summary(self, json_raw, test_name):
+ # pylint: disable=too-many-locals
"""Update statistics summary info."""
nb_tests = 0
nb_success = 0
overall_duration = 0.0
+ success = []
+ failures = []
rally_report = json.loads(json_raw)
for task in rally_report.get('tasks'):
for subtask in task.get('subtasks'):
+ has_errors = False
for workload in subtask.get('workloads'):
if workload.get('full_duration'):
overall_duration += workload.get('full_duration')
@@ -390,34 +473,80 @@ class RallyBase(singlevm.VmReady1):
for result in workload.get('data'):
if not result.get('error'):
nb_success += 1
+ else:
+ has_errors = True
+
+ if has_errors:
+ failures.append(subtask['title'])
+ else:
+ success.append(subtask['title'])
scenario_summary = {'test_name': test_name,
'overall_duration': overall_duration,
'nb_tests': nb_tests,
'nb_success': nb_success,
+ 'success': success,
+ 'failures': failures,
'task_status': self.task_succeed(json_raw)}
self.summary.append(scenario_summary)
- def _prepare_env(self):
- """Create resources needed by test scenarios."""
+ def prepare_run(self, **kwargs):
+ """Prepare resources needed by test scenarios."""
assert self.cloud
- LOGGER.debug('Validating the test name...')
- if self.test_name not in self.TESTS:
- raise Exception("Test name '%s' is invalid" % self.test_name)
-
- self.compute_cnt = len(self.cloud.list_hypervisors())
+ LOGGER.debug('Validating run tests...')
+ for test in kwargs.get('tests', self.stests):
+ if test in self.stests:
+ self.tests.append(test)
+ else:
+ raise Exception(f"Test name '{test}' is invalid")
+
+ if not os.path.exists(self.task_dir):
+ os.makedirs(self.task_dir)
+
+ task = os.path.join(self.rally_dir, 'task.yaml')
+ if not os.path.exists(task):
+ LOGGER.error("Task file '%s' does not exist.", task)
+ raise Exception(f"Task file '{task}' does not exist.")
+ self.task_file = os.path.join(self.task_dir, 'task.yaml')
+ shutil.copyfile(task, self.task_file)
+
+ task_macro = os.path.join(self.rally_dir, 'macro')
+ if not os.path.exists(task_macro):
+ LOGGER.error("Task macro dir '%s' does not exist.", task_macro)
+ raise Exception(f"Task macro dir '{task_macro}' does not exist.")
+ macro_dir = os.path.join(self.task_dir, 'macro')
+ if os.path.exists(macro_dir):
+ shutil.rmtree(macro_dir)
+ shutil.copytree(task_macro, macro_dir)
+
+ self.update_keystone_default_role()
+ self.compute_cnt = self.count_hypervisors()
+ self.network_extensions = self.cloud.get_network_extensions()
self.flavor_alt = self.create_flavor_alt()
+ self.services = [service.name for service in
+ functest_utils.list_services(self.cloud)]
+
LOGGER.debug("flavor: %s", self.flavor_alt)
- def _run_tests(self):
+ def prepare_task(self, test_name):
+ """Prepare resources for test run."""
+ file_name = self._prepare_test_list(test_name)
+ if self.file_is_empty(file_name):
+ LOGGER.info('No tests for scenario "%s"', test_name)
+ return False
+ self.run_cmd = (["rally", "task", "start", "--tag", test_name,
+ "--abort-on-sla-failure",
+ "--task", self.task_file, "--task-args",
+ str(self.build_task_args(test_name))])
+ return True
+
+ def run_tests(self, **kwargs):
"""Execute tests."""
- if self.test_name == 'all':
- for test in self.TESTS:
- if test == 'all' or test == 'vm':
- continue
- self._run_task(test)
- else:
- self._run_task(self.test_name)
+ optional = kwargs.get('optional', [])
+ for test in self.tests:
+ if test in self.services or test not in optional:
+ if self.prepare_task(test):
+ self.run_task(test)
def _generate_report(self):
"""Generate test execution summary report."""
@@ -445,15 +574,17 @@ class RallyBase(singlevm.VmReady1):
success_avg = 100 * item['nb_success'] / item['nb_tests']
except ZeroDivisionError:
success_avg = 0
- success_str = str("{:0.2f}".format(success_avg)) + '%'
- duration_str = time.strftime("%M:%S",
+ success_str = f"{success_avg:0.2f}%"
+ duration_str = time.strftime("%H:%M:%S",
time.gmtime(item['overall_duration']))
res_table.add_row([item['test_name'], duration_str,
item['nb_tests'], success_str])
payload.append({'module': item['test_name'],
'details': {'duration': item['overall_duration'],
'nb tests': item['nb_tests'],
- 'success': success_str}})
+ 'success rate': success_str,
+ 'success': item['success'],
+ 'failures': item['failures']}})
total_duration_str = time.strftime("%H:%M:%S",
time.gmtime(total_duration))
@@ -461,7 +592,7 @@ class RallyBase(singlevm.VmReady1):
self.result = 100 * total_nb_success / total_nb_tests
except ZeroDivisionError:
self.result = 100
- success_rate = "{:0.2f}".format(self.result)
+ success_rate = f"{self.result:0.2f}"
success_rate_str = str(success_rate) + '%'
res_table.add_row(["", "", "", ""])
res_table.add_row(["TOTAL:", total_duration_str, total_nb_tests,
@@ -471,16 +602,52 @@ class RallyBase(singlevm.VmReady1):
LOGGER.info("Rally '%s' success_rate is %s%% in %s/%s modules",
self.case_name, success_rate, nb_modules,
len(self.summary))
- payload.append({'summary': {'duration': total_duration,
- 'nb tests': total_nb_tests,
- 'nb success': success_rate}})
- self.details = payload
+ self.details['summary'] = {'duration': total_duration,
+ 'nb tests': total_nb_tests,
+ 'nb success': success_rate}
+ self.details["modules"] = payload
+
+ @staticmethod
+ def export_task(file_name, export_type="html"):
+ """Export all task results (e.g. html or xunit report)
+
+ Raises:
+ subprocess.CalledProcessError: if Rally doesn't return 0
+
+ Returns:
+ None
+ """
+ cmd = ["rally", "task", "export", "--type", export_type,
+ "--deployment",
+ str(getattr(config.CONF, 'rally_deployment_name')),
+ "--to", file_name]
+ LOGGER.debug('running command: %s', cmd)
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+
+ @staticmethod
+ def verify_report(file_name, uuid, export_type="html"):
+ """Generate the verifier report (e.g. html or xunit report)
+
+ Raises:
+ subprocess.CalledProcessError: if Rally doesn't return 0
+
+ Returns:
+ None
+ """
+ cmd = ["rally", "verify", "report", "--type", export_type,
+ "--uuid", uuid, "--to", file_name]
+ LOGGER.debug('running command: %s', cmd)
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
def clean(self):
"""Cleanup of OpenStack resources. Should be called on completion."""
- super(RallyBase, self).clean()
+ self.clean_rally_conf()
+ self.clean_rally_logs()
if self.flavor_alt:
self.orig_cloud.delete_flavor(self.flavor_alt.id)
+ super().clean()
def is_successful(self):
"""The overall result of the test."""
@@ -488,22 +655,57 @@ class RallyBase(singlevm.VmReady1):
if item['task_status'] is False:
return testcase.TestCase.EX_TESTCASE_FAILED
- return super(RallyBase, self).is_successful()
+ return super().is_successful()
+
+ @staticmethod
+ def update_rally_logs(res_dir, rally_conf='/etc/rally/rally.conf'):
+ """Print rally logs in res dir"""
+ if not os.path.exists(res_dir):
+ os.makedirs(res_dir)
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(rally_conf)
+ rconfig.set('DEFAULT', 'debug', True)
+ rconfig.set('DEFAULT', 'use_stderr', False)
+ rconfig.set('DEFAULT', 'log-file', 'rally.log')
+ rconfig.set('DEFAULT', 'log_dir', res_dir)
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ @staticmethod
+ def clean_rally_logs(rally_conf='/etc/rally/rally.conf'):
+ """Clean Rally config"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(rally_conf)
+ if rconfig.has_option('DEFAULT', 'use_stderr'):
+ rconfig.remove_option('DEFAULT', 'use_stderr')
+ if rconfig.has_option('DEFAULT', 'debug'):
+ rconfig.remove_option('DEFAULT', 'debug')
+ if rconfig.has_option('DEFAULT', 'log-file'):
+ rconfig.remove_option('DEFAULT', 'log-file')
+ if rconfig.has_option('DEFAULT', 'log_dir'):
+ rconfig.remove_option('DEFAULT', 'log_dir')
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
- @energy.enable_recording
def run(self, **kwargs):
"""Run testcase."""
self.start_time = time.time()
try:
- assert super(RallyBase, self).run(
+ assert super().run(
**kwargs) == testcase.TestCase.EX_OK
- conf_utils.create_rally_deployment()
- self._prepare_env()
- self._run_tests()
+ self.update_rally_logs(self.res_dir)
+ self.create_rally_deployment(environ=self.project.get_environ())
+ self.prepare_run(**kwargs)
+ self.run_tests(**kwargs)
self._generate_report()
+ self.export_task(
+ f"{self.results_dir}/{self.case_name}.html")
+ self.export_task(
+ f"{self.results_dir}/{self.case_name}.xml",
+ export_type="junit-xml")
res = testcase.TestCase.EX_OK
- except Exception as exc: # pylint: disable=broad-except
- LOGGER.error('Error with run: %s', exc)
+ except Exception: # pylint: disable=broad-except
+ LOGGER.exception('Error with run:')
self.result = 0
res = testcase.TestCase.EX_RUN_ERROR
self.stop_time = time.time()
@@ -517,22 +719,120 @@ class RallySanity(RallyBase):
"""Initialize RallySanity object."""
if "case_name" not in kwargs:
kwargs["case_name"] = "rally_sanity"
- super(RallySanity, self).__init__(**kwargs)
- self.mode = 'sanity'
- self.test_name = 'all'
+ super().__init__(**kwargs)
self.smoke = True
- self.scenario_dir = os.path.join(self.RALLY_SCENARIO_DIR, 'sanity')
+ self.scenario_dir = os.path.join(self.rally_scenario_dir, 'sanity')
class RallyFull(RallyBase):
"""Rally full testcase implementation."""
+ task_timeout = 7200
+
def __init__(self, **kwargs):
"""Initialize RallyFull object."""
if "case_name" not in kwargs:
kwargs["case_name"] = "rally_full"
- super(RallyFull, self).__init__(**kwargs)
- self.mode = 'full'
- self.test_name = 'all'
+ super().__init__(**kwargs)
self.smoke = False
- self.scenario_dir = os.path.join(self.RALLY_SCENARIO_DIR, 'full')
+ self.scenario_dir = os.path.join(self.rally_scenario_dir, 'full')
+
+
+class RallyJobs(RallyBase):
+ """Rally OpenStack CI testcase implementation."""
+
+ stests = ["neutron"]
+ task_timeout = 7200
+
+ def __init__(self, **kwargs):
+ """Initialize RallyJobs object."""
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "rally_jobs"
+ super().__init__(**kwargs)
+ self.task_file = os.path.join(self.rally_dir, 'rally_jobs.yaml')
+ self.task_yaml = None
+
+ def prepare_run(self, **kwargs):
+ """Create resources needed by test scenarios."""
+ super().prepare_run(**kwargs)
+ with open(
+ os.path.join(self.rally_dir, 'rally_jobs.yaml'),
+ 'r', encoding='utf-8') as task_file:
+ self.task_yaml = yaml.safe_load(task_file)
+
+ for task in self.task_yaml:
+ if task not in self.tests:
+ raise Exception(f"Test '{task}' not in '{self.tests}'")
+
+ def apply_blacklist(self, case_file_name, result_file_name):
+ # pylint: disable=too-many-branches
+ """Apply blacklist."""
+ LOGGER.debug("Applying blacklist...")
+ black_tests = list(set(self.excl_func() +
+ self.excl_scenario()))
+ if black_tests:
+ LOGGER.debug("Blacklisted tests: %s", str(black_tests))
+
+ template = YAML(typ='jinja2')
+ with open(case_file_name, 'r', encoding='utf-8') as fname:
+ cases = template.load(fname)
+ if cases.get("version", 1) == 1:
+ # scenarios in dictionary
+ for name in cases.keys():
+ if self.in_iterable_re(name, black_tests):
+ cases.pop(name)
+ else:
+ # workloads in subtasks
+ for sind, subtask in reversed(list(
+ enumerate(cases.get('subtasks', [])))):
+ for wind, workload in reversed(list(
+ enumerate(subtask.get('workloads', [])))):
+ scenario = workload.get('scenario', {})
+ for name in scenario.keys():
+ if self.in_iterable_re(name, black_tests):
+ cases['subtasks'][sind]['workloads'].pop(wind)
+ break
+ if 'workloads' in cases['subtasks'][sind]:
+ if not cases['subtasks'][sind]['workloads']:
+ cases['subtasks'].pop(sind)
+ # scenarios in subtasks
+ for sind, subtask in reversed(list(
+ enumerate(cases.get('subtasks', [])))):
+ scenario = subtask.get('scenario', {})
+ for name in scenario.keys():
+ if self.in_iterable_re(name, black_tests):
+ cases['subtasks'].pop(sind)
+ break
+
+ with open(result_file_name, 'w', encoding='utf-8') as fname:
+ template.dump(cases, fname)
+
+ def build_task_args(self, test_name):
+ """Build arguments for the Rally task."""
+ task_args = {}
+ if self.ext_net:
+ task_args['floating_network'] = str(self.ext_net.name)
+ else:
+ task_args['floating_network'] = ''
+ task_args['image_name'] = str(self.image.name)
+ task_args['flavor_name'] = str(self.flavor.name)
+ return task_args
+
+ def prepare_task(self, test_name):
+ """Prepare resources for test run."""
+ jobs_dir = os.path.join(
+ getattr(config.CONF, 'dir_rally_data'), test_name, 'rally-jobs')
+ task_name = self.task_yaml.get(test_name).get("task")
+ task = os.path.join(jobs_dir, task_name)
+ if not os.path.exists(task):
+ raise Exception(f"The scenario '{task}' does not exist.")
+ LOGGER.debug('Scenario fetched from : %s', task)
+
+ if not os.path.exists(self.temp_dir):
+ os.makedirs(self.temp_dir)
+ task_file_name = os.path.join(self.temp_dir, task_name)
+ self.apply_blacklist(task, task_file_name)
+ self.run_cmd = (["rally", "task", "start", "--tag", test_name,
+ "--task", task_file_name,
+ "--task-args", str(self.build_task_args(test_name))])
+ return True
diff --git a/functest/opnfv_tests/openstack/rally/rally_jobs.yaml b/functest/opnfv_tests/openstack/rally/rally_jobs.yaml
new file mode 100644
index 000000000..2092fb4cf
--- /dev/null
+++ b/functest/opnfv_tests/openstack/rally/rally_jobs.yaml
@@ -0,0 +1,3 @@
+---
+neutron:
+ task: task-neutron.yaml
diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml
index f36d0b2d9..7abeeac68 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml
@@ -8,6 +8,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -23,6 +25,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{{ volumes() }}
{% endcall %}
runner:
@@ -39,6 +43,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -52,6 +58,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -70,6 +78,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -91,6 +101,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -103,7 +115,7 @@
{{ vm_params(image_name,flavor_name) }}
size:
min: 1
- max: 5
+ max: 1
create_vm_params:
nics:
- net-id: {{ netid }}
@@ -111,6 +123,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -123,17 +137,21 @@
size: 1
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
-
args:
size:
min: 1
- max: 5
+ max: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -148,6 +166,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
volumes:
size: 1
volumes_per_tenant: 4
@@ -165,6 +185,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{{ volumes() }}
{% endcall %}
runner:
@@ -182,6 +204,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -194,6 +218,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -206,6 +232,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -221,6 +249,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -235,6 +265,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{{ volumes() }}
{% endcall %}
runner:
@@ -250,6 +282,8 @@
read_iops_sec: "1000"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -263,6 +297,8 @@
read_iops_sec: "1000"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -279,6 +315,8 @@
set_read_iops_sec: "1001"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -290,6 +328,8 @@
description: "rally tests creating types"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -301,18 +341,8 @@
description: "rally tests creating types"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
- runner:
- {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
- sla:
- {{ no_failures_sla() }}
-
- CinderVolumeTypes.create_and_update_volume_type:
- -
- args:
- description: "test"
- update_description: "test update"
- context:
- {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -328,17 +358,8 @@
control_location: "front-end"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
- runner:
- {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
- sla:
- {{ no_failures_sla() }}
-
- CinderVolumeTypes.create_volume_type_add_and_list_type_access:
- -
- args:
- description: "rally tests creating types"
- context:
- {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml
index dfc1fc156..993b83ff7 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml
@@ -36,8 +36,9 @@
flavor:
name: {{ flavor_name }}
number_instances: 2
- nics:
- - net-id: {{ netid }}
+ boot_server_kwargs:
+ nics:
+ - net-id: {{ netid }}
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
quotas:
diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml
index 2951e953a..b2248d499 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml
@@ -27,7 +27,8 @@
ports_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
+ network:
+ router: {}
quotas:
neutron:
network: -1
@@ -50,7 +51,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -74,7 +74,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -108,7 +107,8 @@
ports_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
+ network:
+ router: {}
quotas:
neutron:
network: -1
@@ -129,7 +129,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -151,7 +150,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -185,7 +183,8 @@
ports_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
+ network:
+ router: {}
quotas:
neutron:
network: -1
@@ -206,7 +205,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -227,7 +225,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -315,7 +312,8 @@
ports_per_network: 2
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
+ network:
+ router: {}
quotas:
neutron:
network: -1
@@ -332,7 +330,6 @@
subnets_per_network: 2
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -350,7 +347,8 @@
subnets_per_network: 2
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
+ network:
+ router: {}
quotas:
neutron:
network: -1
diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml
index 512448fd4..210591f9b 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml
@@ -39,9 +39,6 @@
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
@@ -59,9 +56,6 @@
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
@@ -80,9 +74,6 @@
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
@@ -104,9 +95,6 @@
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
@@ -124,9 +112,6 @@
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
@@ -140,11 +125,13 @@
-
args:
{{ vm_params(image_name, flavor_name) }}
- volume_size: 10
+ volume_size: 1
nics:
- net-id: {{ netid }}
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -200,7 +187,7 @@
NovaServers.boot_and_live_migrate_server:
- args:
{{ vm_params(image_name, flavor_name) }}
- block_migration: false
+ block_migration: {{ block_migration }}
nics:
- net-id: {{ netid }}
context:
@@ -214,13 +201,15 @@
-
args:
{{ vm_params(image_name, flavor_name) }}
- size: 10
- block_migration: false
+ size: 1
+ block_migration: {{ block_migration }}
boot_server_kwargs:
nics:
- net-id: {{ netid }}
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -229,13 +218,15 @@
NovaServers.boot_server_from_volume_and_live_migrate:
- args:
{{ vm_params(image_name, flavor_name) }}
- block_migration: false
- volume_size: 10
+ block_migration: {{ block_migration }}
+ volume_size: 1
force_delete: false
nics:
- net-id: {{ netid }}
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -245,14 +236,11 @@
-
args:
{{ vm_params(image_name, flavor_name) }}
- server_kwargs:
+ boot_server_kwargs:
nics:
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova(keypairs=true) }}
@@ -266,18 +254,17 @@
-
args:
{{ vm_params(image_name, flavor_name) }}
- volume_size: 5
+ volume_size: 1
nics:
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_volumes() }}
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -293,9 +280,6 @@
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
@@ -375,6 +359,40 @@
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
network: {}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
+ {% endcall %}
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ NovaServers.boot_server_associate_and_dissociate_floating_ip:
+ -
+ args:
+ {{ vm_params(image_name, flavor_name) }}
+ floating_network: {{ floating_network }}
+ nics:
+ - net-id: {{ netid }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ network: {}
+ {% endcall %}
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ NovaServers.boot_and_associate_floating_ip:
+ -
+ args:
+ {{ vm_params(image_name, flavor_name) }}
+ floating_network: {{ floating_network }}
+ nics:
+ - net-id: {{ netid }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ network: {}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
diff --git a/functest/opnfv_tests/openstack/rally/scenario/opnfv-barbican.yaml b/functest/opnfv_tests/openstack/rally/scenario/opnfv-barbican.yaml
new file mode 100644
index 000000000..9dd9ca271
--- /dev/null
+++ b/functest/opnfv_tests/openstack/rally/scenario/opnfv-barbican.yaml
@@ -0,0 +1,98 @@
+ BarbicanContainers.create_and_add:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanContainers.create_certificate_and_delete:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanContainers.create_and_delete:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanContainers.create_rsa_and_delete:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanSecrets.create_and_delete:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanSecrets.create_and_get:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanSecrets.create_and_list:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanSecrets.create:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanSecrets.get:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanContainers.list:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ BarbicanSecrets.list:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
diff --git a/functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml b/functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml
index a0682acce..dcb007c50 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml
@@ -4,6 +4,8 @@
max_quota: 1024
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -15,6 +17,8 @@
max_quota: 1024
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -31,17 +35,6 @@
sla:
{{ no_failures_sla() }}
- Quotas.nova_update_and_delete:
- -
- args:
- max_quota: 1024
- context:
- {{ user_context(tenants_amount, users_amount, use_existing_users) }}
- runner:
- {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
- sla:
- {{ no_failures_sla() }}
-
Quotas.nova_update:
-
args:
diff --git a/functest/opnfv_tests/openstack/rally/scenario/opnfv-swift.yaml b/functest/opnfv_tests/openstack/rally/scenario/opnfv-swift.yaml
new file mode 100644
index 000000000..66d7cd24d
--- /dev/null
+++ b/functest/opnfv_tests/openstack/rally/scenario/opnfv-swift.yaml
@@ -0,0 +1,71 @@
+ SwiftObjects.create_container_and_object_then_list_objects:
+ -
+ args:
+ objects_per_container: 2
+ object_size: 5120
+ runner:
+ {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ roles:
+ - "admin"
+ sla:
+ {{ no_failures_sla() }}
+
+ SwiftObjects.list_objects_in_containers:
+ -
+ runner:
+ {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ roles:
+ - "admin"
+ swift_objects:
+ containers_per_tenant: 1
+ objects_per_container: 10
+ object_size: 1024
+ sla:
+ {{ no_failures_sla() }}
+
+ SwiftObjects.create_container_and_object_then_download_object:
+ -
+ args:
+ objects_per_container: 5
+ object_size: 1024
+ runner:
+ {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ roles:
+ - "admin"
+ sla:
+ {{ no_failures_sla() }}
+
+ SwiftObjects.create_container_and_object_then_delete_all:
+ -
+ args:
+ objects_per_container: 5
+ object_size: 102400
+ runner:
+ {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ roles:
+ - "admin"
+ sla:
+ {{ no_failures_sla() }}
+
+ SwiftObjects.list_and_download_objects_in_containers:
+ -
+ runner:
+ {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ roles:
+ - "admin"
+ swift_objects:
+ containers_per_tenant: 1
+ objects_per_container: 5
+ object_size: 10240
+ sla:
+ {{ no_failures_sla() }}
diff --git a/functest/opnfv_tests/openstack/rally/scenario/opnfv-vm.yaml b/functest/opnfv_tests/openstack/rally/scenario/opnfv-vm.yaml
index 74f509925..3aa8ac8e5 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/opnfv-vm.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/opnfv-vm.yaml
@@ -1,42 +1,19 @@
- VMTasks.boot_runcommand_delete:
+ VMTasks.dd_load_test:
-
args:
- {{ vm_params(image_name, flavor_name) }}
- floating_network: {{ floating_network }}
- force_delete: false
- command:
- interpreter: /bin/sh
- script_file: {{ sup_dir }}/instance_dd_test.sh
- username: cirros
+ flavor:
+ name: {{ flavor_name }}
+ image:
+ name: {{ image_name }}
nics:
- net-id: {{ netid }}
- context:
- {% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
- {% endcall %}
- runner:
- {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
- sla:
- {{ no_failures_sla() }}
-
- -
- args:
- {{ vm_params(image_name, flavor_name) }}
- fixed_network: private
floating_network: {{ floating_network }}
force_delete: false
- command:
- interpreter: /bin/sh
- script_file: {{ sup_dir }}/instance_dd_test.sh
- use_floatingip: true
- username: cirros
- nics:
- - net-id: {{ netid }}
- volume_args:
- size: 2
+ username: {{ username }}
+ runner:
+ {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }}
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
- runner:
- {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ network: {}
sla:
{{ no_failures_sla() }}
diff --git a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-cinder.yaml b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-cinder.yaml
index 832358075..f94a5a1a4 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-cinder.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-cinder.yaml
@@ -6,6 +6,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{{ volumes() }}
{% endcall %}
runner:
@@ -23,6 +25,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -35,6 +39,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -47,6 +53,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -62,6 +70,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -76,6 +86,8 @@
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
quotas:
{{ unlimited_volumes() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{{ volumes() }}
{% endcall %}
runner:
@@ -91,6 +103,8 @@
read_iops_sec: "1000"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -107,6 +121,8 @@
set_read_iops_sec: "1001"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -118,6 +134,8 @@
description: "rally tests creating types"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -133,6 +151,8 @@
control_location: "front-end"
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
diff --git a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml
index 1b61762f9..279e81439 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml
@@ -36,8 +36,9 @@
flavor:
name: {{ flavor_name }}
number_instances: 2
- nics:
- - net-id: {{ netid }}
+ boot_server_kwargs:
+ nics:
+ - net-id: {{ netid }}
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
quotas:
diff --git a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-neutron.yaml b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-neutron.yaml
index da99a48b5..3eb7652c0 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-neutron.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-neutron.yaml
@@ -21,7 +21,8 @@
ports_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
+ network:
+ router: {}
quotas:
neutron:
network: -1
@@ -42,7 +43,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -64,7 +64,8 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
+ network:
+ router: {}
quotas:
neutron:
network: -1
@@ -98,7 +99,8 @@
ports_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
+ network:
+ router: {}
quotas:
neutron:
network: -1
@@ -119,7 +121,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
@@ -140,7 +141,6 @@
subnets_per_network: 1
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network: {}
quotas:
neutron:
network: -1
diff --git a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml
index 801938c4e..1fbfccb5a 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml
+++ b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml
@@ -1,7 +1,7 @@
NovaServers.boot_and_live_migrate_server:
- args:
{{ vm_params(image_name, flavor_name) }}
- block_migration: false
+ block_migration: {{ block_migration }}
nics:
- net-id: {{ netid }}
context:
@@ -15,13 +15,15 @@
-
args:
{{ vm_params(image_name, flavor_name) }}
- size: 10
- block_migration: false
+ size: 1
+ block_migration: {{ block_migration }}
boot_server_kwargs:
nics:
- net-id: {{ netid }}
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -30,13 +32,15 @@
NovaServers.boot_server_from_volume_and_live_migrate:
- args:
{{ vm_params(image_name, flavor_name) }}
- block_migration: false
- volume_size: 10
+ block_migration: {{ block_migration }}
+ volume_size: 1
force_delete: false
nics:
- net-id: {{ netid }}
context:
{{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
sla:
@@ -46,14 +50,11 @@
-
args:
{{ vm_params(image_name, flavor_name) }}
- server_kwargs:
+ boot_server_kwargs:
nics:
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova(keypairs=true) }}
@@ -67,18 +68,17 @@
-
args:
{{ vm_params(image_name, flavor_name) }}
- volume_size: 5
+ volume_size: 1
nics:
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_volumes() }}
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
+ api_versions:
+ {{ volume_service(version=volume_version, service_type=volume_service_type) }}
{% endcall %}
runner:
{{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
@@ -94,9 +94,6 @@
- net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
- network:
- networks_per_tenant: 1
- start_cidr: "100.1.0.0/25"
quotas:
{{ unlimited_neutron() }}
{{ unlimited_nova() }}
@@ -122,7 +119,24 @@
-
args:
{{ vm_params(image_name, flavor_name) }}
- auto_assign_nic: true
+ nics:
+ - net-id: {{ netid }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ network: {}
+ {% endcall %}
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ NovaServers.boot_server_associate_and_dissociate_floating_ip:
+ -
+ args:
+ {{ vm_params(image_name, flavor_name) }}
+ floating_network: {{ floating_network }}
+ nics:
+ - net-id: {{ netid }}
context:
{% call user_context(tenants_amount, users_amount, use_existing_users) %}
network: {}
diff --git a/functest/opnfv_tests/openstack/rally/scenario/support/instance_dd_test.sh b/functest/opnfv_tests/openstack/rally/scenario/support/instance_dd_test.sh
deleted file mode 100644
index e3bf23405..000000000
--- a/functest/opnfv_tests/openstack/rally/scenario/support/instance_dd_test.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-time_seconds(){ (time -p $1 ) 2>&1 |awk '/real/{print $2}'; }
-file=/tmp/test.img
-c=${1:-$SIZE}
-c=${c:-1000} #default is 1GB
-write_seq=$(time_seconds "dd if=/dev/zero of=$file bs=1M count=$c")
-read_seq=$(time_seconds "dd if=$file of=/dev/null bs=1M count=$c")
-[ -f $file ] && rm $file
-
-echo "{
- \"write_seq_${c}m\": $write_seq,
- \"read_seq_${c}m\": $read_seq
- }"
diff --git a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template
index 35b107838..75afb2dbe 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template
+++ b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template
@@ -7,7 +7,7 @@ parameters:
default: public
image:
type: string
- default: cirros-0.4.0-x86_64-uec
+ default: cirros-0.6.1-x86_64-uec
flavor:
type: string
default: m1.tiny
diff --git a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template
index 5c9a86b79..9a0f1aa72 100644
--- a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template
+++ b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template
@@ -4,7 +4,7 @@ parameters:
# set all correct defaults for parameters before launch test
image:
type: string
- default: cirros-0.4.0-x86_64-uec
+ default: cirros-0.5.1-x86_64-uec
flavor:
type: string
default: m1.tiny
diff --git a/functest/opnfv_tests/openstack/rally/task.yaml b/functest/opnfv_tests/openstack/rally/task.yaml
index fe9304fc2..649c04557 100644
--- a/functest/opnfv_tests/openstack/rally/task.yaml
+++ b/functest/opnfv_tests/openstack/rally/task.yaml
@@ -4,7 +4,7 @@
{%- endif %}
{%- from "macro/macro.yaml" import user_context, vm_params, unlimited_volumes, constant_runner, rps_runner, no_failures_sla -%}
-{%- from "macro/macro.yaml" import volumes, unlimited_nova, unlimited_neutron, glance_args -%}
+{%- from "macro/macro.yaml" import volumes, unlimited_nova, unlimited_neutron, glance_args, volume_service -%}
---
{% if "authenticate" in service_list %}
@@ -43,6 +43,14 @@
{%- include "var/opnfv-heat.yaml"-%}
{% endif %}
+{% if "swift" in service_list %}
+{%- include "var/opnfv-swift.yaml"-%}
+{% endif %}
+
+{% if "barbican" in service_list %}
+{%- include "var/opnfv-barbican.yaml"-%}
+{% endif %}
+
{% if "vm" in service_list %}
{%- include "var/opnfv-vm.yaml"-%}
{% endif %}
diff --git a/functest/opnfv_tests/openstack/refstack/refstack.py b/functest/opnfv_tests/openstack/refstack/refstack.py
index 8266e281d..87932020b 100644
--- a/functest/opnfv_tests/openstack/refstack/refstack.py
+++ b/functest/opnfv_tests/openstack/refstack/refstack.py
@@ -11,9 +11,9 @@
import logging
import os
-import shutil
-
-from refstack_client import list_parser
+import re
+import subprocess
+import yaml
from functest.opnfv_tests.openstack.tempest import tempest
from functest.utils import config
@@ -24,11 +24,58 @@ class Refstack(tempest.TempestCommon):
__logger = logging.getLogger(__name__)
- defcorelist = os.path.join(
- getattr(config.CONF, 'dir_refstack_data'), 'defcore.txt')
+ def _extract_refstack_data(self, refstack_list):
+ yaml_data = ""
+ with open(refstack_list, encoding='utf-8') as def_file:
+ for line in def_file:
+ try:
+ grp = re.search(r'^([^\[]*)(\[.*\])\n*$', line)
+ yaml_data = f"{yaml_data}\n{grp.group(1)}: {grp.group(2)}"
+ except Exception: # pylint: disable=broad-except
+ self.__logger.warning("Cannot parse %s", line)
+ return yaml.full_load(yaml_data)
+
+ def _extract_tempest_data(self):
+ olddir = os.getcwd()
+ try:
+ os.chdir(self.verifier_repo_dir)
+ cmd = ['stestr', 'list', '^tempest.']
+ output = subprocess.check_output(cmd)
+ except subprocess.CalledProcessError as cpe:
+ self.__logger.error(
+ "Exception when listing tempest tests: %s\n%s",
+ cpe.cmd, cpe.output.decode("utf-8"))
+ raise
+ finally:
+ os.chdir(olddir)
+ yaml_data2 = ""
+ for line in output.splitlines():
+ try:
+ grp = re.search(r'^([^\[]*)(\[.*\])\n*$', line.decode("utf-8"))
+ yaml_data2 = f"{yaml_data2}\n{grp.group(1)}: {grp.group(2)}"
+ except Exception: # pylint: disable=broad-except
+ self.__logger.warning("Cannot parse %s. skipping it", line)
+ return yaml.full_load(yaml_data2)
def generate_test_list(self, **kwargs):
- parser = list_parser.TestListParser(
- getattr(config.CONF, 'dir_repo_tempest'))
- nfile = parser.get_normalized_test_list(Refstack.defcorelist)
- shutil.copyfile(nfile, self.list)
+ refstack_list = os.path.join(
+ getattr(config.CONF, 'dir_refstack_data'),
+ f"{kwargs.get('target', 'compute')}.txt")
+ self.backup_tempest_config(self.conf_file, '/etc')
+ refstack_data = self._extract_refstack_data(refstack_list)
+ tempest_data = self._extract_tempest_data()
+ with open(self.list, 'w', encoding='utf-8') as ref_file:
+ for key in refstack_data.keys():
+ try:
+ for data in tempest_data[key]:
+ if data == refstack_data[key][0]:
+ break
+ else:
+ self.__logger.info("%s: ids differ. skipping it", key)
+ continue
+ value = str(tempest_data[key]).replace(
+ "'", "").replace(", ", ",")
+ ref_file.write(f"{key}{value}\n")
+ except Exception: # pylint: disable=broad-except
+ self.__logger.info("%s: not found. skipping it", key)
+ continue
diff --git a/functest/opnfv_tests/openstack/shaker/shaker.py b/functest/opnfv_tests/openstack/shaker/shaker.py
index ca405ae55..275cc3077 100644
--- a/functest/opnfv_tests/openstack/shaker/shaker.py
+++ b/functest/opnfv_tests/openstack/shaker/shaker.py
@@ -19,9 +19,11 @@ and list of tests to execute.
import logging
import os
+import json
import scp
from functest.core import singlevm
+from functest.utils import env
class Shaker(singlevm.SingleVm2):
@@ -30,16 +32,32 @@ class Shaker(singlevm.SingleVm2):
__logger = logging.getLogger(__name__)
- filename = '/home/opnfv/functest/images/shaker-image.qcow2'
+ filename = '/home/opnfv/functest/images/shaker-image-1.3.4+stretch.qcow2'
flavor_ram = 512
flavor_vcpus = 1
flavor_disk = 3
- username = 'ubuntu'
+ username = 'debian'
port = 9000
ssh_connect_loops = 12
+ create_server_timeout = 300
+ check_console_loop = 12
+ shaker_timeout = '3600'
+ quota_instances = -1
+ quota_cores = -1
+ check_console_loop = 12
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.role = None
+
+ def check_requirements(self):
+ if self.count_hypervisors() < 2:
+ self.__logger.warning("Shaker requires at least 2 hypervisors")
+ self.is_skipped = True
+ self.project.clean()
def prepare(self):
- super(Shaker, self).prepare()
+ super().prepare()
self.cloud.create_security_group_rule(
self.sec.id, port_range_min=self.port, port_range_max=self.port,
protocol='tcp', direction='ingress')
@@ -51,48 +69,59 @@ class Shaker(singlevm.SingleVm2):
- 1 on operation error
"""
assert self.ssh
- keystone_id = self.orig_cloud.search_services('keystone')[0].id
- self.__logger.debug("keystone id: %s", keystone_id)
- endpoint = self.orig_cloud.search_endpoints(
- filters={'interface': 'public',
- 'service_id': keystone_id})[0].url
+ endpoint = self.get_public_auth_url(self.orig_cloud)
self.__logger.debug("keystone endpoint: %s", endpoint)
+ if self.orig_cloud.get_role("admin"):
+ role_name = "admin"
+ elif self.orig_cloud.get_role("Admin"):
+ role_name = "Admin"
+ else:
+ raise Exception("Cannot detect neither admin nor Admin")
self.orig_cloud.grant_role(
- "admin", user=self.project.user.id,
+ role_name, user=self.project.user.id,
project=self.project.project.id,
domain=self.project.domain.id)
+ if not self.orig_cloud.get_role("heat_stack_owner"):
+ self.role = self.orig_cloud.create_role("heat_stack_owner")
self.orig_cloud.grant_role(
"heat_stack_owner", user=self.project.user.id,
project=self.project.project.id,
domain=self.project.domain.id)
+ self.orig_cloud.set_compute_quotas(
+ self.project.project.name,
+ instances=self.quota_instances,
+ cores=self.quota_cores)
scpc = scp.SCPClient(self.ssh.get_transport())
scpc.put('/home/opnfv/functest/conf/env_file', remote_path='~/')
if os.environ.get('OS_CACERT'):
scpc.put(os.environ.get('OS_CACERT'), remote_path='~/os_cacert')
+ opt = 'export OS_CACERT=~/os_cacert && ' if os.environ.get(
+ 'OS_CACERT') else ''
(_, stdout, stderr) = self.ssh.exec_command(
'source ~/env_file && '
'export OS_INTERFACE=public && '
- 'export OS_AUTH_URL={} && '
- 'export OS_USERNAME={} && '
- 'export OS_PROJECT_NAME={} && '
- 'export OS_PASSWORD={} && '
- '{}'
+ f'export OS_AUTH_URL={endpoint} && '
+ f'export OS_USERNAME={self.project.user.name} && '
+ f'export OS_PROJECT_NAME={self.project.project.name} && '
+ f'export OS_PROJECT_ID={self.project.project.id} && '
+ 'unset OS_TENANT_NAME && '
+ 'unset OS_TENANT_ID && '
+ 'unset OS_ENDPOINT_TYPE && '
+ f'export OS_PASSWORD="{self.project.password}" && '
+ f'{opt}'
'env && '
- 'shaker --image-name {} --flavor-name {} '
- '--server-endpoint {}:9000 --scenario '
- 'openstack/full_l2,'
+ f'timeout {self.shaker_timeout} shaker --debug '
+ f'--image-name {self.image.name} --flavor-name {self.flavor.name} '
+ f'--server-endpoint {self.fip.floating_ip_address}:9000 '
+ f'--external-net {self.ext_net.id} '
+ f"--dns-nameservers {env.get('NAMESERVER')} "
+ '--scenario openstack/full_l2,'
'openstack/full_l3_east_west,'
'openstack/full_l3_north_south,'
'openstack/perf_l3_north_south '
- '--report report.html --output report.json'.format(
- endpoint, self.project.user.name, self.project.project.name,
- self.project.password,
- 'export OS_CACERT=~/os_cacert && ' if os.environ.get(
- 'OS_CACERT') else '',
- self.image.name, self.flavor.name,
- self.fip.floating_ip_address))
- self.__logger.info("output:\n%s", stdout.read())
- self.__logger.info("error:\n%s", stderr.read())
+ '--report report.html --output report.json')
+ self.__logger.info("output:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.info("error:\n%s", stderr.read().decode("utf-8"))
if not os.path.exists(self.res_dir):
os.makedirs(self.res_dir)
try:
@@ -101,4 +130,18 @@ class Shaker(singlevm.SingleVm2):
except scp.SCPException:
self.__logger.exception("cannot get report files")
return 1
+ with open(
+ os.path.join(self.res_dir, 'report.json'),
+ encoding='utf-8') as json_file:
+ data = json.load(json_file)
+ for value in data["records"].values():
+ if value["status"] != "ok":
+ self.__logger.error(
+ "%s failed\n%s", value["scenario"], value["stderr"])
+ return 1
return stdout.channel.recv_exit_status()
+
+ def clean(self):
+ super().clean()
+ if self.role:
+ self.orig_cloud.delete_role(self.role.id)
diff --git a/functest/opnfv_tests/openstack/snaps/api_check.py b/functest/opnfv_tests/openstack/snaps/api_check.py
deleted file mode 100644
index d4204bff1..000000000
--- a/functest/opnfv_tests/openstack/snaps/api_check.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
-#
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""api_check test case implementation"""
-
-import unittest
-
-from functest.opnfv_tests.openstack.snaps import snaps_suite_builder
-from functest.opnfv_tests.openstack.snaps.snaps_test_runner import \
- SnapsTestRunner
-
-
-class ApiCheck(SnapsTestRunner):
- """
- This test executes the Python Tests included with the SNAPS libraries
- that exercise many of the OpenStack APIs within Keystone, Glance, Neutron,
- and Nova
- """
- def __init__(self, **kwargs):
- if "case_name" not in kwargs:
- kwargs["case_name"] = "api_check"
- super(ApiCheck, self).__init__(**kwargs)
-
- self.suite = unittest.TestSuite()
-
- def run(self, **kwargs):
- """
- Builds the test suite then calls super.run()
- :param kwargs: the arguments to pass on
- :return:
- """
- snaps_suite_builder.add_openstack_client_tests(
- suite=self.suite,
- os_creds=self.os_creds,
- ext_net_name=self.ext_net_name,
- use_keystone=self.use_keystone)
- snaps_suite_builder.add_openstack_api_tests(
- suite=self.suite,
- os_creds=self.os_creds,
- ext_net_name=self.ext_net_name,
- use_keystone=self.use_keystone,
- image_metadata=self.image_metadata)
- return super(ApiCheck, self).run()
diff --git a/functest/opnfv_tests/openstack/snaps/health_check.py b/functest/opnfv_tests/openstack/snaps/health_check.py
deleted file mode 100644
index 3a9c821d2..000000000
--- a/functest/opnfv_tests/openstack/snaps/health_check.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
-#
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""snaps_health_check test case implementation"""
-
-import unittest
-
-from snaps.openstack.tests.create_instance_tests import SimpleHealthCheck
-from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
-
-from functest.opnfv_tests.openstack.snaps.snaps_test_runner import (
- SnapsTestRunner)
-
-
-class HealthCheck(SnapsTestRunner):
- """
- This test executes the SNAPS Python Test case SimpleHealthCheck which
- creates a VM with a single port with an IPv4 address that is assigned by
- DHCP. This test then validates the expected IP with the actual
- """
- def __init__(self, **kwargs):
- if "case_name" not in kwargs:
- kwargs["case_name"] = "snaps_images_cirros"
- super(HealthCheck, self).__init__(**kwargs)
-
- self.suite = unittest.TestSuite()
-
- def run(self, **kwargs):
- """
- Builds the test suite then calls super.run()
- :param kwargs: the arguments to pass on
- :return:
- """
- self.suite.addTest(
- OSIntegrationTestCase.parameterize(
- SimpleHealthCheck, os_creds=self.os_creds,
- ext_net_name=self.ext_net_name,
- use_keystone=self.use_keystone,
- flavor_metadata=self.flavor_metadata,
- image_metadata=self.image_metadata,
- netconf_override=self.netconf_override))
- return super(HealthCheck, self).run()
diff --git a/functest/opnfv_tests/openstack/snaps/smoke.py b/functest/opnfv_tests/openstack/snaps/smoke.py
deleted file mode 100644
index bc6781180..000000000
--- a/functest/opnfv_tests/openstack/snaps/smoke.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
-#
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""snaps_smoke test case implementation"""
-
-import unittest
-
-from functest.opnfv_tests.openstack.snaps import snaps_suite_builder
-from functest.opnfv_tests.openstack.snaps.snaps_test_runner import (
- SnapsTestRunner)
-
-
-class SnapsSmoke(SnapsTestRunner):
- """
- This test executes the Python Tests included with the SNAPS libraries
- that exercise many of the OpenStack APIs within Keystone, Glance, Neutron,
- and Nova
- """
- def __init__(self, **kwargs):
- if "case_name" not in kwargs:
- kwargs["case_name"] = "snaps_smoke"
- super(SnapsSmoke, self).__init__(**kwargs)
-
- self.suite = unittest.TestSuite()
-
- def run(self, **kwargs):
- """
- Builds the test suite then calls super.run()
- :param kwargs: the arguments to pass on
- :return:
- """
- snaps_suite_builder.add_openstack_integration_tests(
- suite=self.suite,
- os_creds=self.os_creds,
- ext_net_name=self.ext_net_name,
- use_keystone=self.use_keystone,
- flavor_metadata=self.flavor_metadata,
- image_metadata=self.image_metadata,
- use_floating_ips=self.use_fip,
- netconf_override=self.netconf_override)
- return super(SnapsSmoke, self).run()
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_suite_builder.py b/functest/opnfv_tests/openstack/snaps/snaps_suite_builder.py
deleted file mode 100644
index 991a63dbb..000000000
--- a/functest/opnfv_tests/openstack/snaps/snaps_suite_builder.py
+++ /dev/null
@@ -1,451 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
-#
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""
-Snaps test suite including openstack client tests, api tests and
-integration tests.
-add_openstack_client_tests: for connection_check
-add_openstack_api_tests: for api_check
-add_openstack_integration_tests: for snaps_smoke
-"""
-
-import logging
-
-from snaps.openstack.tests.create_flavor_tests import (
- CreateFlavorTests)
-from snaps.openstack.tests.create_image_tests import (
- CreateImageSuccessTests, CreateImageNegativeTests,
- CreateMultiPartImageTests)
-from snaps.openstack.tests.create_instance_tests import (
- CreateInstanceSingleNetworkTests, CreateInstanceOnComputeHost,
- CreateInstanceSimpleTests, InstanceSecurityGroupTests,
- CreateInstancePortManipulationTests, SimpleHealthCheck,
- CreateInstanceFromThreePartImage, CreateInstanceTwoNetTests,
- CreateInstanceVolumeTests)
-from snaps.openstack.tests.create_keypairs_tests import (
- CreateKeypairsTests, CreateKeypairsCleanupTests)
-from snaps.openstack.tests.create_network_tests import (
- CreateNetworkSuccessTests)
-from snaps.openstack.tests.create_project_tests import (
- CreateProjectSuccessTests, CreateProjectUserTests)
-from snaps.openstack.tests.create_qos_tests import (
- CreateQoSTests)
-# from snaps.openstack.tests.create_router_tests import
-# CreateRouterSuccessTests
-from snaps.openstack.tests.create_router_tests import CreateRouterNegativeTests
-from snaps.openstack.tests.create_security_group_tests import (
- CreateSecurityGroupTests)
-from snaps.openstack.tests.create_stack_tests import (
- CreateStackSuccessTests, CreateStackNegativeTests,
- CreateStackFlavorTests,
- CreateStackKeypairTests, CreateStackVolumeTests,
- CreateStackSecurityGroupTests)
-from snaps.openstack.tests.create_user_tests import (
- CreateUserSuccessTests)
-from snaps.openstack.tests.create_volume_tests import (
- CreateSimpleVolumeSuccessTests,
- CreateVolumeWithTypeTests, CreateVolumeWithImageTests,
- CreateSimpleVolumeFailureTests)
-from snaps.openstack.tests.create_volume_type_tests import (
- CreateSimpleVolumeTypeSuccessTests,
- CreateVolumeTypeComplexTests)
-from snaps.openstack.tests.os_source_file_test import (
- OSComponentTestCase, OSIntegrationTestCase)
-from snaps.openstack.utils.tests.cinder_utils_tests import (
- CinderSmokeTests, CinderUtilsQoSTests, CinderUtilsSimpleVolumeTypeTests,
- CinderUtilsAddEncryptionTests, CinderUtilsVolumeTypeCompleteTests,
- CinderUtilsVolumeTests)
-from snaps.openstack.utils.tests.glance_utils_tests import (
- GlanceSmokeTests, GlanceUtilsTests)
-from snaps.openstack.utils.tests.heat_utils_tests import (
- HeatSmokeTests, HeatUtilsCreateSimpleStackTests,
- HeatUtilsFlavorTests,
- HeatUtilsKeypairTests, HeatUtilsSecurityGroupTests)
-from snaps.openstack.utils.tests.keystone_utils_tests import (
- KeystoneSmokeTests, KeystoneUtilsTests)
-from snaps.openstack.utils.tests.neutron_utils_tests import (
- NeutronSmokeTests, NeutronUtilsNetworkTests, NeutronUtilsSubnetTests,
- NeutronUtilsRouterTests, NeutronUtilsSecurityGroupTests,
- NeutronUtilsFloatingIpTests)
-from snaps.openstack.utils.tests.nova_utils_tests import (
- NovaSmokeTests, NovaUtilsKeypairTests, NovaUtilsFlavorTests,
- NovaUtilsInstanceTests, NovaUtilsInstanceVolumeTests)
-from snaps.provisioning.tests.ansible_utils_tests import (
- AnsibleProvisioningTests)
-
-
-def add_openstack_client_tests(suite, os_creds, ext_net_name,
- use_keystone=True, log_level=logging.INFO):
- """
- Adds tests written to exercise OpenStack client retrieval
-
- :param suite: the unittest.TestSuite object to which to add the tests
- :param os_creds: and instance of OSCreds that holds the credentials
- required by OpenStack
- :param ext_net_name: the name of an external network on the cloud under
- test
- :param use_keystone: when True, tests requiring direct access to Keystone
- are added as these need to be running on a host that
- has access to the cloud's private network
- :param log_level: the logging level
- :return: None as the tests will be adding to the 'suite' parameter object
- """
- # Basic connection tests
- suite.addTest(
- OSComponentTestCase.parameterize(
- GlanceSmokeTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
-
- if use_keystone:
- suite.addTest(
- OSComponentTestCase.parameterize(
- KeystoneSmokeTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level))
-
- suite.addTest(
- OSComponentTestCase.parameterize(
- NeutronSmokeTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(
- OSComponentTestCase.parameterize(
- NovaSmokeTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(
- OSComponentTestCase.parameterize(
- HeatSmokeTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(
- OSComponentTestCase.parameterize(
- CinderSmokeTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
-
-
-def add_openstack_api_tests(suite, os_creds, ext_net_name, use_keystone=True,
- image_metadata=None, log_level=logging.INFO):
- # pylint: disable=too-many-arguments
- """
- Adds tests written to exercise all existing OpenStack APIs
-
- :param suite: the unittest.TestSuite object to which to add the tests
- :param os_creds: Instance of OSCreds that holds the credentials
- required by OpenStack
- :param ext_net_name: the name of an external network on the cloud under
- test
- :param use_keystone: when True, tests requiring direct access to Keystone
- are added as these need to be running on a host that
- has access to the cloud's private network
- :param image_metadata: dict() object containing metadata for creating an
- image with custom config
- (see YAML files in examples/image-metadata)
- :param log_level: the logging level
- :return: None as the tests will be adding to the 'suite' parameter object
- """
- # Tests the OpenStack API calls
- if use_keystone:
- suite.addTest(OSComponentTestCase.parameterize(
- KeystoneUtilsTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- CreateUserSuccessTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- CreateProjectSuccessTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- CreateProjectUserTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level))
-
- suite.addTest(OSComponentTestCase.parameterize(
- GlanceUtilsTests, os_creds=os_creds, ext_net_name=ext_net_name,
- image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- NeutronUtilsNetworkTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- NeutronUtilsSubnetTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- NeutronUtilsRouterTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- NeutronUtilsSecurityGroupTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- NeutronUtilsFloatingIpTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- NovaUtilsKeypairTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- NovaUtilsFlavorTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- NovaUtilsInstanceTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level, image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- NovaUtilsInstanceVolumeTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- CreateFlavorTests, os_creds=os_creds, ext_net_name=ext_net_name,
- log_level=log_level))
- suite.addTest(OSComponentTestCase.parameterize(
- HeatUtilsCreateSimpleStackTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- # https://gerrit.opnfv.org/gerrit/#/c/59801/
- # suite.addTest(OSComponentTestCase.parameterize(
- # HeatUtilsCreateComplexStackTests, os_creds=os_creds,
- # ext_net_name=ext_net_name, log_level=log_level,
- # image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- HeatUtilsFlavorTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- HeatUtilsKeypairTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- HeatUtilsSecurityGroupTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- CinderUtilsQoSTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- CinderUtilsVolumeTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- CinderUtilsSimpleVolumeTypeTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- CinderUtilsAddEncryptionTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
- suite.addTest(OSComponentTestCase.parameterize(
- CinderUtilsVolumeTypeCompleteTests, os_creds=os_creds,
- ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
-
-
-def add_openstack_integration_tests(suite, os_creds, ext_net_name,
- use_keystone=True, flavor_metadata=None,
- image_metadata=None, use_floating_ips=True,
- netconf_override=None,
- log_level=logging.INFO):
- # pylint: disable=too-many-arguments
- """
- Adds tests written to exercise all long-running OpenStack integration tests
- meaning they will be creating VM instances and potentially performing some
- SSH functions through floatingIPs
-
- :param suite: the unittest.TestSuite object to which to add the tests
- :param os_creds: and instance of OSCreds that holds the credentials
- required by OpenStack
- :param ext_net_name: the name of an external network on the cloud under
- test
- :param use_keystone: when True, tests requiring direct access to Keystone
- are added as these need to be running on a host that
- has access to the cloud's private network
- :param image_metadata: dict() object containing metadata for creating an
- image with custom config
- (see YAML files in examples/image-metadata)
- :param flavor_metadata: dict() object containing the metadata required by
- your flavor based on your configuration:
- (i.e. {'hw:mem_page_size': 'large'})
- :param use_floating_ips: when true, all tests requiring Floating IPs will
- be added to the suite
- :param netconf_override: dict() containing the reconfigured network_type,
- physical_network and segmentation_id
- :param log_level: the logging level
- :return: None as the tests will be adding to the 'suite' parameter object
- """
- # Tests the OpenStack API calls via a creator. If use_keystone, objects
- # will be created with a custom user and project
-
- # Creator Object tests
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateSecurityGroupTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateImageSuccessTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateImageNegativeTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateMultiPartImageTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateKeypairsTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateKeypairsCleanupTests, os_creds=os_creds,
- ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateNetworkSuccessTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- # https://jira.opnfv.org/browse/SNAPS-320
- # suite.addTest(OSIntegrationTestCase.parameterize(
- # CreateRouterSuccessTests, os_creds=os_creds,
- # ext_net_name=ext_net_name,
- # use_keystone=use_keystone,
- # flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- # log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateRouterNegativeTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateQoSTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateSimpleVolumeTypeSuccessTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateVolumeTypeComplexTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateSimpleVolumeSuccessTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateSimpleVolumeFailureTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateVolumeWithTypeTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateVolumeWithImageTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
-
- # VM Instances
- suite.addTest(OSIntegrationTestCase.parameterize(
- SimpleHealthCheck, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateInstanceTwoNetTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateInstanceSimpleTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- netconf_override=netconf_override, log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateInstancePortManipulationTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- netconf_override=netconf_override, log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- InstanceSecurityGroupTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- netconf_override=netconf_override, log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateInstanceOnComputeHost, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- netconf_override=netconf_override, log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateInstanceFromThreePartImage, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- netconf_override=netconf_override, log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateInstanceVolumeTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- netconf_override=netconf_override, log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateStackSuccessTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateStackVolumeTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateStackFlavorTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateStackKeypairTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateStackSecurityGroupTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateStackNegativeTests, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
-
- if use_floating_ips:
- suite.addTest(OSIntegrationTestCase.parameterize(
- CreateInstanceSingleNetworkTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
- # https://gerrit.opnfv.org/gerrit/#/c/59801/
- # suite.addTest(OSIntegrationTestCase.parameterize(
- # CreateStackFloatingIpTests, os_creds=os_creds,
- # ext_net_name=ext_net_name, use_keystone=use_keystone,
- # flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- # log_level=log_level))
- suite.addTest(OSIntegrationTestCase.parameterize(
- AnsibleProvisioningTests, os_creds=os_creds,
- ext_net_name=ext_net_name, use_keystone=use_keystone,
- flavor_metadata=flavor_metadata, image_metadata=image_metadata,
- log_level=log_level))
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
deleted file mode 100644
index 70327ff89..000000000
--- a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
-#
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""configuration params to run snaps tests"""
-
-import logging
-
-from xtesting.core import unit
-
-from functest.opnfv_tests.openstack.snaps import snaps_utils
-from functest.utils import config
-
-
-class SnapsTestRunner(unit.Suite):
- # pylint: disable=too-many-instance-attributes
- """
- This test executes the SNAPS Python Tests
- """
-
- def __init__(self, **kwargs):
- super(SnapsTestRunner, self).__init__(**kwargs)
- self.logger = logging.getLogger(__name__)
- self.os_creds = kwargs.get('os_creds') or snaps_utils.get_credentials()
-
- if 'ext_net_name' in kwargs:
- self.ext_net_name = kwargs['ext_net_name']
- else:
- self.ext_net_name = snaps_utils.get_ext_net_name(self.os_creds)
-
- self.netconf_override = None
- if hasattr(config.CONF, 'snaps_network_config'):
- self.netconf_override = getattr(
- config.CONF, 'snaps_network_config')
-
- self.use_fip = (
- getattr(config.CONF, 'snaps_use_floating_ips') == 'True')
- self.use_keystone = (
- getattr(config.CONF, 'snaps_use_keystone') == 'True')
-
- self.flavor_metadata = getattr(config.CONF, 'snaps_flavor_extra_specs',
- None)
- self.logger.info("Using flavor metadata '%s'", self.flavor_metadata)
-
- self.image_metadata = None
- if hasattr(config.CONF, 'snaps_images'):
- self.image_metadata = getattr(config.CONF, 'snaps_images')
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_utils.py b/functest/opnfv_tests/openstack/snaps/snaps_utils.py
deleted file mode 100644
index 21d1dd60d..000000000
--- a/functest/opnfv_tests/openstack/snaps/snaps_utils.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2015 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""Some common utils wrapping snaps functions"""
-
-from snaps.openstack.tests import openstack_tests
-from snaps.openstack.utils import neutron_utils
-from snaps.openstack.utils import nova_utils
-
-from functest.utils import config
-from functest.utils import constants
-from functest.utils import env
-
-
-def get_ext_net_name(os_creds):
- """
- Returns the configured external network name or
- the first retrieved external network name
- :param: os_creds: an instance of snaps OSCreds object
- :return:
- """
- neutron = neutron_utils.neutron_client(os_creds)
- ext_nets = neutron_utils.get_external_networks(neutron)
- if env.get('EXTERNAL_NETWORK'):
- extnet_config = env.get('EXTERNAL_NETWORK')
- for ext_net in ext_nets:
- if ext_net.name == extnet_config:
- return extnet_config
- return ext_nets[0].name if ext_nets else ""
-
-
-def get_active_compute_cnt(os_creds):
- """
- Returns the number of active compute servers
- :param: os_creds: an instance of snaps OSCreds object
- :return: the number of active compute servers
- """
- nova = nova_utils.nova_client(os_creds)
- computes = nova_utils.get_availability_zone_hosts(nova, zone_name='nova')
- return len(computes)
-
-
-def get_credentials(proxy_settings_str=None, ssh_proxy_cmd=None):
- """
- Returns snaps OSCreds object instance
- :param: proxy_settings_str: proxy settings string <host>:<port>
- :param: ssh_proxy_cmd: the SSH proxy command for the environment
- :return: an instance of snaps OSCreds object
- """
- creds_override = None
- if hasattr(config.CONF, 'snaps_os_creds_override'):
- creds_override = getattr(config.CONF, 'snaps_os_creds_override')
- os_creds = openstack_tests.get_credentials(
- os_env_file=constants.ENV_FILE, proxy_settings_str=proxy_settings_str,
- ssh_proxy_cmd=ssh_proxy_cmd, overrides=creds_override)
- return os_creds
diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py
deleted file mode 100644
index 88ad3b2d9..000000000
--- a/functest/opnfv_tests/openstack/tempest/conf_utils.py
+++ /dev/null
@@ -1,261 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2015 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-
-"""Tempest configuration utilities."""
-
-from __future__ import print_function
-
-import logging
-import fileinput
-import os
-import subprocess
-
-import pkg_resources
-from six.moves import configparser
-import yaml
-
-from functest.utils import config
-from functest.utils import env
-
-
-RALLY_CONF_PATH = "/etc/rally/rally.conf"
-RALLY_AARCH64_PATCH_PATH = pkg_resources.resource_filename(
- 'functest', 'ci/rally_aarch64_patch.conf')
-GLANCE_IMAGE_PATH = os.path.join(
- getattr(config.CONF, 'dir_functest_images'),
- getattr(config.CONF, 'openstack_image_file_name'))
-TEMPEST_CUSTOM = pkg_resources.resource_filename(
- 'functest', 'opnfv_tests/openstack/tempest/custom_tests/test_list.txt')
-TEMPEST_BLACKLIST = pkg_resources.resource_filename(
- 'functest', 'opnfv_tests/openstack/tempest/custom_tests/blacklist.txt')
-TEMPEST_CONF_YAML = pkg_resources.resource_filename(
- 'functest', 'opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml')
-
-CI_INSTALLER_TYPE = env.get('INSTALLER_TYPE')
-
-""" logging configuration """
-LOGGER = logging.getLogger(__name__)
-
-
-def create_rally_deployment():
- """Create new rally deployment"""
- # set the architecture to default
- pod_arch = env.get("POD_ARCH")
- arch_filter = ['aarch64']
-
- if pod_arch and pod_arch in arch_filter:
- LOGGER.info("Apply aarch64 specific to rally config...")
- with open(RALLY_AARCH64_PATCH_PATH, "r") as pfile:
- rally_patch_conf = pfile.read()
-
- for line in fileinput.input(RALLY_CONF_PATH, inplace=1):
- print(line, end=' ')
- if "cirros|testvm" in line:
- print(rally_patch_conf)
-
- LOGGER.info("Creating Rally environment...")
-
- try:
- cmd = ['rally', 'deployment', 'destroy',
- '--deployment',
- str(getattr(config.CONF, 'rally_deployment_name'))]
- output = subprocess.check_output(cmd)
- LOGGER.info("%s\n%s", " ".join(cmd), output)
- except subprocess.CalledProcessError:
- pass
-
- cmd = ['rally', 'deployment', 'create', '--fromenv',
- '--name', str(getattr(config.CONF, 'rally_deployment_name'))]
- output = subprocess.check_output(cmd)
- LOGGER.info("%s\n%s", " ".join(cmd), output)
-
- cmd = ['rally', 'deployment', 'check']
- output = subprocess.check_output(cmd)
- LOGGER.info("%s\n%s", " ".join(cmd), output)
-
-
-def create_verifier():
- """Create new verifier"""
- LOGGER.info("Create verifier from existing repo...")
- cmd = ['rally', 'verify', 'delete-verifier',
- '--id', str(getattr(config.CONF, 'tempest_verifier_name')),
- '--force']
- try:
- output = subprocess.check_output(cmd)
- LOGGER.info("%s\n%s", " ".join(cmd), output)
- except subprocess.CalledProcessError:
- pass
-
- cmd = ['rally', 'verify', 'create-verifier',
- '--source', str(getattr(config.CONF, 'dir_repo_tempest')),
- '--name', str(getattr(config.CONF, 'tempest_verifier_name')),
- '--type', 'tempest', '--system-wide']
- output = subprocess.check_output(cmd)
- LOGGER.info("%s\n%s", " ".join(cmd), output)
-
-
-def get_verifier_id():
- """
- Returns verifier id for current Tempest
- """
- create_rally_deployment()
- create_verifier()
- cmd = ("rally verify list-verifiers | awk '/" +
- getattr(config.CONF, 'tempest_verifier_name') +
- "/ {print $2}'")
- proc = subprocess.Popen(cmd, shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- deployment_uuid = proc.stdout.readline().rstrip()
- if deployment_uuid == "":
- LOGGER.error("Tempest verifier not found.")
- raise Exception('Error with command:%s' % cmd)
- return deployment_uuid
-
-
-def get_verifier_deployment_id():
- """
- Returns deployment id for active Rally deployment
- """
- cmd = ("rally deployment list | awk '/" +
- getattr(config.CONF, 'rally_deployment_name') +
- "/ {print $2}'")
- proc = subprocess.Popen(cmd, shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- deployment_uuid = proc.stdout.readline().rstrip()
- if deployment_uuid == "":
- LOGGER.error("Rally deployment not found.")
- raise Exception('Error with command:%s' % cmd)
- return deployment_uuid
-
-
-def get_verifier_repo_dir(verifier_id):
- """
- Returns installed verifier repo directory for Tempest
- """
- if not verifier_id:
- verifier_id = get_verifier_id()
-
- return os.path.join(getattr(config.CONF, 'dir_rally_inst'),
- 'verification',
- 'verifier-{}'.format(verifier_id),
- 'repo')
-
-
-def get_verifier_deployment_dir(verifier_id, deployment_id):
- """
- Returns Rally deployment directory for current verifier
- """
- if not verifier_id:
- verifier_id = get_verifier_id()
-
- if not deployment_id:
- deployment_id = get_verifier_deployment_id()
-
- return os.path.join(getattr(config.CONF, 'dir_rally_inst'),
- 'verification',
- 'verifier-{}'.format(verifier_id),
- 'for-deployment-{}'.format(deployment_id))
-
-
-def update_tempest_conf_file(conf_file, rconfig):
- """Update defined paramters into tempest config file"""
- with open(TEMPEST_CONF_YAML) as yfile:
- conf_yaml = yaml.safe_load(yfile)
- if conf_yaml:
- sections = rconfig.sections()
- for section in conf_yaml:
- if section not in sections:
- rconfig.add_section(section)
- sub_conf = conf_yaml.get(section)
- for key, value in sub_conf.items():
- rconfig.set(section, key, value)
-
- with open(conf_file, 'wb') as config_file:
- rconfig.write(config_file)
-
-
-def configure_tempest_update_params(
- tempest_conf_file, network_name=None, image_id=None, flavor_id=None,
- compute_cnt=1, image_alt_id=None, flavor_alt_id=None):
- # pylint: disable=too-many-branches, too-many-arguments
- """
- Add/update needed parameters into tempest.conf file
- """
- LOGGER.debug("Updating selected tempest.conf parameters...")
- rconfig = configparser.RawConfigParser()
- rconfig.read(tempest_conf_file)
- rconfig.set('compute', 'fixed_network_name', network_name)
- rconfig.set('compute', 'volume_device_name', env.get('VOLUME_DEVICE_NAME'))
- if image_id is not None:
- rconfig.set('compute', 'image_ref', image_id)
- if image_alt_id is not None:
- rconfig.set('compute', 'image_ref_alt', image_alt_id)
- if flavor_id is not None:
- rconfig.set('compute', 'flavor_ref', flavor_id)
- if flavor_alt_id is not None:
- rconfig.set('compute', 'flavor_ref_alt', flavor_alt_id)
- if compute_cnt > 1:
- # enable multinode tests
- rconfig.set('compute', 'min_compute_nodes', compute_cnt)
- rconfig.set('compute-feature-enabled', 'live_migration', True)
- if os.environ.get('OS_REGION_NAME'):
- rconfig.set('identity', 'region', os.environ.get('OS_REGION_NAME'))
- identity_api_version = os.environ.get("OS_IDENTITY_API_VERSION", '3')
- if identity_api_version == '3':
- auth_version = 'v3'
- rconfig.set('identity-feature-enabled', 'api_v2', False)
- else:
- auth_version = 'v2'
- rconfig.set('identity', 'auth_version', auth_version)
- rconfig.set(
- 'validation', 'ssh_timeout',
- getattr(config.CONF, 'tempest_validation_ssh_timeout'))
- rconfig.set('object-storage', 'operator_role',
- getattr(config.CONF, 'tempest_object_storage_operator_role'))
-
- rconfig.set(
- 'identity', 'v3_endpoint_type',
- os.environ.get('OS_INTERFACE', 'public'))
-
- sections = rconfig.sections()
- services_list = [
- 'compute', 'volume', 'image', 'network', 'data-processing',
- 'object-storage', 'orchestration']
- for service in services_list:
- if service not in sections:
- rconfig.add_section(service)
- rconfig.set(
- service, 'endpoint_type', os.environ.get('OS_INTERFACE', 'public'))
-
- LOGGER.debug('Add/Update required params defined in tempest_conf.yaml '
- 'into tempest.conf file')
- update_tempest_conf_file(tempest_conf_file, rconfig)
-
-
-def configure_verifier(deployment_dir):
- """
- Execute rally verify configure-verifier, which generates tempest.conf
- """
- cmd = ['rally', 'verify', 'configure-verifier', '--reconfigure',
- '--id', str(getattr(config.CONF, 'tempest_verifier_name'))]
- output = subprocess.check_output(cmd)
- LOGGER.info("%s\n%s", " ".join(cmd), output)
-
- LOGGER.debug("Looking for tempest.conf file...")
- tempest_conf_file = os.path.join(deployment_dir, "tempest.conf")
- if not os.path.isfile(tempest_conf_file):
- LOGGER.error("Tempest configuration file %s NOT found.",
- tempest_conf_file)
- raise Exception("Tempest configuration file %s NOT found."
- % tempest_conf_file)
- else:
- return tempest_conf_file
diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
deleted file mode 100644
index bb1aed339..000000000
--- a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-
--
diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml
new file mode 100644
index 000000000..43a77fa3c
--- /dev/null
+++ b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml
@@ -0,0 +1,19 @@
+---
+-
+ scenarios:
+ - os-ovn-nofeature-ha
+ - os-ovn-nofeature-noha
+ tests:
+ - neutron_tempest_plugin.api.admin.test_dhcp_agent_scheduler
+ - neutron_tempest_plugin.api.admin.test_ports.PortTestCasesResourceRequest.test_port_resource_request
+ - neutron_tempest_plugin.api.admin.test_ports.PortTestCasesResourceRequest.test_port_resource_request_empty
+ - neutron_tempest_plugin.api.admin.test_ports.PortTestCasesResourceRequest.test_port_resource_request_inherited_policy
+ - neutron_tempest_plugin.api.admin.test_ports.PortTestCasesResourceRequest.test_port_resource_request_no_provider_net_conflict
+ - neutron_tempest_plugin.api.test_ports.PortsTestJSON.test_create_update_port_with_dns_name
+ - patrole_tempest_plugin.tests.api.network.test_availability_zones_rbac.AvailabilityZoneExtRbacTest.test_list_availability_zone_rbac
+ - patrole_tempest_plugin.tests.api.network.test_agents_rbac.DHCPAgentSchedulersRbacTest.test_add_dhcp_agent_to_network
+ - patrole_tempest_plugin.tests.api.network.test_agents_rbac.DHCPAgentSchedulersRbacTest.test_delete_network_from_dhcp_agent
+ - patrole_tempest_plugin.tests.api.network.test_agents_rbac.DHCPAgentSchedulersRbacTest.test_list_networks_hosted_by_one_dhcp_agent
+ - patrole_tempest_plugin.tests.api.network.test_networks_rbac.NetworksRbacTest.test_create_network_provider_network_type
+ - patrole_tempest_plugin.tests.api.network.test_networks_rbac.NetworksRbacTest.test_create_network_provider_segmentation_id
+ - tempest.api.network.admin.test_dhcp_agent_scheduler
diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml b/functest/opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml
new file mode 100644
index 000000000..e53b577b2
--- /dev/null
+++ b/functest/opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml
@@ -0,0 +1,15 @@
+---
+-
+ scenarios:
+ - os-*
+ tests:
+ - neutron_tempest_plugin.api.admin.test_floating_ips_admin_actions.FloatingIPAdminTestJSON.test_associate_floating_ip_with_port_from_another_project
+ - neutron_tempest_plugin.api.admin.test_quotas.QuotasTest.test_detail_quotas
+ - neutron_tempest_plugin.api.admin.test_quotas.QuotasTest.test_quotas
+ - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_floatingip_when_quotas_is_full
+ - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_network_when_quotas_is_full
+ - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_port_when_quotas_is_full
+ - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_router_when_quotas_is_full
+ - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_security_group_rule_when_quotas_is_full
+ - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_security_group_when_quotas_is_full
+ - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_subnet_when_quotas_is_full
diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml b/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml
index b47a9736a..0ee4ab613 100644
--- a/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml
+++ b/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml
@@ -1,13 +1,104 @@
-# This is an empty configuration file to be filled up with the desired options
-# to generate a custom tempest.conf
-# Examples:
-# network-feature-enabled:
-# port_security: True
-
-# volume-feature-enabled:
-# api_v1: False
-
-# validation:
-# image_ssh_user: root
-# ssh_timeout: 300
-
+---
+compute:
+ min_microversion: '2.44'
+ max_microversion: latest
+compute-feature-enabled:
+ attach_encrypted_volume: false
+ block_migration_for_live_migration: false
+ block_migrate_cinder_iscsi: false
+ change_password: false
+ cold_migration: true
+ config_drive: true
+ console_output: true
+ disk_config: true
+ enable_instance_password: true
+ hostname_fqdn_sanitization: true
+ interface_attach: true
+ live_migration: true
+ live_migrate_back_and_forth: false
+ metadata_service: true
+ pause: true
+ personality: false
+ rdp_console: false
+ rescue: true
+ resize: true
+ scheduler_available_filters: "AvailabilityZoneFilter,ComputeFilter,\
+ ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,\
+ ServerGroupAffinityFilter,SameHostFilter,DifferentHostFilter"
+ serial_console: false
+ shelve: true
+ snapshot: true
+ spice_console: false
+ suspend: true
+ swap_volume: false
+ vnc_console: true
+ volume_backed_live_migration: false
+ volume_multiattach: false
+identity:
+ auth_version: v3
+ user_unique_last_password_count: 2
+ user_lockout_duration: 10
+ user_lockout_failure_attempts: 2
+identity-feature-enabled:
+ trust: true
+ api_v2: false
+ api_v2_admin: false
+ security_compliance: true
+ federation: false
+ external_idp: false
+ project_tags: true
+ application_credentials: true
+ access_rules: true
+image-feature-enabled:
+ api_v2: true
+ api_v1: false
+ import_image: false
+network-feature-enabled:
+ port_admin_state_change: true
+ port_security: true
+placement:
+ max_microversion: latest
+validation:
+ image_ssh_user: cirros
+ ssh_timeout: 196
+ ip_version_for_ssh: 4
+ run_validation: true
+volume:
+ max_microversion: latest
+ storage_protocol: ceph
+ manage_volume_ref: source-name,volume-%s
+ manage_snapshot_ref: source-name,snapshot-%s
+volume-feature-enabled:
+ multi_backend: false
+ backup: true
+ snapshot: true
+ clone: true
+ manage_snapshot: true
+ manage_volume: true
+ extend_attached_volume: true
+ extend_attached_encrypted_volume: false
+ consistency_group: false
+ volume_revert: true
+load_balancer:
+ test_with_ipv6: false
+neutron_plugin_options:
+ agent_availability_zone: nova
+ available_type_drivers: flat,geneve,vlan,gre,local,vxlan
+ provider_vlans: public,
+ create_shared_resources: true
+object-storage-feature-enabled:
+ discoverable_apis: "account_quotas,formpost,bulk_upload,bulk_delete,\
+ tempurl,crossdomain,container_quotas,staticweb,account_quotas,slo"
+ object_versioning: true
+ discoverability: true
+ tempurl_digest_hashlib: sha1
+heat_plugin:
+ skip_functional_test_list: EncryptionVolTypeTest
+ skip_scenario_test_list: "AodhAlarmTest,SoftwareConfigIntegrationTest,\
+ VolumeBackupRestoreIntegrationTest,CfnInitIntegrationTest,\
+ LoadBalancerTest"
+ auth_version: 3
+heat_features_enabled:
+ multi_cloud: false
+rbac:
+ enable_rbac: true
diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf_ovn.yaml b/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf_ovn.yaml
new file mode 100644
index 000000000..6b09d8e5a
--- /dev/null
+++ b/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf_ovn.yaml
@@ -0,0 +1,104 @@
+---
+compute:
+ min_microversion: '2.44'
+ max_microversion: latest
+compute-feature-enabled:
+ attach_encrypted_volume: false
+ block_migration_for_live_migration: false
+ block_migrate_cinder_iscsi: false
+ change_password: false
+ cold_migration: true
+ config_drive: true
+ console_output: true
+ disk_config: true
+ enable_instance_password: true
+ hostname_fqdn_sanitization: true
+ interface_attach: true
+ live_migration: true
+ live_migrate_back_and_forth: false
+ metadata_service: true
+ pause: true
+ personality: false
+ rdp_console: false
+ rescue: true
+ resize: true
+ scheduler_available_filters: "AvailabilityZoneFilter,ComputeFilter,\
+ ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,\
+ ServerGroupAffinityFilter,SameHostFilter,DifferentHostFilter"
+ serial_console: false
+ shelve: true
+ snapshot: true
+ spice_console: false
+ suspend: true
+ swap_volume: false
+ vnc_console: true
+ volume_backed_live_migration: false
+ volume_multiattach: false
+identity:
+ auth_version: v3
+ user_unique_last_password_count: 2
+ user_lockout_duration: 10
+ user_lockout_failure_attempts: 2
+identity-feature-enabled:
+ trust: true
+ api_v2: false
+ api_v2_admin: false
+ security_compliance: true
+ federation: false
+ external_idp: false
+ project_tags: true
+ application_credentials: true
+ access_rules: true
+image-feature-enabled:
+ api_v2: true
+ api_v1: false
+ import_image: false
+network-feature-enabled:
+ port_admin_state_change: true
+ port_security: true
+placement:
+ max_microversion: latest
+validation:
+ image_ssh_user: cirros
+ ssh_timeout: 196
+ ip_version_for_ssh: 4
+ run_validation: true
+volume:
+ max_microversion: latest
+ storage_protocol: ceph
+ manage_volume_ref: source-name,volume-%s
+ manage_snapshot_ref: source-name,snapshot-%s
+volume-feature-enabled:
+ multi_backend: false
+ backup: true
+ snapshot: true
+ clone: true
+ manage_snapshot: true
+ manage_volume: true
+ extend_attached_volume: true
+ extend_attached_encrypted_volume: false
+ consistency_group: false
+ volume_revert: true
+load_balancer:
+ test_with_ipv6: false
+neutron_plugin_options:
+ agent_availability_zone: nova
+ available_type_drivers: flat,geneve,vlan,local
+ provider_vlans: public,
+ create_shared_resources: true
+object-storage-feature-enabled:
+ discoverable_apis: "account_quotas,formpost,bulk_upload,bulk_delete,\
+ tempurl,crossdomain,container_quotas,staticweb,account_quotas,slo"
+ object_versioning: true
+ discoverability: true
+ tempurl_digest_hashlib: sha1
+heat_plugin:
+ skip_functional_test_list: EncryptionVolTypeTest
+ skip_scenario_test_list: "AodhAlarmTest,SoftwareConfigIntegrationTest,\
+ VolumeBackupRestoreIntegrationTest,CfnInitIntegrationTest,\
+ LoadBalancerTest"
+ auth_version: 3
+heat_features_enabled:
+ multi_cloud: false
+rbac:
+ enable_rbac: true
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
index 52cc31c4a..7233ffd60 100644
--- a/functest/opnfv_tests/openstack/tempest/tempest.py
+++ b/functest/opnfv_tests/openstack/tempest/tempest.py
@@ -12,6 +12,7 @@
from __future__ import division
+import json
import logging
import os
import re
@@ -19,34 +20,64 @@ import shutil
import subprocess
import time
+import pkg_resources
from six.moves import configparser
from xtesting.core import testcase
import yaml
from functest.core import singlevm
-from functest.opnfv_tests.openstack.tempest import conf_utils
+from functest.opnfv_tests.openstack.rally import rally
from functest.utils import config
from functest.utils import env
+from functest.utils import functest_utils
LOGGER = logging.getLogger(__name__)
-class TempestCommon(singlevm.VmReady1):
- # pylint: disable=too-many-instance-attributes
+class TempestCommon(singlevm.VmReady2):
+ # pylint: disable=too-many-instance-attributes,too-many-public-methods
"""TempestCommon testcases implementation class."""
visibility = 'public'
+ filename_alt = '/home/opnfv/functest/images/cirros-0.6.1-x86_64-disk.img'
+ shared_network = True
+ tempest_conf_yaml = pkg_resources.resource_filename(
+ 'functest',
+ 'opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml')
+ tempest_custom = pkg_resources.resource_filename(
+ 'functest',
+ 'opnfv_tests/openstack/tempest/custom_tests/test_list.txt')
+ tempest_blacklist = pkg_resources.resource_filename(
+ 'functest',
+ 'opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml')
+ tempest_public_blacklist = pkg_resources.resource_filename(
+ 'functest',
+ 'opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml')
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'tempest'
- super(TempestCommon, self).__init__(**kwargs)
- self.verifier_id = conf_utils.get_verifier_id()
- self.verifier_repo_dir = conf_utils.get_verifier_repo_dir(
- self.verifier_id)
- self.deployment_id = conf_utils.get_verifier_deployment_id()
- self.deployment_dir = conf_utils.get_verifier_deployment_dir(
- self.verifier_id, self.deployment_id)
+ super().__init__(**kwargs)
+ assert self.orig_cloud
+ assert self.cloud
+ assert self.project
+ if self.orig_cloud.get_role("admin"):
+ self.role_name = "admin"
+ elif self.orig_cloud.get_role("Admin"):
+ self.role_name = "Admin"
+ else:
+ raise Exception("Cannot detect neither admin nor Admin")
+ self.orig_cloud.grant_role(
+ self.role_name, user=self.project.user.id,
+ project=self.project.project.id,
+ domain=self.project.domain.id)
+ self.orig_cloud.grant_role(
+ self.role_name, user=self.project.user.id,
+ domain=self.project.domain.id)
+ self.deployment_id = None
+ self.verifier_id = None
+ self.verifier_repo_dir = None
+ self.deployment_dir = None
self.verification_id = None
self.res_dir = os.path.join(
getattr(config.CONF, 'dir_results'), self.case_name)
@@ -66,6 +97,8 @@ class TempestCommon(singlevm.VmReady1):
'neutron_extensions']
except Exception: # pylint: disable=broad-except
pass
+ self.deny_skipping = kwargs.get("deny_skipping", False)
+ self.tests_count = kwargs.get("tests_count", 0)
def check_services(self):
"""Check the mandatory services."""
@@ -89,11 +122,13 @@ class TempestCommon(singlevm.VmReady1):
def check_requirements(self):
self.check_services()
self.check_extensions()
+ if self.is_skipped:
+ self.project.clean()
@staticmethod
def read_file(filename):
"""Read file and return content as a stripped list."""
- with open(filename) as src:
+ with open(filename, encoding='utf-8') as src:
return [line.strip() for line in src.readlines()]
@staticmethod
@@ -107,22 +142,22 @@ class TempestCommon(singlevm.VmReady1):
}
cmd = ["rally", "verify", "show", "--uuid", verif_id]
LOGGER.info("Showing result for a verification: '%s'.", cmd)
- proc = subprocess.Popen(cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- for line in proc.stdout:
- new_line = line.replace(' ', '').split('|')
- if 'Tests' in new_line:
- break
- LOGGER.info(line)
- if 'Testscount' in new_line:
- result['num_tests'] = int(new_line[2])
- elif 'Success' in new_line:
- result['num_success'] = int(new_line[2])
- elif 'Skipped' in new_line:
- result['num_skipped'] = int(new_line[2])
- elif 'Failures' in new_line:
- result['num_failures'] = int(new_line[2])
+ with subprocess.Popen(
+ cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT) as proc:
+ for line in proc.stdout:
+ LOGGER.info(line.decode("utf-8").rstrip())
+ new_line = line.decode("utf-8").replace(' ', '').split('|')
+ if 'Tests' in new_line:
+ break
+ if 'Testscount' in new_line:
+ result['num_tests'] = int(new_line[2])
+ elif 'Success' in new_line:
+ result['num_success'] = int(new_line[2])
+ elif 'Skipped' in new_line:
+ result['num_skipped'] = int(new_line[2])
+ elif 'Failures' in new_line:
+ result['num_failures'] = int(new_line[2])
return result
@staticmethod
@@ -135,64 +170,203 @@ class TempestCommon(singlevm.VmReady1):
shutil.copyfile(conf_file,
os.path.join(res_dir, 'tempest.conf'))
+ @staticmethod
+ def create_verifier():
+ """Create new verifier"""
+ LOGGER.info("Create verifier from existing repo...")
+ cmd = ['rally', 'verify', 'delete-verifier',
+ '--id', str(getattr(config.CONF, 'tempest_verifier_name')),
+ '--force']
+ try:
+ output = subprocess.check_output(cmd)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+ except subprocess.CalledProcessError:
+ pass
+
+ cmd = ['rally', 'verify', 'create-verifier',
+ '--source', str(getattr(config.CONF, 'dir_repo_tempest')),
+ '--name', str(getattr(config.CONF, 'tempest_verifier_name')),
+ '--type', 'tempest', '--system-wide']
+ output = subprocess.check_output(cmd)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+ return TempestCommon.get_verifier_id()
+
+ @staticmethod
+ def get_verifier_id():
+ """
+ Returns verifier id for current Tempest
+ """
+ cmd = ("rally verify list-verifiers | awk '/" +
+ getattr(config.CONF, 'tempest_verifier_name') +
+ "/ {print $2}'")
+ with subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE,
+ stderr=subprocess.DEVNULL) as proc:
+ verifier_uuid = proc.stdout.readline().rstrip()
+ return verifier_uuid.decode("utf-8")
+
+ @staticmethod
+ def get_verifier_repo_dir(verifier_id):
+ """
+ Returns installed verifier repo directory for Tempest
+ """
+ return os.path.join(getattr(config.CONF, 'dir_rally_inst'),
+ 'verification',
+ f'verifier-{verifier_id}',
+ 'repo')
+
+ @staticmethod
+ def get_verifier_deployment_dir(verifier_id, deployment_id):
+ """
+ Returns Rally deployment directory for current verifier
+ """
+ return os.path.join(getattr(config.CONF, 'dir_rally_inst'),
+ 'verification',
+ f'verifier-{verifier_id}',
+ f'for-deployment-{deployment_id}')
+
+ @staticmethod
+ def update_tempest_conf_file(conf_file, rconfig):
+ """Update defined paramters into tempest config file"""
+ with open(TempestCommon.tempest_conf_yaml, encoding='utf-8') as yfile:
+ conf_yaml = yaml.safe_load(yfile)
+ if conf_yaml:
+ sections = rconfig.sections()
+ for section in conf_yaml:
+ if section not in sections:
+ rconfig.add_section(section)
+ sub_conf = conf_yaml.get(section)
+ for key, value in sub_conf.items():
+ rconfig.set(section, key, value)
+
+ with open(conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ @staticmethod
+ def configure_tempest_update_params(
+ tempest_conf_file, image_id=None, flavor_id=None,
+ compute_cnt=1, image_alt_id=None, flavor_alt_id=None,
+ admin_role_name='admin', cidr='192.168.120.0/24',
+ domain_id='default'):
+ # pylint: disable=too-many-branches,too-many-arguments
+ # pylint: disable=too-many-statements,too-many-locals
+ """
+ Add/update needed parameters into tempest.conf file
+ """
+ LOGGER.debug("Updating selected tempest.conf parameters...")
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(tempest_conf_file)
+ rconfig.set(
+ 'compute', 'volume_device_name', env.get('VOLUME_DEVICE_NAME'))
+ if image_id is not None:
+ rconfig.set('compute', 'image_ref', image_id)
+ if image_alt_id is not None:
+ rconfig.set('compute', 'image_ref_alt', image_alt_id)
+ if flavor_id is not None:
+ rconfig.set('compute', 'flavor_ref', flavor_id)
+ if flavor_alt_id is not None:
+ rconfig.set('compute', 'flavor_ref_alt', flavor_alt_id)
+ if compute_cnt > 1:
+ # enable multinode tests
+ rconfig.set('compute', 'min_compute_nodes', compute_cnt)
+ rconfig.set('compute-feature-enabled', 'live_migration', True)
+ if os.environ.get('OS_REGION_NAME'):
+ rconfig.set('identity', 'region', os.environ.get('OS_REGION_NAME'))
+ rconfig.set('identity', 'admin_role', admin_role_name)
+ rconfig.set('identity', 'default_domain_id', domain_id)
+ if not rconfig.has_section('network'):
+ rconfig.add_section('network')
+ rconfig.set('network', 'default_network', cidr)
+ rconfig.set('network', 'project_network_cidr', cidr)
+ rconfig.set('network', 'project_networks_reachable', False)
+ rconfig.set(
+ 'identity', 'v3_endpoint_type',
+ os.environ.get('OS_INTERFACE', 'public'))
+
+ sections = rconfig.sections()
+ services_list = [
+ 'compute', 'volume', 'image', 'network', 'data-processing',
+ 'object-storage', 'orchestration']
+ for service in services_list:
+ if service not in sections:
+ rconfig.add_section(service)
+ rconfig.set(service, 'endpoint_type',
+ os.environ.get('OS_INTERFACE', 'public'))
+
+ LOGGER.debug('Add/Update required params defined in tempest_conf.yaml '
+ 'into tempest.conf file')
+ TempestCommon.update_tempest_conf_file(tempest_conf_file, rconfig)
+
+ @staticmethod
+ def configure_verifier(deployment_dir):
+ """
+ Execute rally verify configure-verifier, which generates tempest.conf
+ """
+ cmd = ['rally', 'verify', 'configure-verifier', '--reconfigure',
+ '--id', str(getattr(config.CONF, 'tempest_verifier_name'))]
+ output = subprocess.check_output(cmd)
+ LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
+
+ LOGGER.debug("Looking for tempest.conf file...")
+ tempest_conf_file = os.path.join(deployment_dir, "tempest.conf")
+ if not os.path.isfile(tempest_conf_file):
+ LOGGER.error("Tempest configuration file %s NOT found.",
+ tempest_conf_file)
+ return None
+ return tempest_conf_file
+
def generate_test_list(self, **kwargs):
"""Generate test list based on the test mode."""
LOGGER.debug("Generating test case list...")
self.backup_tempest_config(self.conf_file, '/etc')
if kwargs.get('mode') == 'custom':
- if os.path.isfile(conf_utils.TEMPEST_CUSTOM):
+ if os.path.isfile(self.tempest_custom):
shutil.copyfile(
- conf_utils.TEMPEST_CUSTOM, self.list)
+ self.tempest_custom, self.list)
else:
- raise Exception("Tempest test list file %s NOT found."
- % conf_utils.TEMPEST_CUSTOM)
+ raise Exception(
+ f"Tempest test list file {self.tempest_custom} NOT found.")
else:
testr_mode = kwargs.get(
'mode', r'^tempest\.(api|scenario).*\[.*\bsmoke\b.*\]$')
- cmd = "(cd {0}; stestr list '{1}' >{2} 2>/dev/null)".format(
- self.verifier_repo_dir, testr_mode, self.list)
+ cmd = (f"(cd {self.verifier_repo_dir}; "
+ f"stestr list '{testr_mode}' > {self.list} 2>/dev/null)")
output = subprocess.check_output(cmd, shell=True)
- LOGGER.info("%s\n%s", cmd, output)
+ LOGGER.info("%s\n%s", cmd, output.decode("utf-8"))
os.remove('/etc/tempest.conf')
- def apply_tempest_blacklist(self):
+ def apply_tempest_blacklist(self, black_list):
"""Exclude blacklisted test cases."""
LOGGER.debug("Applying tempest blacklist...")
if os.path.exists(self.raw_list):
os.remove(self.raw_list)
os.rename(self.list, self.raw_list)
cases_file = self.read_file(self.raw_list)
- result_file = open(self.list, 'w')
- black_tests = []
- try:
- installer_type = env.get('INSTALLER_TYPE')
- deploy_scenario = env.get('DEPLOY_SCENARIO')
- if bool(installer_type) * bool(deploy_scenario):
- # if INSTALLER_TYPE and DEPLOY_SCENARIO are set we read the
- # file
- black_list_file = open(conf_utils.TEMPEST_BLACKLIST)
- black_list_yaml = yaml.safe_load(black_list_file)
- black_list_file.close()
- for item in black_list_yaml:
- scenarios = item['scenarios']
- installers = item['installers']
- if (deploy_scenario in scenarios and
- installer_type in installers):
- tests = item['tests']
- for test in tests:
- black_tests.append(test)
- break
- except Exception: # pylint: disable=broad-except
+ with open(self.list, 'w', encoding='utf-8') as result_file:
black_tests = []
- LOGGER.debug("Tempest blacklist file does not exist.")
+ try:
+ deploy_scenario = env.get('DEPLOY_SCENARIO')
+ if bool(deploy_scenario):
+ # if DEPLOY_SCENARIO is set we read the file
+ with open(black_list, encoding='utf-8') as black_list_file:
+ black_list_yaml = yaml.safe_load(black_list_file)
+ black_list_file.close()
+ for item in black_list_yaml:
+ scenarios = item['scenarios']
+ in_it = rally.RallyBase.in_iterable_re
+ if in_it(deploy_scenario, scenarios):
+ tests = item['tests']
+ black_tests.extend(tests)
+ except Exception: # pylint: disable=broad-except
+ black_tests = []
+ LOGGER.debug("Tempest blacklist file does not exist.")
- for cases_line in cases_file:
- for black_tests_line in black_tests:
- if black_tests_line in cases_line:
- break
- else:
- result_file.write(str(cases_line) + '\n')
- result_file.close()
+ for cases_line in cases_file:
+ for black_tests_line in black_tests:
+ if re.search(black_tests_line, cases_line):
+ break
+ else:
+ result_file.write(str(cases_line) + '\n')
def run_verifier_tests(self, **kwargs):
"""Execute tempest test cases."""
@@ -201,34 +375,31 @@ class TempestCommon(singlevm.VmReady1):
cmd.extend(kwargs.get('option', []))
LOGGER.info("Starting Tempest test suite: '%s'.", cmd)
- f_stdout = open(
- os.path.join(self.res_dir, "tempest.log"), 'w+')
- f_stderr = open(
- os.path.join(self.res_dir,
- "tempest-error.log"), 'w+')
-
- proc = subprocess.Popen(
- cmd,
- stdout=subprocess.PIPE,
- stderr=f_stderr,
- bufsize=1)
-
- with proc.stdout:
- for line in iter(proc.stdout.readline, b''):
- if re.search(r"\} tempest\.", line):
- LOGGER.info(line.replace('\n', ''))
- elif re.search(r'(?=\(UUID=(.*)\))', line):
- self.verification_id = re.search(
- r'(?=\(UUID=(.*)\))', line).group(1)
- LOGGER.info('Verification UUID: %s', self.verification_id)
- f_stdout.write(line)
- proc.wait()
-
- f_stdout.close()
- f_stderr.close()
+ with open(
+ os.path.join(self.res_dir, "tempest.log"), 'w+',
+ encoding='utf-8') as f_stdout:
+ with subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ bufsize=1) as proc:
+ with proc.stdout:
+ for line in iter(proc.stdout.readline, b''):
+ if re.search(r"\} tempest\.", line.decode("utf-8")):
+ LOGGER.info(line.rstrip())
+ elif re.search(r'(?=\(UUID=(.*)\))',
+ line.decode("utf-8")):
+ self.verification_id = re.search(
+ r'(?=\(UUID=(.*)\))',
+ line.decode("utf-8")).group(1)
+ f_stdout.write(line.decode("utf-8"))
+ proc.wait()
if self.verification_id is None:
raise Exception('Verification UUID not found')
+ LOGGER.info('Verification UUID: %s', self.verification_id)
+
+ shutil.copy(
+ f"{self.deployment_dir}/tempest.log",
+ f"{self.res_dir}/tempest.debug.log")
def parse_verifier_result(self):
"""Parse and save test results."""
@@ -245,8 +416,8 @@ class TempestCommon(singlevm.VmReady1):
LOGGER.error("No test has been executed")
return
- with open(os.path.join(self.res_dir,
- "tempest-error.log"), 'r') as logfile:
+ with open(os.path.join(self.res_dir, "rally.log"),
+ 'r', encoding='utf-8') as logfile:
output = logfile.read()
success_testcases = []
@@ -258,7 +429,7 @@ class TempestCommon(singlevm.VmReady1):
output):
failed_testcases.append(match)
skipped_testcases = []
- for match in re.findall(r'.*\{\d{1,2}\} (.*?) \.{3} skip:',
+ for match in re.findall(r'.*\{\d{1,2}\} (.*?) \.{3} skip(?::| )',
output):
skipped_testcases.append(match)
@@ -275,24 +446,14 @@ class TempestCommon(singlevm.VmReady1):
LOGGER.info("Tempest %s success_rate is %s%%",
self.case_name, self.result)
- def generate_report(self):
- """Generate verification report."""
- html_file = os.path.join(self.res_dir,
- "tempest-report.html")
- cmd = ["rally", "verify", "report", "--type", "html", "--uuid",
- self.verification_id, "--to", html_file]
- subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
-
def update_rally_regex(self, rally_conf='/etc/rally/rally.conf'):
"""Set image name as tempest img_name_regex"""
rconfig = configparser.RawConfigParser()
rconfig.read(rally_conf)
- if not rconfig.has_section('tempest'):
- rconfig.add_section('tempest')
- rconfig.set('tempest', 'img_name_regex', '^{}$'.format(
- self.image.name))
- with open(rally_conf, 'wb') as config_file:
+ if not rconfig.has_section('openstack'):
+ rconfig.add_section('openstack')
+ rconfig.set('openstack', 'img_name_regex', f'^{self.image.name}$')
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
def update_default_role(self, rally_conf='/etc/rally/rally.conf'):
@@ -302,10 +463,131 @@ class TempestCommon(singlevm.VmReady1):
return
rconfig = configparser.RawConfigParser()
rconfig.read(rally_conf)
- if not rconfig.has_section('tempest'):
- rconfig.add_section('tempest')
- rconfig.set('tempest', 'swift_operator_role', '^{}$'.format(role.name))
- with open(rally_conf, 'wb') as config_file:
+ if not rconfig.has_section('openstack'):
+ rconfig.add_section('openstack')
+ rconfig.set('openstack', 'swift_operator_role', role.name)
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ @staticmethod
+ def clean_rally_conf(rally_conf='/etc/rally/rally.conf'):
+ """Clean Rally config"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(rally_conf)
+ if rconfig.has_option('openstack', 'img_name_regex'):
+ rconfig.remove_option('openstack', 'img_name_regex')
+ if rconfig.has_option('openstack', 'swift_operator_role'):
+ rconfig.remove_option('openstack', 'swift_operator_role')
+ with open(rally_conf, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ def update_auth_section(self):
+ """Update auth section in tempest.conf"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if not rconfig.has_section("auth"):
+ rconfig.add_section("auth")
+ if env.get("NEW_USER_ROLE").lower() != "member":
+ tempest_roles = []
+ if rconfig.has_option("auth", "tempest_roles"):
+ tempest_roles = functest_utils.convert_ini_to_list(
+ rconfig.get("auth", "tempest_roles"))
+ rconfig.set(
+ 'auth', 'tempest_roles',
+ functest_utils.convert_list_to_ini(
+ [env.get("NEW_USER_ROLE")] + tempest_roles))
+ if not json.loads(env.get("USE_DYNAMIC_CREDENTIALS").lower()):
+ rconfig.set('auth', 'use_dynamic_credentials', False)
+ account_file = os.path.join(
+ getattr(config.CONF, 'dir_functest_data'), 'accounts.yaml')
+ assert os.path.exists(
+ account_file), f"{account_file} doesn't exist"
+ rconfig.set('auth', 'test_accounts_file', account_file)
+ if env.get('NO_TENANT_NETWORK').lower() == 'true':
+ rconfig.set('auth', 'create_isolated_networks', False)
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ def update_network_section(self):
+ """Update network section in tempest.conf"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if self.ext_net:
+ if not rconfig.has_section('network'):
+ rconfig.add_section('network')
+ rconfig.set('network', 'public_network_id', self.ext_net.id)
+ rconfig.set('network', 'floating_network_name', self.ext_net.name)
+ rconfig.set('network-feature-enabled', 'floating_ips', True)
+ else:
+ if not rconfig.has_section('network-feature-enabled'):
+ rconfig.add_section('network-feature-enabled')
+ rconfig.set('network-feature-enabled', 'floating_ips', False)
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ def update_compute_section(self):
+ """Update compute section in tempest.conf"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if not rconfig.has_section('compute'):
+ rconfig.add_section('compute')
+ rconfig.set(
+ 'compute', 'fixed_network_name',
+ self.network.name if self.network else env.get("EXTERNAL_NETWORK"))
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ def update_validation_section(self):
+ """Update validation section in tempest.conf"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if not rconfig.has_section('validation'):
+ rconfig.add_section('validation')
+ rconfig.set(
+ 'validation', 'connect_method',
+ 'floating' if self.ext_net else 'fixed')
+ rconfig.set(
+ 'validation', 'network_for_ssh',
+ self.network.name if self.network else env.get("EXTERNAL_NETWORK"))
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ def update_scenario_section(self):
+ """Update scenario section in tempest.conf"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ filename = getattr(
+ config.CONF, f'{self.case_name}_image', self.filename)
+ if not rconfig.has_section('scenario'):
+ rconfig.add_section('scenario')
+ rconfig.set('scenario', 'img_file', filename)
+ rconfig.set('scenario', 'img_disk_format', getattr(
+ config.CONF, f'{self.case_name}_image_format',
+ self.image_format))
+ extra_properties = self.extra_properties.copy()
+ if env.get('IMAGE_PROPERTIES'):
+ extra_properties.update(
+ functest_utils.convert_ini_to_dict(
+ env.get('IMAGE_PROPERTIES')))
+ extra_properties.update(
+ getattr(config.CONF, f'{self.case_name}_extra_properties', {}))
+ rconfig.set(
+ 'scenario', 'img_properties',
+ functest_utils.convert_dict_to_ini(extra_properties))
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+
+ def update_dashboard_section(self):
+ """Update dashboard section in tempest.conf"""
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if env.get('DASHBOARD_URL'):
+ if not rconfig.has_section('dashboard'):
+ rconfig.add_section('dashboard')
+ rconfig.set('dashboard', 'dashboard_url', env.get('DASHBOARD_URL'))
+ else:
+ rconfig.set('service_available', 'horizon', False)
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
rconfig.write(config_file)
def configure(self, **kwargs): # pylint: disable=unused-argument
@@ -315,36 +597,69 @@ class TempestCommon(singlevm.VmReady1):
"""
if not os.path.exists(self.res_dir):
os.makedirs(self.res_dir)
- compute_cnt = len(self.cloud.list_hypervisors())
+ self.deployment_id = rally.RallyBase.create_rally_deployment(
+ environ=self.project.get_environ())
+ if not self.deployment_id:
+ raise Exception("Deployment create failed")
+ self.verifier_id = self.create_verifier()
+ if not self.verifier_id:
+ raise Exception("Verifier create failed")
+ self.verifier_repo_dir = self.get_verifier_repo_dir(
+ self.verifier_id)
+ self.deployment_dir = self.get_verifier_deployment_dir(
+ self.verifier_id, self.deployment_id)
- self.image_alt = self.publish_image(
- '{}-img_alt_{}'.format(self.case_name, self.guid))
+ compute_cnt = self.count_hypervisors() if self.count_hypervisors(
+ ) <= 10 else 10
+ self.image_alt = self.publish_image_alt()
self.flavor_alt = self.create_flavor_alt()
LOGGER.debug("flavor: %s", self.flavor_alt)
- self.conf_file = conf_utils.configure_verifier(self.deployment_dir)
- conf_utils.configure_tempest_update_params(
- self.conf_file, network_name=self.network.id,
+ self.conf_file = self.configure_verifier(self.deployment_dir)
+ if not self.conf_file:
+ raise Exception("Tempest verifier configuring failed")
+ self.configure_tempest_update_params(
+ self.conf_file,
image_id=self.image.id,
flavor_id=self.flavor.id,
compute_cnt=compute_cnt,
image_alt_id=self.image_alt.id,
- flavor_alt_id=self.flavor_alt.id)
+ flavor_alt_id=self.flavor_alt.id,
+ admin_role_name=self.role_name, cidr=self.cidr,
+ domain_id=self.project.domain.id)
+ self.update_auth_section()
+ self.update_network_section()
+ self.update_compute_section()
+ self.update_validation_section()
+ self.update_scenario_section()
+ self.update_dashboard_section()
self.backup_tempest_config(self.conf_file, self.res_dir)
def run(self, **kwargs):
self.start_time = time.time()
try:
- assert super(TempestCommon, self).run(
+ assert super().run(
**kwargs) == testcase.TestCase.EX_OK
+ if not os.path.exists(self.res_dir):
+ os.makedirs(self.res_dir)
self.update_rally_regex()
self.update_default_role()
+ rally.RallyBase.update_rally_logs(self.res_dir)
+ shutil.copy("/etc/rally/rally.conf", self.res_dir)
self.configure(**kwargs)
self.generate_test_list(**kwargs)
- self.apply_tempest_blacklist()
+ self.apply_tempest_blacklist(TempestCommon.tempest_blacklist)
+ if env.get('PUBLIC_ENDPOINT_ONLY').lower() == 'true':
+ self.apply_tempest_blacklist(
+ TempestCommon.tempest_public_blacklist)
self.run_verifier_tests(**kwargs)
self.parse_verifier_result()
- self.generate_report()
+ rally.RallyBase.verify_report(
+ os.path.join(self.res_dir, "tempest-report.html"),
+ self.verification_id)
+ rally.RallyBase.verify_report(
+ os.path.join(self.res_dir, "tempest-report.xml"),
+ self.verification_id, "junit-xml")
res = testcase.TestCase.EX_OK
except Exception: # pylint: disable=broad-except
LOGGER.exception('Error with run')
@@ -357,8 +672,103 @@ class TempestCommon(singlevm.VmReady1):
"""
Cleanup all OpenStack objects. Should be called on completion.
"""
- super(TempestCommon, self).clean()
+ self.clean_rally_conf()
+ rally.RallyBase.clean_rally_logs()
if self.image_alt:
self.cloud.delete_image(self.image_alt)
if self.flavor_alt:
self.orig_cloud.delete_flavor(self.flavor_alt.id)
+ super().clean()
+
+ def is_successful(self):
+ """The overall result of the test."""
+ skips = self.details.get("skipped_number", 0)
+ if skips > 0 and self.deny_skipping:
+ return testcase.TestCase.EX_TESTCASE_FAILED
+ if self.tests_count and (
+ self.details.get("tests_number", 0) != self.tests_count):
+ return testcase.TestCase.EX_TESTCASE_FAILED
+ return super().is_successful()
+
+
+class TempestHeat(TempestCommon):
+ """Tempest Heat testcase implementation class."""
+
+ filename_alt = ('/home/opnfv/functest/images/'
+ 'Fedora-Cloud-Base-30-1.2.x86_64.qcow2')
+ flavor_alt_ram = 512
+ flavor_alt_vcpus = 1
+ flavor_alt_disk = 4
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.user2 = self.orig_cloud.create_user(
+ name=f'{self.case_name}-user2_{self.project.guid}',
+ password=self.project.password,
+ domain_id=self.project.domain.id)
+ self.orig_cloud.grant_role(
+ self.role_name, user=self.user2.id,
+ project=self.project.project.id, domain=self.project.domain.id)
+ if not self.orig_cloud.get_role("heat_stack_owner"):
+ self.role = self.orig_cloud.create_role("heat_stack_owner")
+ self.orig_cloud.grant_role(
+ "heat_stack_owner", user=self.user2.id,
+ project=self.project.project.id,
+ domain=self.project.domain.id)
+
+ def configure(self, **kwargs):
+ assert self.user2
+ super().configure(**kwargs)
+ rconfig = configparser.RawConfigParser()
+ rconfig.read(self.conf_file)
+ if not rconfig.has_section('heat_plugin'):
+ rconfig.add_section('heat_plugin')
+ # It fails if region and domain ids are unset
+ rconfig.set(
+ 'heat_plugin', 'region',
+ os.environ.get('OS_REGION_NAME', 'RegionOne'))
+ rconfig.set('heat_plugin', 'auth_url', os.environ["OS_AUTH_URL"])
+ rconfig.set('heat_plugin', 'project_domain_id', self.project.domain.id)
+ rconfig.set('heat_plugin', 'user_domain_id', self.project.domain.id)
+ rconfig.set(
+ 'heat_plugin', 'project_domain_name', self.project.domain.name)
+ rconfig.set(
+ 'heat_plugin', 'user_domain_name', self.project.domain.name)
+ rconfig.set('heat_plugin', 'username', self.user2.name)
+ rconfig.set('heat_plugin', 'password', self.project.password)
+ rconfig.set('heat_plugin', 'project_name', self.project.project.name)
+ rconfig.set('heat_plugin', 'admin_username', self.project.user.name)
+ rconfig.set('heat_plugin', 'admin_password', self.project.password)
+ rconfig.set(
+ 'heat_plugin', 'admin_project_name', self.project.project.name)
+ rconfig.set('heat_plugin', 'image_ref', self.image_alt.id)
+ rconfig.set('heat_plugin', 'instance_type', self.flavor_alt.id)
+ rconfig.set('heat_plugin', 'minimal_image_ref', self.image.id)
+ rconfig.set('heat_plugin', 'minimal_instance_type', self.flavor.id)
+ if self.ext_net:
+ rconfig.set(
+ 'heat_plugin', 'floating_network_name', self.ext_net.name)
+ if self.network:
+ rconfig.set('heat_plugin', 'fixed_network_name', self.network.name)
+ rconfig.set('heat_plugin', 'fixed_subnet_name', self.subnet.name)
+ rconfig.set('heat_plugin', 'network_for_ssh', self.network.name)
+ else:
+ LOGGER.warning(
+ 'No tenant network created. '
+ 'Trying EXTERNAL_NETWORK as a fallback')
+ rconfig.set(
+ 'heat_plugin', 'fixed_network_name',
+ env.get("EXTERNAL_NETWORK"))
+ rconfig.set(
+ 'heat_plugin', 'network_for_ssh', env.get("EXTERNAL_NETWORK"))
+ with open(self.conf_file, 'w', encoding='utf-8') as config_file:
+ rconfig.write(config_file)
+ self.backup_tempest_config(self.conf_file, self.res_dir)
+
+ def clean(self):
+ """
+ Cleanup all OpenStack objects. Should be called on completion.
+ """
+ super().clean()
+ if self.user2:
+ self.orig_cloud.delete_user(self.user2.id)
diff --git a/functest/opnfv_tests/openstack/vmtp/vmtp.py b/functest/opnfv_tests/openstack/vmtp/vmtp.py
index 326a4f383..9833cc72a 100644
--- a/functest/opnfv_tests/openstack/vmtp/vmtp.py
+++ b/functest/opnfv_tests/openstack/vmtp/vmtp.py
@@ -33,9 +33,10 @@ from xtesting.core import testcase
from functest.core import singlevm
from functest.utils import env
+from functest.utils import functest_utils
-class Vmtp(singlevm.VmReady1):
+class Vmtp(singlevm.VmReady2):
"""Class to run Vmtp_ as an OPNFV Functest testcase
.. _Vmtp: http://vmtp.readthedocs.io/en/latest/
@@ -49,28 +50,50 @@ class Vmtp(singlevm.VmReady1):
flavor_ram = 2048
flavor_vcpus = 1
flavor_disk = 0
+ create_server_timeout = 300
+ ssh_retry_timeout = 240
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = 'vmtp'
- super(Vmtp, self).__init__(**kwargs)
- self.config = "{}/vmtp.conf".format(self.res_dir)
+ super().__init__(**kwargs)
+ self.config = f"{self.res_dir}/vmtp.conf"
(_, self.privkey_filename) = tempfile.mkstemp()
(_, self.pubkey_filename) = tempfile.mkstemp()
+ def check_requirements(self):
+ if self.count_hypervisors() < 2:
+ self.__logger.warning("Vmtp requires at least 2 hypervisors")
+ self.is_skipped = True
+ self.project.clean()
+
+ def create_network_resources(self):
+ """Create router
+
+ It creates a router which gateway is the external network detected.
+
+ Raises: expection on error
+ """
+ assert self.cloud
+ assert self.ext_net
+ self.router = self.cloud.create_router(
+ name=f'{self.case_name}-router_{self.guid}',
+ ext_gateway_net_id=self.ext_net.id)
+ self.__logger.debug("router: %s", self.router)
+
def generate_keys(self):
"""Generate Keys
Raises: Exception on error
"""
assert self.cloud
- name = "vmtp_{}".format(self.guid)
+ name = f"vmtp_{self.guid}"
self.__logger.info("Creating keypair with name: '%s'", name)
keypair = self.cloud.create_keypair(name)
self.__logger.debug("keypair: %s", keypair)
- with open(self.privkey_filename, 'w') as key_file:
+ with open(self.privkey_filename, 'w', encoding='utf-8') as key_file:
key_file.write(keypair.private_key)
- with open(self.pubkey_filename, 'w') as key_file:
+ with open(self.pubkey_filename, 'w', encoding='utf-8') as key_file:
key_file.write(keypair.public_key)
self.cloud.delete_keypair(keypair.id)
@@ -83,40 +106,66 @@ class Vmtp(singlevm.VmReady1):
if not os.path.exists(self.res_dir):
os.makedirs(self.res_dir)
cmd = ['vmtp', '-sc']
- output = subprocess.check_output(cmd)
+ output = subprocess.check_output(cmd).decode("utf-8")
self.__logger.info("%s\n%s", " ".join(cmd), output)
- with open(self.config, "w+") as conf:
- vmtp_conf = yaml.load(output)
+ with open(self.config, "w+", encoding='utf-8') as conf:
+ vmtp_conf = yaml.full_load(output)
vmtp_conf["private_key_file"] = self.privkey_filename
vmtp_conf["public_key_file"] = self.pubkey_filename
vmtp_conf["image_name"] = str(self.image.name)
- vmtp_conf["router_name"] = "pns_router_{}".format(self.guid)
+ vmtp_conf["router_name"] = str(self.router.name)
vmtp_conf["flavor_type"] = str(self.flavor.name)
vmtp_conf["internal_network_name"] = [
- "pns-internal-net_{}".format(self.guid),
- "pns-internal-net2_{}".format(self.guid)]
- vmtp_conf["vm_name_client"] = "TestClient_{}".format(self.guid)
- vmtp_conf["vm_name_server"] = "TestServer_{}".format(self.guid)
- vmtp_conf["security_group_name"] = "pns-security{}".format(
- self.guid)
+ f"pns-internal-net_{self.guid}",
+ f"pns-internal-net2_{self.guid}"]
+ vmtp_conf["vm_name_client"] = f"TestClient_{self.guid}"
+ vmtp_conf["vm_name_server"] = f"TestServer_{self.guid}"
+ vmtp_conf["security_group_name"] = f"pns-security{self.guid}"
vmtp_conf["dns_nameservers"] = [env.get('NAMESERVER')]
+ vmtp_conf["generic_retry_count"] = self.create_server_timeout // 2
+ vmtp_conf["ssh_retry_count"] = self.ssh_retry_timeout // 2
conf.write(yaml.dump(vmtp_conf))
def run_vmtp(self):
+ # pylint: disable=unexpected-keyword-arg
"""Run Vmtp and generate charts
Raises: Exception on error
"""
assert self.cloud
- cmd = ['vmtp', '-d', '--json', '{}/vmtp.json'.format(self.res_dir),
+ new_env = dict(
+ os.environ,
+ OS_USERNAME=self.project.user.name,
+ OS_PROJECT_NAME=self.project.project.name,
+ OS_PROJECT_ID=self.project.project.id,
+ OS_PROJECT_DOMAIN_NAME=self.project.domain.name,
+ OS_USER_DOMAIN_NAME=self.project.domain.name,
+ OS_PASSWORD=self.project.password)
+ if not new_env["OS_AUTH_URL"].endswith(('v3', 'v3/')):
+ new_env["OS_AUTH_URL"] = f'{new_env["OS_AUTH_URL"]}/v3'
+ try:
+ del new_env['OS_TENANT_NAME']
+ del new_env['OS_TENANT_ID']
+ except Exception: # pylint: disable=broad-except
+ pass
+ cmd = ['vmtp', '-d', '--json', f'{self.res_dir}/vmtp.json',
'-c', self.config]
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ if env.get("VMTP_HYPERVISORS"):
+ hypervisors = functest_utils.convert_ini_to_list(
+ env.get("VMTP_HYPERVISORS"))
+ for hypervisor in hypervisors:
+ cmd.extend(["--hypervisor", hypervisor])
+ self.__logger.debug("cmd: %s", cmd)
+ output = subprocess.check_output(
+ cmd, stderr=subprocess.STDOUT, env=new_env).decode("utf-8")
self.__logger.info("%s\n%s", " ".join(cmd), output)
- cmd = ['vmtp_genchart', '-c', '{}/vmtp.html'.format(self.res_dir),
- '{}/vmtp.json'.format(self.res_dir)]
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ cmd = ['vmtp_genchart', '-c', f'{self.res_dir}/vmtp.html',
+ f'{self.res_dir}/vmtp.json']
+ output = subprocess.check_output(
+ cmd, stderr=subprocess.STDOUT).decode("utf-8")
self.__logger.info("%s\n%s", " ".join(cmd), output)
- with open('{}/vmtp.json'.format(self.res_dir), 'r') as res_file:
+ with open(f'{self.res_dir}/vmtp.json', 'r',
+ encoding='utf-8') as res_file:
self.details = json.load(res_file)
def run(self, **kwargs):
@@ -124,8 +173,18 @@ class Vmtp(singlevm.VmReady1):
status = testcase.TestCase.EX_RUN_ERROR
try:
assert self.cloud
- self.image = self.publish_image()
- self.flavor = self.create_flavor()
+ assert super().run(**kwargs) == self.EX_OK
+ status = testcase.TestCase.EX_RUN_ERROR
+ if self.orig_cloud.get_role("admin"):
+ role_name = "admin"
+ elif self.orig_cloud.get_role("Admin"):
+ role_name = "Admin"
+ else:
+ raise Exception("Cannot detect neither admin nor Admin")
+ self.orig_cloud.grant_role(
+ role_name, user=self.project.user.id,
+ project=self.project.project.id,
+ domain=self.project.domain.id)
self.generate_keys()
self.write_config()
self.run_vmtp()
@@ -133,7 +192,8 @@ class Vmtp(singlevm.VmReady1):
status = testcase.TestCase.EX_OK
except subprocess.CalledProcessError as cpe:
self.__logger.error(
- "Exception when calling %s\n%s", cpe.cmd, cpe.output)
+ "Exception when calling %s\n%s", cpe.cmd,
+ cpe.output.decode("utf-8"))
self.result = 0
except Exception: # pylint: disable=broad-except
self.__logger.exception("Cannot run vmtp")
@@ -144,11 +204,10 @@ class Vmtp(singlevm.VmReady1):
def clean(self):
try:
assert self.cloud
+ super().clean()
os.remove(self.privkey_filename)
os.remove(self.pubkey_filename)
- if self.image:
- self.cloud.delete_image(self.image)
- self.cloud.delete_network("pns-internal-net_{}".format(self.guid))
- self.cloud.delete_network("pns-internal-net2_{}".format(self.guid))
+ self.cloud.delete_network(f"pns-internal-net_{self.guid}")
+ self.cloud.delete_network(f"pns-internal-net2_{self.guid}")
except Exception: # pylint: disable=broad-except
pass
diff --git a/functest/opnfv_tests/openstack/vping/vping_ssh.py b/functest/opnfv_tests/openstack/vping/vping_ssh.py
index 643f4f6de..ad64348c4 100644
--- a/functest/opnfv_tests/openstack/vping/vping_ssh.py
+++ b/functest/opnfv_tests/openstack/vping/vping_ssh.py
@@ -29,13 +29,13 @@ class VPingSSH(singlevm.SingleVm2):
"""Initialize testcase."""
if "case_name" not in kwargs:
kwargs["case_name"] = "vping_ssh"
- super(VPingSSH, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.vm2 = None
def prepare(self):
- super(VPingSSH, self).prepare()
+ super().prepare()
self.vm2 = self.boot_vm(
- '{}-vm2_{}'.format(self.case_name, self.guid),
+ f'{self.case_name}-vm2_{self.guid}',
security_groups=[self.sec.id])
def execute(self):
@@ -44,9 +44,13 @@ class VPingSSH(singlevm.SingleVm2):
Returns: ping exit codes
"""
assert self.ssh
- (_, stdout, _) = self.ssh.exec_command(
- 'ping -c 1 ' + self.vm2.private_v4)
- self.__logger.debug("output:\n%s", stdout.read())
+ if not self.check_regex_in_console(self.vm2.name):
+ return 1
+ ip4 = self.vm2.private_v4 or self.vm2.addresses[
+ self.network.name][0].addr
+ (_, stdout, stderr) = self.ssh.exec_command(f'ping -c 1 {ip4}')
+ self.__logger.info("output:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.info("error:\n%s", stderr.read().decode("utf-8"))
return stdout.channel.recv_exit_status()
def clean(self):
@@ -55,4 +59,4 @@ class VPingSSH(singlevm.SingleVm2):
self.cloud.delete_server(
self.vm2, wait=True,
timeout=getattr(config.CONF, 'vping_vm_delete_timeout'))
- super(VPingSSH, self).clean()
+ super().clean()
diff --git a/functest/opnfv_tests/openstack/vping/vping_userdata.py b/functest/opnfv_tests/openstack/vping/vping_userdata.py
index 421ea6a2c..8a8f26f37 100644
--- a/functest/opnfv_tests/openstack/vping/vping_userdata.py
+++ b/functest/opnfv_tests/openstack/vping/vping_userdata.py
@@ -26,7 +26,7 @@ class VPingUserdata(singlevm.VmReady2):
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = "vping_userdata"
- super(VPingUserdata, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.logger = logging.getLogger(__name__)
self.vm1 = None
self.vm2 = None
@@ -39,14 +39,13 @@ class VPingUserdata(singlevm.VmReady2):
"""
try:
assert self.cloud
- assert super(VPingUserdata, self).run(
+ assert super().run(
**kwargs) == testcase.TestCase.EX_OK
self.result = 0
self.vm1 = self.boot_vm()
self.vm2 = self.boot_vm(
- '{}-vm2_{}'.format(self.case_name, self.guid),
+ f'{self.case_name}-vm2_{self.guid}',
userdata=self._get_userdata())
- self.vm2 = self.cloud.wait_for_server(self.vm2, auto_ip=False)
result = self._do_vping()
self.stop_time = time.time()
@@ -62,7 +61,8 @@ class VPingUserdata(singlevm.VmReady2):
"""
Override from super
"""
- if not self.vm1.private_v4:
+ if not (self.vm1.private_v4 or self.vm1.addresses[
+ self.network.name][0].addr):
self.logger.error("vm1: IP addr missing")
return testcase.TestCase.EX_TESTCASE_FAILED
@@ -79,22 +79,23 @@ class VPingUserdata(singlevm.VmReady2):
self.logger.info("vPing detected!")
exit_code = testcase.TestCase.EX_OK
break
- elif "failed to read iid from metadata" in p_console or tries > 5:
+ if "failed to read iid from metadata" in p_console or tries > 5:
self.logger.info("Failed to read iid from metadata")
break
- elif sec == getattr(config.CONF, 'vping_ping_timeout'):
+ if sec == getattr(config.CONF, 'vping_ping_timeout'):
self.logger.info("Timeout reached.")
break
- elif sec % 10 == 0:
+ if sec % 10 == 0:
if "request failed" in p_console:
self.logger.debug(
- "It seems userdata is not supported in nova boot. " +
+ "It seems userdata is not supported in nova boot. "
"Waiting a bit...")
tries += 1
else:
self.logger.debug(
"Pinging %s. Waiting for response...",
- self.vm1.private_v4)
+ self.vm1.private_v4 or self.vm1.addresses[
+ self.network.name][0].addr)
sec += 1
return exit_code
@@ -103,12 +104,15 @@ class VPingUserdata(singlevm.VmReady2):
"""
Returns the post VM creation script to be added into the VM's userdata
:param test_ip: the IP value to substitute into the script
- :return: the bash script contents
+ :return: the shell script contents
"""
- if self.vm1.private_v4:
+ ip4 = self.vm1.private_v4 or self.vm1.addresses[
+ self.network.name][0].addr
+ if self.vm1.private_v4 or self.vm1.addresses[
+ self.network.name][0].addr:
return ("#!/bin/sh\n\n"
"while true; do\n"
- " ping -c 1 %s 2>&1 >/dev/null\n"
+ f" ping -c 1 {ip4} 2>&1 >/dev/null\n"
" RES=$?\n"
" if [ \"Z$RES\" = \"Z0\" ] ; then\n"
" echo 'vPing OK'\n"
@@ -117,7 +121,7 @@ class VPingUserdata(singlevm.VmReady2):
" echo 'vPing KO'\n"
" fi\n"
" sleep 1\n"
- "done\n" % str(self.vm1.private_v4))
+ "done\n")
return None
def clean(self):
@@ -130,4 +134,4 @@ class VPingUserdata(singlevm.VmReady2):
self.cloud.delete_server(
self.vm2, wait=True,
timeout=getattr(config.CONF, 'vping_vm_delete_timeout'))
- super(VPingUserdata, self).clean()
+ super().clean()
diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py
index 43476d8bf..72c38ce2c 100644
--- a/functest/opnfv_tests/sdn/odl/odl.py
+++ b/functest/opnfv_tests/sdn/odl/odl.py
@@ -49,7 +49,7 @@ class ODLTests(robotframework.RobotFramework):
__logger = logging.getLogger(__name__)
def __init__(self, **kwargs):
- super(ODLTests, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.res_dir = os.path.join(
getattr(config.CONF, 'dir_results'), 'odl')
self.xml_file = os.path.join(self.res_dir, 'output.xml')
@@ -66,10 +66,10 @@ class ODLTests(robotframework.RobotFramework):
try:
for line in fileinput.input(cls.odl_variables_file,
inplace=True):
- print(re.sub("@{AUTH}.*",
- "@{{AUTH}} {} {}".format(
- odlusername, odlpassword),
- line.rstrip()))
+ print(re.sub(
+ "@{AUTH}.*",
+ f"@{{AUTH}} {odlusername} {odlpassword}",
+ line.rstrip()))
return True
except Exception: # pylint: disable=broad-except
cls.__logger.exception("Cannot set ODL creds:")
@@ -111,9 +111,8 @@ class ODLTests(robotframework.RobotFramework):
odlusername = kwargs['odlusername']
odlpassword = kwargs['odlpassword']
osauthurl = kwargs['osauthurl']
- keystoneurl = "{}://{}".format(
- urllib.parse.urlparse(osauthurl).scheme,
- urllib.parse.urlparse(osauthurl).netloc)
+ keystoneurl = (f"{urllib.parse.urlparse(osauthurl).scheme}://"
+ f"{urllib.parse.urlparse(osauthurl).netloc}")
variable = ['KEYSTONEURL:' + keystoneurl,
'NEUTRONURL:' + kwargs['neutronurl'],
'OS_AUTH_URL:"' + osauthurl + '"',
@@ -135,7 +134,7 @@ class ODLTests(robotframework.RobotFramework):
else:
if not self.set_robotframework_vars(odlusername, odlpassword):
return self.EX_RUN_ERROR
- return super(ODLTests, self).run(variable=variable, suites=suites)
+ return super().run(variable=variable, suites=suites)
def run(self, **kwargs):
"""Run suites in OPNFV environment
@@ -169,7 +168,6 @@ class ODLTests(robotframework.RobotFramework):
kwargs['odlrestconfport'] = env.get('SDN_CONTROLLER_RESTCONFPORT')
kwargs['odlusername'] = env.get('SDN_CONTROLLER_USER')
kwargs['odlpassword'] = env.get('SDN_CONTROLLER_PASSWORD')
- installer_type = env.get('INSTALLER_TYPE')
kwargs['osusername'] = os.environ['OS_USERNAME']
kwargs['osuserdomainname'] = os.environ.get(
'OS_USER_DOMAIN_NAME', 'Default')
@@ -178,17 +176,6 @@ class ODLTests(robotframework.RobotFramework):
'OS_PROJECT_DOMAIN_NAME', 'Default')
kwargs['osauthurl'] = os.environ['OS_AUTH_URL']
kwargs['ospassword'] = os.environ['OS_PASSWORD']
- if installer_type == 'fuel':
- kwargs['odlwebport'] = '8282'
- kwargs['odlrestconfport'] = '8282'
- elif installer_type == 'apex' or installer_type == 'netvirt':
- kwargs['odlwebport'] = '8081'
- kwargs['odlrestconfport'] = '8081'
- elif installer_type == 'compass':
- kwargs['odlrestconfport'] = '8080'
- elif installer_type == 'daisy':
- kwargs['odlwebport'] = '8181'
- kwargs['odlrestconfport'] = '8087'
assert kwargs['odlip']
except KeyError as ex:
self.__logger.error(
@@ -201,7 +188,7 @@ class ODLTests(robotframework.RobotFramework):
return self.run_suites(suites, **kwargs)
-class ODLParser(object): # pylint: disable=too-few-public-methods
+class ODLParser(): # pylint: disable=too-few-public-methods
"""Parser to run ODL test suites."""
def __init__(self):
diff --git a/functest/opnfv_tests/vnf/epc/juju_epc.py b/functest/opnfv_tests/vnf/epc/juju_epc.py
index 3f2a9ff93..1cf240b80 100644
--- a/functest/opnfv_tests/vnf/epc/juju_epc.py
+++ b/functest/opnfv_tests/vnf/epc/juju_epc.py
@@ -14,35 +14,16 @@ import os
import time
import json
import re
-import subprocess
import sys
-import uuid
+
from copy import deepcopy
import pkg_resources
-import yaml
-
-import six
-from snaps.config.flavor import FlavorConfig
-from snaps.config.image import ImageConfig
-from snaps.config.network import NetworkConfig, SubnetConfig
-from snaps.config.router import RouterConfig
-from snaps.config.security_group import (
- Direction, Protocol, SecurityGroupConfig, SecurityGroupRuleConfig)
-from snaps.config.user import UserConfig
-from snaps.openstack.create_flavor import OpenStackFlavor
-from snaps.openstack.create_image import OpenStackImage
-from snaps.openstack.create_network import OpenStackNetwork
-from snaps.openstack.create_router import OpenStackRouter
-from snaps.openstack.create_security_group import OpenStackSecurityGroup
-from snaps.openstack.create_user import OpenStackUser
-from snaps.openstack.utils import keystone_utils
-from snaps.openstack.utils import nova_utils
-from snaps.openstack.utils import neutron_utils
-
-from functest.core import vnf
-from functest.opnfv_tests.openstack.snaps import snaps_utils
+import scp
+
+from functest.core import singlevm
from functest.utils import config
from functest.utils import env
+from functest.utils import functest_utils
__author__ = "Amarendra Meher <amarendra@rebaca.com>"
__author__ = "Soumaya K Nayek <soumaya.nayek@rebaca.com>"
@@ -61,188 +42,186 @@ CREDS_TEMPLATE2 = """credentials:
default-credential: abot-epc
abot-epc:
auth-type: userpass
- password: {pass}
+ password: '{pass}'
project-domain-name: {project_domain_n}
tenant-name: {tenant_n}"""
-CREDS_TEMPLATE3 = """credentials:
+CREDS_TEMPLATE = """credentials:
abot-epc:
default-credential: abot-epc
abot-epc:
auth-type: userpass
- password: {pass}
+ password: '{pass}'
project-domain-name: {project_domain_n}
tenant-name: {tenant_n}
user-domain-name: {user_domain_n}
username: {user_n}"""
-class JujuEpc(vnf.VnfOnBoarding):
+class JujuEpc(singlevm.SingleVm2):
# pylint:disable=too-many-instance-attributes
"""Abot EPC deployed with JUJU Orchestrator Case"""
__logger = logging.getLogger(__name__)
- juju_timeout = '3600'
+ cidr = '192.168.120.0/24'
+
+ filename = ('/home/opnfv/functest/images/'
+ 'ubuntu-16.04-server-cloudimg-amd64-disk1.img')
+ filename_alt = ('/home/opnfv/functest/images/'
+ 'ubuntu-14.04-server-cloudimg-amd64-disk1.img')
+
+ flavor_ram = 2048
+ flavor_vcpus = 1
+ flavor_disk = 10
+ flavor_alt_ram = 4096
+ flavor_alt_vcpus = 1
+ flavor_alt_disk = 10
+ username = 'ubuntu'
+ juju_timeout = '4800'
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = "juju_epc"
- super(JujuEpc, self).__init__(**kwargs)
+ super().__init__(**kwargs)
# Retrieve the configuration
self.case_dir = pkg_resources.resource_filename(
'functest', 'opnfv_tests/vnf/epc')
try:
self.config = getattr(
- config.CONF, 'vnf_{}_config'.format(self.case_name))
- except Exception:
- raise Exception("VNF config file not found")
+ config.CONF, f'vnf_{self.case_name}_config')
+ except Exception as exc:
+ raise Exception("VNF config file not found") from exc
self.config_file = os.path.join(self.case_dir, self.config)
- self.orchestrator = dict(requirements=get_config(
- "orchestrator.requirements", self.config_file))
+ self.orchestrator = dict(
+ requirements=functest_utils.get_parameter_from_yaml(
+ "orchestrator.requirements", self.config_file))
self.created_object = []
self.details['orchestrator'] = dict(
- name=get_config("orchestrator.name", self.config_file),
- version=get_config("orchestrator.version", self.config_file),
+ name=functest_utils.get_parameter_from_yaml(
+ "orchestrator.name", self.config_file),
+ version=functest_utils.get_parameter_from_yaml(
+ "orchestrator.version", self.config_file),
status='ERROR',
result=''
)
self.vnf = dict(
- descriptor=get_config("vnf.descriptor", self.config_file),
- requirements=get_config("vnf.requirements", self.config_file)
+ descriptor=functest_utils.get_parameter_from_yaml(
+ "vnf.descriptor", self.config_file),
+ requirements=functest_utils.get_parameter_from_yaml(
+ "vnf.requirements", self.config_file)
)
self.details['vnf'] = dict(
descriptor_version=self.vnf['descriptor']['version'],
- name=get_config("vnf.name", self.config_file),
- version=get_config("vnf.version", self.config_file),
+ name=functest_utils.get_parameter_from_yaml(
+ "vnf.name", self.config_file),
+ version=functest_utils.get_parameter_from_yaml(
+ "vnf.version", self.config_file),
)
self.__logger.debug("VNF configuration: %s", self.vnf)
self.details['test_vnf'] = dict(
- name=get_config("vnf_test_suite.name", self.config_file),
- version=get_config("vnf_test_suite.version", self.config_file),
- tag_name=get_config("vnf_test_suite.tag_name", self.config_file)
+ name=functest_utils.get_parameter_from_yaml(
+ "vnf_test_suite.name", self.config_file),
+ version=functest_utils.get_parameter_from_yaml(
+ "vnf_test_suite.version", self.config_file),
+ tag_name=functest_utils.get_parameter_from_yaml(
+ "vnf_test_suite.tag_name", self.config_file)
)
- self.public_auth_url = None
self.res_dir = os.path.join(
getattr(config.CONF, 'dir_results'), self.case_name)
- def _bypass_juju_netdiscovery_bug(self, name):
- user_creator = OpenStackUser(
- self.snaps_creds,
- UserConfig(
- name=name,
- password=str(uuid.uuid4()),
- project_name=self.tenant_name,
- domain_name=self.snaps_creds.user_domain_name,
- roles={'_member_': self.tenant_name}))
- user_creator.create()
- self.created_object.append(user_creator)
- return user_creator
+ try:
+ self.public_auth_url = self.get_public_auth_url(self.orig_cloud)
+ if not self.public_auth_url.endswith(('v3', 'v3/')):
+ self.public_auth_url = f"{self.public_auth_url}/v3"
+ except Exception: # pylint: disable=broad-except
+ self.public_auth_url = None
+ self.sec = None
+ self.image_alt = None
+ self.flavor_alt = None
+
+ def _install_juju(self):
+ (_, stdout, stderr) = self.ssh.exec_command(
+ 'sudo snap install juju --channel=2.3/stable --classic')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ return not stdout.channel.recv_exit_status()
+
+ def _install_juju_wait(self):
+ (_, stdout, stderr) = self.ssh.exec_command(
+ 'sudo apt-get update && sudo apt-get install python3-pip -y && '
+ 'sudo pip3 install juju_wait===2.6.4')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ return not stdout.channel.recv_exit_status()
def _register_cloud(self):
+ assert self.public_auth_url
self.__logger.info("Creating Cloud for Abot-epc .....")
clouds_yaml = os.path.join(self.res_dir, "clouds.yaml")
cloud_data = {
'url': self.public_auth_url,
- 'region': self.snaps_creds.region_name if (
- self.snaps_creds.region_name) else 'RegionOne'}
- with open(clouds_yaml, 'w') as yfile:
+ 'region': self.cloud.region_name if self.cloud.region_name else (
+ 'RegionOne')}
+ with open(clouds_yaml, 'w', encoding='utf-8') as yfile:
yfile.write(CLOUD_TEMPLATE.format(**cloud_data))
- cmd = ['juju', 'add-cloud', 'abot-epc', '-f', clouds_yaml, '--replace']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
-
- def _register_credentials_v2(self):
+ scpc = scp.SCPClient(self.ssh.get_transport())
+ scpc.put(clouds_yaml, remote_path='~/')
+ (_, stdout, stderr) = self.ssh.exec_command(
+ '/snap/bin/juju add-cloud abot-epc -f clouds.yaml --replace')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ return not stdout.channel.recv_exit_status()
+
+ def _register_credentials(self):
self.__logger.info("Creating Credentials for Abot-epc .....")
- user_creator = self._bypass_juju_netdiscovery_bug(
- 'juju_network_discovery_bug')
- snaps_creds = user_creator.get_os_creds(self.snaps_creds.project_name)
- self.__logger.debug("snaps creds: %s", snaps_creds)
credentials_yaml = os.path.join(self.res_dir, "credentials.yaml")
creds_data = {
- 'pass': snaps_creds.password,
- 'tenant_n': snaps_creds.project_name,
- 'user_n': snaps_creds.username}
- with open(credentials_yaml, 'w') as yfile:
- yfile.write(CREDS_TEMPLATE2.format(**creds_data))
- cmd = ['juju', 'add-credential', 'abot-epc', '-f', credentials_yaml,
- '--replace']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
-
- def _register_credentials_v3(self):
- self.__logger.info("Creating Credentials for Abot-epc .....")
- user_creator = self._bypass_juju_netdiscovery_bug(
- 'juju_network_discovery_bug')
- snaps_creds = user_creator.get_os_creds(self.snaps_creds.project_name)
- self.__logger.debug("snaps creds: %s", snaps_creds)
- credentials_yaml = os.path.join(self.res_dir, "credentials.yaml")
- creds_data = {
- 'pass': snaps_creds.password,
- 'tenant_n': snaps_creds.project_name,
- 'user_n': snaps_creds.username,
- 'project_domain_n': snaps_creds.project_domain_name,
- 'user_domain_n': snaps_creds.user_domain_name}
- with open(credentials_yaml, 'w') as yfile:
- yfile.write(CREDS_TEMPLATE3.format(**creds_data))
- cmd = ['juju', 'add-credential', 'abot-epc', '-f', credentials_yaml,
- '--replace']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
-
- def _add_custom_rule(self, sec_grp_name):
- """ To add custom rule for SCTP Traffic """
-
- security_group = OpenStackSecurityGroup(
- self.snaps_creds,
- SecurityGroupConfig(
- name=sec_grp_name))
-
- security_group.create()
-
- # Add custom security rule to the obtained Security Group
- self.__logger.info("Adding SCTP ingress rule to SG:%s",
- security_group.sec_grp_settings.name)
-
- try:
- security_group.add_rule(SecurityGroupRuleConfig(
- sec_grp_name=sec_grp_name, direction=Direction.ingress,
- protocol=Protocol.sctp))
- except Exception: # pylint: disable=broad-except
- self.__logger.exception(
- "Some issue encountered with adding SCTP security rule ...")
-
- def prepare(self):
- """Prepare testcase (Additional pre-configuration steps)."""
- self.__logger.info("Additional pre-configuration steps")
- super(JujuEpc, self).prepare()
- try:
- os.makedirs(self.res_dir)
- except OSError as ex:
- if ex.errno != errno.EEXIST:
- self.__logger.exception("Cannot create %s", self.res_dir)
- raise vnf.VnfPreparationException
-
- self.__logger.info("ENV:\n%s", env.string())
-
- self.public_auth_url = keystone_utils.get_endpoint(
- self.snaps_creds, 'identity')
-
- # it enforces a versioned public identity endpoint as juju simply
- # adds /auth/tokens wich fails vs an unversioned endpoint.
- if not self.public_auth_url.endswith(('v3', 'v3/', 'v2.0', 'v2.0/')):
- self.public_auth_url = six.moves.urllib.parse.urljoin(
- self.public_auth_url, 'v3')
- self._register_cloud()
- if self.snaps_creds.identity_api_version == 3:
- self._register_credentials_v3()
- else:
- self._register_credentials_v2()
+ 'pass': self.project.password,
+ 'tenant_n': self.project.project.name,
+ 'user_n': self.project.user.name,
+ 'project_domain_n': self.cloud.auth.get(
+ "project_domain_name", "Default"),
+ 'user_domain_n': self.cloud.auth.get(
+ "user_domain_name", "Default")}
+ with open(credentials_yaml, 'w', encoding='utf-8') as yfile:
+ yfile.write(CREDS_TEMPLATE.format(**creds_data))
+ scpc = scp.SCPClient(self.ssh.get_transport())
+ scpc.put(credentials_yaml, remote_path='~/')
+ (_, stdout, stderr) = self.ssh.exec_command(
+ '/snap/bin/juju add-credential abot-epc -f credentials.yaml '
+ ' --replace --debug')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ return not stdout.channel.recv_exit_status()
+
+ def _publish_image(self):
+ region_name = self.cloud.region_name if self.cloud.region_name else (
+ 'RegionOne')
+ (_, stdout, stderr) = self.ssh.exec_command(
+ '/snap/bin/juju metadata generate-image -d /home/ubuntu '
+ f'-i {self.image.id} -s xenial -r {region_name} '
+ f'-u {self.public_auth_url}')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ return not stdout.channel.recv_exit_status()
+
+ def publish_image_alt(self, name=None):
+ image_alt = super().publish_image_alt(name)
+ region_name = self.cloud.region_name if self.cloud.region_name else (
+ 'RegionOne')
+ (_, stdout, stderr) = self.ssh.exec_command(
+ '/snap/bin/juju metadata generate-image -d /home/ubuntu '
+ f'-i {image_alt.id} -s trusty -r {region_name} '
+ f'-u {self.public_auth_url}')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ return image_alt
def deploy_orchestrator(self): # pylint: disable=too-many-locals
"""
@@ -250,204 +229,128 @@ class JujuEpc(vnf.VnfOnBoarding):
Bootstrap juju
"""
- self.__logger.info("Deploying Juju Orchestrator")
- private_net_name = getattr(
- config.CONF, 'vnf_{}_private_net_name'.format(self.case_name))
- private_subnet_name = '{}-{}'.format(
- getattr(config.CONF,
- 'vnf_{}_private_subnet_name'.format(self.case_name)),
- self.uuid)
- private_subnet_cidr = getattr(
- config.CONF, 'vnf_{}_private_subnet_cidr'.format(self.case_name))
- abot_router = '{}-{}'.format(
- getattr(config.CONF,
- 'vnf_{}_external_router'.format(self.case_name)),
- self.uuid)
- self.__logger.info("Creating full network with nameserver: %s",
- env.get('NAMESERVER'))
- subnet_settings = SubnetConfig(
- name=private_subnet_name,
- cidr=private_subnet_cidr,
- dns_nameservers=[env.get('NAMESERVER')])
- network_settings = NetworkConfig(
- name=private_net_name, subnet_settings=[subnet_settings])
- network_creator = OpenStackNetwork(self.snaps_creds, network_settings)
- net_id = network_creator.create().id
- self.created_object.append(network_creator)
-
- ext_net_name = snaps_utils.get_ext_net_name(self.snaps_creds)
- self.__logger.info("Creating network Router ....")
- router_creator = OpenStackRouter(
- self.snaps_creds, RouterConfig(
- name=abot_router,
- external_gateway=ext_net_name,
- internal_subnets=[subnet_settings.name]))
- router_creator.create()
- self.created_object.append(router_creator)
- self.__logger.info("Creating Flavor ....")
- flavor_settings = FlavorConfig(
- name=self.orchestrator['requirements']['flavor']['name'],
- ram=self.orchestrator['requirements']['flavor']['ram_min'],
- disk=10, vcpus=1)
- flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
- flavor_creator.create()
- self.created_object.append(flavor_creator)
-
- self.__logger.info("Upload some OS images if it doesn't exist")
- images = get_config("tenant_images", self.config_file)
- self.__logger.info("Images needed for vEPC: %s", images)
- for image_name, image_file in six.iteritems(images):
- self.__logger.info("image: %s, file: %s", image_name, image_file)
- if image_file and image_name:
- image_creator = OpenStackImage(self.snaps_creds, ImageConfig(
- name=image_name, image_user='cloud', img_format='qcow2',
- image_file=image_file))
- image_id = image_creator.create().id
- cmd = ['juju', 'metadata', 'generate-image', '-d', '/root',
- '-i', image_id, '-s', image_name, '-r',
- self.snaps_creds.region_name if (
- self.snaps_creds.region_name) else 'RegionOne',
- '-u', self.public_auth_url]
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
- self.created_object.append(image_creator)
- self.__logger.info("Network ID : %s", net_id)
-
+ self._publish_image()
+ self.image_alt = self.publish_image_alt()
+ self.flavor_alt = self.create_flavor_alt()
self.__logger.info("Starting Juju Bootstrap process...")
- try:
- cmd = ['timeout', '-t', JujuEpc.juju_timeout,
- 'juju', 'bootstrap', 'abot-epc', 'abot-controller',
- '--metadata-source', '/root',
- '--constraints', 'mem=2G',
- '--bootstrap-series', 'xenial',
- '--config', 'network={}'.format(net_id),
- '--config', 'ssl-hostname-verification=false',
- '--config', 'use-floating-ip=true',
- '--config', 'use-default-secgroup=true',
- '--debug']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
- except subprocess.CalledProcessError as cpe:
- self.__logger.error(
- "Exception with Juju Bootstrap: %s\n%s",
- cpe.cmd, cpe.output)
- return False
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Some issue with Juju Bootstrap ...")
- return False
-
- return True
+ region_name = self.cloud.region_name if self.cloud.region_name else (
+ 'RegionOne')
+ (_, stdout, stderr) = self.ssh.exec_command(
+ f'timeout {JujuEpc.juju_timeout} '
+ f'/snap/bin/juju bootstrap abot-epc/{region_name} abot-controller '
+ '--agent-version 2.3.9 --metadata-source /home/ubuntu '
+ '--constraints mem=2G --bootstrap-series xenial '
+ f'--config network={self.network.id} '
+ '--config ssl-hostname-verification=false '
+ f'--config external-network={self.ext_net.id} '
+ '--config use-floating-ip=true '
+ '--config use-default-secgroup=true '
+ '--debug')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ return not stdout.channel.recv_exit_status()
def check_app(self, name='abot-epc-basic', status='active'):
"""Check application status."""
- cmd = ['juju', 'status', '--format', 'short', name]
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
- ret = re.search(r'(?=workload:({})\))'.format(status), output)
- if ret:
- self.__logger.info("%s workload is %s", name, status)
- return True
- self.__logger.error("%s workload differs from %s", name, status)
- return False
+ for i in range(10):
+ (_, stdout, stderr) = self.ssh.exec_command(
+ f'/snap/bin/juju status --format short {name}')
+ output = stdout.read().decode("utf-8")
+ self.__logger.debug("stdout:\n%s", output)
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ if stdout.channel.recv_exit_status():
+ continue
+ ret = re.search(
+ rf'(?=workload:({status})\))', output)
+ if ret:
+ self.__logger.info("%s workload is %s", name, status)
+ break
+ self.__logger.info(
+ "loop %d: %s workload differs from %s", i + 1, name, status)
+ time.sleep(60)
+ else:
+ self.__logger.error("%s workload differs from %s", name, status)
+ return False
+ return True
def deploy_vnf(self):
"""Deploy ABOT-OAI-EPC."""
self.__logger.info("Upload VNFD")
- descriptor = self.vnf['descriptor']
- self.__logger.info("Get or create flavor for all Abot-EPC")
- flavor_settings = FlavorConfig(
- name=self.vnf['requirements']['flavor']['name'],
- ram=self.vnf['requirements']['flavor']['ram_min'],
- disk=10,
- vcpus=1)
- flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
- flavor_creator.create()
- self.created_object.append(flavor_creator)
-
+ scpc = scp.SCPClient(self.ssh.get_transport())
+ scpc.put(
+ '/src/epc-requirements/abot_charm', remote_path='~/',
+ recursive=True)
self.__logger.info("Deploying Abot-epc bundle file ...")
- cmd = ['juju', 'deploy', '{}'.format(descriptor.get('file_name'))]
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
- self.__logger.info("Waiting for instances .....")
- try:
- cmd = ['timeout', '-t', JujuEpc.juju_timeout, 'juju-wait']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
- self.__logger.info("Deployed Abot-epc on Openstack")
- except subprocess.CalledProcessError as cpe:
- self.__logger.error(
- "Exception with Juju VNF Deployment: %s\n%s",
- cpe.cmd, cpe.output)
- return False
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Some issue with the VNF Deployment ..")
- return False
-
+ (_, stdout, stderr) = self.ssh.exec_command(
+ 'sudo mkdir -p /src/epc-requirements && '
+ 'sudo mv abot_charm /src/epc-requirements/abot_charm && '
+ '/snap/bin/juju deploy '
+ '/src/epc-requirements/abot_charm/functest-abot-epc-bundle/'
+ 'bundle.yaml')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ if stdout.channel.recv_exit_status():
+ return not stdout.channel.recv_exit_status()
+ (_, stdout, stderr) = self.ssh.exec_command(
+ 'PATH=/snap/bin/:$PATH '
+ f'timeout {JujuEpc.juju_timeout} juju-wait')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ if stdout.channel.recv_exit_status():
+ return not stdout.channel.recv_exit_status()
self.__logger.info("Checking status of ABot and EPC units ...")
- cmd = ['juju', 'status']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.debug("%s\n%s", " ".join(cmd), output)
+ (_, stdout, stderr) = self.ssh.exec_command('/snap/bin/juju status')
+ output = stdout.read().decode("utf-8")
+ self.__logger.debug("stdout:\n%s", output)
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ if stdout.channel.recv_exit_status():
+ return not stdout.channel.recv_exit_status()
for app in ['abot-epc-basic', 'oai-epc', 'oai-hss']:
if not self.check_app(app):
return False
-
- nova_client = nova_utils.nova_client(self.snaps_creds)
- instances = get_instances(nova_client)
- self.__logger.info("List of Instance: %s", instances)
- for items in instances:
- metadata = get_instance_metadata(nova_client, items)
- if 'juju-units-deployed' in metadata:
- sec_group = 'juju-{}-{}'.format(
- metadata['juju-controller-uuid'],
- metadata['juju-model-uuid'])
- self.__logger.info("Instance: %s", sec_group)
- break
- self.__logger.info("Adding Security group rule....")
- # This will add sctp rule to a common Security Group Created
- # by juju and shared to all deployed units.
- self._add_custom_rule(sec_group)
-
- self.__logger.info("Transferring the feature files to Abot_node ...")
- cmd = ['timeout', '-t', JujuEpc.juju_timeout,
- 'juju', 'scp', '--', '-r', '-v',
- '{}/featureFiles'.format(self.case_dir), 'abot-epc-basic/0:~/']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
-
- self.__logger.info("Copying the feature files within Abot_node ")
- cmd = ['timeout', '-t', JujuEpc.juju_timeout,
- 'juju', 'ssh', 'abot-epc-basic/0',
- 'sudo', 'cp', '-vfR', '~/featureFiles/*',
- '/etc/rebaca-test-suite/featureFiles']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
- return True
+ scpc = scp.SCPClient(self.ssh.get_transport())
+ scpc.put(
+ f'{self.case_dir}/featureFiles', remote_path='~/',
+ recursive=True)
+ (_, stdout, stderr) = self.ssh.exec_command(
+ f'timeout {JujuEpc.juju_timeout} /snap/bin/juju scp -- -r -v '
+ '~/featureFiles abot-epc-basic/0:/etc/rebaca-test-suite/')
+ output = stdout.read().decode("utf-8")
+ self.__logger.debug("stdout:\n%s", output)
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ return not stdout.channel.recv_exit_status()
def test_vnf(self):
"""Run test on ABoT."""
start_time = time.time()
- self.__logger.info("Running VNF Test cases....")
- cmd = ['juju', 'run-action', 'abot-epc-basic/0', 'run',
- 'tagnames={}'.format(self.details['test_vnf']['tag_name'])]
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
-
- cmd = ['timeout', '-t', JujuEpc.juju_timeout, 'juju-wait']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
-
+ (_, stdout, stderr) = self.ssh.exec_command(
+ "/snap/bin/juju run-action abot-epc-basic/0 "
+ f"run tagnames={self.details['test_vnf']['tag_name']}")
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ if stdout.channel.recv_exit_status():
+ return not stdout.channel.recv_exit_status()
+ (_, stdout, stderr) = self.ssh.exec_command(
+ 'PATH=/snap/bin/:$PATH '
+ f'timeout {JujuEpc.juju_timeout} juju-wait')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ if stdout.channel.recv_exit_status():
+ return not stdout.channel.recv_exit_status()
duration = time.time() - start_time
self.__logger.info("Getting results from Abot node....")
- cmd = ['timeout', '-t', JujuEpc.juju_timeout,
- 'juju', 'scp', '--', '-v',
- 'abot-epc-basic/0:'
- '/var/lib/abot-epc-basic/artifacts/TestResults.json',
- '{}/.'.format(self.res_dir)]
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
+ (_, stdout, stderr) = self.ssh.exec_command(
+ f'timeout {JujuEpc.juju_timeout} /snap/bin/juju scp '
+ '-- -v abot-epc-basic/0:'
+ '/var/lib/abot-epc-basic/artifacts/TestResults.json .')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ if stdout.channel.recv_exit_status():
+ return not stdout.channel.recv_exit_status()
+ scpc = scp.SCPClient(self.ssh.get_transport())
+ scpc.get('TestResults.json', self.res_dir)
self.__logger.info("Parsing the Test results...")
- res = (process_abot_test_result('{}/TestResults.json'.format(
- self.res_dir)))
+ res = process_abot_test_result(f'{self.res_dir}/TestResults.json')
short_result = sig_test_format(res)
self.__logger.info(short_result)
self.details['test_vnf'].update(
@@ -459,99 +362,48 @@ class JujuEpc(vnf.VnfOnBoarding):
short_result['failures'], short_result['skipped'])
return True
- def _get_floating_ips(self):
- """Get the list of floating IPs associated with the current project"""
-
- project_id = self.os_project.get_project().id
-
- neutron_client = neutron_utils.neutron_client(self.snaps_creds)
- floating_ips = neutron_utils.get_floating_ips(neutron_client)
-
- project_floating_ip_list = list()
- for floating_ip in floating_ips:
- if project_id and project_id == floating_ip.project_id:
- project_floating_ip_list.append(floating_ip)
-
- return project_floating_ip_list
-
- def _release_floating_ips(self, fip_list):
- """
- Responsible for deleting a list of floating IPs
- :param fip_list: A list of SNAPS FloatingIp objects
- :return:
- """
- if not fip_list:
- return
-
- neutron_client = neutron_utils.neutron_client(self.snaps_creds)
-
- for floating_ip in fip_list:
- neutron_utils.delete_floating_ip(neutron_client, floating_ip)
-
- def clean(self):
- """Clean created objects/functions."""
-
- # Store Floating IPs of instances created by Juju
- fip_list = self._get_floating_ips()
- self.__logger.info("Floating IPs assigned to project:%s",
- self.os_project.get_project().name)
- for floating_ip in fip_list:
- self.__logger.debug("%s:%s", floating_ip.ip,
- floating_ip.description)
-
+ def execute(self):
+ """Prepare testcase (Additional pre-configuration steps)."""
+ assert self.public_auth_url
+ self.__logger.info("Additional pre-configuration steps")
+ try:
+ os.makedirs(self.res_dir)
+ except OSError as ex:
+ if ex.errno != errno.EEXIST:
+ self.__logger.exception("Cannot create %s", self.res_dir)
+ raise Exception from ex
+ self.__logger.info("ENV:\n%s", env.string())
try:
- cmd = ['juju', 'debug-log', '--replay', '--no-tail']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.debug("%s\n%s", " ".join(cmd), output)
- if not self.orchestrator['requirements']['preserve_setup']:
- self.__logger.info("Destroying Orchestrator...")
- cmd = ['timeout', '-t', JujuEpc.juju_timeout,
- 'juju', 'destroy-controller', '-y', 'abot-controller',
- '--destroy-all-models']
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- self.__logger.info("%s\n%s", " ".join(cmd), output)
- except subprocess.CalledProcessError as cpe:
- self.__logger.error(
- "Exception with Juju Cleanup: %s\n%s",
- cpe.cmd, cpe.output)
+ assert self._install_juju()
+ assert self._install_juju_wait()
+ assert self._register_cloud()
+ assert self._register_credentials()
+ assert self.deploy_orchestrator()
+ assert self.deploy_vnf()
+ assert self.test_vnf()
except Exception: # pylint: disable=broad-except
- self.__logger.exception("General issue during the undeployment ..")
-
- if not self.orchestrator['requirements']['preserve_setup']:
- try:
- self.__logger.info('Release floating IPs assigned by Juju...')
- self._release_floating_ips(fip_list)
- except Exception: # pylint: disable=broad-except
- self.__logger.exception(
- "Exception while releasing floating IPs ...")
+ self.__logger.exception("juju_epc failed")
+ return 1
+ return 0
- self.__logger.info('Remove the Abot_epc OS objects ..')
- super(JujuEpc, self).clean()
-
- return True
-
-
-# ----------------------------------------------------------
-#
-# YAML UTILS
-#
-# -----------------------------------------------------------
-def get_config(parameter, file_path):
- """
- Returns the value of a given parameter in file.yaml
- parameter must be given in string format with dots
- Example: general.openstack.image_name
- """
- with open(file_path) as config_file:
- file_yaml = yaml.safe_load(config_file)
- config_file.close()
- value = file_yaml
- for element in parameter.split("."):
- value = value.get(element)
- if value is None:
- raise ValueError("The parameter %s is not defined in"
- " reporting.yaml" % parameter)
- return value
+ def clean(self):
+ """Clean created objects/functions."""
+ (_, stdout, stderr) = self.ssh.exec_command(
+ '/snap/bin/juju debug-log --replay --no-tail')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ (_, stdout, stderr) = self.ssh.exec_command(
+ '/snap/bin/juju destroy-controller -y abot-controller '
+ '--destroy-all-models')
+ self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8"))
+ self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8"))
+ for fip in self.cloud.list_floating_ips():
+ self.cloud.delete_floating_ip(fip.id)
+ if self.image_alt:
+ self.cloud.delete_image(self.image_alt)
+ if self.flavor_alt:
+ self.orig_cloud.delete_flavor(self.flavor_alt.id)
+ super().clean()
def sig_test_format(sig_test):
@@ -577,7 +429,7 @@ def sig_test_format(sig_test):
def process_abot_test_result(file_path):
""" Process ABoT Result """
- with open(file_path) as test_result:
+ with open(file_path, encoding='utf-8') as test_result:
data = json.load(test_result)
res = []
for tests in data:
@@ -629,23 +481,3 @@ def update_data(obj):
raise
return obj
-
-
-def get_instances(nova_client):
- """ To get all vm info of a project """
- try:
- instances = nova_client.servers.list()
- return instances
- except Exception as exc: # pylint: disable=broad-except
- logging.error("Error [get_instances(nova_client)]: %s", exc)
- return None
-
-
-def get_instance_metadata(nova_client, instance):
- """ Get instance Metadata - Instance ID """
- try:
- instance = nova_client.servers.get(instance.id)
- return instance.metadata
- except Exception as exc: # pylint: disable=broad-except
- logging.error("Error [get_instance_status(nova_client)]: %s", exc)
- return None
diff --git a/functest/opnfv_tests/vnf/ims/clearwater.py b/functest/opnfv_tests/vnf/ims/clearwater.py
new file mode 100644
index 000000000..4c143fd70
--- /dev/null
+++ b/functest/opnfv_tests/vnf/ims/clearwater.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2017 All rights reserved
+# This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Ease testing any Clearwater deployment"""
+
+import logging
+import os
+import re
+import time
+
+import pkg_resources
+import requests
+
+from functest.utils import config
+import functest.utils.functest_utils as ft_utils
+
+__author__ = ("Valentin Boucher <valentin.boucher@orange.com>, "
+ "Helen Yao <helanyao@gmail.com>")
+
+
+class ClearwaterTesting():
+ """vIMS clearwater base usable by several orchestrators"""
+
+ def __init__(self, case_name, bono_ip, ellis_ip):
+ self.logger = logging.getLogger(__name__)
+ self.case_dir = pkg_resources.resource_filename(
+ 'functest', 'opnfv_tests/vnf/ims')
+ self.data_dir = getattr(config.CONF, 'dir_ims_data')
+ self.result_dir = os.path.join(
+ getattr(config.CONF, 'dir_results'), case_name)
+ self.test_dir = getattr(config.CONF, 'dir_repo_vims_test')
+
+ if not os.path.exists(self.data_dir):
+ os.makedirs(self.data_dir)
+ if not os.path.exists(self.result_dir):
+ os.makedirs(self.result_dir)
+
+ self.ellis_ip = ellis_ip
+ self.bono_ip = bono_ip
+
+ def availability_check(self, signup_code='secret', two_numbers=False):
+ """Create one or two numbers"""
+ assert self.ellis_ip
+ output_dict = {}
+ self.logger.debug('Ellis IP: %s', self.ellis_ip)
+ output_dict['ellis_ip'] = self.ellis_ip
+ account_url = f'http://{self.ellis_ip}/accounts'
+ params = {"password": "functest",
+ "full_name": "opnfv functest user",
+ "email": "functest@opnfv.org",
+ "signup_code": signup_code}
+ output_dict['login'] = params
+
+ number_res = self._create_ellis_account(account_url, params)
+ output_dict['number'] = number_res
+
+ session_url = f'http://{self.ellis_ip}/session'
+ session_data = {
+ 'username': params['email'],
+ 'password': params['password'],
+ 'email': params['email']
+ }
+ cookies = self._get_ellis_session_cookies(session_url, session_data)
+
+ number_url = (
+ f"http://{self.ellis_ip}/accounts/{params['email']}/numbers")
+ self.logger.debug('Create 1st calling number on Ellis')
+ number_res = self._create_ellis_number(number_url, cookies)
+
+ if two_numbers:
+ self.logger.debug('Create 2nd calling number on Ellis')
+ number_res = self._create_ellis_number(number_url, cookies)
+ output_dict['number2'] = number_res
+
+ return output_dict
+
+ def _create_ellis_account(self, account_url, params):
+ i = 80
+ for iloop in range(i):
+ try:
+ req = requests.post(account_url, data=params)
+ if req.status_code == 201:
+ account_res = req.json()
+ self.logger.info(
+ 'Account %s is created on Ellis\n%s',
+ params.get('full_name'), account_res)
+ return account_res
+ raise Exception("Cannot create ellis account")
+ except Exception: # pylint: disable=broad-except
+ self.logger.info(
+ "try %s: cannot create ellis account", iloop + 1)
+ time.sleep(30)
+ raise Exception(
+ f"Unable to create an account {params.get('full_name')}")
+
+ def _get_ellis_session_cookies(self, session_url, params):
+ i = 15
+ for iloop in range(i):
+ try:
+ req = requests.post(session_url, data=params)
+ if req.status_code == 201:
+ cookies = req.cookies
+ self.logger.debug('cookies: %s', cookies)
+ return cookies
+ raise Exception('Failed to get cookies for Ellis')
+ except Exception: # pylint: disable=broad-except
+ self.logger.info(
+ "try %s: cannot get cookies for Ellis", iloop + 1)
+ time.sleep(10)
+ raise Exception('Failed to get cookies for Ellis')
+
+ def _create_ellis_number(self, number_url, cookies):
+ i = 30
+ for iloop in range(i):
+ try:
+ req = requests.post(number_url, cookies=cookies)
+ if req.status_code == 200:
+ number_res = req.json()
+ self.logger.info(
+ 'Calling number is created: %s', number_res)
+ return number_res
+ if req and req.json():
+ reason = req.json()['reason']
+ else:
+ reason = req
+ self.logger.info("cannot create a number: %s", reason)
+ raise Exception('Failed to create a number')
+ except Exception: # pylint: disable=broad-except
+ self.logger.info(
+ "try %s: cannot create a number", iloop + 1)
+ time.sleep(25)
+ raise Exception('Failed to create a number')
+
+ def run_clearwater_live_test(self, public_domain, signup_code='secret'):
+ """Run the Clearwater live tests
+
+ It first runs dnsmasq to reach clearwater services by FQDN and then the
+ Clearwater live tests. All results are saved in ims_test_output.txt.
+
+ Returns:
+ - a dict containing the overall results
+ - None on error
+ """
+ # pylint: disable=too-many-locals,too-many-arguments
+ self.logger.info('Run Clearwater live test')
+ script = (f'cd {self.test_dir};'
+ f'rake test[{public_domain}] SIGNUP_CODE={signup_code}')
+ if self.bono_ip and self.ellis_ip:
+ subscript = f' PROXY={self.bono_ip} ELLIS={self.ellis_ip}'
+ script = f'{script}{subscript}'
+ script = f'{script} --trace'
+ cmd = f"/bin/sh -c '{script}'"
+ self.logger.debug('Live test cmd: %s', cmd)
+ output_file = os.path.join(self.result_dir, "ims_test_output.txt")
+ ft_utils.execute_command(cmd,
+ error_msg='Clearwater live test failed',
+ output_file=output_file)
+
+ with open(output_file, 'r', encoding='utf-8') as ofile:
+ result = ofile.read()
+
+ if result != "":
+ self.logger.debug(result)
+
+ vims_test_result = {}
+ try:
+ grp = re.search(
+ r'^(\d+) failures out of (\d+) tests run.*\n'
+ r'(\d+) tests skipped$', result, re.MULTILINE | re.DOTALL)
+ assert grp
+ vims_test_result["failures"] = int(grp.group(1))
+ vims_test_result["total"] = int(grp.group(2))
+ vims_test_result["skipped"] = int(grp.group(3))
+ vims_test_result['passed'] = (
+ int(grp.group(2)) - int(grp.group(3)) - int(grp.group(1)))
+ if vims_test_result['total'] - vims_test_result['skipped'] > 0:
+ vnf_test_rate = vims_test_result['passed'] / (
+ vims_test_result['total'] - vims_test_result['skipped'])
+ else:
+ vnf_test_rate = 0
+ except Exception: # pylint: disable=broad-except
+ self.logger.exception("Cannot parse live tests results")
+ return None, 0
+ return vims_test_result, vnf_test_rate
diff --git a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
deleted file mode 100644
index add99468b..000000000
--- a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2017 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-
-"""Ease testing any Clearwater deployment"""
-
-import logging
-import os
-import re
-import shlex
-import shutil
-import subprocess
-import time
-
-import pkg_resources
-import requests
-
-import functest.core.vnf as vnf
-from functest.utils import config
-import functest.utils.functest_utils as ft_utils
-
-__author__ = ("Valentin Boucher <valentin.boucher@orange.com>, "
- "Helen Yao <helanyao@gmail.com>")
-
-
-class ClearwaterOnBoardingBase(vnf.VnfOnBoarding):
- """vIMS clearwater base usable by several orchestrators"""
-
- def __init__(self, **kwargs):
- self.logger = logging.getLogger(__name__)
- super(ClearwaterOnBoardingBase, self).__init__(**kwargs)
- self.case_dir = pkg_resources.resource_filename(
- 'functest', 'opnfv_tests/vnf/ims')
- self.data_dir = getattr(config.CONF, 'dir_ims_data')
- self.result_dir = os.path.join(getattr(config.CONF, 'dir_results'),
- self.case_name)
- self.test_dir = getattr(config.CONF, 'dir_repo_vims_test')
-
- if not os.path.exists(self.data_dir):
- os.makedirs(self.data_dir)
- if not os.path.exists(self.result_dir):
- os.makedirs(self.result_dir)
-
- def config_ellis(self, ellis_ip, signup_code='secret', two_numbers=False):
- """Create one or two numbers"""
- output_dict = {}
- self.logger.debug('Configure Ellis: %s', ellis_ip)
- output_dict['ellis_ip'] = ellis_ip
- account_url = 'http://{0}/accounts'.format(ellis_ip)
- params = {"password": "functest",
- "full_name": "opnfv functest user",
- "email": "functest@opnfv.org",
- "signup_code": signup_code}
- req = requests.post(account_url, data=params)
- output_dict['login'] = params
- if req.status_code != 201 and req.status_code != 409:
- raise Exception(
- "Unable to create an account {}\n{}".format(
- params, req.text))
- self.logger.debug(
- 'Account %s is created on Ellis\n%s', params, req.json())
-
- session_url = 'http://{0}/session'.format(ellis_ip)
- session_data = {
- 'username': params['email'],
- 'password': params['password'],
- 'email': params['email']
- }
- req = requests.post(session_url, data=session_data)
- if req.status_code != 201:
- raise Exception('Failed to get cookie for Ellis\n{}'.format(
- req.text))
- cookies = req.cookies
- self.logger.debug('Cookies: %s', cookies)
-
- number_url = 'http://{0}/accounts/{1}/numbers'.format(
- ellis_ip, params['email'])
- self.logger.debug('Create 1st calling number on Ellis')
- i = 30
- while req.status_code != 200 and i > 0:
- try:
- number_res = self._create_ellis_number(number_url, cookies)
- break
- except Exception: # pylint: disable=broad-except
- if i == 1:
- self.logger.exception("Unable to create a number")
- raise Exception("Unable to create a number")
- self.logger.info("Unable to create a number. Retry ..")
- time.sleep(25)
- i = i - 1
- output_dict['number'] = number_res
-
- if two_numbers:
- self.logger.debug('Create 2nd calling number on Ellis')
- number_res = self._create_ellis_number(number_url, cookies)
- output_dict['number2'] = number_res
-
- return output_dict
-
- def _create_ellis_number(self, number_url, cookies):
- req = requests.post(number_url, cookies=cookies)
-
- if req.status_code != 200:
- if req and req.json():
- reason = req.json()['reason']
- else:
- reason = req
- raise Exception("Unable to create a number: %s" % reason)
- number_res = req.json()
- self.logger.info('Calling number is created: %s', number_res)
- return number_res
-
- def run_clearwater_live_test(self, dns_ip, public_domain,
- bono_ip=None, ellis_ip=None,
- signup_code='secret'):
- """Run the Clearwater live tests
-
- It first runs dnsmasq to reach clearwater services by FQDN and then the
- Clearwater live tests. All results are saved in ims_test_output.txt.
-
- Returns:
- - a dict containing the overall results
- - None on error
- """
- # pylint: disable=too-many-locals,too-many-arguments
- self.logger.info('Run Clearwater live test')
- dns_file = '/etc/resolv.conf'
- dns_file_bak = '/etc/resolv.conf.bak'
- self.logger.debug('Backup %s -> %s', dns_file, dns_file_bak)
- shutil.copy(dns_file, dns_file_bak)
- cmd = ("dnsmasq -d -u root --server=/clearwater.opnfv/{0} "
- "-r /etc/resolv.conf.bak".format(dns_ip))
- dnsmasq_process = subprocess.Popen(shlex.split(cmd))
- script = ('echo -e "nameserver {0}" > {1};'
- 'cd {2};'
- 'rake test[{3}] SIGNUP_CODE={4}'
- .format('127.0.0.1',
- dns_file,
- self.test_dir,
- public_domain,
- signup_code))
- if bono_ip and ellis_ip:
- subscript = ' PROXY={0} ELLIS={1}'.format(bono_ip, ellis_ip)
- script = '{0}{1}'.format(script, subscript)
- script = ('{0}{1}'.format(script, ' --trace'))
- cmd = "/bin/bash -c '{0}'".format(script)
- self.logger.debug('Live test cmd: %s', cmd)
- output_file = os.path.join(self.result_dir, "ims_test_output.txt")
- ft_utils.execute_command(cmd,
- error_msg='Clearwater live test failed',
- output_file=output_file)
- dnsmasq_process.kill()
- with open(dns_file_bak, 'r') as bak_file:
- result = bak_file.read()
- with open(dns_file, 'w') as dfile:
- dfile.write(result)
-
- with open(output_file, 'r') as ofile:
- result = ofile.read()
-
- if result != "":
- self.logger.debug(result)
-
- vims_test_result = {}
- try:
- grp = re.search(
- r'(\d+) failures out of (\d+) tests run.*'
- r'(\d+) tests skipped', result, re.MULTILINE | re.DOTALL)
- assert grp
- vims_test_result["failures"] = int(grp.group(1))
- vims_test_result["total"] = int(grp.group(2))
- vims_test_result["skipped"] = int(grp.group(3))
- vims_test_result['passed'] = (
- int(grp.group(2)) - int(grp.group(3)) - int(grp.group(1)))
- except Exception: # pylint: disable=broad-except
- self.logger.exception("Cannot parse live tests results")
- return None
- return vims_test_result
diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.py b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
index 786c535ed..b93af7d6d 100644
--- a/functest/opnfv_tests/vnf/ims/cloudify_ims.py
+++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
@@ -14,532 +14,249 @@ from __future__ import division
import logging
import os
import time
-import uuid
-from cloudify_rest_client import CloudifyClient
-from cloudify_rest_client.executions import Execution
-from scp import SCPClient
+import pkg_resources
import six
-from snaps.config.flavor import FlavorConfig
-from snaps.config.image import ImageConfig
-from snaps.config.keypair import KeypairConfig
-from snaps.config.network import NetworkConfig, PortConfig, SubnetConfig
-from snaps.config.router import RouterConfig
-from snaps.config.security_group import (
- Direction, Protocol, SecurityGroupConfig, SecurityGroupRuleConfig)
-from snaps.config.user import UserConfig
-from snaps.config.vm_inst import FloatingIpConfig, VmInstanceConfig
-from snaps.openstack.create_flavor import OpenStackFlavor
-from snaps.openstack.create_image import OpenStackImage
-from snaps.openstack.create_instance import OpenStackVmInstance
-from snaps.openstack.create_keypairs import OpenStackKeypair
-from snaps.openstack.create_network import OpenStackNetwork
-from snaps.openstack.create_router import OpenStackRouter
-from snaps.openstack.create_security_group import OpenStackSecurityGroup
-from snaps.openstack.create_user import OpenStackUser
-from snaps.openstack.utils import keystone_utils
-from xtesting.energy import energy
-import yaml
-
-from functest.opnfv_tests.openstack.snaps import snaps_utils
-from functest.opnfv_tests.vnf.ims import clearwater_ims_base
+
+from functest.core import cloudify
+from functest.opnfv_tests.vnf.ims import clearwater
from functest.utils import config
from functest.utils import env
+from functest.utils import functest_utils
__author__ = "Valentin Boucher <valentin.boucher@orange.com>"
-class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
+class CloudifyIms(cloudify.Cloudify):
"""Clearwater vIMS deployed with Cloudify Orchestrator Case."""
__logger = logging.getLogger(__name__)
+ filename_alt = ('/home/opnfv/functest/images/'
+ 'ubuntu-14.04-server-cloudimg-amd64-disk1.img')
+
+ flavor_alt_ram = 1024
+ flavor_alt_vcpus = 1
+ flavor_alt_disk = 3
+
+ quota_security_group = 20
+ quota_security_group_rule = 100
+ quota_port = 50
+
+ cop_yaml = ("https://github.com/cloudify-cosmo/cloudify-openstack-plugin/"
+ "releases/download/2.14.7/plugin.yaml")
+ cop_wgn = ("https://github.com/cloudify-cosmo/cloudify-openstack-plugin/"
+ "releases/download/2.14.7/cloudify_openstack_plugin-2.14.7-py27"
+ "-none-linux_x86_64-centos-Core.wgn")
+
def __init__(self, **kwargs):
"""Initialize CloudifyIms testcase object."""
if "case_name" not in kwargs:
kwargs["case_name"] = "cloudify_ims"
- super(CloudifyIms, self).__init__(**kwargs)
+ super().__init__(**kwargs)
# Retrieve the configuration
try:
self.config = getattr(
- config.CONF, 'vnf_{}_config'.format(self.case_name))
- except Exception:
- raise Exception("VNF config file not found")
+ config.CONF, f'vnf_{self.case_name}_config')
+ except Exception as exc:
+ raise Exception("VNF config file not found") from exc
+ self.case_dir = pkg_resources.resource_filename(
+ 'functest', 'opnfv_tests/vnf/ims')
config_file = os.path.join(self.case_dir, self.config)
- self.orchestrator = dict(
- requirements=get_config("orchestrator.requirements", config_file),
- )
+
self.details['orchestrator'] = dict(
- name=get_config("orchestrator.name", config_file),
- version=get_config("orchestrator.version", config_file),
+ name=functest_utils.get_parameter_from_yaml(
+ "orchestrator.name", config_file),
+ version=functest_utils.get_parameter_from_yaml(
+ "orchestrator.version", config_file),
status='ERROR',
result=''
)
- self.__logger.debug("Orchestrator configuration %s", self.orchestrator)
+
self.vnf = dict(
- descriptor=get_config("vnf.descriptor", config_file),
- inputs=get_config("vnf.inputs", config_file),
- requirements=get_config("vnf.requirements", config_file)
+ descriptor=functest_utils.get_parameter_from_yaml(
+ "vnf.descriptor", config_file),
+ inputs=functest_utils.get_parameter_from_yaml(
+ "vnf.inputs", config_file)
)
self.details['vnf'] = dict(
descriptor_version=self.vnf['descriptor']['version'],
- name=get_config("vnf.name", config_file),
- version=get_config("vnf.version", config_file),
+ name=functest_utils.get_parameter_from_yaml(
+ "vnf.name", config_file),
+ version=functest_utils.get_parameter_from_yaml(
+ "vnf.version", config_file),
)
self.__logger.debug("VNF configuration: %s", self.vnf)
self.details['test_vnf'] = dict(
- name=get_config("vnf_test_suite.name", config_file),
- version=get_config("vnf_test_suite.version", config_file)
+ name=functest_utils.get_parameter_from_yaml(
+ "vnf_test_suite.name", config_file),
+ version=functest_utils.get_parameter_from_yaml(
+ "vnf_test_suite.version", config_file)
)
- self.images = get_config("tenant_images", config_file)
- self.__logger.info("Images needed for vIMS: %s", self.images)
-
- def prepare(self):
- """Prepare testscase (Additional pre-configuration steps)."""
- super(CloudifyIms, self).prepare()
-
- self.__logger.info("Additional pre-configuration steps")
-
- compute_quotas = self.os_project.get_compute_quotas()
- network_quotas = self.os_project.get_network_quotas()
- for key, value in (
- self.vnf['requirements']['compute_quotas'].items()):
- setattr(compute_quotas, key, value)
+ self.image_alt = None
+ self.flavor_alt = None
+ self.clearwater = None
- for key, value in (
- self.vnf['requirements']['network_quotas'].items()):
- setattr(network_quotas, key, value)
+ def check_requirements(self):
+ if env.get('NEW_USER_ROLE').lower() == "admin":
+ self.__logger.warning(
+ "Defining NEW_USER_ROLE=admin will easily break the testcase "
+ "because Cloudify doesn't manage tenancy (e.g. subnet "
+ "overlapping)")
- compute_quotas = self.os_project.update_compute_quotas(compute_quotas)
- network_quotas = self.os_project.update_network_quotas(network_quotas)
-
- def deploy_orchestrator(self):
- # pylint: disable=too-many-locals,too-many-statements
+ def execute(self):
"""
Deploy Cloudify Manager.
network, security group, fip, VM creation
"""
+ assert super().execute() == 0
start_time = time.time()
-
- # orchestrator VM flavor
- self.__logger.info("Get or create flavor for cloudify manager vm ...")
- flavor_settings = FlavorConfig(
- name="{}-{}".format(
- self.orchestrator['requirements']['flavor']['name'],
- self.uuid),
- ram=self.orchestrator['requirements']['flavor']['ram_min'],
- disk=50,
- vcpus=2)
- flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
- flavor_creator.create()
- self.created_object.append(flavor_creator)
-
- self.__logger.info("Creating a second user to bypass issues ...")
- user_creator = OpenStackUser(
- self.snaps_creds,
- UserConfig(
- name='cloudify_network_bug-{}'.format(self.uuid),
- password=str(uuid.uuid4()),
- project_name=self.tenant_name,
- domain_name=self.snaps_creds.user_domain_name,
- roles={'_member_': self.tenant_name}))
- user_creator.create()
- self.created_object.append(user_creator)
-
- snaps_creds = user_creator.get_os_creds(self.snaps_creds.project_name)
- self.__logger.debug("snaps creds: %s", snaps_creds)
-
- self.__logger.info("Creating keypair ...")
- kp_file = os.path.join(self.data_dir, "cloudify_ims.pem")
- keypair_settings = KeypairConfig(
- name='cloudify_ims_kp-{}'.format(self.uuid),
- private_filepath=kp_file)
- keypair_creator = OpenStackKeypair(snaps_creds, keypair_settings)
- keypair_creator.create()
- self.created_object.append(keypair_creator)
-
- # needs some images
- self.__logger.info("Upload some OS images if it doesn't exist")
- for image_name, image_file in six.iteritems(self.images):
- self.__logger.info("image: %s, file: %s", image_name, image_file)
- if image_file and image_name:
- image_creator = OpenStackImage(
- snaps_creds,
- ImageConfig(
- name=image_name, image_user='cloud',
- img_format='qcow2', image_file=image_file))
- image_creator.create()
- self.created_object.append(image_creator)
-
- # network creation
- self.__logger.info("Creating full network ...")
- subnet_settings = SubnetConfig(
- name='cloudify_ims_subnet-{}'.format(self.uuid),
- cidr='10.67.79.0/24',
- dns_nameservers=[env.get('NAMESERVER')])
- network_settings = NetworkConfig(
- name='cloudify_ims_network-{}'.format(self.uuid),
- subnet_settings=[subnet_settings])
- network_creator = OpenStackNetwork(snaps_creds, network_settings)
- network_creator.create()
- self.created_object.append(network_creator)
- ext_net_name = snaps_utils.get_ext_net_name(snaps_creds)
- router_creator = OpenStackRouter(
- snaps_creds,
- RouterConfig(
- name='cloudify_ims_router-{}'.format(self.uuid),
- external_gateway=ext_net_name,
- internal_subnets=[subnet_settings.name]))
- router_creator.create()
- self.created_object.append(router_creator)
-
- # security group creation
- self.__logger.info("Creating security group for cloudify manager vm")
- sg_rules = list()
- sg_rules.append(
- SecurityGroupRuleConfig(
- sec_grp_name="sg-cloudify-manager-{}".format(self.uuid),
- direction=Direction.ingress, protocol=Protocol.tcp,
- port_range_min=1, port_range_max=65535))
- sg_rules.append(
- SecurityGroupRuleConfig(
- sec_grp_name="sg-cloudify-manager-{}".format(self.uuid),
- direction=Direction.ingress, protocol=Protocol.udp,
- port_range_min=1, port_range_max=65535))
- security_group_creator = OpenStackSecurityGroup(
- snaps_creds,
- SecurityGroupConfig(
- name="sg-cloudify-manager-{}".format(self.uuid),
- rule_settings=sg_rules))
- security_group_creator.create()
- self.created_object.append(security_group_creator)
-
- image_settings = ImageConfig(
- name=self.orchestrator['requirements']['os_image'],
- image_user='centos',
- exists=True)
- port_settings = PortConfig(
- name='cloudify_manager_port-{}'.format(self.uuid),
- network_name=network_settings.name)
- manager_settings = VmInstanceConfig(
- name='cloudify_manager-{}'.format(self.uuid),
- flavor=flavor_settings.name,
- port_settings=[port_settings],
- security_group_names=[
- security_group_creator.sec_grp_settings.name],
- floating_ip_settings=[FloatingIpConfig(
- name='cloudify_manager_fip-{}'.format(self.uuid),
- port_name=port_settings.name,
- router_name=router_creator.router_settings.name)])
- manager_creator = OpenStackVmInstance(
- snaps_creds, manager_settings, image_settings,
- keypair_settings)
- self.__logger.info("Creating cloudify manager VM")
- manager_creator.create()
- self.created_object.append(manager_creator)
-
- public_auth_url = keystone_utils.get_endpoint(snaps_creds, 'identity')
-
+ self.orig_cloud.set_network_quotas(
+ self.project.project.name,
+ security_group=self.quota_security_group,
+ security_group_rule=self.quota_security_group_rule,
+ port=self.quota_port)
+ self.__logger.info("Put OpenStack creds in manager")
cfy_creds = dict(
- keystone_username=snaps_creds.username,
- keystone_password=snaps_creds.password,
- keystone_tenant_name=snaps_creds.project_name,
- keystone_url=public_auth_url,
- region=snaps_creds.region_name if snaps_creds.region_name else (
- 'RegionOne'),
- user_domain_name=snaps_creds.user_domain_name,
- project_domain_name=snaps_creds.project_domain_name)
+ keystone_username=self.project.user.name,
+ keystone_password=self.project.password,
+ keystone_tenant_name=self.project.project.name,
+ keystone_url=self.get_public_auth_url(self.orig_cloud),
+ region=os.environ.get('OS_REGION_NAME', 'RegionOne'),
+ user_domain_name=os.environ.get(
+ 'OS_USER_DOMAIN_NAME', 'Default'),
+ project_domain_name=os.environ.get(
+ 'OS_PROJECT_DOMAIN_NAME', 'Default'))
self.__logger.info("Set creds for cloudify manager %s", cfy_creds)
- cfy_client = CloudifyClient(
- host=manager_creator.get_floating_ip().ip,
- username='admin', password='admin', tenant='default_tenant',
- api_version='v3')
-
- self.orchestrator['object'] = cfy_client
-
- self.__logger.info("Attemps running status of the Manager")
for loop in range(10):
try:
- self.__logger.debug(
- "status %s", cfy_client.manager.get_status())
- cfy_status = cfy_client.manager.get_status()['status']
- self.__logger.info(
- "The current manager status is %s", cfy_status)
- if str(cfy_status) != 'running':
- raise Exception("Cloudify Manager isn't up and running")
- self.__logger.info("Put OpenStack creds in manager")
- secrets_list = cfy_client.secrets.list()
+ secrets_list = self.cfy_client.secrets.list()
for k, val in six.iteritems(cfy_creds):
if not any(d.get('key', None) == k for d in secrets_list):
- cfy_client.secrets.create(k, val)
+ self.cfy_client.secrets.create(k, val)
else:
- cfy_client.secrets.update(k, val)
+ self.cfy_client.secrets.update(k, val)
break
except Exception: # pylint: disable=broad-except
- self.logger.info(
- "try %s: Cloudify Manager isn't up and running", loop + 1)
+ self.__logger.info(
+ "try %s: Cannot create secrets", loop + 1)
time.sleep(30)
else:
- self.logger.error("Cloudify Manager isn't up and running")
- return False
+ self.__logger.error("Cannot create secrets")
+ return 1
duration = time.time() - start_time
- if manager_creator.vm_ssh_active(block=True):
- self.__logger.info("Put private keypair in manager")
- ssh = manager_creator.ssh_client()
- scp = SCPClient(ssh.get_transport(), socket_timeout=15.0)
- scp.put(kp_file, '~/')
- cmd = "sudo cp ~/cloudify_ims.pem /etc/cloudify/"
- self.run_blocking_ssh_command(ssh, cmd)
- cmd = "sudo chmod 444 /etc/cloudify/cloudify_ims.pem"
- self.run_blocking_ssh_command(ssh, cmd)
- # cmd2 is badly unpinned by Cloudify
- cmd = "sudo yum install -y gcc python-devel python-cmd2"
- self.run_blocking_ssh_command(
- ssh, cmd, "Unable to install packages on manager")
- self.run_blocking_ssh_command(ssh, 'cfy status')
- else:
- self.__logger.error("Cannot connect to manager")
- return False
+ self.put_private_key()
+ self.upload_cfy_plugins(self.cop_yaml, self.cop_wgn)
self.details['orchestrator'].update(status='PASS', duration=duration)
self.vnf['inputs'].update(dict(
- external_network_name=ext_net_name,
- network_name=network_settings.name,
- key_pair_name=keypair_settings.name
+ external_network_name=self.ext_net.name,
+ network_name=self.network.name,
+ key_pair_name=self.keypair.name
))
+ if self.deploy_vnf() and self.test_vnf():
+ self.result = 100
+ return 0
self.result = 1/3 * 100
- return True
+ return 1
def deploy_vnf(self):
"""Deploy Clearwater IMS."""
start_time = time.time()
+ secgroups = self.cloud.list_security_groups(
+ filters={'name': 'default',
+ 'project_id': self.project.project.id})
+ if secgroups:
+ secgroup = secgroups[0]
+ else:
+ self.__logger.error("No 'default' security group in project %s",
+ self.project.project.name)
+ return False
+
+ self.cloud.create_security_group_rule(
+ secgroup.id, port_range_min=22, port_range_max=22,
+ protocol='tcp', direction='ingress')
+
self.__logger.info("Upload VNFD")
- cfy_client = self.orchestrator['object']
descriptor = self.vnf['descriptor']
- cfy_client.blueprints.upload(
+ self.cfy_client.blueprints.upload(
descriptor.get('file_name'), descriptor.get('name'))
- self.__logger.info("Get or create flavor for all clearwater vm")
- flavor_settings = FlavorConfig(
- name="{}-{}".format(
- self.vnf['requirements']['flavor']['name'],
- self.uuid),
- ram=self.vnf['requirements']['flavor']['ram_min'],
- disk=25,
- vcpus=2)
- flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
- flavor_creator.create()
- self.created_object.append(flavor_creator)
+ self.image_alt = self.publish_image_alt()
+ self.flavor_alt = self.create_flavor_alt()
self.vnf['inputs'].update(dict(
- flavor_id=flavor_settings.name,
+ image_id=self.image_alt.id,
+ flavor_id=self.flavor_alt.id,
))
self.__logger.info("Create VNF Instance")
- cfy_client.deployments.create(descriptor.get('name'),
- descriptor.get('name'),
- self.vnf.get('inputs'))
+ self.cfy_client.deployments.create(
+ descriptor.get('name'), descriptor.get('name'),
+ self.vnf.get('inputs'))
- wait_for_execution(
- cfy_client,
- get_execution_id(cfy_client, descriptor.get('name')),
+ cloudify.wait_for_execution(
+ self.cfy_client,
+ cloudify.get_execution_id(self.cfy_client, descriptor.get('name')),
self.__logger, timeout=300)
self.__logger.info("Start the VNF Instance deployment")
- execution = cfy_client.executions.start(descriptor.get('name'),
- 'install')
+ execution = self.cfy_client.executions.start(
+ descriptor.get('name'), 'install')
# Show execution log
- execution = wait_for_execution(
- cfy_client, execution, self.__logger, timeout=3600)
-
- duration = time.time() - start_time
+ execution = cloudify.wait_for_execution(
+ self.cfy_client, execution, self.__logger, timeout=3600)
self.__logger.info(execution)
- if execution.status == 'terminated':
- self.details['vnf'].update(status='PASS', duration=duration)
- self.result += 1/3 * 100
- result = True
- else:
- self.details['vnf'].update(status='FAIL', duration=duration)
- result = False
- return result
+ if execution.status != 'terminated':
+ self.details['vnf'].update(status='FAIL',
+ duration=time.time() - start_time)
+ return False
+
+ ellis_ip = self.cfy_client.deployments.outputs.get(
+ self.vnf['descriptor'].get('name'))['outputs']['ellis_ip']
+ bono_ip = self.cfy_client.deployments.outputs.get(
+ self.vnf['descriptor'].get('name'))['outputs']['bono_ip']
+ self.clearwater = clearwater.ClearwaterTesting(
+ self.case_name, bono_ip, ellis_ip)
+ self.clearwater.availability_check()
+
+ self.details['vnf'].update(status='PASS',
+ duration=time.time() - start_time)
+ self.result += 1/3 * 100
+ return True
def test_vnf(self):
"""Run test on clearwater ims instance."""
start_time = time.time()
-
- cfy_client = self.orchestrator['object']
-
- outputs = cfy_client.deployments.outputs.get(
- self.vnf['descriptor'].get('name'))['outputs']
- dns_ip = outputs['dns_ip']
- ellis_ip = outputs['ellis_ip']
- self.config_ellis(ellis_ip)
-
+ dns_ip = self.cfy_client.deployments.outputs.get(
+ self.vnf['descriptor'].get('name'))['outputs']['dns_ip']
if not dns_ip:
return False
-
- short_result = self.run_clearwater_live_test(
- dns_ip=dns_ip,
+ short_result, vnf_test_rate = self.clearwater.run_clearwater_live_test(
public_domain=self.vnf['inputs']["public_domain"])
duration = time.time() - start_time
self.__logger.info(short_result)
- self.details['test_vnf'].update(result=short_result,
- duration=duration)
- try:
- vnf_test_rate = short_result['passed'] / (
- short_result['total'] - short_result['skipped'])
- # orchestrator + vnf + test_vnf
- self.result += vnf_test_rate / 3 * 100
- except ZeroDivisionError:
- self.__logger.error("No test has been executed")
- self.details['test_vnf'].update(status='FAIL')
- return False
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot calculate results")
+ self.details['test_vnf'].update(result=short_result, duration=duration)
+ self.result += vnf_test_rate / 3 * 100
+ if vnf_test_rate == 0:
self.details['test_vnf'].update(status='FAIL')
- return False
- return True if vnf_test_rate > 0 else False
+ return bool(vnf_test_rate > 0)
def clean(self):
"""Clean created objects/functions."""
- try:
- cfy_client = self.orchestrator['object']
- dep_name = self.vnf['descriptor'].get('name')
- # kill existing execution
- self.__logger.info('Deleting the current deployment')
- exec_list = cfy_client.executions.list(dep_name)
- for execution in exec_list:
- if execution['status'] == "started":
- try:
- cfy_client.executions.cancel(execution['id'],
- force=True)
- except Exception: # pylint: disable=broad-except
- self.__logger.warn("Can't cancel the current exec")
-
- execution = cfy_client.executions.start(
- dep_name,
- 'uninstall',
- parameters=dict(ignore_failure=True),
- force=True)
-
- wait_for_execution(cfy_client, execution, self.__logger)
- cfy_client.deployments.delete(self.vnf['descriptor'].get('name'))
- cfy_client.blueprints.delete(self.vnf['descriptor'].get('name'))
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Some issue during the undeployment ..")
-
- super(CloudifyIms, self).clean()
-
- @staticmethod
- def run_blocking_ssh_command(ssh, cmd,
- error_msg="Unable to run this command"):
- """Command to run ssh command with the exit status."""
- _, stdout, stderr = ssh.exec_command(cmd)
- CloudifyIms.__logger.debug("SSH %s stdout: %s", cmd, stdout.read())
- if stdout.channel.recv_exit_status() != 0:
- CloudifyIms.__logger.error("SSH %s stderr: %s", cmd, stderr.read())
- raise Exception(error_msg)
-
- @energy.enable_recording
- def run(self, **kwargs):
- """Execute CloudifyIms test case."""
- return super(CloudifyIms, self).run(**kwargs)
-
-
-# ----------------------------------------------------------
-#
-# YAML UTILS
-#
-# -----------------------------------------------------------
-def get_config(parameter, file_path):
- """
- Get config parameter.
-
- Returns the value of a given parameter in file.yaml
- parameter must be given in string format with dots
- Example: general.openstack.image_name
- """
- with open(file_path) as config_file:
- file_yaml = yaml.safe_load(config_file)
- config_file.close()
- value = file_yaml
- for element in parameter.split("."):
- value = value.get(element)
- if value is None:
- raise ValueError("The parameter %s is not defined in"
- " reporting.yaml" % parameter)
- return value
-
-
-def wait_for_execution(client, execution, logger, timeout=3600, ):
- """Wait for a workflow execution on Cloudify Manager."""
- # if execution already ended - return without waiting
- if execution.status in Execution.END_STATES:
- return execution
-
- if timeout is not None:
- deadline = time.time() + timeout
-
- # Poll for execution status and execution logs, until execution ends
- # and we receive an event of type in WORKFLOW_END_TYPES
- offset = 0
- batch_size = 50
- event_list = []
- execution_ended = False
- while True:
- event_list = client.events.list(
- execution_id=execution.id,
- _offset=offset,
- _size=batch_size,
- include_logs=True,
- sort='@timestamp').items
-
- offset = offset + len(event_list)
- for event in event_list:
- logger.debug(event.get('message'))
-
- if timeout is not None:
- if time.time() > deadline:
- raise RuntimeError(
- 'execution of operation {0} for deployment {1} '
- 'timed out'.format(execution.workflow_id,
- execution.deployment_id))
- else:
- # update the remaining timeout
- timeout = deadline - time.time()
-
- if not execution_ended:
- execution = client.executions.get(execution.id)
- execution_ended = execution.status in Execution.END_STATES
-
- if execution_ended:
- break
-
- time.sleep(5)
-
- return execution
-
-
-def get_execution_id(client, deployment_id):
- """
- Get the execution id of a env preparation.
-
- network, security group, fip, VM creation
- """
- executions = client.executions.list(deployment_id=deployment_id)
- for execution in executions:
- if execution.workflow_id == 'create_deployment_environment':
- return execution
- raise RuntimeError('Failed to get create_deployment_environment '
- 'workflow execution.'
- 'Available executions: {0}'.format(executions))
+ self.kill_existing_execution(self.vnf['descriptor'].get('name'))
+ if self.image_alt:
+ self.cloud.delete_image(self.image_alt)
+ if self.flavor_alt:
+ self.orig_cloud.delete_flavor(self.flavor_alt.id)
+ super().clean()
diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml b/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml
index 6808cf33d..869281a20 100644
--- a/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml
+++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml
@@ -1,35 +1,14 @@
---
-tenant_images:
- ubuntu_14.04:
- /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.img
- cloudify_manager_4.0:
- /home/opnfv/functest/images/cloudify-manager-premium-4.0.1.qcow2
orchestrator:
name: cloudify
version: '4.0'
- requirements:
- flavor:
- name: cloudify.medium
- ram_min: 4096
- os_image: 'cloudify_manager_4.0'
vnf:
name: clearwater
- version: '107'
+ version: '129'
descriptor:
- file_name: /src/vims/openstack-blueprint.yaml
+ file_name: /src/cloudify_vims/openstack-blueprint.yaml
name: clearwater-opnfv
- version: '122'
- requirements:
- flavor:
- name: cloudify.small
- ram_min: 2048
- compute_quotas:
- cores: 50
- instances: 15
- network_quotas:
- security_group: 20
- security_group_rule: 100
- port: 50
+ version: '129'
inputs:
image_id: 'ubuntu_14.04'
flavor_id: 'cloudify.small'
@@ -46,4 +25,4 @@ vnf:
homer_cluster_size: 1
vnf_test_suite:
name: clearwater-live-test
- version: "1.0"
+ version: '1.0'
diff --git a/functest/opnfv_tests/vnf/ims/heat_ims.py b/functest/opnfv_tests/vnf/ims/heat_ims.py
new file mode 100644
index 000000000..0d4e345a0
--- /dev/null
+++ b/functest/opnfv_tests/vnf/ims/heat_ims.py
@@ -0,0 +1,253 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2018 Kontron, Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""HeatIms testcase implementation."""
+
+from __future__ import division
+
+import logging
+import os
+import re
+import time
+import tempfile
+
+import paramiko
+import pkg_resources
+from xtesting.core import testcase
+
+from functest.core import singlevm
+from functest.opnfv_tests.vnf.ims import clearwater
+from functest.utils import config
+from functest.utils import env
+from functest.utils import functest_utils
+
+__author__ = "Valentin Boucher <valentin.boucher@kontron.com>"
+
+
+class HeatIms(singlevm.VmReady2):
+ # pylint: disable=too-many-instance-attributes
+ """Clearwater vIMS deployed with Heat Orchestrator Case."""
+
+ __logger = logging.getLogger(__name__)
+
+ filename = ('/home/opnfv/functest/images/'
+ 'ubuntu-14.04-server-cloudimg-amd64-disk1.img')
+
+ flavor_ram = 1024
+ flavor_vcpus = 1
+ flavor_disk = 3
+
+ quota_security_group = 20
+ quota_security_group_rule = 100
+ quota_port = 50
+
+ parameters = {
+ 'private_mgmt_net_cidr': '192.168.100.0/24',
+ 'private_mgmt_net_gateway': '192.168.100.254',
+ 'private_mgmt_net_pool_start': '192.168.100.1',
+ 'private_mgmt_net_pool_end': '192.168.100.253'}
+
+ def __init__(self, **kwargs):
+ """Initialize HeatIms testcase object."""
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "heat_ims"
+ super().__init__(**kwargs)
+
+ # Retrieve the configuration
+ try:
+ self.config = getattr(
+ config.CONF, f'vnf_{self.case_name}_config')
+ except Exception as exc:
+ raise Exception("VNF config file not found") from exc
+
+ self.case_dir = pkg_resources.resource_filename(
+ 'functest', 'opnfv_tests/vnf/ims')
+ config_file = os.path.join(self.case_dir, self.config)
+
+ self.vnf = dict(
+ descriptor=functest_utils.get_parameter_from_yaml(
+ "vnf.descriptor", config_file),
+ parameters=functest_utils.get_parameter_from_yaml(
+ "vnf.inputs", config_file)
+ )
+ self.details['vnf'] = dict(
+ descriptor_version=self.vnf['descriptor']['version'],
+ name=functest_utils.get_parameter_from_yaml(
+ "vnf.name", config_file),
+ version=functest_utils.get_parameter_from_yaml(
+ "vnf.version", config_file),
+ )
+ self.__logger.debug("VNF configuration: %s", self.vnf)
+ self.keypair = None
+ self.stack = None
+ self.clearwater = None
+ self.role = None
+ (_, self.key_filename) = tempfile.mkstemp()
+
+ def create_network_resources(self):
+ pass
+
+ def execute(self):
+ # pylint: disable=too-many-locals,too-many-statements
+ """
+ Prepare Tenant/User
+
+ network, security group, fip, VM creation
+ """
+ self.orig_cloud.set_network_quotas(
+ self.project.project.name,
+ security_group=self.quota_security_group,
+ security_group_rule=self.quota_security_group_rule,
+ port=self.quota_port)
+ if not self.orig_cloud.get_role("heat_stack_owner"):
+ self.role = self.orig_cloud.create_role("heat_stack_owner")
+ self.orig_cloud.grant_role(
+ "heat_stack_owner", user=self.project.user.id,
+ project=self.project.project.id,
+ domain=self.project.domain.id)
+ self.keypair = self.cloud.create_keypair(
+ f'{self.case_name}-kp_{self.guid}')
+ self.__logger.info("keypair:\n%s", self.keypair.private_key)
+ with open(
+ self.key_filename, 'w', encoding='utf-8') as private_key_file:
+ private_key_file.write(self.keypair.private_key)
+
+ if self.deploy_vnf() and self.test_vnf():
+ self.result = 100
+ return 0
+ self.result = 1/3 * 100
+ return 1
+
+ def run(self, **kwargs):
+ """Deploy and test clearwater
+
+ Here are the main actions:
+ - deploy clearwater stack via heat
+ - test the vnf instance
+
+ Returns:
+ - TestCase.EX_OK
+ - TestCase.EX_RUN_ERROR on error
+ """
+ status = testcase.TestCase.EX_RUN_ERROR
+ try:
+ assert self.cloud
+ assert super().run(
+ **kwargs) == testcase.TestCase.EX_OK
+ self.result = 0
+ if not self.execute():
+ self.result = 100
+ status = testcase.TestCase.EX_OK
+ except Exception: # pylint: disable=broad-except
+ self.__logger.exception('Cannot run %s', self.case_name)
+ finally:
+ self.stop_time = time.time()
+ return status
+
+ def _monit(self, username="ubuntu", timeout=60):
+ servers = self.cloud.list_servers(detailed=True)
+ self.__logger.debug("servers: %s", servers)
+ for server in servers:
+ if 'ns' in server.name:
+ break
+ self.__logger.info("server:\n%s", server.name)
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
+ ssh.connect(
+ server.public_v4, username=username,
+ key_filename=self.key_filename, timeout=timeout)
+ (_, stdout, _) = ssh.exec_command('sudo monit summary')
+ self.__logger.info("output:\n%s", stdout.read().decode("utf-8"))
+ ssh.close()
+
+ def deploy_vnf(self):
+ """Deploy Clearwater IMS."""
+ start_time = time.time()
+ descriptor = self.vnf['descriptor']
+ parameters = self.vnf['parameters']
+
+ parameters['public_mgmt_net_id'] = self.ext_net.id
+ parameters['flavor'] = self.flavor.name
+ parameters['image'] = self.image.name
+ parameters['key_name'] = self.keypair.name
+ parameters['external_mgmt_dns_ip'] = env.get('NAMESERVER')
+ parameters.update(self.parameters)
+
+ self.__logger.info("Create Heat Stack")
+ self.stack = self.cloud.create_stack(
+ name=descriptor.get('name'),
+ template_file=descriptor.get('file_name'),
+ wait=True, **parameters)
+ self.__logger.debug("stack: %s", self.stack)
+
+ self._monit()
+
+ servers = self.cloud.list_servers(detailed=True)
+ self.__logger.debug("servers: %s", servers)
+ for server in servers:
+ if not self.check_regex_in_console(
+ server.name, regex='Cloud-init .* finished at ', loop=1):
+ return False
+ if 'ellis' in server.name:
+ self.__logger.debug("ellis: %s", server)
+ ellis_ip = server.public_v4
+ elif 'bono' in server.name:
+ self.__logger.debug("bono: %s", server)
+ bono_ip = server.public_v4
+
+ assert ellis_ip
+ assert bono_ip
+ self.clearwater = clearwater.ClearwaterTesting(
+ self.case_name, bono_ip, ellis_ip)
+ # This call can take time and many retry because Heat is
+ # an infrastructure orchestrator so when Heat say "stack created"
+ # it means that all OpenStack ressources are created but not that
+ # Clearwater are up and ready (Cloud-Init script still running)
+ self.clearwater.availability_check()
+
+ duration = time.time() - start_time
+
+ self.details['vnf'].update(status='PASS', duration=duration)
+ self.result += 1/3 * 100
+
+ return True
+
+ def test_vnf(self):
+ """Run test on clearwater ims instance."""
+ start_time = time.time()
+ outputs = self.cloud.get_stack(self.stack.id).outputs
+ self.__logger.debug("stack outputs: %s", outputs)
+ dns_ip = re.findall(r'[0-9]+(?:\.[0-9]+){3}', str(outputs))[0]
+ if not dns_ip:
+ return False
+ short_result, vnf_test_rate = self.clearwater.run_clearwater_live_test(
+ public_domain=self.vnf['parameters']["zone"])
+ duration = time.time() - start_time
+ self.__logger.info(short_result)
+ self.details['test_vnf'] = dict(result=short_result, duration=duration)
+ self.result += vnf_test_rate / 3 * 100
+ if vnf_test_rate == 0:
+ self.details['test_vnf'].update(status='FAIL')
+ self._monit()
+ return bool(vnf_test_rate > 0)
+
+ def clean(self):
+ """Clean created objects/functions."""
+ assert self.cloud
+ try:
+ if self.stack:
+ self.cloud.delete_stack(self.stack.id, wait=True)
+ except TypeError:
+ # shade raises TypeError exceptions when checking stack status
+ pass
+ except Exception: # pylint: disable=broad-except
+ self.__logger.exception("Cannot clean stack ressources")
+ super().clean()
+ if self.role:
+ self.orig_cloud.delete_role(self.role.id)
diff --git a/functest/opnfv_tests/vnf/ims/heat_ims.yaml b/functest/opnfv_tests/vnf/ims/heat_ims.yaml
new file mode 100644
index 000000000..2ccdc0bf7
--- /dev/null
+++ b/functest/opnfv_tests/vnf/ims/heat_ims.yaml
@@ -0,0 +1,22 @@
+---
+orchestrator:
+ name: heat
+ version: '4.0'
+vnf:
+ name: clearwater
+ version: '130'
+ descriptor:
+ file_name: /src/heat_vims/clearwater.yaml
+ name: clearwater-opnfv
+ version: '130'
+ inputs:
+ zone: clearwater.opnfv
+ dn_range_start: "6505550000"
+ dn_range_length: "1000"
+ bono_cluster_size: 1
+ sprout_cluster_size: 1
+ vellum_cluster_size: 1
+ dime_cluster_size: 1
+ homer_cluster_size: 1
+ dnssec_key:
+ GkBraPnditvP2Em4oXV5wUTawmZaGGuO+Jt3ZnFkznGV3zFoQ+Ak13nuuOnO0JV5FqAr/KitdW6siqjXSjROXg==
diff --git a/functest/opnfv_tests/vnf/router/cloudify_vrouter.py b/functest/opnfv_tests/vnf/router/cloudify_vrouter.py
index e56f23cfc..32d675347 100644
--- a/functest/opnfv_tests/vnf/router/cloudify_vrouter.py
+++ b/functest/opnfv_tests/vnf/router/cloudify_vrouter.py
@@ -14,64 +14,54 @@
import logging
import os
import time
-import uuid
-
-from cloudify_rest_client import CloudifyClient
-from cloudify_rest_client.executions import Execution
-from scp import SCPClient
-import six
-from snaps.config.flavor import FlavorConfig
-from snaps.config.image import ImageConfig
-from snaps.config.keypair import KeypairConfig
-from snaps.config.network import NetworkConfig, PortConfig, SubnetConfig
-from snaps.config.router import RouterConfig
-from snaps.config.security_group import (
- Direction, Protocol, SecurityGroupConfig, SecurityGroupRuleConfig)
-from snaps.config.user import UserConfig
-from snaps.config.vm_inst import FloatingIpConfig, VmInstanceConfig
-from snaps.openstack.create_flavor import OpenStackFlavor
-from snaps.openstack.create_image import OpenStackImage
-from snaps.openstack.create_instance import OpenStackVmInstance
-from snaps.openstack.create_keypairs import OpenStackKeypair
-from snaps.openstack.create_network import OpenStackNetwork
-from snaps.openstack.create_security_group import OpenStackSecurityGroup
-from snaps.openstack.create_router import OpenStackRouter
-from snaps.openstack.create_user import OpenStackUser
-import snaps.openstack.utils.glance_utils as glance_utils
-from snaps.openstack.utils import keystone_utils
-
-from functest.opnfv_tests.openstack.snaps import snaps_utils
-import functest.opnfv_tests.vnf.router.vrouter_base as vrouter_base
+
+import pkg_resources
+
+from functest.core import cloudify
+from functest.opnfv_tests.vnf.router import vrouter_base
from functest.opnfv_tests.vnf.router.utilvnf import Utilvnf
from functest.utils import config
from functest.utils import env
from functest.utils import functest_utils
+
__author__ = "Shuya Nakama <shuya.nakama@okinawaopenlabs.org>"
-class CloudifyVrouter(vrouter_base.VrouterOnBoardingBase):
+class CloudifyVrouter(cloudify.Cloudify):
# pylint: disable=too-many-instance-attributes
"""vrouter testcase deployed with Cloudify Orchestrator."""
__logger = logging.getLogger(__name__)
- name = __name__
+
+ filename_alt = '/home/opnfv/functest/images/vyos-1.1.8-amd64.qcow2'
+
+ flavor_alt_ram = 1024
+ flavor_alt_vcpus = 1
+ flavor_alt_disk = 3
+
+ check_console_loop = 12
+
+ cop_yaml = ("https://github.com/cloudify-cosmo/cloudify-openstack-plugin/"
+ "releases/download/2.14.7/plugin.yaml")
+ cop_wgn = ("https://github.com/cloudify-cosmo/cloudify-openstack-plugin/"
+ "releases/download/2.14.7/cloudify_openstack_plugin-2.14.7-py27"
+ "-none-linux_x86_64-centos-Core.wgn")
def __init__(self, **kwargs):
if "case_name" not in kwargs:
kwargs["case_name"] = "vyos_vrouter"
- super(CloudifyVrouter, self).__init__(**kwargs)
+ super().__init__(**kwargs)
# Retrieve the configuration
try:
self.config = getattr(
- config.CONF, 'vnf_{}_config'.format(self.case_name))
- except Exception:
- raise Exception("VNF config file not found")
-
- self.cfy_manager_ip = ''
- self.deployment_name = ''
+ config.CONF, f'vnf_{self.case_name}_config')
+ except Exception as exc:
+ raise Exception("VNF config file not found") from exc
+ self.case_dir = pkg_resources.resource_filename(
+ 'functest', 'opnfv_tests/vnf/router')
config_file = os.path.join(self.case_dir, self.config)
self.orchestrator = dict(
requirements=functest_utils.get_parameter_from_yaml(
@@ -86,7 +76,7 @@ class CloudifyVrouter(vrouter_base.VrouterOnBoardingBase):
result=''
)
self.__logger.debug("Orchestrator configuration %s", self.orchestrator)
- self.__logger.debug("name = %s", self.name)
+ self.__logger.debug("name = %s", __name__)
self.vnf = dict(
descriptor=functest_utils.get_parameter_from_yaml(
"vnf.descriptor", config_file),
@@ -105,6 +95,10 @@ class CloudifyVrouter(vrouter_base.VrouterOnBoardingBase):
self.__logger.debug("VNF configuration: %s", self.vnf)
self.util = Utilvnf()
+ self.util.set_credentials(self.cloud)
+ credentials = {"cloud": self.cloud}
+ self.util_info = {"credentials": credentials,
+ "vnf_data_dir": self.util.vnf_data_dir}
self.details['test_vnf'] = dict(
name=functest_utils.get_parameter_from_yaml(
@@ -116,263 +110,94 @@ class CloudifyVrouter(vrouter_base.VrouterOnBoardingBase):
"tenant_images", config_file)
self.__logger.info("Images needed for vrouter: %s", self.images)
- @staticmethod
- def run_blocking_ssh_command(ssh, cmd,
- error_msg="Unable to run this command"):
- """Command to run ssh command with the exit status."""
- (_, stdout, stderr) = ssh.exec_command(cmd)
- CloudifyVrouter.__logger.debug("SSH %s stdout: %s", cmd, stdout.read())
- if stdout.channel.recv_exit_status() != 0:
- CloudifyVrouter.__logger.error(
- "SSH %s stderr: %s", cmd, stderr.read())
- raise Exception(error_msg)
-
- def prepare(self):
- super(CloudifyVrouter, self).prepare()
- self.__logger.info("Additional pre-configuration steps")
- self.util.set_credentials(self.snaps_creds)
-
- def deploy_orchestrator(self):
+ self.image_alt = None
+ self.flavor_alt = None
+
+ def check_requirements(self):
+ if env.get('NEW_USER_ROLE').lower() == "admin":
+ self.__logger.warning(
+ "Defining NEW_USER_ROLE=admin will easily break the testcase "
+ "because Cloudify doesn't manage tenancy (e.g. subnet "
+ "overlapping)")
+
+ def execute(self):
# pylint: disable=too-many-locals,too-many-statements
"""
Deploy Cloudify Manager.
network, security group, fip, VM creation
"""
# network creation
+ super().execute()
start_time = time.time()
+ self.put_private_key()
+ self.upload_cfy_plugins(self.cop_yaml, self.cop_wgn)
- # orchestrator VM flavor
- self.__logger.info("Get or create flavor for cloudify manager vm ...")
- flavor_settings = FlavorConfig(
- name="{}-{}".format(
- self.orchestrator['requirements']['flavor']['name'],
- self.uuid),
- ram=self.orchestrator['requirements']['flavor']['ram_min'],
- disk=50, vcpus=2)
- flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
- flavor_creator.create()
- self.created_object.append(flavor_creator)
-
- user_creator = OpenStackUser(
- self.snaps_creds,
- UserConfig(
- name='cloudify_network_bug-{}'.format(self.uuid),
- password=str(uuid.uuid4()),
- project_name=self.tenant_name,
- domain_name=self.snaps_creds.user_domain_name,
- roles={'_member_': self.tenant_name}))
- user_creator.create()
- self.created_object.append(user_creator)
-
- snaps_creds = user_creator.get_os_creds(self.snaps_creds.project_name)
- self.__logger.debug("snaps creds: %s", snaps_creds)
-
- self.__logger.info("Creating keypair ...")
- kp_file = os.path.join(self.data_dir, "cloudify_vrouter.pem")
- keypair_settings = KeypairConfig(
- name='cloudify_vrouter_kp-{}'.format(self.uuid),
- private_filepath=kp_file)
- keypair_creator = OpenStackKeypair(snaps_creds, keypair_settings)
- keypair_creator.create()
- self.created_object.append(keypair_creator)
-
- self.__logger.info("Upload some OS images if it doesn't exist")
- for image_name, image_file in six.iteritems(self.images):
- self.__logger.info("image: %s, file: %s", image_name, image_file)
- if image_file and image_name:
- image_creator = OpenStackImage(
- snaps_creds,
- ImageConfig(
- name=image_name, image_user='cloud',
- img_format='qcow2', image_file=image_file))
- image_creator.create()
- self.created_object.append(image_creator)
-
- self.__logger.info("Creating full network ...")
- subnet_settings = SubnetConfig(
- name='cloudify_vrouter_subnet-{}'.format(self.uuid),
- cidr='10.67.79.0/24',
- dns_nameservers=[env.get('NAMESERVER')])
- network_settings = NetworkConfig(
- name='cloudify_vrouter_network-{}'.format(self.uuid),
- subnet_settings=[subnet_settings])
- network_creator = OpenStackNetwork(snaps_creds, network_settings)
- network_creator.create()
- self.created_object.append(network_creator)
- ext_net_name = snaps_utils.get_ext_net_name(snaps_creds)
- router_creator = OpenStackRouter(
- snaps_creds,
- RouterConfig(
- name='cloudify_vrouter_router-{}'.format(self.uuid),
- external_gateway=ext_net_name,
- internal_subnets=[subnet_settings.name]))
- router_creator.create()
- self.created_object.append(router_creator)
-
- # security group creation
- self.__logger.info("Creating security group for cloudify manager vm")
- sg_rules = list()
- sg_rules.append(
- SecurityGroupRuleConfig(
- sec_grp_name="sg-cloudify-manager-{}".format(self.uuid),
- direction=Direction.ingress,
- protocol=Protocol.tcp, port_range_min=1,
- port_range_max=65535))
- sg_rules.append(
- SecurityGroupRuleConfig(
- sec_grp_name="sg-cloudify-manager-{}".format(self.uuid),
- direction=Direction.ingress,
- protocol=Protocol.udp, port_range_min=1,
- port_range_max=65535))
- security_group_creator = OpenStackSecurityGroup(
- snaps_creds,
- SecurityGroupConfig(
- name="sg-cloudify-manager-{}".format(self.uuid),
- rule_settings=sg_rules))
- security_group_creator.create()
- self.created_object.append(security_group_creator)
-
- image_settings = ImageConfig(
- name=self.orchestrator['requirements']['os_image'],
- image_user='centos', exists=True)
- port_settings = PortConfig(
- name='cloudify_manager_port-{}'.format(self.uuid),
- network_name=network_settings.name)
- manager_settings = VmInstanceConfig(
- name='cloudify_manager-{}'.format(self.uuid),
- flavor=flavor_settings.name,
- port_settings=[port_settings],
- security_group_names=[
- security_group_creator.sec_grp_settings.name],
- floating_ip_settings=[FloatingIpConfig(
- name='cloudify_manager_fip-{}'.format(self.uuid),
- port_name=port_settings.name,
- router_name=router_creator.router_settings.name)])
- manager_creator = OpenStackVmInstance(
- snaps_creds, manager_settings, image_settings,
- keypair_settings)
-
- self.__logger.info("Creating cloudify manager VM")
- manager_creator.create()
- self.created_object.append(manager_creator)
-
- cfy_client = CloudifyClient(
- host=manager_creator.get_floating_ip().ip,
- username='admin', password='admin', tenant='default_tenant',
- api_version='v3')
-
- self.orchestrator['object'] = cfy_client
-
- self.cfy_manager_ip = manager_creator.get_floating_ip().ip
-
- self.__logger.info("Attemps running status of the Manager")
- for loop in range(10):
- try:
- self.__logger.debug(
- "status %s", cfy_client.manager.get_status())
- cfy_status = cfy_client.manager.get_status()['status']
- self.__logger.info(
- "The current manager status is %s", cfy_status)
- if str(cfy_status) != 'running':
- raise Exception("Cloudify Manager isn't up and running")
- break
- except Exception: # pylint: disable=broad-except
- self.logger.info(
- "try %s: Cloudify Manager isn't up and running", loop + 1)
- time.sleep(30)
- else:
- self.logger.error("Cloudify Manager isn't up and running")
- return False
+ self.image_alt = self.publish_image_alt()
+ self.flavor_alt = self.create_flavor_alt()
duration = time.time() - start_time
-
- self.__logger.info("Put private keypair in manager")
- if manager_creator.vm_ssh_active(block=True):
- ssh = manager_creator.ssh_client()
- scp = SCPClient(ssh.get_transport(), socket_timeout=15.0)
- scp.put(kp_file, '~/')
- cmd = "sudo cp ~/cloudify_vrouter.pem /etc/cloudify/"
- self.run_blocking_ssh_command(ssh, cmd)
- cmd = "sudo chmod 444 /etc/cloudify/cloudify_vrouter.pem"
- self.run_blocking_ssh_command(ssh, cmd)
- # cmd2 is badly unpinned by Cloudify
- cmd = "sudo yum install -y gcc python-devel python-cmd2"
- self.run_blocking_ssh_command(
- ssh, cmd, "Unable to install packages on manager")
- else:
- self.__logger.error("Cannot connect to manager")
- return False
-
self.details['orchestrator'].update(status='PASS', duration=duration)
- self.__logger.info("Get or create flavor for vrouter")
- flavor_settings = FlavorConfig(
- name="{}-{}".format(
- self.vnf['requirements']['flavor']['name'],
- self.uuid),
- ram=self.vnf['requirements']['flavor']['ram_min'],
- disk=25, vcpus=1)
- flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
- flavor = flavor_creator.create()
- self.created_object.append(flavor_creator)
-
- # set image name
- glance = glance_utils.glance_client(snaps_creds)
- image = glance_utils.get_image(glance, "vyos1.1.7")
- self.vnf['inputs'].update(dict(external_network_name=ext_net_name))
- self.vnf['inputs'].update(dict(target_vnf_image_id=image.id))
- self.vnf['inputs'].update(dict(reference_vnf_image_id=image.id))
- self.vnf['inputs'].update(dict(target_vnf_flavor_id=flavor.id))
- self.vnf['inputs'].update(dict(reference_vnf_flavor_id=flavor.id))
self.vnf['inputs'].update(dict(
- keystone_username=snaps_creds.username))
+ external_network_name=self.ext_net.name))
self.vnf['inputs'].update(dict(
- keystone_password=snaps_creds.password))
+ target_vnf_image_id=self.image_alt.id))
self.vnf['inputs'].update(dict(
- keystone_tenant_name=snaps_creds.project_name))
+ reference_vnf_image_id=self.image_alt.id))
self.vnf['inputs'].update(dict(
- keystone_user_domain_name=snaps_creds.user_domain_name))
+ target_vnf_flavor_id=self.flavor_alt.id))
self.vnf['inputs'].update(dict(
- keystone_project_domain_name=snaps_creds.project_domain_name))
+ reference_vnf_flavor_id=self.flavor_alt.id))
self.vnf['inputs'].update(dict(
- region=snaps_creds.region_name if snaps_creds.region_name else (
- 'RegionOne')))
+ keystone_username=self.project.user.name))
self.vnf['inputs'].update(dict(
- keystone_url=keystone_utils.get_endpoint(
- snaps_creds, 'identity')))
-
- credentials = {"snaps_creds": snaps_creds}
- self.util_info = {"credentials": credentials,
- "cfy": cfy_client,
- "vnf_data_dir": self.util.vnf_data_dir}
+ keystone_password=self.project.password))
+ self.vnf['inputs'].update(dict(
+ keystone_tenant_name=self.project.project.name))
+ self.vnf['inputs'].update(dict(
+ keystone_user_domain_name=os.environ.get(
+ 'OS_USER_DOMAIN_NAME', 'Default')))
+ self.vnf['inputs'].update(dict(
+ keystone_project_domain_name=os.environ.get(
+ 'OS_PROJECT_DOMAIN_NAME', 'Default')))
+ self.vnf['inputs'].update(dict(
+ region=os.environ.get('OS_REGION_NAME', 'RegionOne')))
+ self.vnf['inputs'].update(dict(
+ keystone_url=self.get_public_auth_url(self.orig_cloud)))
- return True
+ if self.deploy_vnf() and self.test_vnf():
+ self.result = 100
+ return 0
+ self.result = 1/3 * 100
+ return 1
def deploy_vnf(self):
start_time = time.time()
-
self.__logger.info("Upload VNFD")
- cfy_client = self.orchestrator['object']
descriptor = self.vnf['descriptor']
- self.deployment_name = descriptor.get('name')
+ self.util_info["cfy"] = self.cfy_client
+ self.util_info["cfy_manager_ip"] = self.fip.floating_ip_address
+ self.util_info["deployment_name"] = descriptor.get('name')
- cfy_client.blueprints.upload(
+ self.cfy_client.blueprints.upload(
descriptor.get('file_name'), descriptor.get('name'))
self.__logger.info("Create VNF Instance")
- cfy_client.deployments.create(
+ self.cfy_client.deployments.create(
descriptor.get('name'), descriptor.get('name'),
self.vnf.get('inputs'))
- wait_for_execution(
- cfy_client, get_execution_id(cfy_client, descriptor.get('name')),
+ cloudify.wait_for_execution(
+ self.cfy_client, cloudify.get_execution_id(
+ self.cfy_client, descriptor.get('name')),
self.__logger, timeout=7200)
self.__logger.info("Start the VNF Instance deployment")
- execution = cfy_client.executions.start(descriptor.get('name'),
- 'install')
+ execution = self.cfy_client.executions.start(
+ descriptor.get('name'), 'install')
# Show execution log
- execution = wait_for_execution(cfy_client, execution, self.__logger)
+ execution = cloudify.wait_for_execution(
+ self.cfy_client, execution, self.__logger)
duration = time.time() - start_time
@@ -387,7 +212,8 @@ class CloudifyVrouter(vrouter_base.VrouterOnBoardingBase):
def test_vnf(self):
start_time = time.time()
- result, test_result_data = super(CloudifyVrouter, self).test_vnf()
+ testing = vrouter_base.VrouterOnBoardingBase(self.util, self.util_info)
+ result, test_result_data = testing.test_vnf()
duration = time.time() - start_time
if result:
self.details['test_vnf'].update(
@@ -400,91 +226,9 @@ class CloudifyVrouter(vrouter_base.VrouterOnBoardingBase):
return True
def clean(self):
- try:
- cfy_client = self.orchestrator['object']
- dep_name = self.vnf['descriptor'].get('name')
- # kill existing execution
- self.__logger.info('Deleting the current deployment')
- exec_list = cfy_client.executions.list(dep_name)
- for execution in exec_list:
- if execution['status'] == "started":
- try:
- cfy_client.executions.cancel(
- execution['id'], force=True)
- except Exception: # pylint: disable=broad-except
- self.__logger.warn("Can't cancel the current exec")
-
- execution = cfy_client.executions.start(
- dep_name, 'uninstall', parameters=dict(ignore_failure=True))
-
- wait_for_execution(cfy_client, execution, self.__logger)
- cfy_client.deployments.delete(self.vnf['descriptor'].get('name'))
- cfy_client.blueprints.delete(self.vnf['descriptor'].get('name'))
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Some issue during the undeployment ..")
-
- super(CloudifyVrouter, self).clean()
-
- def get_vnf_info_list(self, target_vnf_name):
- return self.util.get_vnf_info_list(
- self.cfy_manager_ip, self.deployment_name, target_vnf_name)
-
-
-def wait_for_execution(client, execution, logger, timeout=7200, ):
- """Wait for a workflow execution on Cloudify Manager."""
- # if execution already ended - return without waiting
- if execution.status in Execution.END_STATES:
- return execution
-
- if timeout is not None:
- deadline = time.time() + timeout
-
- # Poll for execution status and execution logs, until execution ends
- # and we receive an event of type in WORKFLOW_END_TYPES
- offset = 0
- batch_size = 50
- event_list = []
- execution_ended = False
- while True:
- event_list = client.events.list(
- execution_id=execution.id, _offset=offset, _size=batch_size,
- include_logs=True, sort='@timestamp').items
-
- offset = offset + len(event_list)
- for event in event_list:
- logger.debug(event.get('message'))
-
- if timeout is not None:
- if time.time() > deadline:
- raise RuntimeError(
- 'execution of operation {0} for deployment {1} '
- 'timed out'.format(execution.workflow_id,
- execution.deployment_id))
- else:
- # update the remaining timeout
- timeout = deadline - time.time()
-
- if not execution_ended:
- execution = client.executions.get(execution.id)
- execution_ended = execution.status in Execution.END_STATES
-
- if execution_ended:
- break
-
- time.sleep(5)
-
- return execution
-
-
-def get_execution_id(client, deployment_id):
- """
- Get the execution id of a env preparation.
- network, security group, fip, VM creation
- """
- executions = client.executions.list(deployment_id=deployment_id)
- for execution in executions:
- if execution.workflow_id == 'create_deployment_environment':
- return execution
- raise RuntimeError('Failed to get create_deployment_environment '
- 'workflow execution.'
- 'Available executions: {0}'.format(executions))
+ self.kill_existing_execution(self.vnf['descriptor'].get('name'))
+ if self.image_alt:
+ self.cloud.delete_image(self.image_alt)
+ if self.flavor_alt:
+ self.orig_cloud.delete_flavor(self.flavor_alt.id)
+ super().clean()
diff --git a/functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml b/functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml
index 649cd6ccd..2d98dffa5 100644
--- a/functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml
+++ b/functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml
@@ -3,9 +3,6 @@ tenant_images:
cloudify_manager_4.0:
/home/opnfv/functest/images/cloudify-manager-premium-4.0.1.qcow2
vyos1.1.7: /home/opnfv/functest/images/vyos-1.1.7.img
-test_data:
- url: 'https://github.com/oolorg/opnfv-vnf-data.git'
- branch: 'fraser'
orchestrator:
name: cloudify
version: '4.0'
diff --git a/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py b/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py
index be7bee889..9eb3c5d69 100644
--- a/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py
+++ b/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py
@@ -12,6 +12,7 @@
"""vrouter function test execution module"""
import logging
+import os
import time
import yaml
@@ -20,7 +21,7 @@ from functest.opnfv_tests.vnf.router.vnf_controller.vnf_controller import (
VnfController)
-class FunctionTestExec(object):
+class FunctionTestExec():
"""vrouter function test execution class"""
logger = logging.getLogger(__name__)
@@ -31,17 +32,16 @@ class FunctionTestExec(object):
credentials = util_info["credentials"]
self.vnf_ctrl = VnfController(util_info)
- test_cmd_map_file = open(self.util.vnf_data_dir +
- self.util.opnfv_vnf_data_dir +
- self.util.command_template_dir +
- self.util.test_cmd_map_yaml_file,
- 'r')
- self.test_cmd_map_yaml = yaml.safe_load(test_cmd_map_file)
- test_cmd_map_file.close()
+ with open(
+ os.path.join(
+ self.util.vnf_data_dir, self.util.command_template_dir,
+ self.util.test_cmd_map_yaml_file),
+ 'r', encoding='utf-8') as test_cmd_map_file:
+ self.test_cmd_map_yaml = yaml.safe_load(test_cmd_map_file)
- self.util.set_credentials(credentials["snaps_creds"])
+ self.util.set_credentials(credentials["cloud"])
- with open(self.util.test_env_config_yaml) as file_fd:
+ with open(self.util.test_env_config_yaml, encoding='utf-8') as file_fd:
test_env_config_yaml = yaml.safe_load(file_fd)
file_fd.close()
diff --git a/functest/opnfv_tests/vnf/router/utilvnf.py b/functest/opnfv_tests/vnf/router/utilvnf.py
index 31e1b9196..111f20c1a 100644
--- a/functest/opnfv_tests/vnf/router/utilvnf.py
+++ b/functest/opnfv_tests/vnf/router/utilvnf.py
@@ -14,13 +14,9 @@
import json
import logging
import os
-import pkg_resources
import requests
import yaml
-from git import Repo
-from snaps.openstack.utils import nova_utils
-
from functest.utils import config
RESULT_SPRIT_INDEX = {
@@ -47,22 +43,19 @@ NUMBER_OF_DIGITS_FOR_AVG_JITTER = 3
NUMBER_OF_DIGITS_FOR_AVG_PKT_LOSS = 1
-class Utilvnf(object): # pylint: disable=too-many-instance-attributes
+class Utilvnf(): # pylint: disable=too-many-instance-attributes
""" Utility class of vrouter testcase """
logger = logging.getLogger(__name__)
def __init__(self):
- self.snaps_creds = ""
self.vnf_data_dir = getattr(config.CONF, 'dir_router_data')
- self.opnfv_vnf_data_dir = "opnfv-vnf-data/"
self.command_template_dir = "command_template/"
self.test_scenario_yaml = "test_scenario.yaml"
test_env_config_yaml_file = "test_env_config.yaml"
self.test_cmd_map_yaml_file = "test_cmd_map.yaml"
self.test_env_config_yaml = os.path.join(
self.vnf_data_dir,
- self.opnfv_vnf_data_dir,
test_env_config_yaml_file)
self.blueprint_dir = "opnfv-vnf-vyos-blueprint/"
@@ -71,29 +64,7 @@ class Utilvnf(object): # pylint: disable=too-many-instance-attributes
if not os.path.exists(self.vnf_data_dir):
os.makedirs(self.vnf_data_dir)
- case_dir = pkg_resources.resource_filename(
- 'functest', 'opnfv_tests/vnf/router')
-
- config_file_name = getattr(
- config.CONF, 'vnf_{}_config'.format("vyos_vrouter"))
-
- config_file = os.path.join(case_dir, config_file_name)
-
- with open(config_file) as file_fd:
- vrouter_config_yaml = yaml.safe_load(file_fd)
- file_fd.close()
-
- test_data = vrouter_config_yaml.get("test_data")
-
- self.logger.debug("Downloading the test data.")
- vrouter_data_path = self.vnf_data_dir + self.opnfv_vnf_data_dir
-
- if not os.path.exists(vrouter_data_path):
- Repo.clone_from(test_data['url'],
- vrouter_data_path,
- branch=test_data['branch'])
-
- with open(self.test_env_config_yaml) as file_fd:
+ with open(self.test_env_config_yaml, encoding='utf-8') as file_fd:
test_env_config_yaml = yaml.safe_load(file_fd)
file_fd.close()
@@ -107,71 +78,27 @@ class Utilvnf(object): # pylint: disable=too-many-instance-attributes
os.remove(self.test_result_json_file)
self.logger.debug("removed %s", self.test_result_json_file)
- def get_nova_client(self):
- nova_client = nova_utils.nova_client(self.snaps_creds)
-
- return nova_client
+ self.cloud = None
- def set_credentials(self, snaps_creds):
- self.snaps_creds = snaps_creds
+ def set_credentials(self, cloud):
+ self.cloud = cloud
def get_address(self, server_name, network_name):
- nova_client = self.get_nova_client()
- servers_list = nova_client.servers.list()
- server = None
-
- for server in servers_list:
- if server.name == server_name:
- break
-
+ server = self.cloud.get_server(server_name)
address = server.addresses[
network_name][NOVA_CILENT_NETWORK_INFO_INDEX]["addr"]
return address
def get_mac_address(self, server_name, network_name):
- nova_client = self.get_nova_client()
- servers_list = nova_client.servers.list()
- server = None
-
- for server in servers_list:
- if server.name == server_name:
- break
-
+ server = self.cloud.get_server(server_name)
mac_address = server.addresses[network_name][
NOVA_CILENT_NETWORK_INFO_INDEX]["OS-EXT-IPS-MAC:mac_addr"]
return mac_address
- def reboot_vm(self, server_name):
- nova_client = self.get_nova_client()
- servers_list = nova_client.servers.list()
- server = None
-
- for server in servers_list:
- if server.name == server_name:
- break
-
- server.reboot()
-
- return
-
- def delete_vm(self, server_name):
- nova_client = self.get_nova_client()
- servers_list = nova_client.servers.list()
- server = None
-
- for server in servers_list:
- if server.name == server_name:
- nova_client.servers.delete(server)
- break
-
- return
-
def get_blueprint_outputs(self, cfy_manager_ip, deployment_name):
- url = "http://%s/deployments/%s/outputs" % (
- cfy_manager_ip, deployment_name)
-
+ url = f"http://{cfy_manager_ip}/deployments/{deployment_name}/outputs"
response = requests.get(
url,
auth=requests.auth.HTTPBasicAuth('admin', 'admin'),
@@ -200,15 +127,10 @@ class Utilvnf(object): # pylint: disable=too-many-instance-attributes
network_list.append(networks[network_name])
return network_list
- def request_vnf_reboot(self, vnf_info_list):
- for vnf in vnf_info_list:
- self.logger.debug("reboot the %s", vnf["vnf_name"])
- self.reboot_vm(vnf["vnf_name"])
-
def request_vm_delete(self, vnf_info_list):
for vnf in vnf_info_list:
self.logger.debug("delete the %s", vnf["vnf_name"])
- self.delete_vm(vnf["vnf_name"])
+ self.cloud.delete_server(vnf["vnf_name"])
def get_vnf_info_list(self, cfy_manager_ip, topology_deploy_name,
target_vnf_name):
@@ -288,24 +210,29 @@ class Utilvnf(object): # pylint: disable=too-many-instance-attributes
def write_result_data(self, result_data):
test_result = []
if not os.path.isfile(self.test_result_json_file):
- file_fd = open(self.test_result_json_file, "w")
- file_fd.close()
+ with open(
+ self.test_result_json_file, "w",
+ encoding="utf-8") as file_fd:
+ pass
else:
- file_fd = open(self.test_result_json_file, "r")
- test_result = json.load(file_fd)
- file_fd.close()
+ with open(
+ self.test_result_json_file, "r",
+ encoding="utf-8") as file_fd:
+ test_result = json.load(file_fd)
test_result.append(result_data)
- file_fd = open(self.test_result_json_file, "w")
- json.dump(test_result, file_fd)
- file_fd.close()
+ with open(
+ self.test_result_json_file, "w",
+ encoding="utf-8") as file_fd:
+ json.dump(test_result, file_fd)
def output_test_result_json(self):
if os.path.isfile(self.test_result_json_file):
- file_fd = open(self.test_result_json_file, "r")
- test_result = json.load(file_fd)
- file_fd.close()
+ with open(
+ self.test_result_json_file, "r",
+ encoding="utf-8") as file_fd:
+ test_result = json.load(file_fd)
output_json_data = json.dumps(test_result,
sort_keys=True,
indent=4)
@@ -315,8 +242,6 @@ class Utilvnf(object): # pylint: disable=too-many-instance-attributes
@staticmethod
def get_test_scenario(file_path):
- test_scenario_file = open(file_path,
- 'r')
- test_scenario_yaml = yaml.safe_load(test_scenario_file)
- test_scenario_file.close()
+ with open(file_path, "r", encoding="utf-8") as test_scenario_file:
+ test_scenario_yaml = yaml.safe_load(test_scenario_file)
return test_scenario_yaml["test_scenario_list"]
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/checker.py b/functest/opnfv_tests/vnf/router/vnf_controller/checker.py
index a7a70f6d7..d3a216ed0 100644
--- a/functest/opnfv_tests/vnf/router/vnf_controller/checker.py
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/checker.py
@@ -18,7 +18,7 @@ import re
from jinja2 import Environment, FileSystemLoader
-class Checker(object):
+class Checker():
"""vrouter test result check class"""
logger = logging.getLogger(__name__)
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py b/functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py
index 7d9116bcc..a86a16485 100644
--- a/functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py
@@ -15,7 +15,7 @@ import logging
from jinja2 import Environment, FileSystemLoader
-class CommandGenerator(object):
+class CommandGenerator():
"""command generator class for vrouter testing"""
logger = logging.getLogger(__name__)
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py b/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py
index c5f554cbd..269f6526b 100644
--- a/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py
@@ -24,7 +24,7 @@ DEFAULT_CONNECT_RETRY_COUNT = 10
DEFAULT_SEND_TIMEOUT = 10
-class SshClient(object): # pylint: disable=too-many-instance-attributes
+class SshClient(): # pylint: disable=too-many-instance-attributes
"""ssh client class for vrouter testing"""
logger = logging.getLogger(__name__)
@@ -43,7 +43,7 @@ class SshClient(object): # pylint: disable=too-many-instance-attributes
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.util = Utilvnf()
- with open(self.util.test_env_config_yaml) as file_fd:
+ with open(self.util.test_env_config_yaml, encoding='utf-8') as file_fd:
test_env_config_yaml = yaml.safe_load(file_fd)
file_fd.close()
@@ -80,7 +80,7 @@ class SshClient(object): # pylint: disable=too-many-instance-attributes
retrycount -= 1
if retrycount == 0:
- self.logger.warn(
+ self.logger.warning(
"Cannot establish connection to IP '%s'", self.ip_address)
self.connected = False
return self.connected
@@ -110,7 +110,7 @@ class SshClient(object): # pylint: disable=too-many-instance-attributes
cmd)
break
- res_buff += res
+ res_buff += res.decode("utf-8")
self.logger.debug("Response : '%s'", res_buff)
return res_buff
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py b/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py
index 79acc776f..2210b3909 100644
--- a/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py
@@ -23,7 +23,7 @@ from functest.opnfv_tests.vnf.router.vnf_controller.ssh_client import (
SshClient)
-class VmController(object):
+class VmController():
"""vm controll class"""
logger = logging.getLogger(__name__)
@@ -34,14 +34,12 @@ class VmController(object):
credentials = util_info["credentials"]
self.util = Utilvnf()
- self.util.set_credentials(credentials["snaps_creds"])
+ self.util.set_credentials(credentials["cloud"])
- with open(self.util.test_env_config_yaml) as file_fd:
+ with open(self.util.test_env_config_yaml, encoding='utf-8') as file_fd:
test_env_config_yaml = yaml.safe_load(file_fd)
file_fd.close()
- self.reboot_wait = test_env_config_yaml.get("general").get(
- "reboot_wait")
self.command_wait = test_env_config_yaml.get("general").get(
"command_wait")
self.ssh_connect_timeout = test_env_config_yaml.get("general").get(
@@ -85,16 +83,10 @@ class VmController(object):
result = ssh.connect(self.ssh_connect_timeout,
self.ssh_connect_retry_count)
if not result:
- self.logger.warn("Reboot %s", vm_info["vnf_name"])
- self.util.reboot_vm(vm_info["vnf_name"])
- time.sleep(self.reboot_wait)
- result = ssh.connect(self.ssh_connect_timeout,
- self.ssh_connect_retry_count)
- if not result:
- self.logger.error(
- "Cannot establish connection to IP '%s'. Aborting!",
- ssh.ip_address)
- return None
+ self.logger.error(
+ "Cannot establish connection to IP '%s'. Aborting!",
+ ssh.ip_address)
+ return None
(result, _) = self.command_create_and_execute(
ssh,
@@ -109,10 +101,8 @@ class VmController(object):
def command_create_and_execute(self, ssh, test_cmd_file_path,
cmd_input_param, prompt_file_path):
- prompt_file = open(prompt_file_path,
- 'r')
- prompt = yaml.safe_load(prompt_file)
- prompt_file.close()
+ with open(prompt_file_path, 'r', encoding='utf-8') as prompt_file:
+ prompt = yaml.safe_load(prompt_file)
config_mode_prompt = prompt["config_mode"]
commands = self.command_gen_from_template(test_cmd_file_path,
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py b/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py
index a5b1ad856..46584456f 100644
--- a/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py
@@ -26,7 +26,7 @@ from functest.opnfv_tests.vnf.router.vnf_controller.vm_controller import (
VmController)
-class VnfController(object):
+class VnfController():
"""vrouter controll class"""
logger = logging.getLogger(__name__)
@@ -36,7 +36,7 @@ class VnfController(object):
self.util = Utilvnf()
self.vm_controller = VmController(util_info)
- with open(self.util.test_env_config_yaml) as file_fd:
+ with open(self.util.test_env_config_yaml, encoding='utf-8') as file_fd:
test_env_config_yaml = yaml.safe_load(file_fd)
file_fd.close()
@@ -49,10 +49,9 @@ class VnfController(object):
def config_vnf(self, source_vnf, destination_vnf, test_cmd_file_path,
parameter_file_path, prompt_file_path):
# pylint: disable=too-many-arguments
- parameter_file = open(parameter_file_path,
- 'r')
- cmd_input_param = yaml.safe_load(parameter_file)
- parameter_file.close()
+ with open(
+ parameter_file_path, 'r', encoding='utf-8') as parameter_file:
+ cmd_input_param = yaml.safe_load(parameter_file)
cmd_input_param["macaddress"] = source_vnf["data_plane_network_mac"]
cmd_input_param["source_ip"] = source_vnf["data_plane_network_ip"]
@@ -71,19 +70,16 @@ class VnfController(object):
res_dict_data_list = []
- parameter_file = open(parameter_file_path,
- 'r')
- cmd_input_param = yaml.safe_load(parameter_file)
- parameter_file.close()
+ with open(
+ parameter_file_path, 'r', encoding='utf-8') as parameter_file:
+ cmd_input_param = yaml.safe_load(parameter_file)
cmd_input_param["source_ip"] = target_vnf["data_plane_network_ip"]
cmd_input_param["destination_ip"] = reference_vnf[
"data_plane_network_ip"]
- prompt_file = open(prompt_file_path,
- 'r')
- prompt = yaml.safe_load(prompt_file)
- prompt_file.close()
+ with open(prompt_file_path, 'r', encoding='utf-8') as prompt_file:
+ prompt = yaml.safe_load(prompt_file)
terminal_mode_prompt = prompt["terminal_mode"]
ssh = SshClient(target_vnf["floating_ip"],
diff --git a/functest/opnfv_tests/vnf/router/vrouter_base.py b/functest/opnfv_tests/vnf/router/vrouter_base.py
index 6c4e5ce0d..932770b9c 100644
--- a/functest/opnfv_tests/vnf/router/vrouter_base.py
+++ b/functest/opnfv_tests/vnf/router/vrouter_base.py
@@ -19,37 +19,22 @@ import time
import pkg_resources
-import functest.core.vnf as vnf
-from functest.utils import config
from functest.opnfv_tests.vnf.router.test_controller import function_test_exec
-from functest.opnfv_tests.vnf.router.utilvnf import Utilvnf
__author__ = "Shuya Nakama <shuya.nakama@okinawaopenlabs.org>"
-REBOOT_WAIT = 30
-
-class VrouterOnBoardingBase(vnf.VnfOnBoarding):
+class VrouterOnBoardingBase():
"""vrouter testing base class"""
- def __init__(self, **kwargs):
+ def __init__(self, util, util_info):
self.logger = logging.getLogger(__name__)
- super(VrouterOnBoardingBase, self).__init__(**kwargs)
self.case_dir = pkg_resources.resource_filename(
'functest', 'opnfv_tests/vnf/router')
- self.data_dir = getattr(config.CONF, 'dir_router_data')
- self.result_dir = os.path.join(getattr(config.CONF, 'dir_results'),
- self.case_name)
- self.util = Utilvnf()
- self.util_info = {}
-
+ self.util = util
+ self.util_info = util_info
self.vnf_list = []
- if not os.path.exists(self.data_dir):
- os.makedirs(self.data_dir)
- if not os.path.exists(self.result_dir):
- os.makedirs(self.result_dir)
-
def test_vnf(self):
"""vrouter test execution"""
result = False
@@ -89,10 +74,6 @@ class VrouterOnBoardingBase(vnf.VnfOnBoarding):
vnf_info_list = self.get_vnf_info_list(target_vnf_name)
self.vnf_list = vnf_info_list
- self.logger.debug("request vnf's reboot.")
- self.util.request_vnf_reboot(vnf_info_list)
- time.sleep(REBOOT_WAIT)
-
target_vnf = self.util.get_target_vnf(vnf_info_list)
reference_vnf_list = self.util.get_reference_vnf_list(vnf_info_list)
@@ -117,6 +98,7 @@ class VrouterOnBoardingBase(vnf.VnfOnBoarding):
return result, test_result_data
def get_vnf_info_list(self, target_vnf_name):
- # pylint: disable=unused-argument,no-self-use
- vnf_info_list = []
- return vnf_info_list
+ return self.util.get_vnf_info_list(
+ self.util_info["cfy_manager_ip"],
+ self.util_info["deployment_name"],
+ target_vnf_name)
diff --git a/functest/tests/unit/ci/__init__.py b/functest/tests/unit/ci/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/functest/tests/unit/ci/__init__.py
+++ /dev/null
diff --git a/functest/tests/unit/ci/test_check_deployment.py b/functest/tests/unit/ci/test_check_deployment.py
deleted file mode 100644
index aeeca5871..000000000
--- a/functest/tests/unit/ci/test_check_deployment.py
+++ /dev/null
@@ -1,286 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 Ericsson and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-# pylint: disable=missing-docstring
-
-import socket
-import unittest
-
-import logging
-import mock
-
-from functest.ci import check_deployment
-
-__author__ = "Jose Lausuch <jose.lausuch@ericsson.com>"
-
-
-class CheckDeploymentTesting(unittest.TestCase):
- """The super class which testing classes could inherit."""
- # pylint: disable=missing-docstring,too-many-public-methods
-
- logging.disable(logging.CRITICAL)
-
- def setUp(self):
- self.client_test = mock.Mock()
- self.deployment = check_deployment.CheckDeployment()
- self.service_test = 'compute'
- self.rc_file = self.deployment.rc_file
- self.endpoint_test = 'http://192.168.0.6:5000/v3'
- creds_attr = {'auth_url': self.endpoint_test,
- 'proxy_settings': ''}
- proxy_attr = {'host': '192.168.0.1', 'port': '5000'}
- proxy_settings = mock.Mock()
- proxy_settings.configure_mock(**proxy_attr)
- self.os_creds = mock.Mock()
- self.os_creds.configure_mock(**creds_attr)
- self.os_creds.proxy_settings = proxy_settings
- self.deployment.os_creds = self.os_creds
-
- @mock.patch('socket.socket.connect', side_effect=TypeError)
- def test_verify_connectivity_ko1(self, *args):
- self.assertFalse(check_deployment.verify_connectivity("127.0.0.1"))
- args[0].assert_called_once_with((None, 80))
-
- @mock.patch('socket.socket.connect', side_effect=socket.error)
- def test_verify_connectivity_ko2(self, *args):
- self.assertFalse(
- check_deployment.verify_connectivity("http://127.0.0.1"))
- args[0].assert_called_once_with(("127.0.0.1", 80))
-
- @mock.patch('socket.socket.connect', side_effect=socket.error)
- def test_verify_connectivity_ko3(self, *args):
- self.assertFalse(
- check_deployment.verify_connectivity("https://127.0.0.1"))
- args[0].assert_called_once_with(("127.0.0.1", 443))
-
- @mock.patch('socket.socket.connect')
- def test_verify_connectivity(self, *args):
- self.assertTrue(
- check_deployment.verify_connectivity("https://127.0.0.1"))
- args[0].assert_called_once_with(("127.0.0.1", 443))
-
- @mock.patch('snaps.openstack.utils.keystone_utils.keystone_session',
- return_value=mock.Mock(
- get_token=mock.Mock(side_effect=Exception)))
- def test_get_auth_token_ko(self, *args):
- with self.assertRaises(Exception):
- check_deployment.get_auth_token(self.os_creds)
- args[0].assert_called_once_with(self.os_creds)
-
- @mock.patch('snaps.openstack.utils.keystone_utils.keystone_session',
- return_value=mock.Mock(
- get_token=mock.Mock(return_value="foo")))
- def test_get_auth_token(self, *args):
- self.assertEqual(check_deployment.get_auth_token(self.os_creds), "foo")
- args[0].assert_called_once_with(self.os_creds)
-
- @mock.patch('six.moves.builtins.open',
- mock.mock_open(read_data='OS_AUTH_URL'))
- @mock.patch('functest.ci.check_deployment.os.path.isfile', returns=True)
- def test_check_rc(self, *args):
- self.deployment.check_rc()
- args[0].assert_called_once_with(self.rc_file)
-
- @mock.patch('functest.ci.check_deployment.os.path.isfile',
- return_value=False)
- def test_check_rc_missing_file(self, *args):
- with self.assertRaises(Exception) as context:
- self.deployment.check_rc()
- args[0].assert_called_once_with(self.rc_file)
- msg = 'RC file {} does not exist!'.format(self.rc_file)
- self.assertTrue(msg in str(context.exception))
-
- @mock.patch('six.moves.builtins.open',
- mock.mock_open(read_data='test'))
- @mock.patch('functest.ci.check_deployment.os.path.isfile',
- return_value=True)
- def test_check_rc_missing_os_auth(self, *args):
- with self.assertRaises(Exception) as context:
- self.deployment.check_rc()
- args[0].assert_called_once_with(self.rc_file)
- msg = 'OS_AUTH_URL not defined in {}.'.format(self.rc_file)
- self.assertTrue(msg in str(context.exception))
-
- @mock.patch('functest.ci.check_deployment.get_auth_token',
- return_value='gAAAAABaOhXGS')
- @mock.patch('functest.ci.check_deployment.verify_connectivity',
- return_value=True)
- def test_check_auth_endpoint(self, *args):
- self.deployment.check_auth_endpoint()
- args[0].assert_called_once_with(self.endpoint_test)
- args[1].assert_called_once_with(mock.ANY)
-
- @mock.patch('functest.ci.check_deployment.verify_connectivity',
- return_value=False)
- def test_check_auth_endpoint_ko(self, *args):
- with self.assertRaises(Exception) as context:
- self.deployment.check_auth_endpoint()
- msg = "OS_AUTH_URL {} is not reachable.".format(self.os_creds.auth_url)
- args[0].assert_called_once_with(self.os_creds.auth_url)
- self.assertTrue(msg in str(context.exception))
-
- @mock.patch('functest.ci.check_deployment.verify_connectivity',
- return_value=True)
- @mock.patch('functest.ci.check_deployment.keystone_utils.get_endpoint')
- def test_check_public_endpoint(self, *args):
- args[0].return_value = self.endpoint_test
- self.deployment.check_public_endpoint()
- args[0].assert_called_once_with(
- mock.ANY, 'identity', interface='public')
- args[1].assert_called_once_with(self.endpoint_test)
-
- @mock.patch('functest.ci.check_deployment.verify_connectivity',
- return_value=False)
- @mock.patch('functest.ci.check_deployment.keystone_utils.get_endpoint')
- def test_check_public_endpoint_ko(self, *args):
- args[0].return_value = self.endpoint_test
- with self.assertRaises(Exception) as context:
- self.deployment.check_public_endpoint()
- args[0].assert_called_once_with(
- mock.ANY, 'identity', interface='public')
- args[1].assert_called_once_with(self.endpoint_test)
- msg = "Public endpoint {} is not reachable.".format(self.endpoint_test)
- self.assertTrue(msg in str(context.exception))
-
- @mock.patch('functest.ci.check_deployment.verify_connectivity',
- return_value=True)
- @mock.patch('functest.ci.check_deployment.keystone_utils.get_endpoint')
- def test_check_service_endpoint(self, *args):
- self.deployment.check_service_endpoint(self.service_test)
- args[0].assert_called_once_with(
- mock.ANY, self.service_test, interface='public')
- args[1].assert_called_once_with(args[0].return_value)
-
- @mock.patch('functest.ci.check_deployment.verify_connectivity',
- return_value=False)
- @mock.patch('functest.ci.check_deployment.keystone_utils.get_endpoint')
- def test_check_service_endpoint_ko(self, *args):
- args[0].return_value = self.endpoint_test
- with self.assertRaises(Exception) as context:
- self.deployment.check_service_endpoint(self.service_test)
- msg = "{} endpoint {} is not reachable.".format(
- self.service_test, self.endpoint_test)
- self.assertTrue(msg in str(context.exception))
- args[0].assert_called_once_with(
- mock.ANY, self.service_test, interface='public')
- args[1].assert_called_once_with(args[0].return_value)
-
- @mock.patch('functest.ci.check_deployment.nova_utils.nova_client')
- def test_check_nova(self, mock_method):
- self.deployment.check_nova()
- mock_method.assert_called_once_with(mock.ANY)
-
- @mock.patch('functest.ci.check_deployment.nova_utils.nova_client',
- return_value=mock.Mock(
- servers=mock.Mock(list=mock.Mock(side_effect=Exception))))
- def test_check_nova_fail(self, mock_method):
- with self.assertRaises(Exception):
- self.deployment.check_nova()
- mock_method.assert_called_once_with(mock.ANY)
-
- @mock.patch('functest.ci.check_deployment.neutron_utils.neutron_client')
- def test_check_neutron(self, mock_method):
- self.deployment.check_neutron()
- mock_method.assert_called_once_with(mock.ANY)
-
- @mock.patch('functest.ci.check_deployment.neutron_utils.neutron_client',
- return_value=mock.Mock(
- list_networks=mock.Mock(side_effect=Exception)))
- def test_check_neutron_fail(self, mock_method):
- with self.assertRaises(Exception):
- self.deployment.check_neutron()
- mock_method.assert_called_once_with(mock.ANY)
-
- @mock.patch('functest.ci.check_deployment.glance_utils.glance_client')
- def test_check_glance(self, mock_method):
- self.deployment.check_glance()
- mock_method.assert_called_once_with(mock.ANY)
-
- @mock.patch('functest.ci.check_deployment.glance_utils.glance_client',
- return_value=mock.Mock(
- images=mock.Mock(list=mock.Mock(side_effect=Exception))))
- def test_check_glance_fail(self, mock_method):
- with self.assertRaises(Exception):
- self.deployment.check_glance()
- mock_method.assert_called_once_with(mock.ANY)
-
- @mock.patch('functest.ci.check_deployment.LOGGER.info')
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.'
- 'get_ext_net_name', return_value='ext-net')
- def test_check_extnet(self, *args):
- self.deployment.check_ext_net()
- args[0].assert_called_once_with(mock.ANY)
- args[1].assert_called_once_with(
- "External network found: %s", "ext-net")
-
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.'
- 'get_ext_net_name', return_value='')
- def test_check_extnet_none(self, mock_getext):
- with self.assertRaises(Exception) as context:
- self.deployment.check_ext_net()
- self.assertTrue(mock_getext.called)
- msg = 'ERROR: No external networks in the deployment.'
- self.assertTrue(msg in str(context.exception))
-
- @mock.patch('functest.ci.check_deployment.CheckDeployment.check_rc',
- side_effect=Exception)
- def test_check_all_exc1(self, *args):
- with self.assertRaises(Exception):
- self.deployment.check_all()
- args[0].assert_called_once_with()
-
- @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials',
- side_effect=Exception)
- @mock.patch('functest.ci.check_deployment.CheckDeployment.check_rc')
- def test_check_all_exc2(self, *args):
- with self.assertRaises(Exception):
- self.deployment.check_all()
- args[0].assert_called_once_with()
- args[1].assert_called_once_with(
- os_env_file=self.rc_file, proxy_settings_str=None,
- ssh_proxy_cmd=None)
-
- @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials',
- return_value=None)
- @mock.patch('functest.ci.check_deployment.CheckDeployment.check_rc')
- def test_check_all_exc3(self, *args):
- with self.assertRaises(Exception):
- self.deployment.check_all()
- args[0].assert_called_once_with()
- args[1].assert_called_once_with(
- os_env_file=self.rc_file, proxy_settings_str=None,
- ssh_proxy_cmd=None)
-
- @mock.patch('functest.ci.check_deployment.CheckDeployment.check_ext_net')
- @mock.patch('functest.ci.check_deployment.CheckDeployment.check_glance')
- @mock.patch('functest.ci.check_deployment.CheckDeployment.check_neutron')
- @mock.patch('functest.ci.check_deployment.CheckDeployment.check_nova')
- @mock.patch(
- 'functest.ci.check_deployment.CheckDeployment.check_service_endpoint')
- @mock.patch(
- 'functest.ci.check_deployment.CheckDeployment.check_public_endpoint')
- @mock.patch(
- 'functest.ci.check_deployment.CheckDeployment.check_auth_endpoint')
- @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials')
- @mock.patch('functest.ci.check_deployment.CheckDeployment.check_rc')
- def test_check_all(self, *args):
- self.assertEqual(self.deployment.check_all(), 0)
- for i in [0, 2, 3, 5, 6, 7, 8]:
- args[i].assert_called_once_with()
- args[1].assert_called_once_with(
- os_env_file=self.rc_file, proxy_settings_str=None,
- ssh_proxy_cmd=None)
- calls = [mock.call('compute'), mock.call('network'),
- mock.call('image')]
- args[4].assert_has_calls(calls)
-
-
-if __name__ == "__main__":
- logging.disable(logging.CRITICAL)
- unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_vnf.py b/functest/tests/unit/core/test_vnf.py
deleted file mode 100644
index 81d9eef76..000000000
--- a/functest/tests/unit/core/test_vnf.py
+++ /dev/null
@@ -1,196 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2016 Orange and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-# pylint: disable=missing-docstring
-
-import logging
-import unittest
-
-import mock
-from snaps.openstack.os_credentials import OSCreds
-from xtesting.core import testcase
-
-from functest.core import vnf
-from functest.utils import constants
-
-
-class VnfBaseTesting(unittest.TestCase):
- """The class testing VNF."""
- # pylint: disable=missing-docstring,too-many-public-methods
-
- tenant_name = 'test_tenant_name'
- tenant_description = 'description'
-
- def setUp(self):
- self.test = vnf.VnfOnBoarding(project='functest', case_name='foo')
-
- def test_run_deploy_orch_exc(self):
- with mock.patch.object(self.test, 'prepare'), \
- mock.patch.object(self.test, 'deploy_orchestrator',
- side_effect=Exception) as mock_method, \
- mock.patch.object(self.test, 'deploy_vnf',
- return_value=True), \
- mock.patch.object(self.test, 'test_vnf',
- return_value=True):
- self.assertEqual(self.test.run(),
- testcase.TestCase.EX_TESTCASE_FAILED)
- mock_method.assert_called_with()
-
- def test_run_deploy_vnf_exc(self):
- with mock.patch.object(self.test, 'prepare'),\
- mock.patch.object(self.test, 'deploy_orchestrator',
- return_value=True), \
- mock.patch.object(self.test, 'deploy_vnf',
- side_effect=Exception) as mock_method:
- self.assertEqual(self.test.run(),
- testcase.TestCase.EX_TESTCASE_FAILED)
- mock_method.assert_called_with()
-
- def test_run_test_vnf_exc(self):
- with mock.patch.object(self.test, 'prepare'),\
- mock.patch.object(self.test, 'deploy_orchestrator',
- return_value=True), \
- mock.patch.object(self.test, 'deploy_vnf', return_value=True), \
- mock.patch.object(self.test, 'test_vnf',
- side_effect=Exception) as mock_method:
- self.assertEqual(self.test.run(),
- testcase.TestCase.EX_TESTCASE_FAILED)
- mock_method.assert_called_with()
-
- def test_run_deploy_orch_ko(self):
- with mock.patch.object(self.test, 'prepare'),\
- mock.patch.object(self.test, 'deploy_orchestrator',
- return_value=False), \
- mock.patch.object(self.test, 'deploy_vnf',
- return_value=True), \
- mock.patch.object(self.test, 'test_vnf',
- return_value=True):
- self.assertEqual(self.test.run(),
- testcase.TestCase.EX_TESTCASE_FAILED)
-
- def test_run_vnf_deploy_ko(self):
- with mock.patch.object(self.test, 'prepare'),\
- mock.patch.object(self.test, 'deploy_orchestrator',
- return_value=True), \
- mock.patch.object(self.test, 'deploy_vnf',
- return_value=False), \
- mock.patch.object(self.test, 'test_vnf',
- return_value=True):
- self.assertEqual(self.test.run(),
- testcase.TestCase.EX_TESTCASE_FAILED)
-
- def test_run_vnf_test_ko(self):
- with mock.patch.object(self.test, 'prepare'),\
- mock.patch.object(self.test, 'deploy_orchestrator',
- return_value=True), \
- mock.patch.object(self.test, 'deploy_vnf',
- return_value=True), \
- mock.patch.object(self.test, 'test_vnf',
- return_value=False):
- self.assertEqual(self.test.run(),
- testcase.TestCase.EX_TESTCASE_FAILED)
-
- def test_run_default(self):
- with mock.patch.object(self.test, 'prepare'),\
- mock.patch.object(self.test, 'deploy_orchestrator',
- return_value=True), \
- mock.patch.object(self.test, 'deploy_vnf',
- return_value=True), \
- mock.patch.object(self.test, 'test_vnf',
- return_value=True):
- self.assertEqual(self.test.run(), testcase.TestCase.EX_OK)
-
- @mock.patch('functest.core.vnf.OpenStackUser')
- @mock.patch('functest.core.vnf.OpenStackProject')
- @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials',
- side_effect=Exception)
- def test_prepare_exc1(self, *args):
- with self.assertRaises(Exception):
- self.test.prepare()
- args[0].assert_called_with(os_env_file=constants.ENV_FILE)
- args[1].assert_not_called()
- args[2].assert_not_called()
-
- @mock.patch('functest.core.vnf.OpenStackUser')
- @mock.patch('functest.core.vnf.OpenStackProject', side_effect=Exception)
- @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials')
- def test_prepare_exc2(self, *args):
- with self.assertRaises(Exception):
- self.test.prepare()
- args[0].assert_called_with(os_env_file=constants.ENV_FILE)
- args[1].assert_called_with(mock.ANY, mock.ANY)
- args[2].assert_not_called()
-
- @mock.patch('functest.core.vnf.OpenStackUser', side_effect=Exception)
- @mock.patch('snaps.openstack.utils.keystone_utils.get_role_by_name',
- return_value="admin")
- @mock.patch('snaps.openstack.utils.keystone_utils.keystone_client')
- @mock.patch('functest.core.vnf.OpenStackProject')
- @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials')
- def test_prepare_exc3(self, *args):
- with self.assertRaises(Exception):
- self.test.prepare()
- args[0].assert_called_with(os_env_file=constants.ENV_FILE)
- args[1].assert_called_with(mock.ANY, mock.ANY)
- args[2].assert_called_with(mock.ANY)
- args[3].assert_called_with(mock.ANY, mock.ANY)
- args[4].assert_called_with(mock.ANY, mock.ANY)
-
- @mock.patch('functest.core.vnf.OpenStackUser')
- @mock.patch('snaps.openstack.utils.keystone_utils.get_role_by_name',
- return_value="admin")
- @mock.patch('snaps.openstack.utils.keystone_utils.keystone_client')
- @mock.patch('functest.core.vnf.OpenStackProject')
- @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials')
- def test_prepare_default(self, *args):
- self.assertEqual(self.test.prepare(), testcase.TestCase.EX_OK)
- args[0].assert_called_with(os_env_file=constants.ENV_FILE)
- args[1].assert_called_with(mock.ANY, mock.ANY)
- args[2].assert_called_with(mock.ANY)
- args[3].assert_called_with(mock.ANY, mock.ANY)
- args[4].assert_called_with(mock.ANY, mock.ANY)
-
- def test_deploy_vnf_unimplemented(self):
- with self.assertRaises(vnf.VnfDeploymentException):
- self.test.deploy_vnf()
-
- def test_test_vnf_unimplemented(self):
- with self.assertRaises(vnf.VnfTestException):
- self.test.test_vnf()
-
- def test_deploy_orch_unimplemented(self):
- self.assertTrue(self.test.deploy_orchestrator())
-
- @mock.patch('snaps.openstack.tests.openstack_tests.get_credentials',
- return_value=OSCreds(
- username='user', password='pass',
- auth_url='http://foo.com:5000/v3', project_name='bar'),
- side_effect=Exception)
- def test_prepare_keystone_client_ko(self, *args):
- with self.assertRaises(vnf.VnfPreparationException):
- self.test.prepare()
- args[0].assert_called_once()
-
- def test_vnf_clean_exc(self):
- obj = mock.Mock()
- obj.clean.side_effect = Exception
- self.test.created_object = [obj]
- self.test.clean()
- obj.clean.assert_called_with()
-
- def test_vnf_clean(self):
- obj = mock.Mock()
- self.test.created_object = [obj]
- self.test.clean()
- obj.clean.assert_called_with()
-
-
-if __name__ == "__main__":
- logging.disable(logging.CRITICAL)
- unittest.main(verbosity=2)
diff --git a/functest/tests/unit/odl/test_odl.py b/functest/tests/unit/odl/test_odl.py
index 58a699f0b..c675c2988 100644
--- a/functest/tests/unit/odl/test_odl.py
+++ b/functest/tests/unit/odl/test_odl.py
@@ -33,10 +33,10 @@ class ODLTesting(unittest.TestCase):
logging.disable(logging.CRITICAL)
_keystone_ip = "127.0.0.1"
- _neutron_url = u"https://127.0.0.1:9696"
- _neutron_id = u"dummy"
+ _neutron_url = "https://127.0.0.1:9696"
+ _neutron_id = "dummy"
_sdn_controller_ip = "127.0.0.3"
- _os_auth_url = "http://{}:5000/v3".format(_keystone_ip)
+ _os_auth_url = f"http://{_keystone_ip}:5000/v3"
_os_projectname = "admin"
_os_username = "admin"
_os_password = "admin"
@@ -49,7 +49,7 @@ class ODLTesting(unittest.TestCase):
_os_interface = "public"
def setUp(self):
- for var in ("INSTALLER_TYPE", "SDN_CONTROLLER", "SDN_CONTROLLER_IP"):
+ for var in ("SDN_CONTROLLER", "SDN_CONTROLLER_IP"):
if var in os.environ:
del os.environ[var]
os.environ["OS_AUTH_URL"] = self._os_auth_url
@@ -63,8 +63,7 @@ class ODLTesting(unittest.TestCase):
self.test = odl.ODLTests(case_name='odl', project_name='functest')
self.defaultargs = {'odlusername': self._odl_username,
'odlpassword': self._odl_password,
- 'neutronurl': "http://{}:9696".format(
- self._keystone_ip),
+ 'neutronurl': f"http://{self._keystone_ip}:9696",
'osauthurl': self._os_auth_url,
'osusername': self._os_username,
'osuserdomainname': self._os_userdomainname,
@@ -105,7 +104,7 @@ class ODLRobotTesting(ODLTesting):
mock_method.assert_called_once_with(
os.path.join(odl.ODLTests.odl_test_repo,
'csit/variables/Variables.robot'), inplace=True)
- self.assertEqual(args[0].getvalue(), "{}\n".format(msg2))
+ self.assertEqual(args[0].getvalue(), f"{msg2}\n")
def test_set_vars_auth_default(self):
self._test_set_vars(
@@ -160,19 +159,19 @@ class ODLMainTesting(ODLTesting):
args[0].assert_called_once_with(self.test.odl_variables_file)
if len(args) > 1:
variable = [
- 'KEYSTONEURL:{}://{}'.format(
- urllib.parse.urlparse(self._os_auth_url).scheme,
- urllib.parse.urlparse(self._os_auth_url).netloc),
- 'NEUTRONURL:{}'.format(self._neutron_url),
- 'OS_AUTH_URL:"{}"'.format(self._os_auth_url),
- 'OSUSERNAME:"{}"'.format(self._os_username),
- 'OSUSERDOMAINNAME:"{}"'.format(self._os_userdomainname),
- 'OSTENANTNAME:"{}"'.format(self._os_projectname),
- 'OSPROJECTDOMAINNAME:"{}"'.format(self._os_projectdomainname),
- 'OSPASSWORD:"{}"'.format(self._os_password),
- 'ODL_SYSTEM_IP:{}'.format(self._sdn_controller_ip),
- 'PORT:{}'.format(self._odl_webport),
- 'RESTCONFPORT:{}'.format(self._odl_restconfport)]
+ ('KEYSTONEURL:'
+ f'{urllib.parse.urlparse(self._os_auth_url).scheme}://'
+ f'{urllib.parse.urlparse(self._os_auth_url).netloc}'),
+ f'NEUTRONURL:{self._neutron_url}',
+ f'OS_AUTH_URL:"{self._os_auth_url}"',
+ f'OSUSERNAME:"{self._os_username}"',
+ f'OSUSERDOMAINNAME:"{self._os_userdomainname}"',
+ f'OSTENANTNAME:"{self._os_projectname}"',
+ f'OSPROJECTDOMAINNAME:"{self._os_projectdomainname}"',
+ f'OSPASSWORD:"{self._os_password}"',
+ f'ODL_SYSTEM_IP:{self._sdn_controller_ip}',
+ f'PORT:{self._odl_webport}',
+ f'RESTCONFPORT:{self._odl_restconfport}']
args[1].assert_called_once_with(
odl.ODLTests.basic_suite_dir, odl.ODLTests.neutron_suite_dir,
include=[],
@@ -247,10 +246,34 @@ class ODLMainTesting(ODLTesting):
@mock.patch('os.makedirs')
@mock.patch('robot.run')
@mock.patch('os.path.isfile', return_value=True)
+ def test_generate_report_ko(self, *args):
+ with mock.patch.object(self.test, 'set_robotframework_vars',
+ return_value=True), \
+ mock.patch.object(self.test, 'parse_results'), \
+ mock.patch.object(self.test, 'generate_report',
+ return_value=1):
+ self._test_run_suites(testcase.TestCase.EX_OK, *args)
+
+ @mock.patch('os.makedirs')
+ @mock.patch('robot.run')
+ @mock.patch('os.path.isfile', return_value=True)
+ def test_generate_report_exc(self, *args):
+ with mock.patch.object(self.test, 'set_robotframework_vars',
+ return_value=True), \
+ mock.patch.object(self.test, 'parse_results'), \
+ mock.patch.object(self.test, 'generate_report',
+ side_effect=Exception):
+ self._test_run_suites(testcase.TestCase.EX_RUN_ERROR, *args)
+
+ @mock.patch('os.makedirs')
+ @mock.patch('robot.run')
+ @mock.patch('os.path.isfile', return_value=True)
def test_ok(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(self.test, 'parse_results'):
+ mock.patch.object(self.test, 'parse_results'), \
+ mock.patch.object(self.test, 'generate_report',
+ return_value=0):
self._test_run_suites(testcase.TestCase.EX_OK, *args)
@mock.patch('os.makedirs')
@@ -259,7 +282,9 @@ class ODLMainTesting(ODLTesting):
def test_ok_no_creds(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True) as mock_method, \
- mock.patch.object(self.test, 'parse_results'):
+ mock.patch.object(self.test, 'parse_results'), \
+ mock.patch.object(self.test, 'generate_report',
+ return_value=0):
self._test_run_suites(testcase.TestCase.EX_OK, *args)
mock_method.assert_not_called()
@@ -269,7 +294,9 @@ class ODLMainTesting(ODLTesting):
def test_testcases_in_failure(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(self.test, 'parse_results'):
+ mock.patch.object(self.test, 'parse_results'), \
+ mock.patch.object(self.test, 'generate_report',
+ return_value=0):
self._test_run_suites(testcase.TestCase.EX_OK, *args)
@@ -505,58 +532,6 @@ class ODLRunTesting(ODLTesting):
odlip=self._sdn_controller_ip,
odlwebport=self._odl_webport)
- def test_fuel_no_controller_ip(self):
- os.environ["INSTALLER_TYPE"] = "fuel"
- self._test_missing_value()
-
- def test_fuel(self):
- os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
- os.environ["INSTALLER_TYPE"] = "fuel"
- self._test_run(testcase.TestCase.EX_OK, None,
- odlip=self._sdn_controller_ip,
- odlwebport='8282',
- odlrestconfport='8282')
-
- def test_apex_no_controller_ip(self):
- os.environ["INSTALLER_TYPE"] = "apex"
- self._test_missing_value()
-
- def test_apex(self):
- os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
- os.environ["INSTALLER_TYPE"] = "apex"
- self._test_run(testcase.TestCase.EX_OK, None,
- odlip=self._sdn_controller_ip, odlwebport='8081',
- odlrestconfport='8081')
-
- def test_netvirt_no_controller_ip(self):
- os.environ["INSTALLER_TYPE"] = "netvirt"
- self._test_missing_value()
-
- def test_netvirt(self):
- os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
- os.environ["INSTALLER_TYPE"] = "netvirt"
- self._test_run(testcase.TestCase.EX_OK, None,
- odlip=self._sdn_controller_ip, odlwebport='8081',
- odlrestconfport='8081')
-
- def test_compass(self):
- os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
- os.environ["INSTALLER_TYPE"] = "compass"
- self._test_run(testcase.TestCase.EX_OK, None,
- odlip=self._sdn_controller_ip,
- odlrestconfport='8080')
-
- def test_daisy_no_controller_ip(self):
- os.environ["INSTALLER_TYPE"] = "daisy"
- self._test_missing_value()
-
- def test_daisy(self):
- os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
- os.environ["INSTALLER_TYPE"] = "daisy"
- self._test_run(testcase.TestCase.EX_OK, None,
- odlip=self._sdn_controller_ip, odlwebport='8181',
- odlrestconfport='8087')
-
class ODLArgParserTesting(ODLTesting):
@@ -565,7 +540,7 @@ class ODLArgParserTesting(ODLTesting):
def setUp(self):
self.parser = odl.ODLParser()
- super(ODLArgParserTesting, self).setUp()
+ super().setUp()
def test_default(self):
self.assertEqual(self.parser.parse_args(), self.defaultargs)
@@ -575,8 +550,8 @@ class ODLArgParserTesting(ODLTesting):
self.defaultargs['odlip'] = self._sdn_controller_ip
self.assertEqual(
self.parser.parse_args(
- ["--neutronurl={}".format(self._neutron_url),
- "--odlip={}".format(self._sdn_controller_ip)]),
+ [f"--neutronurl={self._neutron_url}",
+ f"--odlip={self._sdn_controller_ip}"]),
self.defaultargs)
@mock.patch('sys.stderr', new_callable=six.StringIO)
@@ -589,7 +564,7 @@ class ODLArgParserTesting(ODLTesting):
def _test_arg(self, arg, value):
self.defaultargs[arg] = value
self.assertEqual(
- self.parser.parse_args(["--{}={}".format(arg, value)]),
+ self.parser.parse_args([f"--{arg}={value}"]),
self.defaultargs)
def test_odlusername(self):
@@ -630,7 +605,7 @@ class ODLArgParserTesting(ODLTesting):
def test_pushtodb(self):
self.defaultargs['pushtodb'] = True
- self.assertEqual(self.parser.parse_args(["--{}".format('pushtodb')]),
+ self.assertEqual(self.parser.parse_args(["--pushtodb"]),
self.defaultargs)
def test_multiple_args(self):
@@ -638,8 +613,8 @@ class ODLArgParserTesting(ODLTesting):
self.defaultargs['odlip'] = self._sdn_controller_ip
self.assertEqual(
self.parser.parse_args(
- ["--neutronurl={}".format(self._neutron_url),
- "--odlip={}".format(self._sdn_controller_ip)]),
+ [f"--neutronurl={self._neutron_url}",
+ f"--odlip={self._sdn_controller_ip}"]),
self.defaultargs)
diff --git a/functest/opnfv_tests/openstack/snaps/__init__.py b/functest/tests/unit/openstack/cinder/__init__.py
index e69de29bb..e69de29bb 100644
--- a/functest/opnfv_tests/openstack/snaps/__init__.py
+++ b/functest/tests/unit/openstack/cinder/__init__.py
diff --git a/functest/tests/unit/openstack/cinder/test_cinder.py b/functest/tests/unit/openstack/cinder/test_cinder.py
new file mode 100644
index 000000000..d3c9cabb6
--- /dev/null
+++ b/functest/tests/unit/openstack/cinder/test_cinder.py
@@ -0,0 +1,270 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2018 Enea AB and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+
+import logging
+import unittest
+
+import pkg_resources
+import mock
+import munch
+import shade
+
+from functest.opnfv_tests.openstack.cinder import cinder_test
+from functest.utils import config
+from functest.utils import env
+
+
+class CinderTesting(unittest.TestCase):
+
+ def setUp(self):
+ with mock.patch('functest.core.singlevm.SingleVm2.__init__'):
+ self.cinder = cinder_test.CinderCheck()
+ self.cinder.cloud = mock.Mock()
+ self.cinder.case_name = 'cinder'
+ self.cinder.guid = '1'
+
+ @mock.patch('functest.opnfv_tests.openstack.cinder.cinder_test.'
+ 'CinderCheck.connect')
+ @mock.patch('functest.core.singlevm.SingleVm2.prepare',
+ side_effect=Exception)
+ def test_prepare_exc1(self, *args):
+ self.cinder.cloud.boot_vm = mock.Mock()
+ with self.assertRaises(Exception):
+ self.cinder.prepare()
+ args[0].assert_called_once_with()
+ args[1].assert_not_called()
+ self.cinder.cloud.boot_vm.assert_not_called()
+ self.cinder.cloud.create_volume.assert_not_called()
+
+ @mock.patch('functest.opnfv_tests.openstack.cinder.cinder_test.'
+ 'CinderCheck.connect')
+ @mock.patch('functest.opnfv_tests.openstack.cinder.cinder_test.'
+ 'CinderCheck.boot_vm',
+ side_effect=Exception)
+ @mock.patch('functest.core.singlevm.SingleVm2.prepare')
+ def test_prepare_exc2(self, *args):
+ self.cinder.sec = munch.Munch(id='foo')
+ self.cinder.keypair = munch.Munch(id='foo')
+ self.cinder.volume_timeout = munch.Munch(id='foo')
+ with self.assertRaises(Exception):
+ self.cinder.prepare()
+ args[0].assert_called_with()
+ args[1].assert_called_once_with(
+ f'{self.cinder.case_name}-vm2_{self.cinder.guid}',
+ security_groups=[self.cinder.sec.id],
+ key_name=self.cinder.keypair.id)
+ self.cinder.cloud.create_volume.assert_not_called()
+ args[2].assert_not_called()
+
+ @mock.patch('functest.opnfv_tests.openstack.cinder.cinder_test.'
+ 'CinderCheck.boot_vm', return_value=munch.Munch(id='vm2'))
+ @mock.patch('functest.core.singlevm.SingleVm2.prepare')
+ def test_prepare(self, *args):
+ self.cinder.sec = munch.Munch(id='foo')
+ self.cinder.keypair = munch.Munch(id='foo')
+ self.cinder.ext_net = mock.Mock(id='foo')
+ self.cinder.ssh2 = mock.Mock()
+ self.cinder.fip2 = munch.Munch(id='fip2')
+ self.cinder.connect = mock.Mock(
+ return_value=(self.cinder.fip2, self.cinder.ssh2))
+ self.cinder.cloud.create_volume = mock.Mock(
+ return_value=munch.Munch())
+ self.cinder.prepare()
+ args[0].assert_called_once_with()
+ args[1].assert_called_once_with(
+ f'{self.cinder.case_name}-vm2_{self.cinder.guid}',
+ security_groups=[self.cinder.sec.id],
+ key_name=self.cinder.keypair.id)
+ self.cinder.connect.assert_called_once_with(args[1].return_value)
+ self.cinder.cloud.create_volume.assert_called_once_with(
+ name=f'{self.cinder.case_name}-volume_{self.cinder.guid}',
+ size='2', timeout=self.cinder.volume_timeout, wait=True)
+
+ @mock.patch('scp.SCPClient.put')
+ def test_write(self, *args):
+ # pylint: disable=protected-access
+ self.cinder.ssh = mock.Mock()
+ self.cinder.sshvm = mock.Mock(id='foo')
+ self.cinder.volume = mock.Mock(id='volume')
+ stdout = mock.Mock()
+ stdout.channel.recv_exit_status.return_value = 0
+ self.cinder.ssh.exec_command.return_value = (None, stdout, mock.Mock())
+ self.assertEqual(self.cinder._write_data(), 0)
+ self.cinder.ssh.exec_command.assert_called_once_with(
+ f"sh ~/write_data.sh {env.get('VOLUME_DEVICE_NAME')}")
+ self.cinder.cloud.attach_volume.assert_called_once_with(
+ self.cinder.sshvm, self.cinder.volume,
+ timeout=self.cinder.volume_timeout)
+ self.cinder.cloud.detach_volume.assert_called_once_with(
+ self.cinder.sshvm, self.cinder.volume,
+ timeout=self.cinder.volume_timeout)
+ args[0].assert_called_once_with(
+ pkg_resources.resource_filename(
+ 'functest.opnfv_tests.openstack.cinder', 'write_data.sh'),
+ remote_path="~/")
+
+ @mock.patch('scp.SCPClient.put', side_effect=Exception)
+ def test_write_exc1(self, *args):
+ # pylint: disable=protected-access
+ self.cinder.ssh = mock.Mock()
+ self.cinder.sshvm = mock.Mock(id='foo')
+ self.cinder.cloud.attach_volume = mock.Mock()
+ self.assertEqual(
+ self.cinder._write_data(), self.cinder.EX_RUN_ERROR)
+ args[0].assert_called_once_with(
+ pkg_resources.resource_filename(
+ 'functest.opnfv_tests.openstack.cinder', 'write_data.sh'),
+ remote_path="~/")
+
+ @mock.patch('scp.SCPClient.put')
+ def test_read(self, *args):
+ # pylint: disable=protected-access
+ self.cinder.ssh2 = mock.Mock()
+ self.cinder.vm2 = mock.Mock(id='foo')
+ self.cinder.volume = mock.Mock(id='volume')
+ stdout = mock.Mock()
+ self.cinder.ssh2.exec_command.return_value = (
+ None, stdout, mock.Mock())
+ stdout.channel.recv_exit_status.return_value = 0
+ self.assertEqual(self.cinder._read_data(), 0)
+ self.cinder.ssh2.exec_command.assert_called_once_with(
+ f"sh ~/read_data.sh {env.get('VOLUME_DEVICE_NAME')}")
+ self.cinder.cloud.attach_volume.assert_called_once_with(
+ self.cinder.vm2, self.cinder.volume,
+ timeout=self.cinder.volume_timeout)
+ self.cinder.cloud.detach_volume.assert_called_once_with(
+ self.cinder.vm2, self.cinder.volume,
+ timeout=self.cinder.volume_timeout)
+ args[0].assert_called_once_with(
+ pkg_resources.resource_filename(
+ 'functest.opnfv_tests.openstack.cinder', 'read_data.sh'),
+ remote_path="~/")
+
+ @mock.patch('scp.SCPClient.put', side_effect=Exception)
+ def test_read_exc1(self, *args):
+ # pylint: disable=protected-access
+ self.cinder.ssh = mock.Mock()
+ self.cinder.ssh2 = mock.Mock()
+ self.cinder.sshvm = mock.Mock(id='foo')
+ self.cinder.cloud.attach_volume = mock.Mock()
+ self.assertEqual(
+ self.cinder._read_data(), self.cinder.EX_RUN_ERROR)
+ args[0].assert_called_once_with(
+ pkg_resources.resource_filename(
+ 'functest.opnfv_tests.openstack.cinder', 'read_data.sh'),
+ remote_path="~/")
+
+ def test_execute_exc1(self):
+ # pylint: disable=protected-access
+ self.cinder._write_data = mock.Mock(side_effect=Exception)
+ self.cinder._read_data = mock.Mock()
+ with self.assertRaises(Exception):
+ self.cinder.execute()
+ self.cinder._write_data.assert_called_once_with()
+ self.cinder._read_data.assert_not_called()
+
+ def test_execute_exc2(self):
+ # pylint: disable=protected-access
+ self.cinder._write_data = mock.Mock(return_value=0)
+ self.cinder._read_data = mock.Mock(side_effect=Exception)
+ with self.assertRaises(Exception):
+ self.cinder.execute()
+ self.cinder._write_data.assert_called_once_with()
+ self.cinder._read_data.assert_called_once_with()
+
+ def test_execute_res1(self):
+ # pylint: disable=protected-access
+ self.cinder._write_data = mock.Mock(return_value=1)
+ self.cinder._read_data = mock.Mock()
+ self.assertEqual(self.cinder.execute(), 1)
+ self.cinder._write_data.assert_called_once_with()
+ self.cinder._read_data.assert_not_called()
+
+ def test_execute_res2(self):
+ # pylint: disable=protected-access
+ self.cinder._write_data = mock.Mock(return_value=0)
+ self.cinder._read_data = mock.Mock(return_value=1)
+ self.assertEqual(self.cinder.execute(), 1)
+ self.cinder._write_data.assert_called_once_with()
+ self.cinder._read_data.assert_called_once_with()
+
+ def test_execute_res3(self):
+ # pylint: disable=protected-access
+ self.cinder._write_data = mock.Mock(return_value=0)
+ self.cinder._read_data = mock.Mock(return_value=0)
+ self.assertEqual(self.cinder.execute(), 0)
+ self.cinder._write_data.assert_called_once_with()
+ self.cinder._read_data.assert_called_once_with()
+
+ def test_clean_exc1(self):
+ self.cinder.cloud = None
+ with self.assertRaises(AssertionError):
+ self.cinder.clean()
+
+ @mock.patch('functest.core.singlevm.SingleVm2.clean')
+ def test_clean_exc2(self, *args):
+ self.cinder.vm2 = munch.Munch(id='vm2')
+ self.cinder.cloud.delete_server = mock.Mock(
+ side_effect=shade.OpenStackCloudException("Foo"))
+ with self.assertRaises(shade.OpenStackCloudException):
+ self.cinder.clean()
+ self.cinder.cloud.delete_server.assert_called_once_with(
+ self.cinder.vm2, wait=True,
+ timeout=getattr(config.CONF, 'vping_vm_delete_timeout'))
+ self.cinder.cloud.delete_floating_ip.assert_not_called()
+ self.cinder.cloud.delete_volume.assert_not_called()
+ args[0].assert_not_called()
+
+ @mock.patch('functest.core.singlevm.SingleVm2.clean',
+ side_effect=Exception)
+ def test_clean_exc3(self, mock_clean):
+ self.cinder.vm2 = munch.Munch(id='vm2')
+ self.cinder.volume = munch.Munch(id='volume')
+ self.cinder.fip2 = munch.Munch(id='fip2')
+ with self.assertRaises(Exception):
+ self.cinder.clean()
+ self.cinder.cloud.delete_server.assert_called_once_with(
+ self.cinder.vm2, wait=True,
+ timeout=getattr(config.CONF, 'vping_vm_delete_timeout'))
+ self.cinder.cloud.delete_floating_ip.assert_called_once_with(
+ self.cinder.fip2.id)
+ self.cinder.cloud.delete_volume.assert_called_once_with(
+ self.cinder.volume.id)
+ mock_clean.prepare()
+
+ @mock.patch('functest.core.singlevm.SingleVm2.clean')
+ def test_clean(self, *args):
+ self.cinder.vm2 = munch.Munch(id='vm2')
+ self.cinder.volume = munch.Munch(id='volume')
+ self.cinder.fip2 = munch.Munch(id='fip2')
+ self.cinder.clean()
+ self.cinder.cloud.delete_server.assert_called_once_with(
+ self.cinder.vm2, wait=True,
+ timeout=getattr(config.CONF, 'vping_vm_delete_timeout'))
+ self.cinder.cloud.delete_floating_ip.assert_called_once_with(
+ self.cinder.fip2.id)
+ self.cinder.cloud.delete_volume.assert_called_once_with(
+ self.cinder.volume.id)
+ args[0].assert_called_once_with()
+
+ @mock.patch('functest.core.singlevm.SingleVm2.clean')
+ def test_clean2(self, *args):
+ self.cinder.clean()
+ self.cinder.cloud.delete_server.assert_not_called()
+ self.cinder.cloud.delete_floating_ip.assert_not_called()
+ self.cinder.cloud.delete_volume.assert_not_called()
+ args[0].assert_called_once_with()
+
+
+if __name__ == '__main__':
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/functest/tests/unit/openstack/rally/test_rally.py b/functest/tests/unit/openstack/rally/test_rally.py
index 28f6055bd..f3c2e7cf6 100644
--- a/functest/tests/unit/openstack/rally/test_rally.py
+++ b/functest/tests/unit/openstack/rally/test_rally.py
@@ -10,6 +10,7 @@
import json
import logging
import os
+import subprocess
import unittest
import mock
@@ -17,35 +18,39 @@ import munch
from xtesting.core import testcase
from functest.opnfv_tests.openstack.rally import rally
+from functest.utils import config
class OSRallyTesting(unittest.TestCase):
# pylint: disable=too-many-public-methods
def setUp(self):
with mock.patch('os_client_config.get_config') as mock_get_config, \
- mock.patch('shade.OpenStackCloud') as mock_shade:
+ mock.patch('shade.OpenStackCloud') as mock_shade, \
+ mock.patch('functest.core.tenantnetwork.NewProject') \
+ as mock_new_project:
self.rally_base = rally.RallyBase()
self.rally_base.image = munch.Munch(name='foo')
self.rally_base.flavor = munch.Munch(name='foo')
self.rally_base.flavor_alt = munch.Munch(name='bar')
self.assertTrue(mock_get_config.called)
self.assertTrue(mock_shade.called)
+ self.assertTrue(mock_new_project.called)
def test_build_task_args_missing_floating_network(self):
os.environ['OS_AUTH_URL'] = ''
self.rally_base.ext_net = None
- task_args = self.rally_base._build_task_args('test_file_name')
+ task_args = self.rally_base.build_task_args('test_name')
self.assertEqual(task_args['floating_network'], '')
def test_build_task_args_missing_net_id(self):
os.environ['OS_AUTH_URL'] = ''
self.rally_base.network = None
- task_args = self.rally_base._build_task_args('test_file_name')
+ task_args = self.rally_base.build_task_args('test_name')
self.assertEqual(task_args['netid'], '')
@staticmethod
def check_scenario_file(value):
- yaml_file = 'opnfv-{}.yaml'.format('test_file_name')
+ yaml_file = 'opnfv-test_file_name.yaml'
if yaml_file in value:
return False
return True
@@ -59,36 +64,58 @@ class OSRallyTesting(unittest.TestCase):
@staticmethod
def check_temp_dir(value):
- yaml_file = 'opnfv-{}.yaml'.format('test_file_name')
+ yaml_file = 'opnfv-test_file_name.yaml'
if yaml_file in value:
return True
return False
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.'
+ 'RallyBase.get_verifier_deployment_id', return_value='foo')
+ @mock.patch('subprocess.check_output')
+ def test_create_rally_deployment(self, mock_exec, mock_get_id):
+ # pylint: disable=unused-argument
+ self.assertEqual(rally.RallyBase.create_rally_deployment(), 'foo')
+ calls = [
+ mock.call(['rally', 'deployment', 'destroy', '--deployment',
+ str(getattr(config.CONF, 'rally_deployment_name'))]),
+ mock.call().decode("utf-8"),
+ mock.call(['rally', 'deployment', 'create', '--fromenv', '--name',
+ str(getattr(config.CONF, 'rally_deployment_name'))],
+ env=None),
+ mock.call().decode("utf-8"),
+ mock.call(['rally', 'deployment', 'check']),
+ mock.call().decode("utf-8")]
+ mock_exec.assert_has_calls(calls)
+
@mock.patch('functest.opnfv_tests.openstack.rally.rally.os.path.exists')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.os.makedirs')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- '_apply_blacklist')
+ 'apply_blacklist')
def test_prepare_test_list_missing_temp_dir(
self, mock_method, mock_os_makedirs, mock_path_exists):
mock_path_exists.side_effect = self.check_temp_dir
- yaml_file = 'opnfv-{}.yaml'.format('test_file_name')
- ret_val = os.path.join(self.rally_base.TEMP_DIR, yaml_file)
+ yaml_file = 'opnfv-test_file_name.yaml'
+ ret_val = os.path.join(self.rally_base.temp_dir, yaml_file)
self.assertEqual(self.rally_base._prepare_test_list('test_file_name'),
ret_val)
mock_path_exists.assert_called()
mock_method.assert_called()
mock_os_makedirs.assert_called()
- def test_get_task_id_default(self):
- cmd_raw = 'Task 1: started'
- self.assertEqual(self.rally_base.get_task_id(cmd_raw),
- '1')
+ @mock.patch('subprocess.check_output', return_value=b'1\n')
+ def test_get_task_id_default(self, *args):
+ tag = 'nova'
+ self.assertEqual(self.rally_base.get_task_id(tag), '1')
+ args[0].assert_called_with(
+ ['rally', 'task', 'list', '--tag', tag, '--uuids-only'])
- def test_get_task_id_missing_id(self):
- cmd_raw = ''
- self.assertEqual(self.rally_base.get_task_id(cmd_raw),
- None)
+ @mock.patch('subprocess.check_output', return_value=b'\n')
+ def test_get_task_id_missing_id(self, *args):
+ tag = 'nova'
+ self.assertEqual(self.rally_base.get_task_id(tag), '')
+ args[0].assert_called_with(
+ ['rally', 'task', 'list', '--tag', tag, '--uuids-only'])
def test_task_succeed_fail(self):
json_raw = json.dumps({})
@@ -104,20 +131,12 @@ class OSRallyTesting(unittest.TestCase):
self.assertEqual(self.rally_base.task_succeed(json_raw),
True)
- def test_get_cmd_output(self):
- proc = mock.Mock()
- proc.stdout.__iter__ = mock.Mock(return_value=iter(['line1', 'line2']))
- self.assertEqual(self.rally_base.get_cmd_output(proc),
- 'line1line2')
-
@mock.patch('six.moves.builtins.open', mock.mock_open())
@mock.patch('functest.opnfv_tests.openstack.rally.rally.yaml.safe_load',
return_value={'scenario': [
{'scenarios': ['test_scenario'],
- 'installers': ['test_installer'],
'tests': ['test']},
{'scenarios': ['other_scenario'],
- 'installers': ['test_installer'],
'tests': ['other_test']}]})
def test_excl_scenario_default(self, mock_func):
os.environ['INSTALLER_TYPE'] = 'test_installer'
@@ -129,25 +148,18 @@ class OSRallyTesting(unittest.TestCase):
@mock.patch('functest.opnfv_tests.openstack.rally.rally.yaml.safe_load',
return_value={'scenario': [
{'scenarios': ['^os-[^-]+-featT-modeT$'],
- 'installers': ['test_installer'],
'tests': ['test1']},
{'scenarios': ['^os-ctrlT-[^-]+-modeT$'],
- 'installers': ['test_installer'],
'tests': ['test2']},
{'scenarios': ['^os-ctrlT-featT-[^-]+$'],
- 'installers': ['test_installer'],
'tests': ['test3']},
{'scenarios': ['^os-'],
- 'installers': ['test_installer'],
'tests': ['test4']},
{'scenarios': ['other_scenario'],
- 'installers': ['test_installer'],
'tests': ['test0a']},
{'scenarios': [''], # empty scenario
- 'installers': ['test_installer'],
'tests': ['test0b']}]})
def test_excl_scenario_regex(self, mock_func):
- os.environ['INSTALLER_TYPE'] = 'test_installer'
os.environ['DEPLOY_SCENARIO'] = 'os-ctrlT-featT-modeT'
self.assertEqual(self.rally_base.excl_scenario(),
['test1', 'test2', 'test3', 'test4'])
@@ -164,11 +176,13 @@ class OSRallyTesting(unittest.TestCase):
{'functions': ['no_migration'], 'tests': ['test']}]})
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'_migration_supported', return_value=False)
- def test_excl_func_default(self, mock_func, mock_yaml_load):
- os.environ['INSTALLER_TYPE'] = 'test_installer'
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
+ '_network_trunk_supported', return_value=False)
+ def test_excl_func_default(self, mock_trunk, mock_func, mock_yaml_load):
os.environ['DEPLOY_SCENARIO'] = 'test_scenario'
self.assertEqual(self.rally_base.excl_func(), ['test'])
mock_func.assert_called()
+ mock_trunk.assert_called()
mock_yaml_load.assert_called()
@mock.patch('six.moves.builtins.open', side_effect=Exception)
@@ -194,36 +208,30 @@ class OSRallyTesting(unittest.TestCase):
return_value=False)
def test_run_task_missing_task_file(self, mock_path_exists):
with self.assertRaises(Exception):
- self.rally_base._run_task('test_name')
+ self.rally_base.prepare_run()
mock_path_exists.assert_called()
- @mock.patch('functest.opnfv_tests.openstack.rally.rally.os.path.exists',
- return_value=True)
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'_prepare_test_list', return_value='test_file_name')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'file_is_empty', return_value=True)
@mock.patch('functest.opnfv_tests.openstack.rally.rally.LOGGER.info')
- def test_run_task_no_tests_for_scenario(self, mock_logger_info,
- mock_file_empty, mock_prep_list,
- mock_path_exists):
- self.rally_base._run_task('test_name')
+ def test_prepare_task_no_tests_for_scenario(
+ self, mock_logger_info, mock_file_empty, mock_prep_list):
+ self.rally_base.prepare_task('test_name')
mock_logger_info.assert_any_call('No tests for scenario \"%s\"',
'test_name')
mock_file_empty.assert_called()
mock_prep_list.assert_called()
- mock_path_exists.assert_called()
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'_prepare_test_list', return_value='test_file_name')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'file_is_empty', return_value=False)
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- '_build_task_args', return_value={})
+ 'build_task_args', return_value={})
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'get_task_id', return_value=None)
- @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- 'get_cmd_output', return_value='')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.os.path.exists',
return_value=True)
@mock.patch('functest.opnfv_tests.openstack.rally.rally.subprocess.Popen')
@@ -231,8 +239,8 @@ class OSRallyTesting(unittest.TestCase):
def test_run_task_taskid_missing(self, mock_logger_error, *args):
# pylint: disable=unused-argument
with self.assertRaises(Exception):
- self.rally_base._run_task('test_name')
- text = 'Failed to retrieve task_id, validating task...'
+ self.rally_base.run_task('test_name')
+ text = 'Failed to retrieve task_id'
mock_logger_error.assert_any_call(text)
@mock.patch('six.moves.builtins.open', mock.mock_open())
@@ -241,12 +249,10 @@ class OSRallyTesting(unittest.TestCase):
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'file_is_empty', return_value=False)
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- '_build_task_args', return_value={})
+ 'build_task_args', return_value={})
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'get_task_id', return_value='1')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- 'get_cmd_output', return_value='')
- @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'task_succeed', return_value=True)
@mock.patch('functest.opnfv_tests.openstack.rally.rally.os.path.exists',
return_value=True)
@@ -258,17 +264,15 @@ class OSRallyTesting(unittest.TestCase):
'_save_results')
def test_run_task_default(self, mock_save_res, *args):
# pylint: disable=unused-argument
- self.rally_base._run_task('test_name')
+ self.rally_base.run_task('test_name')
mock_save_res.assert_called()
@mock.patch('six.moves.builtins.open', mock.mock_open())
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'task_succeed', return_value=True)
- @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- 'get_cmd_output', return_value='')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.os.path.exists',
return_value=True)
- @mock.patch('functest.opnfv_tests.openstack.rally.rally.subprocess.Popen')
+ @mock.patch('subprocess.check_output')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.os.makedirs')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.LOGGER.info')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.LOGGER.debug')
@@ -279,92 +283,126 @@ class OSRallyTesting(unittest.TestCase):
self.rally_base._save_results('test_name', '1234')
mock_summary.assert_called()
- def test_prepare_env_testname_invalid(self):
- self.rally_base.TESTS = ['test1', 'test2']
- self.rally_base.test_name = 'test'
+ def test_prepare_run_testname_invalid(self):
+ self.rally_base.stests = ['test1', 'test2']
with self.assertRaises(Exception):
- self.rally_base._prepare_env()
+ self.rally_base.prepare_run(tests=['test'])
- @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- 'get_external_network')
- def test_prepare_env_flavor_alt_creation_failed(self, *args):
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.os.path.exists')
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.shutil.copyfile')
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.shutil.copytree')
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.shutil.rmtree')
+ def test_prepare_run_flavor_alt_creation_failed(self, *args):
# pylint: disable=unused-argument
- self.rally_base.TESTS = ['test1', 'test2']
- self.rally_base.test_name = 'test1'
- with mock.patch.object(self.rally_base.cloud,
- 'list_hypervisors') as mock_list_hyperv, \
- mock.patch.object(self.rally_base.cloud,
- 'set_flavor_specs') as mock_set_flavor_specs, \
- mock.patch.object(self.rally_base.cloud, 'create_flavor',
+ self.rally_base.stests = ['test1', 'test2']
+ with mock.patch.object(self.rally_base, 'count_hypervisors') \
+ as mock_list_hyperv, \
+ mock.patch.object(self.rally_base, 'create_flavor_alt',
side_effect=Exception) \
as mock_create_flavor:
with self.assertRaises(Exception):
- self.rally_base._prepare_env()
+ self.rally_base.prepare_run(tests=['test1'])
mock_list_hyperv.assert_called_once()
mock_create_flavor.assert_called_once()
- mock_set_flavor_specs.assert_not_called()
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- '_run_task')
- def test_run_tests_all(self, mock_run_task):
- self.rally_base.TESTS = ['test1', 'test2']
- self.rally_base.test_name = 'all'
- self.rally_base._run_tests()
+ 'prepare_task', return_value=True)
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
+ 'run_task')
+ def test_run_tests_all(self, mock_run_task, mock_prepare_task):
+ self.rally_base.tests = ['test1', 'test2']
+ self.rally_base.run_tests()
+ mock_prepare_task.assert_any_call('test1')
+ mock_prepare_task.assert_any_call('test2')
mock_run_task.assert_any_call('test1')
mock_run_task.assert_any_call('test2')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- '_run_task')
- def test_run_tests_default(self, mock_run_task):
- self.rally_base.TESTS = ['test1', 'test2']
- self.rally_base.test_name = 'test1'
- self.rally_base._run_tests()
+ 'prepare_task', return_value=True)
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
+ 'run_task')
+ def test_run_tests_default(self, mock_run_task, mock_prepare_task):
+ self.rally_base.tests = ['test1', 'test2']
+ self.rally_base.run_tests()
+ mock_prepare_task.assert_any_call('test1')
+ mock_prepare_task.assert_any_call('test2')
mock_run_task.assert_any_call('test1')
+ mock_run_task.assert_any_call('test2')
- def test_clean_up_default(self):
- with mock.patch.object(self.rally_base.cloud,
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
+ 'clean_rally_logs')
+ def test_clean_up_default(self, *args):
+ with mock.patch.object(self.rally_base.orig_cloud,
'delete_flavor') as mock_delete_flavor:
self.rally_base.flavor_alt = mock.Mock()
self.rally_base.clean()
self.assertEqual(mock_delete_flavor.call_count, 1)
+ args[0].assert_called_once_with()
- @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
+ 'update_rally_logs')
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'create_rally_deployment')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- '_prepare_env')
+ 'prepare_run')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- '_run_tests')
+ 'run_tests')
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'_generate_report')
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
+ 'export_task')
def test_run_default(self, *args):
self.assertEqual(self.rally_base.run(), testcase.TestCase.EX_OK)
for func in args:
func.assert_called()
- @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
+ 'update_rally_logs')
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'create_rally_deployment', side_effect=Exception)
- def test_run_exception_create_rally_dep(self, mock_create_rally_dep):
+ def test_run_exception_create_rally_dep(self, *args):
self.assertEqual(self.rally_base.run(), testcase.TestCase.EX_RUN_ERROR)
- mock_create_rally_dep.assert_called()
+ args[0].assert_called()
+ args[1].assert_called_once_with(self.rally_base.res_dir)
- @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
+ 'update_rally_logs')
+ @mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
'create_rally_deployment', return_value=mock.Mock())
@mock.patch('functest.opnfv_tests.openstack.rally.rally.RallyBase.'
- '_prepare_env', side_effect=Exception)
- def test_run_exception_prepare_env(self, mock_prep_env, *args):
+ 'prepare_run', side_effect=Exception)
+ def test_run_exception_prepare_run(self, mock_prep_env, *args):
# pylint: disable=unused-argument
self.assertEqual(self.rally_base.run(), testcase.TestCase.EX_RUN_ERROR)
mock_prep_env.assert_called()
+ args[1].assert_called_once_with(self.rally_base.res_dir)
def test_append_summary(self):
- text = '{"tasks": [{"subtasks": [{"workloads": [{"full_duration": ' \
- '1.23,"data": [{"error": []}]}]},{"workloads": ' \
- '[{"full_duration": 2.78, "data": [{"error": ["err"]}]}]}]}]}'
- self.rally_base._append_summary(text, "foo_test")
+ json_dict = {
+ 'tasks': [{
+ 'subtasks': [{
+ 'title': 'sub_task',
+ 'workloads': [{
+ 'full_duration': 1.23,
+ 'data': [{
+ 'error': []
+ }]
+ }, {
+ 'full_duration': 2.78,
+ 'data': [{
+ 'error': ['err']
+ }]
+ }]
+ }]
+ }]
+ }
+ self.rally_base._append_summary(json.dumps(json_dict), "foo_test")
self.assertEqual(self.rally_base.summary[0]['test_name'], "foo_test")
self.assertEqual(self.rally_base.summary[0]['overall_duration'], 4.01)
self.assertEqual(self.rally_base.summary[0]['nb_tests'], 2)
self.assertEqual(self.rally_base.summary[0]['nb_success'], 1)
+ self.assertEqual(self.rally_base.summary[0]['success'], [])
+ self.assertEqual(self.rally_base.summary[0]['failures'], ['sub_task'])
def test_is_successful_false(self):
with mock.patch('six.moves.builtins.super') as mock_super:
@@ -382,6 +420,48 @@ class OSRallyTesting(unittest.TestCase):
self.assertEqual(self.rally_base.is_successful(), 424)
mock_super(rally.RallyBase, self).is_successful.assert_called()
+ @mock.patch('subprocess.check_output',
+ side_effect=subprocess.CalledProcessError('', ''))
+ def test_export_task_ko(self, *args):
+ file_name = (f"{self.rally_base.results_dir}/"
+ f"{self.rally_base.case_name}.html")
+ with self.assertRaises(subprocess.CalledProcessError):
+ self.rally_base.export_task(file_name)
+ cmd = ["rally", "task", "export", "--type", "html", "--deployment",
+ str(getattr(config.CONF, 'rally_deployment_name')),
+ "--to", file_name]
+ args[0].assert_called_with(cmd, stderr=subprocess.STDOUT)
+
+ @mock.patch('subprocess.check_output', return_value=b'')
+ def test_export_task(self, *args):
+ file_name = (f"{self.rally_base.results_dir}/"
+ f"{self.rally_base.case_name}.html")
+ self.assertEqual(self.rally_base.export_task(file_name), None)
+ cmd = ["rally", "task", "export", "--type", "html", "--deployment",
+ str(getattr(config.CONF, 'rally_deployment_name')),
+ "--to", file_name]
+ args[0].assert_called_with(cmd, stderr=subprocess.STDOUT)
+
+ @mock.patch('subprocess.check_output',
+ side_effect=subprocess.CalledProcessError('', ''))
+ def test_verify_report_ko(self, *args):
+ file_name = (f"{self.rally_base.results_dir}/"
+ f"{self.rally_base.case_name}.html")
+ with self.assertRaises(subprocess.CalledProcessError):
+ self.rally_base.verify_report(file_name, "1")
+ cmd = ["rally", "verify", "report", "--type", "html", "--uuid", "1",
+ "--to", file_name]
+ args[0].assert_called_with(cmd, stderr=subprocess.STDOUT)
+
+ @mock.patch('subprocess.check_output', return_value=b'')
+ def test_verify_report(self, *args):
+ file_name = (f"{self.rally_base.results_dir}/"
+ f"{self.rally_base.case_name}.html")
+ self.assertEqual(self.rally_base.verify_report(file_name, "1"), None)
+ cmd = ["rally", "verify", "report", "--type", "html", "--uuid", "1",
+ "--to", file_name]
+ args[0].assert_called_with(cmd, stderr=subprocess.STDOUT)
+
if __name__ == "__main__":
logging.disable(logging.CRITICAL)
diff --git a/functest/tests/unit/openstack/snaps/__init__.py b/functest/tests/unit/openstack/snaps/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/functest/tests/unit/openstack/snaps/__init__.py
+++ /dev/null
diff --git a/functest/tests/unit/openstack/snaps/test_snaps.py b/functest/tests/unit/openstack/snaps/test_snaps.py
deleted file mode 100644
index a3760445f..000000000
--- a/functest/tests/unit/openstack/snaps/test_snaps.py
+++ /dev/null
@@ -1,233 +0,0 @@
-# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-
-# pylint: disable=missing-docstring
-
-import logging
-import unittest
-
-import mock
-from snaps.openstack.os_credentials import OSCreds
-from xtesting.core import testcase
-
-from functest.opnfv_tests.openstack.snaps import api_check
-from functest.opnfv_tests.openstack.snaps import health_check
-from functest.opnfv_tests.openstack.snaps import smoke
-
-
-class APICheckTesting(unittest.TestCase):
- """
- Ensures the VPingUserdata class can run in Functest. This test does not
- actually connect with an OpenStack pod.
- """
-
- def setUp(self):
- self.os_creds = OSCreds(
- username='user', password='pass',
- auth_url='http://foo.com:5000/v3', project_name='bar')
-
- self.api_check = api_check.ApiCheck(
- os_creds=self.os_creds, ext_net_name='foo')
-
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_client_tests')
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_api_tests')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_success(self, *args):
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = []
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.api_check.run())
- self.assertEquals(
- testcase.TestCase.EX_OK, self.api_check.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- ext_net_name='foo', image_metadata=mock.ANY,
- os_creds=self.os_creds, suite=mock.ANY, use_keystone=True)
-
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_client_tests')
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_api_tests')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_1_of_100_ko(self, *args):
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = ['foo']
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.api_check.run())
- self.assertEquals(
- testcase.TestCase.EX_TESTCASE_FAILED,
- self.api_check.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- ext_net_name='foo', image_metadata=mock.ANY,
- os_creds=self.os_creds, suite=mock.ANY, use_keystone=True)
-
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_client_tests')
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_api_tests')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_1_of_100_ko_criteria(self, *args):
- self.api_check.criteria = 90
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = ['foo']
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.api_check.run())
- self.assertEquals(
- testcase.TestCase.EX_OK, self.api_check.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- ext_net_name='foo', image_metadata=mock.ANY,
- os_creds=self.os_creds, suite=mock.ANY, use_keystone=True)
-
-
-class HealthCheckTesting(unittest.TestCase):
- """
- Ensures the VPingUserdata class can run in Functest. This test does not
- actually connect with an OpenStack pod.
- """
-
- def setUp(self):
- self.os_creds = OSCreds(
- username='user', password='pass',
- auth_url='http://foo.com:5000/v3', project_name='bar')
-
- self.health_check = health_check.HealthCheck(
- os_creds=self.os_creds, ext_net_name='foo')
-
- @mock.patch('snaps.openstack.tests.os_source_file_test.'
- 'OSIntegrationTestCase.parameterize')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_success(self, *args):
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = []
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.health_check.run())
- self.assertEquals(
- testcase.TestCase.EX_OK, self.health_check.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- mock.ANY, ext_net_name='foo', flavor_metadata=mock.ANY,
- image_metadata=mock.ANY, netconf_override=None,
- os_creds=self.os_creds, use_keystone=True)
-
- @mock.patch('snaps.openstack.tests.os_source_file_test.'
- 'OSIntegrationTestCase.parameterize')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_1_of_100_ko(self, *args):
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = ['foo']
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.health_check.run())
- self.assertEquals(
- testcase.TestCase.EX_TESTCASE_FAILED,
- self.health_check.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- mock.ANY, ext_net_name='foo', flavor_metadata=mock.ANY,
- image_metadata=mock.ANY, netconf_override=None,
- os_creds=self.os_creds, use_keystone=True)
-
- @mock.patch('snaps.openstack.tests.os_source_file_test.'
- 'OSIntegrationTestCase.parameterize')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_1_of_100_ko_criteria(self, *args):
- self.health_check.criteria = 90
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = ['foo']
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.health_check.run())
- self.assertEquals(
- testcase.TestCase.EX_OK, self.health_check.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- mock.ANY, ext_net_name='foo', flavor_metadata=mock.ANY,
- image_metadata=mock.ANY, netconf_override=None,
- os_creds=self.os_creds, use_keystone=True)
-
-
-class SmokeTesting(unittest.TestCase):
- """
- Ensures the VPingUserdata class can run in Functest. This test does not
- actually connect with an OpenStack pod.
- """
-
- def setUp(self):
- self.os_creds = OSCreds(
- username='user', password='pass',
- auth_url='http://foo.com:5000/v3', project_name='bar')
-
- self.smoke = smoke.SnapsSmoke(
- os_creds=self.os_creds, ext_net_name='foo')
-
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_integration_tests')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_success(self, *args):
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = []
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.smoke.run())
- self.assertEquals(testcase.TestCase.EX_OK, self.smoke.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- ext_net_name='foo', flavor_metadata=mock.ANY,
- image_metadata=mock.ANY, netconf_override=None,
- os_creds=self.os_creds, suite=mock.ANY, use_floating_ips=True,
- use_keystone=True)
-
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_integration_tests')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_1_of_100_ko(self, *args):
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = ['foo']
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.smoke.run())
- self.assertEquals(
- testcase.TestCase.EX_TESTCASE_FAILED, self.smoke.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- ext_net_name='foo', flavor_metadata=mock.ANY,
- image_metadata=mock.ANY, netconf_override=mock.ANY,
- os_creds=self.os_creds, suite=mock.ANY, use_floating_ips=True,
- use_keystone=True)
-
- @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_suite_builder.'
- 'add_openstack_integration_tests')
- @mock.patch('unittest.TextTestRunner.run',
- return_value=mock.MagicMock(name='unittest.TextTestResult'))
- def test_run_1_of_100_ko_criteria(self, *args):
- self.smoke.criteria = 90
- args[0].return_value.testsRun = 100
- args[0].return_value.failures = ['foo']
- args[0].return_value.errors = []
- self.assertEquals(testcase.TestCase.EX_OK, self.smoke.run())
- self.assertEquals(
- testcase.TestCase.EX_OK, self.smoke.is_successful())
- args[0].assert_called_with(mock.ANY)
- args[1].assert_called_with(
- ext_net_name='foo', flavor_metadata=mock.ANY,
- image_metadata=mock.ANY, netconf_override=None,
- os_creds=self.os_creds, suite=mock.ANY, use_floating_ips=True,
- use_keystone=True)
-
-
-if __name__ == "__main__":
- logging.disable(logging.CRITICAL)
- unittest.main(verbosity=2)
diff --git a/functest/tests/unit/openstack/tempest/test_conf_utils.py b/functest/tests/unit/openstack/tempest/test_conf_utils.py
deleted file mode 100644
index 1585cac09..000000000
--- a/functest/tests/unit/openstack/tempest/test_conf_utils.py
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/usr/bin/env python
-
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-# pylint: disable=missing-docstring
-
-import logging
-import os
-import unittest
-
-import mock
-
-from functest.opnfv_tests.openstack.tempest import conf_utils
-from functest.utils import config
-
-
-class OSTempestConfUtilsTesting(unittest.TestCase):
- # pylint: disable=too-many-public-methods
-
- @mock.patch('subprocess.check_output')
- def test_create_rally_deployment(self, mock_exec):
- self.assertEqual(conf_utils.create_rally_deployment(), None)
- calls = [
- mock.call(['rally', 'deployment', 'destroy', '--deployment',
- str(getattr(config.CONF, 'rally_deployment_name'))]),
- mock.call(['rally', 'deployment', 'create', '--fromenv', '--name',
- str(getattr(config.CONF, 'rally_deployment_name'))]),
- mock.call(['rally', 'deployment', 'check'])]
- mock_exec.assert_has_calls(calls)
-
- @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils'
- '.LOGGER.debug')
- def test_create_verifier(self, mock_logger_debug):
- mock_popen = mock.Mock()
- attrs = {'poll.return_value': None,
- 'stdout.readline.return_value': '0'}
- mock_popen.configure_mock(**attrs)
-
- setattr(config.CONF, 'tempest_verifier_name', 'test_verifier_name')
- with mock.patch('subprocess.Popen', side_effect=Exception), \
- self.assertRaises(Exception):
- conf_utils.create_verifier()
- mock_logger_debug.assert_any_call("Tempest test_verifier_name"
- " does not exist")
-
- @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'create_verifier', return_value=mock.Mock())
- @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'create_rally_deployment', return_value=mock.Mock())
- def test_get_verif_id_missing_verif(self, mock_rally, mock_tempest):
- # pylint: disable=unused-argument
- setattr(config.CONF, 'tempest_verifier_name', 'test_verifier_name')
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.subprocess.Popen') as mock_popen, \
- self.assertRaises(Exception):
- mock_stdout = mock.Mock()
- attrs = {'stdout.readline.return_value': ''}
- mock_stdout.configure_mock(**attrs)
- mock_popen.return_value = mock_stdout
- conf_utils.get_verifier_id()
-
- @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'create_verifier', return_value=mock.Mock())
- @mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'create_rally_deployment', return_value=mock.Mock())
- def test_get_verifier_id_default(self, mock_rally, mock_tempest):
- # pylint: disable=unused-argument
- setattr(config.CONF, 'tempest_verifier_name', 'test_verifier_name')
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.subprocess.Popen') as mock_popen:
- mock_stdout = mock.Mock()
- attrs = {'stdout.readline.return_value': 'test_deploy_id'}
- mock_stdout.configure_mock(**attrs)
- mock_popen.return_value = mock_stdout
-
- self.assertEqual(conf_utils.get_verifier_id(),
- 'test_deploy_id')
-
- def test_get_depl_id_missing_rally(self):
- setattr(config.CONF, 'tempest_verifier_name', 'test_deploy_name')
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.subprocess.Popen') as mock_popen, \
- self.assertRaises(Exception):
- mock_stdout = mock.Mock()
- attrs = {'stdout.readline.return_value': ''}
- mock_stdout.configure_mock(**attrs)
- mock_popen.return_value = mock_stdout
- conf_utils.get_verifier_deployment_id()
-
- def test_get_depl_id_default(self):
- setattr(config.CONF, 'tempest_verifier_name', 'test_deploy_name')
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.subprocess.Popen') as mock_popen:
- mock_stdout = mock.Mock()
- attrs = {'stdout.readline.return_value': 'test_deploy_id'}
- mock_stdout.configure_mock(**attrs)
- mock_popen.return_value = mock_stdout
-
- self.assertEqual(conf_utils.get_verifier_deployment_id(),
- 'test_deploy_id')
-
- def test_get_verif_repo_dir_default(self):
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.os.path.join',
- return_value='test_verifier_repo_dir'), \
- mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.get_verifier_id') as mock_get_id:
- self.assertEqual(conf_utils.get_verifier_repo_dir(''),
- 'test_verifier_repo_dir')
- self.assertTrue(mock_get_id.called)
-
- def test_get_depl_dir_default(self):
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.os.path.join',
- return_value='test_verifier_repo_dir'), \
- mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.get_verifier_id') as mock_get_vid, \
- mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.get_verifier_deployment_id') \
- as mock_get_did:
- self.assertEqual(conf_utils.get_verifier_deployment_dir('', ''),
- 'test_verifier_repo_dir')
- self.assertTrue(mock_get_vid.called)
- self.assertTrue(mock_get_did.called)
-
- def _test_missing_param(self, params, image_id, flavor_id, alt=False):
- with mock.patch('six.moves.configparser.RawConfigParser.'
- 'set') as mset, \
- mock.patch('six.moves.configparser.RawConfigParser.'
- 'read') as mread, \
- mock.patch('six.moves.configparser.RawConfigParser.'
- 'write') as mwrite, \
- mock.patch('six.moves.builtins.open', mock.mock_open()), \
- mock.patch('functest.utils.functest_utils.yaml.safe_load',
- return_value={'validation': {'ssh_timeout': 300}}):
- os.environ['OS_INTERFACE'] = ''
- if not alt:
- conf_utils.configure_tempest_update_params(
- 'test_conf_file', image_id=image_id,
- flavor_id=flavor_id)
- mset.assert_any_call(params[0], params[1], params[2])
- else:
- conf_utils.configure_tempest_update_params(
- 'test_conf_file', image_alt_id=image_id,
- flavor_alt_id=flavor_id)
- mset.assert_any_call(params[0], params[1], params[2])
- self.assertTrue(mread.called)
- self.assertTrue(mwrite.called)
-
- def test_upd_missing_image_id(self):
- self._test_missing_param(('compute', 'image_ref', 'test_image_id'),
- 'test_image_id', None)
-
- def test_upd_missing_image_id_alt(self):
- self._test_missing_param(
- ('compute', 'image_ref_alt', 'test_image_id_alt'),
- 'test_image_id_alt', None, alt=True)
-
- def test_upd_missing_flavor_id(self):
- self._test_missing_param(('compute', 'flavor_ref', 'test_flavor_id'),
- None, 'test_flavor_id')
-
- def test_upd_missing_flavor_id_alt(self):
- self._test_missing_param(
- ('compute', 'flavor_ref_alt', 'test_flavor_id_alt'),
- None, 'test_flavor_id_alt', alt=True)
-
- def test_verif_missing_conf_file(self):
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.os.path.isfile',
- return_value=False), \
- mock.patch('subprocess.check_output') as mexe, \
- self.assertRaises(Exception) as context:
- conf_utils.configure_verifier('test_dep_dir')
- mexe.assert_called_once_with("rally verify configure-verifier")
- msg = ("Tempest configuration file 'test_dep_dir/tempest.conf'"
- " NOT found.")
- self.assertTrue(msg in context.exception)
-
- def test_configure_verifier_default(self):
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.os.path.isfile',
- return_value=True), \
- mock.patch('subprocess.check_output') as mexe:
- self.assertEqual(conf_utils.configure_verifier('test_dep_dir'),
- 'test_dep_dir/tempest.conf')
- mexe.assert_called_once_with(
- ['rally', 'verify', 'configure-verifier', '--reconfigure',
- '--id', str(getattr(config.CONF, 'tempest_verifier_name'))])
-
-
-if __name__ == "__main__":
- logging.disable(logging.CRITICAL)
- unittest.main(verbosity=2)
diff --git a/functest/tests/unit/openstack/tempest/test_tempest.py b/functest/tests/unit/openstack/tempest/test_tempest.py
index 23dcd6c75..efc4393c8 100644
--- a/functest/tests/unit/openstack/tempest/test_tempest.py
+++ b/functest/tests/unit/openstack/tempest/test_tempest.py
@@ -14,8 +14,8 @@ import unittest
import mock
from xtesting.core import testcase
+from functest.opnfv_tests.openstack.rally import rally
from functest.opnfv_tests.openstack.tempest import tempest
-from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils import config
@@ -23,17 +23,24 @@ class OSTempestTesting(unittest.TestCase):
# pylint: disable=too-many-public-methods
def setUp(self):
- with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.get_verifier_id',
- return_value='test_deploy_id'), \
+ with mock.patch('os_client_config.get_config'), \
+ mock.patch('shade.OpenStackCloud'), \
+ mock.patch('functest.core.tenantnetwork.NewProject'), \
+ mock.patch('functest.opnfv_tests.openstack.rally.rally.'
+ 'RallyBase.create_rally_deployment'), \
+ mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'TempestCommon.create_verifier'), \
mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.get_verifier_deployment_id',
+ 'TempestCommon.get_verifier_id',
+ return_value='test_deploy_id'), \
+ mock.patch('functest.opnfv_tests.openstack.rally.rally.'
+ 'RallyBase.get_verifier_deployment_id',
return_value='test_deploy_id'), \
mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.get_verifier_repo_dir',
+ 'TempestCommon.get_verifier_repo_dir',
return_value='test_verifier_repo_dir'), \
mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.get_verifier_deployment_dir',
+ 'TempestCommon.get_verifier_deployment_dir',
return_value='test_verifier_deploy_dir'), \
mock.patch('os_client_config.make_shade'):
self.tempestcommon = tempest.TempestCommon()
@@ -50,7 +57,7 @@ class OSTempestTesting(unittest.TestCase):
msg = "Tempest test list file %s NOT found."
self.tempestcommon.generate_test_list()
self.assertTrue(
- (msg % conf_utils.TEMPEST_CUSTOM) in context.exception)
+ (msg % self.tempestcommon.tempest_custom) in context.exception)
@mock.patch('subprocess.check_output')
@mock.patch('os.remove')
@@ -75,8 +82,9 @@ class OSTempestTesting(unittest.TestCase):
else:
testr_mode = self.tempestcommon.mode
verifier_repo_dir = 'test_verifier_repo_dir'
- cmd = "(cd {0}; stestr list '{1}' >{2} 2>/dev/null)".format(
- verifier_repo_dir, testr_mode, self.tempestcommon.list)
+ self.tempestcommon.verifier_repo_dir = verifier_repo_dir
+ cmd = (f"(cd {verifier_repo_dir}; stestr list '{testr_mode}' > "
+ f"{self.tempestcommon.list} 2>/dev/null)")
self.tempestcommon.generate_test_list(mode=testr_mode)
args[0].assert_called_once_with(cmd, shell=True)
args[2].assert_called_once_with('/etc/tempest.conf')
@@ -115,10 +123,10 @@ class OSTempestTesting(unittest.TestCase):
mock.mock_open()) as mock_open, \
mock.patch.object(self.tempestcommon, 'read_file',
return_value=['test1', 'test2']):
- conf_utils.TEMPEST_BLACKLIST = Exception
- os.environ['INSTALLER_TYPE'] = 'installer_type'
+ self.tempestcommon.tempest_blacklist = Exception
os.environ['DEPLOY_SCENARIO'] = 'deploy_scenario'
- self.tempestcommon.apply_tempest_blacklist()
+ self.tempestcommon.apply_tempest_blacklist(
+ self.tempestcommon.tempest_blacklist)
obj = mock_open()
obj.write.assert_any_call('test1\n')
obj.write.assert_any_call('test2\n')
@@ -132,7 +140,6 @@ class OSTempestTesting(unittest.TestCase):
@mock.patch("os.path.exists", return_value=True)
def test_apply_blacklist_default(self, *args):
item_dict = {'scenarios': ['deploy_scenario'],
- 'installers': ['installer_type'],
'tests': ['test2']}
with mock.patch('six.moves.builtins.open',
mock.mock_open()) as mock_open, \
@@ -140,9 +147,9 @@ class OSTempestTesting(unittest.TestCase):
return_value=['test1', 'test2']), \
mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
'yaml.safe_load', return_value=item_dict):
- os.environ['INSTALLER_TYPE'] = 'installer_type'
os.environ['DEPLOY_SCENARIO'] = 'deploy_scenario'
- self.tempestcommon.apply_tempest_blacklist()
+ self.tempestcommon.apply_tempest_blacklist(
+ self.tempestcommon.tempest_blacklist)
obj = mock_open()
obj.write.assert_any_call('test1\n')
self.assertFalse(obj.write.assert_any_call('test2\n'))
@@ -151,35 +158,17 @@ class OSTempestTesting(unittest.TestCase):
args[2].assert_called_once_with(
self.tempestcommon.list, self.tempestcommon.raw_list)
- @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.LOGGER.info')
- def test_run_verifier_tests_default(self, mock_logger_info):
- with mock.patch('six.moves.builtins.open', mock.mock_open()), \
- mock.patch('six.moves.builtins.iter',
- return_value=[r'\} tempest\.']), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'subprocess.Popen'):
- conf_utils.TEMPEST_LIST = 'test_tempest_list'
- cmd = ["rally", "verify", "start", "--load-list",
- conf_utils.TEMPEST_LIST]
- with self.assertRaises(Exception):
- self.tempestcommon.run_verifier_tests()
- mock_logger_info. \
- assert_any_call("Starting Tempest test suite: '%s'.", cmd)
-
@mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
'subprocess.Popen')
- def test_generate_report(self, mock_popen):
- self.tempestcommon.verification_id = "1234"
- html_file = os.path.join(
- os.path.join(
- getattr(config.CONF, 'dir_results'),
- self.tempestcommon.case_name),
- "tempest-report.html")
- cmd = ["rally", "verify", "report", "--type", "html", "--uuid",
- "1234", "--to", html_file]
- self.tempestcommon.generate_report()
- mock_popen.assert_called_once_with(cmd, stdout=mock.ANY,
- stderr=mock.ANY)
+ @mock.patch('six.moves.builtins.open', mock.mock_open())
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.LOGGER.info')
+ def test_run_verifier_tests_default(self, *args):
+ self.tempestcommon.tempest_list = 'test_tempest_list'
+ cmd = ["rally", "verify", "start", "--load-list",
+ self.tempestcommon.tempest_list]
+ with self.assertRaises(Exception):
+ self.tempestcommon.run_verifier_tests()
+ args[0].assert_any_call("Starting Tempest test suite: '%s'.", cmd)
@mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
'os.path.exists', return_value=False)
@@ -224,9 +213,9 @@ class OSTempestTesting(unittest.TestCase):
def test_run_apply_blacklist_ko(self):
with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
- mock.patch.object(
- self.tempestcommon, 'apply_tempest_blacklist',
- side_effect=Exception()):
+ mock.patch.object(self.tempestcommon,
+ 'apply_tempest_blacklist',
+ side_effect=Exception()):
self._test_run(testcase.TestCase.EX_RUN_ERROR)
def test_run_verifier_tests_ko(self):
@@ -257,11 +246,147 @@ class OSTempestTesting(unittest.TestCase):
'apply_tempest_blacklist'), \
mock.patch.object(self.tempestcommon, 'run_verifier_tests'), \
mock.patch.object(self.tempestcommon,
- 'parse_verifier_result'), \
- mock.patch.object(self.tempestcommon, 'generate_report'):
+ 'parse_verifier_result'):
self._test_run(testcase.TestCase.EX_OK)
args[0].assert_called_once_with()
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.LOGGER.debug')
+ def test_create_verifier(self, mock_logger_debug):
+ mock_popen = mock.Mock()
+ attrs = {'poll.return_value': None,
+ 'stdout.readline.return_value': '0'}
+ mock_popen.configure_mock(**attrs)
+
+ setattr(config.CONF, 'tempest_verifier_name', 'test_verifier_name')
+ with mock.patch('subprocess.Popen', side_effect=Exception), \
+ self.assertRaises(Exception):
+ self.tempestcommon.create_verifier()
+ mock_logger_debug.assert_any_call("Tempest test_verifier_name"
+ " does not exist")
+
+ def test_get_verifier_id_default(self):
+ setattr(config.CONF, 'tempest_verifier_name', 'test_verifier_name')
+
+ with mock.patch('functest.opnfv_tests.openstack.tempest.'
+ 'tempest.subprocess.Popen') as mock_popen:
+ attrs = {'return_value.__enter__.return_value.'
+ 'stdout.readline.return_value': b'test_deploy_id'}
+ mock_popen.configure_mock(**attrs)
+
+ self.assertEqual(self.tempestcommon.get_verifier_id(),
+ 'test_deploy_id')
+
+ def test_get_depl_id_default(self):
+ setattr(config.CONF, 'tempest_verifier_name', 'test_deploy_name')
+ with mock.patch('functest.opnfv_tests.openstack.tempest.'
+ 'tempest.subprocess.Popen') as mock_popen:
+ attrs = {'return_value.__enter__.return_value.'
+ 'stdout.readline.return_value': b'test_deploy_id'}
+ mock_popen.configure_mock(**attrs)
+
+ self.assertEqual(rally.RallyBase.get_verifier_deployment_id(),
+ 'test_deploy_id')
+
+ def test_get_verif_repo_dir_default(self):
+ with mock.patch('functest.opnfv_tests.openstack.tempest.'
+ 'tempest.os.path.join',
+ return_value='test_verifier_repo_dir'):
+ self.assertEqual(self.tempestcommon.get_verifier_repo_dir(''),
+ 'test_verifier_repo_dir')
+
+ def test_get_depl_dir_default(self):
+ with mock.patch('functest.opnfv_tests.openstack.tempest.'
+ 'tempest.os.path.join',
+ return_value='test_verifier_repo_dir'):
+ self.assertEqual(
+ self.tempestcommon.get_verifier_deployment_dir('', ''),
+ 'test_verifier_repo_dir')
+
+ def _test_missing_param(self, params, image_id, flavor_id, alt=False):
+ with mock.patch('six.moves.configparser.RawConfigParser.'
+ 'set') as mset, \
+ mock.patch('six.moves.configparser.RawConfigParser.'
+ 'read') as mread, \
+ mock.patch('six.moves.configparser.RawConfigParser.'
+ 'write') as mwrite, \
+ mock.patch('six.moves.builtins.open', mock.mock_open()), \
+ mock.patch('functest.utils.functest_utils.yaml.safe_load',
+ return_value={'validation': {'ssh_timeout': 300}}):
+ os.environ['OS_INTERFACE'] = ''
+ if not alt:
+ self.tempestcommon.configure_tempest_update_params(
+ 'test_conf_file', image_id=image_id,
+ flavor_id=flavor_id)
+ mset.assert_any_call(params[0], params[1], params[2])
+ else:
+ self.tempestcommon.configure_tempest_update_params(
+ 'test_conf_file', image_alt_id=image_id,
+ flavor_alt_id=flavor_id)
+ mset.assert_any_call(params[0], params[1], params[2])
+ self.assertTrue(mread.called)
+ self.assertTrue(mwrite.called)
+
+ def test_upd_missing_image_id(self):
+ self._test_missing_param(('compute', 'image_ref', 'test_image_id'),
+ 'test_image_id', None)
+
+ def test_upd_missing_image_id_alt(self):
+ self._test_missing_param(
+ ('compute', 'image_ref_alt', 'test_image_id_alt'),
+ 'test_image_id_alt', None, alt=True)
+
+ def test_upd_missing_flavor_id(self):
+ self._test_missing_param(('compute', 'flavor_ref', 'test_flavor_id'),
+ None, 'test_flavor_id')
+
+ def test_upd_missing_flavor_id_alt(self):
+ self._test_missing_param(
+ ('compute', 'flavor_ref_alt', 'test_flavor_id_alt'),
+ None, 'test_flavor_id_alt', alt=True)
+
+ def test_verif_missing_conf_file(self):
+ with mock.patch('functest.opnfv_tests.openstack.tempest.'
+ 'tempest.os.path.isfile',
+ return_value=False), \
+ mock.patch('subprocess.check_output') as mexe, \
+ self.assertRaises(Exception) as context:
+ self.tempestcommon.configure_verifier('test_dep_dir')
+ mexe.assert_called_once_with("rally verify configure-verifier")
+ msg = ("Tempest configuration file 'test_dep_dir/tempest.conf'"
+ " NOT found.")
+ self.assertTrue(msg in context.exception)
+
+ def test_configure_verifier_default(self):
+ with mock.patch('functest.opnfv_tests.openstack.tempest.'
+ 'tempest.os.path.isfile',
+ return_value=True), \
+ mock.patch('subprocess.check_output') as mexe:
+ self.assertEqual(
+ self.tempestcommon.configure_verifier('test_dep_dir'),
+ 'test_dep_dir/tempest.conf')
+ mexe.assert_called_once_with(
+ ['rally', 'verify', 'configure-verifier', '--reconfigure',
+ '--id', str(getattr(config.CONF, 'tempest_verifier_name'))])
+
+ def test_is_successful_false(self):
+ with mock.patch('six.moves.builtins.super') as mock_super:
+ self.tempestcommon.deny_skipping = True
+ self.tempestcommon.details = {"skipped_number": 2}
+ self.assertEqual(self.tempestcommon.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+ mock_super(tempest.TempestCommon,
+ self).is_successful.assert_not_called()
+
+ def test_is_successful_true(self):
+ with mock.patch('six.moves.builtins.super') as mock_super:
+ self.tempestcommon.deny_skipping = False
+ self.tempestcommon.details = {"skipped_number": 2}
+ mock_super(tempest.TempestCommon,
+ self).is_successful.return_value = 567
+ self.assertEqual(self.tempestcommon.is_successful(), 567)
+ mock_super(tempest.TempestCommon,
+ self).is_successful.assert_called()
+
if __name__ == "__main__":
logging.disable(logging.CRITICAL)
diff --git a/functest/tests/unit/openstack/vmtp/test_vmtp.py b/functest/tests/unit/openstack/vmtp/test_vmtp.py
index 7f8cf40c7..850273476 100644
--- a/functest/tests/unit/openstack/vmtp/test_vmtp.py
+++ b/functest/tests/unit/openstack/vmtp/test_vmtp.py
@@ -66,23 +66,25 @@ class VmtpTesting(unittest.TestCase):
def test_generate_keys1(self, *args):
self.testcase.generate_keys()
self.testcase.cloud.create_keypair.assert_called_once_with(
- 'vmtp_{}'.format(self.testcase.guid))
+ f'vmtp_{self.testcase.guid}')
self.testcase.cloud.delete_keypair.assert_called_once_with('id')
- calls = [mock.call(self.testcase.privkey_filename, 'w'),
- mock.call(self.testcase.pubkey_filename, 'w')]
+ calls = [mock.call(
+ self.testcase.privkey_filename, 'w', encoding='utf-8'),
+ mock.call(
+ self.testcase.pubkey_filename, 'w', encoding='utf-8')]
args[0].assert_has_calls(calls, any_order=True)
@mock.patch('six.moves.builtins.open')
def test_generate_keys2(self, *args):
- # pylint: disable=bad-continuation
with mock.patch.object(
self.testcase.cloud, "create_keypair",
side_effect=shade.OpenStackCloudException(None)) as mock_obj, \
self.assertRaises(shade.OpenStackCloudException):
self.testcase.generate_keys()
- mock_obj.assert_called_once_with('vmtp_{}'.format(self.testcase.guid))
+ mock_obj.assert_called_once_with(f'vmtp_{self.testcase.guid}')
args[0].assert_not_called()
+
if __name__ == "__main__":
logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/openstack/vping/test_vping_ssh.py b/functest/tests/unit/openstack/vping/test_vping_ssh.py
index 3595638ec..a07148aab 100644
--- a/functest/tests/unit/openstack/vping/test_vping_ssh.py
+++ b/functest/tests/unit/openstack/vping/test_vping_ssh.py
@@ -47,7 +47,7 @@ class VpingSSHTesting(unittest.TestCase):
self.vping.prepare()
args[0].assert_called_once_with()
args[1].assert_called_once_with(
- '{}-vm2_{}'.format(self.vping.case_name, self.vping.guid),
+ f'{self.vping.case_name}-vm2_{self.vping.guid}',
security_groups=[self.vping.sec.id])
@mock.patch('functest.opnfv_tests.openstack.vping.vping_ssh.VPingSSH.'
@@ -58,27 +58,43 @@ class VpingSSHTesting(unittest.TestCase):
self.vping.prepare()
args[0].assert_called_once_with()
args[1].assert_called_once_with(
- '{}-vm2_{}'.format(self.vping.case_name, self.vping.guid),
+ f'{self.vping.case_name}-vm2_{self.vping.guid}',
security_groups=[self.vping.sec.id])
- def test_execute_exc(self):
- self.vping.vm2 = munch.Munch(private_v4='127.0.0.1')
+ @mock.patch('functest.opnfv_tests.openstack.vping.vping_ssh.VPingSSH.'
+ 'check_regex_in_console', return_value=True)
+ def test_execute_exc(self, *args):
+ self.vping.vm2 = munch.Munch(private_v4='127.0.0.1', name='foo')
self.vping.ssh = mock.Mock()
self.vping.ssh.exec_command.side_effect = ssh_exception.SSHException
with self.assertRaises(ssh_exception.SSHException):
self.vping.execute()
self.vping.ssh.exec_command.assert_called_once_with(
- 'ping -c 1 {}'.format(self.vping.vm2.private_v4))
+ f'ping -c 1 {self.vping.vm2.private_v4}')
+ args[0].assert_called_once_with('foo')
+
+ @mock.patch('functest.opnfv_tests.openstack.vping.vping_ssh.VPingSSH.'
+ 'check_regex_in_console', return_value=False)
+ def test_execute_exc2(self, *args):
+ self.vping.vm2 = munch.Munch(private_v4='127.0.0.1', name='foo')
+ self.vping.ssh = mock.Mock()
+ self.vping.execute()
+ self.vping.ssh.exec_command.assert_not_called()
+ args[0].assert_called_once_with('foo')
def _test_execute(self, ret=0):
- self.vping.vm2 = munch.Munch(private_v4='127.0.0.1')
+ self.vping.vm2 = munch.Munch(private_v4='127.0.0.1', name='foo')
self.vping.ssh = mock.Mock()
stdout = mock.Mock()
stdout.channel.recv_exit_status.return_value = ret
- self.vping.ssh.exec_command.return_value = (None, stdout, None)
- self.assertEqual(self.vping.execute(), ret)
+ self.vping.ssh.exec_command.return_value = (None, stdout, mock.Mock())
+ with mock.patch(
+ 'functest.opnfv_tests.openstack.vping.vping_ssh.VPingSSH.'
+ 'check_regex_in_console', return_value=True) as mock_check:
+ self.assertEqual(self.vping.execute(), ret)
+ mock_check.assert_called_once_with('foo')
self.vping.ssh.exec_command.assert_called_once_with(
- 'ping -c 1 {}'.format(self.vping.vm2.private_v4))
+ f'ping -c 1 {self.vping.vm2.private_v4}')
def test_execute1(self):
self._test_execute()
diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py
index d35ed8ced..4b642ff9d 100644
--- a/functest/tests/unit/utils/test_functest_utils.py
+++ b/functest/tests/unit/utils/test_functest_utils.py
@@ -15,12 +15,13 @@ import unittest
import mock
import pkg_resources
+import six
from functest.utils import functest_utils
class FunctestUtilsTesting(unittest.TestCase):
- # pylint: disable=too-many-instance-attributes
+ # pylint: disable=too-many-instance-attributes,too-many-public-methods
readline = 0
test_ip = ['10.1.23.4', '10.1.14.15', '10.1.16.15']
@@ -81,7 +82,7 @@ class FunctestUtilsTesting(unittest.TestCase):
def _get_environ(self, var, *args): # pylint: disable=unused-argument
if var == 'INSTALLER_TYPE':
return self.installer
- elif var == 'DEPLOY_SCENARIO':
+ if var == 'DEPLOY_SCENARIO':
return self.scenario
return var
@@ -97,27 +98,20 @@ class FunctestUtilsTesting(unittest.TestCase):
as mock_subproc_open, \
mock.patch('six.moves.builtins.open',
mock.mock_open()) as mopen:
-
- FunctestUtilsTesting.readline = 0
-
- mock_obj = mock.Mock()
- attrs = {'readline.side_effect': self.cmd_readline()}
- mock_obj.configure_mock(**attrs)
-
- mock_obj2 = mock.Mock()
- attrs = {'stdout': mock_obj, 'wait.return_value': 1}
- mock_obj2.configure_mock(**attrs)
-
- mock_subproc_open.return_value = mock_obj2
-
- resp = functest_utils.execute_command(self.cmd, info=True,
- error_msg=self.error_msg,
- verbose=True,
- output_file=self.output_file)
+ stream = six.BytesIO()
+ stream.write(self.cmd_readline().encode("utf-8"))
+ attrs = {
+ 'return_value.__enter__.return_value.stdout': stream,
+ 'return_value.__enter__.return_value.wait.return_value': 1}
+ mock_subproc_open.configure_mock(**attrs)
+ resp = functest_utils.execute_command(
+ self.cmd, info=True, error_msg=self.error_msg, verbose=True,
+ output_file=self.output_file)
self.assertEqual(resp, 1)
- msg_exec = ("Executing command: '%s'" % self.cmd)
+ msg_exec = f"Executing command: '{self.cmd}'"
mock_logger_info.assert_called_once_with(msg_exec)
- mopen.assert_called_once_with(self.output_file, "w")
+ mopen.assert_called_once_with(
+ self.output_file, "w", encoding='utf-8')
mock_logger_error.assert_called_once_with(self.error_msg)
@mock.patch('functest.utils.functest_utils.LOGGER.info')
@@ -126,50 +120,35 @@ class FunctestUtilsTesting(unittest.TestCase):
as mock_subproc_open, \
mock.patch('six.moves.builtins.open',
mock.mock_open()) as mopen:
-
- FunctestUtilsTesting.readline = 0
-
- mock_obj = mock.Mock()
- attrs = {'readline.side_effect': self.cmd_readline()}
- mock_obj.configure_mock(**attrs)
-
- mock_obj2 = mock.Mock()
- attrs = {'stdout': mock_obj, 'wait.return_value': 0}
- mock_obj2.configure_mock(**attrs)
-
- mock_subproc_open.return_value = mock_obj2
-
- resp = functest_utils.execute_command(self.cmd, info=True,
- error_msg=self.error_msg,
- verbose=True,
- output_file=self.output_file)
+ stream = six.BytesIO()
+ stream.write(self.cmd_readline().encode("utf-8"))
+ attrs = {
+ 'return_value.__enter__.return_value.stdout': stream,
+ 'return_value.__enter__.return_value.wait.return_value': 0}
+ mock_subproc_open.configure_mock(**attrs)
+ resp = functest_utils.execute_command(
+ self.cmd, info=True, error_msg=self.error_msg, verbose=True,
+ output_file=self.output_file)
self.assertEqual(resp, 0)
- msg_exec = ("Executing command: '%s'" % self.cmd)
+ msg_exec = (f"Executing command: '{self.cmd}'")
mock_logger_info.assert_called_once_with(msg_exec)
- mopen.assert_called_once_with(self.output_file, "w")
+ mopen.assert_called_once_with(
+ self.output_file, "w", encoding='utf-8')
@mock.patch('sys.stdout')
def test_exec_cmd_args_missing_ok(self, stdout=None):
# pylint: disable=unused-argument
with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
as mock_subproc_open:
-
- FunctestUtilsTesting.readline = 2
-
- mock_obj = mock.Mock()
- attrs = {'readline.side_effect': self.cmd_readline()}
- mock_obj.configure_mock(**attrs)
-
- mock_obj2 = mock.Mock()
- attrs = {'stdout': mock_obj, 'wait.return_value': 0}
- mock_obj2.configure_mock(**attrs)
-
- mock_subproc_open.return_value = mock_obj2
-
- resp = functest_utils.execute_command(self.cmd, info=False,
- error_msg="",
- verbose=False,
- output_file=None)
+ stream = six.BytesIO()
+ stream.write(self.cmd_readline().encode("utf-8"))
+ attrs = {
+ 'return_value.__enter__.return_value.stdout': stream,
+ 'return_value.__enter__.return_value.wait.return_value': 0}
+ mock_subproc_open.configure_mock(**attrs)
+ resp = functest_utils.execute_command(
+ self.cmd, info=False, error_msg="", verbose=False,
+ output_file=None)
self.assertEqual(resp, 0)
@mock.patch('sys.stdout')
@@ -177,22 +156,16 @@ class FunctestUtilsTesting(unittest.TestCase):
# pylint: disable=unused-argument
with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
as mock_subproc_open:
-
- FunctestUtilsTesting.readline = 2
- mock_obj = mock.Mock()
- attrs = {'readline.side_effect': self.cmd_readline()}
- mock_obj.configure_mock(**attrs)
-
- mock_obj2 = mock.Mock()
- attrs = {'stdout': mock_obj, 'wait.return_value': 1}
- mock_obj2.configure_mock(**attrs)
-
- mock_subproc_open.return_value = mock_obj2
-
- resp = functest_utils.execute_command(self.cmd, info=False,
- error_msg="",
- verbose=False,
- output_file=None)
+ attrs = {}
+ stream = six.BytesIO()
+ stream.write(self.cmd_readline().encode("utf-8"))
+ attrs = {
+ 'return_value.__enter__.return_value.stdout': stream,
+ 'return_value.__enter__.return_value.wait.return_value': 1}
+ mock_subproc_open.configure_mock(**attrs)
+ resp = functest_utils.execute_command(
+ self.cmd, info=False, error_msg="", verbose=False,
+ output_file=None)
self.assertEqual(resp, 1)
def test_get_param_from_yaml_failed(self):
@@ -204,9 +177,9 @@ class FunctestUtilsTesting(unittest.TestCase):
mock_yaml.return_value = self.file_yaml
functest_utils.get_parameter_from_yaml(self.parameter,
self.test_file)
- self.assertTrue(("The parameter %s is not"
- " defined in config_functest.yaml" %
- self.parameter) in excep.exception)
+ self.assertTrue((f"The parameter {self.parameter} is not"
+ " defined in config_functest.yaml"
+ ) in excep.exception)
def test_get_param_from_yaml_def(self):
with mock.patch('six.moves.builtins.open', mock.mock_open()), \
@@ -218,6 +191,218 @@ class FunctestUtilsTesting(unittest.TestCase):
self.test_file),
'test_image_name')
+ def test_nova_version_exc1(self):
+ # pylint: disable=protected-access
+ cloud = mock.Mock()
+ cloud._compute_client.request.return_value = None
+ self.assertEqual(functest_utils.get_nova_version(cloud), None)
+ cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+ def test_nova_version_exc2(self):
+ # pylint: disable=protected-access
+ cloud = mock.Mock()
+ cloud._compute_client.request.return_value = {"version": None}
+ self.assertEqual(functest_utils.get_nova_version(cloud), None)
+ cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+ def test_nova_version_exc3(self):
+ # pylint: disable=protected-access
+ cloud = mock.Mock()
+ cloud._compute_client.request.return_value = {
+ "version": {"version": None}}
+ self.assertEqual(functest_utils.get_nova_version(cloud), None)
+ cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+ def test_nova_version_exc4(self):
+ # pylint: disable=protected-access
+ cloud = mock.Mock()
+ cloud._compute_client.request.return_value = {
+ "version": {"version": "a.b"}}
+ self.assertEqual(functest_utils.get_nova_version(cloud), None)
+ cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+ def test_nova_version(self):
+ # pylint: disable=protected-access
+ cloud = mock.Mock()
+ cloud._compute_client.request.return_value = {
+ "version": {"version": "2.1"}}
+ self.assertEqual(functest_utils.get_nova_version(cloud), (2, 1))
+ cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 61))
+ def test_openstack_version1(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(
+ cloud), "Rocky")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 60))
+ def test_openstack_version2(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(cloud), "Queens")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 43))
+ def test_openstack_version3(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(cloud), "Pike")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 39))
+ def test_openstack_version4(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(cloud), "Ocata")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 26))
+ def test_openstack_version5(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(cloud), "Newton")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 13))
+ def test_openstack_version6(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(cloud), "Mitaka")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 4))
+ def test_openstack_version7(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(
+ functest_utils.get_openstack_version(cloud), "Liberty")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 1))
+ def test_openstack_version8(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(cloud), "Kilo")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(1, 9))
+ def test_openstack_version9(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(
+ functest_utils.get_openstack_version(cloud), "Unknown")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(3, 1))
+ def test_openstack_version10(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(
+ functest_utils.get_openstack_version(cloud), "Master")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 66))
+ def test_openstack_version11(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(
+ cloud), "Stein")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 78))
+ def test_openstack_version12(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(
+ cloud), "Train")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 87))
+ def test_openstack_version13(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(
+ cloud), "Ussuri")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 88))
+ def test_openstack_version14(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(
+ cloud), "Wallaby")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 89))
+ def test_openstack_version15(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(
+ cloud), "Xena")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=(2, 92))
+ def test_openstack_version16(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(functest_utils.get_openstack_version(
+ cloud), "Zed")
+ args[0].assert_called_once_with(cloud)
+
+ @mock.patch('functest.utils.functest_utils.get_nova_version',
+ return_value=None)
+ def test_openstack_version_exc(self, *args):
+ cloud = mock.Mock()
+ self.assertEqual(
+ functest_utils.get_openstack_version(cloud), "Unknown")
+ args[0].assert_called_once_with(cloud)
+
+ def test_convert_dict_to_ini(self):
+ self.assertEqual(
+ functest_utils.convert_dict_to_ini({}), "")
+ self.assertEqual(
+ functest_utils.convert_dict_to_ini({"a": "b"}), "a:b")
+ value = functest_utils.convert_dict_to_ini({"a": "b", "c": "d"})
+ self.assertTrue(value in ('a:b,c:d', 'c:d,a:b'))
+ with self.assertRaises(AssertionError):
+ functest_utils.convert_list_to_ini("")
+
+ def test_convert_list_to_ini(self):
+ self.assertEqual(
+ functest_utils.convert_list_to_ini([]), "")
+ self.assertEqual(
+ functest_utils.convert_list_to_ini(["a"]), "a")
+ self.assertEqual(
+ functest_utils.convert_list_to_ini(["a", "b"]), "a,b")
+ with self.assertRaises(AssertionError):
+ functest_utils.convert_list_to_ini("")
+
+ def test_convert_ini_to_dict(self):
+ self.assertEqual(
+ functest_utils.convert_ini_to_dict(""), {})
+ self.assertEqual(
+ functest_utils.convert_ini_to_dict("a:b"), {"a": "b"})
+ self.assertEqual(
+ functest_utils.convert_ini_to_dict(
+ "a:b,c:d"), {"a": "b", "c": "d"})
+ self.assertEqual(
+ functest_utils.convert_ini_to_dict(
+ "a:b:c,d:e:f"), {"a:b": "c", "d:e": "f"})
+ with self.assertRaises(AssertionError):
+ functest_utils.convert_list_to_ini({})
+
+ def test_convert_ini_to_list(self):
+ self.assertEqual(
+ functest_utils.convert_ini_to_list(""), [])
+ self.assertEqual(
+ functest_utils.convert_ini_to_list("a"), ["a"])
+ self.assertEqual(
+ functest_utils.convert_ini_to_list("a,b"), ["a", "b"])
+ with self.assertRaises(AssertionError):
+ functest_utils.convert_ini_to_list([])
+
if __name__ == "__main__":
logging.disable(logging.CRITICAL)
diff --git a/functest/tests/unit/vnf/epc/test_juju_epc.py b/functest/tests/unit/vnf/epc/test_juju_epc.py
index 6b4137069..a72c61586 100644
--- a/functest/tests/unit/vnf/epc/test_juju_epc.py
+++ b/functest/tests/unit/vnf/epc/test_juju_epc.py
@@ -62,7 +62,6 @@ class JujuEpcTesting(unittest.TestCase):
'test_vnf': {}}
@unittest.skip("It must be fixed. Please see JIRA FUNCTEST-915")
- @mock.patch('snaps.openstack.create_image.OpenStackImage.create')
@mock.patch('os.system')
def test_prepare_default(self, *args):
""" Unittest for Prepare testcase """
diff --git a/functest/tests/unit/vnf/ims/test_ims_base.py b/functest/tests/unit/vnf/ims/test_clearwater.py
index 97654748a..f590a2857 100644
--- a/functest/tests/unit/vnf/ims/test_ims_base.py
+++ b/functest/tests/unit/vnf/ims/test_clearwater.py
@@ -12,15 +12,16 @@ import unittest
import mock
-from functest.opnfv_tests.vnf.ims import clearwater_ims_base as ims_base
+from functest.opnfv_tests.vnf.ims import clearwater
-class ClearwaterOnBoardingBaseTesting(unittest.TestCase):
+class ClearwaterTesting(unittest.TestCase):
def setUp(self):
with mock.patch('functest.opnfv_tests.vnf.ims.cloudify_ims.'
'os.makedirs'):
- self.ims_vnf = ims_base.ClearwaterOnBoardingBase()
+ self.ims_vnf = clearwater.ClearwaterTesting(
+ "foo", "0.0.0.0", "0.0.0.0")
self.mock_post = mock.Mock()
attrs = {'status_code': 201,
@@ -37,6 +38,7 @@ class ClearwaterOnBoardingBaseTesting(unittest.TestCase):
'cookies': ""}
self.mock_post_200.configure_mock(**attrs)
+
if __name__ == "__main__":
logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/vnf/ims/test_cloudify_ims.py b/functest/tests/unit/vnf/ims/test_cloudify_ims.py
index 79069a5de..c84adf0ff 100644
--- a/functest/tests/unit/vnf/ims/test_cloudify_ims.py
+++ b/functest/tests/unit/vnf/ims/test_cloudify_ims.py
@@ -10,56 +10,9 @@
import logging
import unittest
-import mock
-
-from functest.core import vnf
-from functest.opnfv_tests.vnf.ims import cloudify_ims
-
class CloudifyImsTesting(unittest.TestCase):
-
- def setUp(self):
-
- self.tenant = 'cloudify_ims'
- self.creds = {'username': 'user',
- 'password': 'pwd'}
- self.orchestrator = {'name': 'cloudify',
- 'version': '4.0',
- 'object': 'foo',
- 'requirements': {'flavor': {'name': 'm1.medium',
- 'ram_min': 4096},
- 'os_image': 'manager_4.0'}}
-
- self.vnf = {'name': 'clearwater',
- 'descriptor': {'version': '108',
- 'file_name': 'openstack-blueprint.yaml',
- 'name': 'clearwater-opnfv',
- 'url': 'https://foo',
- 'requirements': {'flavor':
- {'name': 'm1.medium',
- 'ram_min': 2048}}}}
-
- with mock.patch('functest.opnfv_tests.vnf.ims.cloudify_ims.'
- 'os.makedirs'), \
- mock.patch('functest.opnfv_tests.vnf.ims.cloudify_ims.'
- 'get_config', return_value={
- 'tenant_images': 'foo',
- 'orchestrator': self.orchestrator,
- 'vnf': self.vnf,
- 'vnf_test_suite': '',
- 'version': 'whatever'}):
-
- self.ims_vnf = cloudify_ims.CloudifyIms()
-
- self.images = {'image1': 'url1',
- 'image2': 'url2'}
- self.details = {'orchestrator': {'status': 'PASS', 'duration': 120},
- 'vnf': {},
- 'test_vnf': {}}
-
- def test_prepare_missing_param(self):
- with self.assertRaises(vnf.VnfPreparationException):
- self.ims_vnf.prepare()
+ pass
if __name__ == "__main__":
diff --git a/functest/tests/unit/vnf/router/test_cloudify_vrouter.py b/functest/tests/unit/vnf/router/test_cloudify_vrouter.py
index db03d716c..b3f83e946 100644
--- a/functest/tests/unit/vnf/router/test_cloudify_vrouter.py
+++ b/functest/tests/unit/vnf/router/test_cloudify_vrouter.py
@@ -12,61 +12,10 @@
import logging
import unittest
-import mock
-
-from functest.core import vnf
-from functest.opnfv_tests.vnf.router import cloudify_vrouter
-
class CloudifyVrouterTesting(unittest.TestCase):
- def setUp(self):
-
- self.tenant = 'cloudify_vrouter'
- self.creds = {'username': 'user',
- 'password': 'pwd'}
- self.orchestrator = {'name': 'cloudify',
- 'version': '4.0',
- 'object': 'foo',
- 'requirements': {'flavor': {'name': 'm1.medium',
- 'ram_min': 4096},
- 'os_image': 'manager_4.0'}}
-
- self.vnf = {'name': 'vrouter',
- 'descriptor': {'version': '100',
- 'file_name': 'function-test-' +
- 'openstack-blueprint.yaml',
- 'name': 'vrouter-opnfv',
- 'url': 'https://foo',
- 'requirements': {'flavor':
- {'name': 'm1.medium',
- 'ram_min': 2048}}}}
-
- # pylint: disable=bad-continuation
- with mock.patch(
- 'functest.opnfv_tests.vnf.router.cloudify_vrouter.Utilvnf'), \
- mock.patch('functest.opnfv_tests.vnf.router.'
- 'cloudify_vrouter.vrouter_base.Utilvnf'), \
- mock.patch('os.makedirs'), \
- mock.patch(
- 'functest.utils.functest_utils.get_parameter_from_yaml',
- return_value={
- 'tenant_images': 'foo',
- 'orchestrator': self.orchestrator,
- 'vnf': self.vnf, 'vnf_test_suite': '',
- 'version': 'whatever'}):
-
- self.router_vnf = cloudify_vrouter.CloudifyVrouter()
-
- self.images = {'image1': 'url1',
- 'image2': 'url2'}
- self.details = {'orchestrator': {'status': 'PASS', 'duration': 120},
- 'vnf': {},
- 'test_vnf': {}}
-
- def test_prepare_missing_param(self):
- with self.assertRaises(vnf.VnfPreparationException):
- self.router_vnf.prepare()
+ pass
if __name__ == "__main__":
diff --git a/functest/tests/unit/vnf/router/test_vrouter_base.py b/functest/tests/unit/vnf/router/test_vrouter_base.py
index 1851b201a..330093658 100644
--- a/functest/tests/unit/vnf/router/test_vrouter_base.py
+++ b/functest/tests/unit/vnf/router/test_vrouter_base.py
@@ -12,17 +12,9 @@
import logging
import unittest
-import mock
-
-from functest.opnfv_tests.vnf.router import vrouter_base
-
class VrouterOnBoardingBaseTesting(unittest.TestCase):
-
- def setUp(self):
- with mock.patch('functest.opnfv_tests.vnf.router.cloudify_vrouter.'
- 'os.makedirs'):
- self.vrouter_vnf = vrouter_base.VrouterOnBoardingBase()
+ pass
if __name__ == "__main__":
diff --git a/functest/utils/config.py b/functest/utils/config.py
index 61d8401c5..40414b88b 100644
--- a/functest/utils/config.py
+++ b/functest/utils/config.py
@@ -10,15 +10,16 @@ import six
from functest.utils import env
-class Config(object):
+class Config():
def __init__(self):
try:
- # pylint: disable=bad-continuation
with open(pkg_resources.resource_filename(
- 'functest', 'ci/config_functest.yaml')) as yfile:
+ 'functest', 'ci/config_functest.yaml'),
+ encoding='utf-8') as yfile:
self.functest_yaml = yaml.safe_load(yfile)
except Exception as error:
- raise Exception('Parse config failed: {}'.format(str(error)))
+ raise Exception(
+ f'Parse config failed: {str(error)}') from error
@staticmethod
def _merge_dicts(dict1, dict2):
@@ -34,7 +35,7 @@ class Config(object):
yield (k, dict2[k])
def patch_file(self, patch_file_path):
- with open(patch_file_path) as yfile:
+ with open(patch_file_path, encoding='utf-8') as yfile:
patch_file = yaml.safe_load(yfile)
for key in patch_file:
@@ -53,13 +54,14 @@ class Config(object):
@staticmethod
def _get_attr_further(attr_now, next): # pylint: disable=redefined-builtin
return attr_now if next == 'general' else (
- '{}_{}'.format(attr_now, next) if attr_now else next)
+ f'{attr_now}_{next}' if attr_now else next)
def fill(self):
try:
self._parse(None, self.functest_yaml)
except Exception as error:
- raise Exception('Parse config failed: {}'.format(str(error)))
+ raise Exception(
+ f'Parse config failed: {str(error)}') from error
CONF = Config()
diff --git a/functest/utils/env.py b/functest/utils/env.py
index cba935ab8..2e312726c 100644
--- a/functest/utils/env.py
+++ b/functest/utils/env.py
@@ -17,6 +17,7 @@ from xtesting.utils import env
INPUTS = {
'EXTERNAL_NETWORK': None,
'CI_LOOP': env.INPUTS['CI_LOOP'],
+ 'DEBUG': env.INPUTS['DEBUG'],
'DEPLOY_SCENARIO': env.INPUTS['DEPLOY_SCENARIO'],
'INSTALLER_TYPE': env.INPUTS['INSTALLER_TYPE'],
'SDN_CONTROLLER_IP': None,
@@ -28,11 +29,19 @@ INPUTS = {
'NODE_NAME': env.INPUTS['NODE_NAME'],
'POD_ARCH': None,
'TEST_DB_URL': env.INPUTS['TEST_DB_URL'],
- 'ENERGY_RECORDER_API_URL': env.INPUTS['ENERGY_RECORDER_API_URL'],
- 'ENERGY_RECORDER_API_USER': env.INPUTS['ENERGY_RECORDER_API_USER'],
- 'ENERGY_RECORDER_API_PASSWORD': env.INPUTS['ENERGY_RECORDER_API_PASSWORD'],
'VOLUME_DEVICE_NAME': 'vdb',
- 'NAMESERVER': '8.8.8.8'
+ 'IMAGE_PROPERTIES': '',
+ 'FLAVOR_EXTRA_SPECS': '',
+ 'NAMESERVER': '8.8.8.8',
+ 'NEW_USER_ROLE': 'Member',
+ 'USE_DYNAMIC_CREDENTIALS': 'True',
+ 'BLOCK_MIGRATION': 'False',
+ 'CLEAN_ORPHAN_SECURITY_GROUPS': 'True',
+ 'SKIP_DOWN_HYPERVISORS': 'False',
+ 'PUBLIC_ENDPOINT_ONLY': 'False',
+ 'DASHBOARD_URL': '',
+ 'VMTP_HYPERVISORS': '',
+ 'NO_TENANT_NETWORK': 'False'
}
diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py
index b614af321..eec544489 100644
--- a/functest/utils/functest_utils.py
+++ b/functest/utils/functest_utils.py
@@ -11,10 +11,14 @@
from __future__ import print_function
import logging
+import os
import subprocess
import sys
import yaml
+from shade import _utils
+import six
+
LOGGER = logging.getLogger(__name__)
@@ -28,28 +32,26 @@ def execute_command_raise(cmd, info=False, error_msg="",
def execute_command(cmd, info=False, error_msg="",
verbose=True, output_file=None):
if not error_msg:
- error_msg = ("The command '%s' failed." % cmd)
- msg_exec = ("Executing command: '%s'" % cmd)
+ error_msg = f"The command '{cmd}' failed."
+ msg_exec = f"Executing command: '{cmd}'"
if verbose:
if info:
LOGGER.info(msg_exec)
else:
LOGGER.debug(msg_exec)
- popen = subprocess.Popen(
- cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- if output_file:
- ofd = open(output_file, "w")
- for line in iter(popen.stdout.readline, b''):
+ with subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT) as popen:
if output_file:
- ofd.write(line)
- else:
- line = line.replace('\n', '')
- print (line)
- sys.stdout.flush()
- if output_file:
- ofd.close()
- popen.stdout.close()
- returncode = popen.wait()
+ with open(output_file, "w", encoding='utf-8') as ofd:
+ for line in iter(popen.stdout.readline, b''):
+ if output_file:
+ ofd.write(line.decode("utf-8"))
+ else:
+ line = line.decode("utf-8").replace('\n', '')
+ print(line)
+ sys.stdout.flush()
+ returncode = popen.wait()
if returncode != 0:
if verbose:
LOGGER.error(error_msg)
@@ -63,12 +65,161 @@ def get_parameter_from_yaml(parameter, yfile):
parameter must be given in string format with dots
Example: general.openstack.image_name
"""
- with open(yfile) as yfd:
+ with open(yfile, encoding='utf-8') as yfd:
file_yaml = yaml.safe_load(yfd)
value = file_yaml
for element in parameter.split("."):
value = value.get(element)
if value is None:
- raise ValueError("The parameter %s is not defined in"
- " %s" % (parameter, yfile))
+ raise ValueError(f"The parameter {parameter} is not defined in"
+ f" {yfile}")
return value
+
+
+def get_nova_version(cloud):
+ """ Get Nova API microversion
+
+ Returns:
+
+ - Nova API microversion
+ - None on operation error
+ """
+ # pylint: disable=protected-access
+ try:
+ request = cloud._compute_client.request("/", "GET")
+ LOGGER.debug('cloud._compute_client.request: %s', request)
+ version = request["version"]["version"]
+ major, minor = version.split('.')
+ LOGGER.debug('nova version: %s', (int(major), int(minor)))
+ return (int(major), int(minor))
+ except Exception: # pylint: disable=broad-except
+ LOGGER.exception("Cannot detect Nova version")
+ return None
+
+
+def get_openstack_version(cloud):
+ """ Detect OpenStack version via Nova API microversion
+
+ It follows `MicroversionHistory
+ <https://docs.openstack.org/nova/latest/reference/api-microversion-history.html>`_.
+
+ Returns:
+
+ - OpenStack release
+ - Unknown on operation error
+ """
+ # pylint: disable=too-many-branches
+ version = get_nova_version(cloud)
+ try:
+ assert version
+ if version > (2, 93):
+ osversion = "Master"
+ elif version > (2, 90):
+ osversion = "Zed"
+ elif version > (2, 88):
+ osversion = "Xena"
+ elif version > (2, 87):
+ osversion = "Wallaby"
+ elif version > (2, 79):
+ osversion = "Ussuri"
+ elif version > (2, 72):
+ osversion = "Train"
+ elif version > (2, 65):
+ osversion = "Stein"
+ elif version > (2, 60):
+ osversion = "Rocky"
+ elif version > (2, 53):
+ osversion = "Queens"
+ elif version > (2, 42):
+ osversion = "Pike"
+ elif version > (2, 38):
+ osversion = "Ocata"
+ elif version > (2, 25):
+ osversion = "Newton"
+ elif version > (2, 12):
+ osversion = "Mitaka"
+ elif version > (2, 3):
+ osversion = "Liberty"
+ elif version >= (2, 1):
+ osversion = "Kilo"
+ else:
+ osversion = "Unknown"
+ LOGGER.info('Detect OpenStack version: %s', osversion)
+ return osversion
+ except AssertionError:
+ LOGGER.exception("Cannot detect OpenStack version")
+ return "Unknown"
+
+
+def list_services(cloud):
+ # pylint: disable=protected-access
+ """Search Keystone services via $OS_INTERFACE.
+
+ It mainly conforms with `Shade
+ <https://docs.openstack.org/shade/latest>`_ but allows testing vs
+ public endpoints. It's worth mentioning that it doesn't support keystone
+ v2.
+
+ :returns: a list of ``munch.Munch`` containing the services description
+
+ :raises: ``OpenStackCloudException`` if something goes wrong during the
+ openstack API call.
+ """
+ url, key = '/services', 'services'
+ data = cloud._identity_client.get(
+ url, endpoint_filter={
+ 'interface': os.environ.get('OS_INTERFACE', 'public')},
+ error_message="Failed to list services")
+ services = cloud._get_and_munchify(key, data)
+ return _utils.normalize_keystone_services(services)
+
+
+def search_services(cloud, name_or_id=None, filters=None):
+ # pylint: disable=protected-access
+ """Search Keystone services ia $OS_INTERFACE.
+
+ It mainly conforms with `Shade
+ <https://docs.openstack.org/shade/latest>`_ but allows testing vs
+ public endpoints. It's worth mentioning that it doesn't support keystone
+ v2.
+
+ :param name_or_id: Name or id of the desired service.
+ :param filters: a dict containing additional filters to use. e.g.
+ {'type': 'network'}.
+
+ :returns: a list of ``munch.Munch`` containing the services description
+
+ :raises: ``OpenStackCloudException`` if something goes wrong during the
+ openstack API call.
+ """
+ services = list_services(cloud)
+ return _utils._filter_list(services, name_or_id, filters)
+
+
+def convert_dict_to_ini(value):
+ "Convert dict to oslo.conf input"
+ assert isinstance(value, dict)
+ return ",".join(f"{key}:{val}" for (key, val) in six.iteritems(value))
+
+
+def convert_list_to_ini(value):
+ "Convert list to oslo.conf input"
+ assert isinstance(value, list)
+ return ",".join(val for val in value)
+
+
+def convert_ini_to_dict(value):
+ "Convert oslo.conf input to dict"
+ assert isinstance(value, str)
+ try:
+ return dict((x.rsplit(':', 1) for x in value.split(',')))
+ except ValueError:
+ return {}
+
+
+def convert_ini_to_list(value):
+ "Convert list to oslo.conf input"
+ assert isinstance(value, str)
+ if not value:
+ return []
+ return list(value.split(','))