aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docker/Dockerfile2
-rw-r--r--nfvbench/cfg.default.yaml17
-rw-r--r--nfvbench/cleanup.py2
-rw-r--r--nfvbench/credentials.py117
-rw-r--r--nfvbench/nfvbench.py10
-rw-r--r--nfvbenchvm/README.rst26
-rw-r--r--nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.generator9
-rw-r--r--nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.loopvm3
-rw-r--r--nfvbenchvm/dib/elements/nfvbenchvm/static/nfvbench/configure-nfvbench.sh23
-rw-r--r--nfvbenchvm/dib/elements/nfvbenchvm/static/vpp/startup.conf2
-rw-r--r--requirements.txt2
-rw-r--r--test/test_nfvbench.py36
-rw-r--r--xtesting/behaveframework.py123
13 files changed, 166 insertions, 206 deletions
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 4336261..e851c76 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -40,8 +40,6 @@ RUN apt-get update && apt-get install -y \
&& wget -O nfvbenchvm-$VM_IMAGE_VER.qcow2 http://artifacts.opnfv.org/nfvbench/images/nfvbenchvm_centos-$VM_IMAGE_VER.qcow2 \
# Override Xtesting testcases.yaml file by NFVbench default one
&& cp xtesting/testcases.yaml /usr/local/lib/python3.8/dist-packages/xtesting/ci/testcases.yaml \
- # Temporary override waiting for PR approval : https://gerrit.opnfv.org/gerrit/c/functest-xtesting/+/72431
- && cp xtesting/behaveframework.py /usr/local/lib/python3.8/dist-packages/xtesting/core/behaveframework.py \
&& python3 ./docker/cleanup_generators.py \
&& rm -rf /opt/nfvbench/.git \
# Symlink for retrocompatibility 4.x
diff --git a/nfvbench/cfg.default.yaml b/nfvbench/cfg.default.yaml
index 8e822e5..c76e738 100644
--- a/nfvbench/cfg.default.yaml
+++ b/nfvbench/cfg.default.yaml
@@ -30,8 +30,25 @@
# - availability_zone
# - hypervisor_hostname
# - vlans
+# WARNING: Not used if clouds_detail is sets
openrc_file:
+# The OpenStack clouds configuration from clouds.yaml file to use.
+# clouds.yaml file must be in one of the following paths:
+# - ~/.config/openstack
+# - /etc/openstack
+# Note: If running in a container, this path must be valid in the container.
+# The only case where this field can be empty is when measuring a system that does not run
+# OpenStack or when OpenStack APIs are not accessible or OpenStack APis use is not
+# desirable. In that case the EXT service chain must be used.
+#
+# If user is not admin some parameters are mandatory and must be filled with valid values in config file such as :
+# - availability_zone
+# - hypervisor_hostname
+# - vlans
+# If a value is sets, this parameter disable the use of openrc file
+clouds_detail:
+
# Forwarder to use in nfvbenchvm image. Available options: ['vpp', 'testpmd']
vm_forwarder: testpmd
diff --git a/nfvbench/cleanup.py b/nfvbench/cleanup.py
index 23cdf56..cefdcfa 100644
--- a/nfvbench/cleanup.py
+++ b/nfvbench/cleanup.py
@@ -235,7 +235,7 @@ class Cleaner(object):
"""Cleaner for all NFVbench resources."""
def __init__(self, config):
- cred = credentials.Credentials(config.openrc_file, None, False)
+ cred = credentials.Credentials(config.openrc_file, config.clouds_detail, None, False)
session = cred.get_session()
self.neutron_client = nclient.Client('2.0', session=session)
self.nova_client = Client(2, session=session)
diff --git a/nfvbench/credentials.py b/nfvbench/credentials.py
index 4e4985f..a707ba3 100644
--- a/nfvbench/credentials.py
+++ b/nfvbench/credentials.py
@@ -21,32 +21,40 @@ import getpass
from keystoneauth1.identity import v2
from keystoneauth1.identity import v3
from keystoneauth1 import session
+import openstack
+from keystoneclient.exceptions import HTTPClientError
+
from .log import LOG
class Credentials(object):
def get_session(self):
- dct = {
- 'username': self.rc_username,
- 'password': self.rc_password,
- 'auth_url': self.rc_auth_url
- }
- auth = None
-
- if self.rc_identity_api_version == 3:
- dct.update({
- 'project_name': self.rc_project_name,
- 'project_domain_name': self.rc_project_domain_name,
- 'user_domain_name': self.rc_user_domain_name
- })
- auth = v3.Password(**dct)
+
+ if self.clouds_detail:
+ connection = openstack.connect(cloud=self.clouds_detail)
+ cred_session = connection.session
else:
- dct.update({
- 'tenant_name': self.rc_tenant_name
- })
- auth = v2.Password(**dct)
- return session.Session(auth=auth, verify=self.rc_cacert)
+ dct = {
+ 'username': self.rc_username,
+ 'password': self.rc_password,
+ 'auth_url': self.rc_auth_url
+ }
+
+ if self.rc_identity_api_version == 3:
+ dct.update({
+ 'project_name': self.rc_project_name,
+ 'project_domain_name': self.rc_project_domain_name,
+ 'user_domain_name': self.rc_user_domain_name
+ })
+ auth = v3.Password(**dct)
+ else:
+ dct.update({
+ 'tenant_name': self.rc_tenant_name
+ })
+ auth = v2.Password(**dct)
+ cred_session = session.Session(auth=auth, verify=self.rc_cacert)
+ return cred_session
def __parse_openrc(self, file):
export_re = re.compile('export OS_([A-Z_]*)="?(.*)')
@@ -91,11 +99,28 @@ class Credentials(object):
elif name == "PROJECT_DOMAIN_NAME":
self.rc_project_domain_name = value
+ # /users URL returns exception (HTTP 403) if user is not admin.
+ # try first without the version in case session already has it in
+ # Return HTTP 200 if user is admin
+ def __user_is_admin(self, url):
+ is_admin = False
+ try:
+ # check if user has admin role in OpenStack project
+ filter = {'service_type': 'identity',
+ 'interface': 'public'}
+ self.get_session().get(url, endpoint_filter=filter)
+ is_admin = True
+ except HTTPClientError as exc:
+ if exc.http_status == 403:
+ LOG.warning(
+ "User is not admin, no permission to list user roles. Exception: %s", exc)
+ return is_admin
+
#
# Read a openrc file and take care of the password
# The 2 args are passed from the command line and can be None
#
- def __init__(self, openrc_file, pwd=None, no_env=False):
+ def __init__(self, openrc_file, clouds_detail, pwd=None, no_env=False):
self.rc_password = None
self.rc_username = None
self.rc_tenant_name = None
@@ -105,8 +130,9 @@ class Credentials(object):
self.rc_user_domain_name = None
self.rc_project_domain_name = None
self.rc_project_name = None
- self.rc_identity_api_version = 2
+ self.rc_identity_api_version = 3
self.is_admin = False
+ self.clouds_detail = clouds_detail
success = True
if openrc_file:
@@ -118,7 +144,7 @@ class Credentials(object):
success = False
else:
self.__parse_openrc(openrc_file)
- elif not no_env:
+ elif not clouds_detail and not no_env:
# no openrc file passed - we assume the variables have been
# sourced by the calling shell
# just check that they are present
@@ -153,34 +179,27 @@ class Credentials(object):
# always override with CLI argument if provided
- if pwd:
- self.rc_password = pwd
- # if password not know, check from env variable
- elif self.rc_auth_url and not self.rc_password and success:
- if 'OS_PASSWORD' in os.environ and not no_env:
- self.rc_password = os.environ['OS_PASSWORD']
- else:
- # interactively ask for password
- self.rc_password = getpass.getpass(
- 'Please enter your OpenStack Password: ')
- if not self.rc_password:
- self.rc_password = ""
-
- # check if user has admin role in OpenStack project
- filter = {'service_type': 'identity',
- 'interface': 'public',
- 'region_name': self.rc_region_name}
+ if not clouds_detail:
+ if pwd:
+ self.rc_password = pwd
+ # if password not know, check from env variable
+ elif self.rc_auth_url and not self.rc_password and success:
+ if 'OS_PASSWORD' in os.environ and not no_env:
+ self.rc_password = os.environ['OS_PASSWORD']
+ else:
+ # interactively ask for password
+ self.rc_password = getpass.getpass(
+ 'Please enter your OpenStack Password: ')
+ if not self.rc_password:
+ self.rc_password = ""
+
+
try:
# /users URL returns exception (HTTP 403) if user is not admin.
# try first without the version in case session already has it in
# Return HTTP 200 if user is admin
- self.get_session().get('/users', endpoint_filter=filter)
- self.is_admin = True
- except Exception:
- try:
- # vX/users URL returns exception (HTTP 403) if user is not admin.
- self.get_session().get('/v' + str(self.rc_identity_api_version) + '/users',
- endpoint_filter=filter)
- self.is_admin = True
- except Exception as e:
- LOG.warning("User is not admin, no permission to list user roles. Exception: %s", e)
+ self.is_admin = self.__user_is_admin('/users') or self.__user_is_admin(
+ '/v2/users') or self.__user_is_admin('/v3/users')
+ except Exception as e:
+ LOG.warning("Error occurred during Openstack API access. "
+ "Unable to check user is admin. Exception: %s", e)
diff --git a/nfvbench/nfvbench.py b/nfvbench/nfvbench.py
index 598247a..0719247 100644
--- a/nfvbench/nfvbench.py
+++ b/nfvbench/nfvbench.py
@@ -60,8 +60,8 @@ class NFVBench(object):
self.config_plugin = config_plugin
self.factory = factory
self.notifier = notifier
- self.cred = credentials.Credentials(config.openrc_file, None, False) \
- if config.openrc_file else None
+ self.cred = credentials.Credentials(config.openrc_file, config.clouds_detail, None, False) \
+ if config.openrc_file or config.clouds_detail else None
self.chain_runner = None
self.specs = Specs()
self.specs.set_openstack_spec(openstack_spec)
@@ -96,8 +96,10 @@ class NFVBench(object):
# check that an empty openrc file (no OpenStack) is only allowed
# with EXT chain
- if not self.config.openrc_file and self.config.service_chain != ChainType.EXT:
- raise Exception("openrc_file in the configuration is required for PVP/PVVP chains")
+ if (not self.config.openrc_file and not self.config.clouds_detail) and \
+ self.config.service_chain != ChainType.EXT:
+ raise Exception("openrc_file or clouds_detail in the configuration is required"
+ " for PVP/PVVP chains")
self.specs.set_run_spec(self.config_plugin.get_run_spec(self.config,
self.specs.openstack))
diff --git a/nfvbenchvm/README.rst b/nfvbenchvm/README.rst
index 0274c75..dad9f46 100644
--- a/nfvbenchvm/README.rst
+++ b/nfvbenchvm/README.rst
@@ -95,6 +95,29 @@ Hardcoded Username and Password
GENERATOR IMAGE INSTANCE AND CONFIG
===================================
+Pre-requisites
+--------------
+To use openstack APIs, NFVbench generator VM will use `clouds.yaml` file as openstack configuration.
+The OpenStack clouds configuration from clouds.yaml file to use.
+clouds.yaml file must be in one of the following paths:
+- ~/.config/openstack
+- /etc/openstack
+
+Example of `clouds.yaml`:
+
+.. code-block:: yaml
+
+ clouds:
+ devstack:
+ auth:
+ auth_url: http://192.168.122.10:35357/
+ project_name: demo
+ username: demo
+ password: 0penstack
+ region_name: RegionOne
+
+.. note:: Add `CLOUD_DETAIL` property with the accurate value for your openstack configuration (`devstack` in the above example) in ``/etc/nfvbenchvm.conf``
+
Interface Requirements
----------------------
The instance must be launched using OpenStack with 2 network interfaces for dataplane traffic (using SR-IOV function) and 1 management interface to control nfvbench.
@@ -135,6 +158,7 @@ Template of a genarator profile using CPU pinning:
pci: "{{PCI_ADDRESS_2}}"
switch:
intf_speed:
+
.. note:: `CORE_THREADS` value is determined automatically based on the cores available on the VM starting from 2 to last worker core available.
Auto-configuration
@@ -155,6 +179,7 @@ Example of configuration:
LOOPBACK_INTF_MAC2=FA:16:3E:10:DA:10
E2E_INTF_MAC1=FA:16:3E:B0:E2:43
E2E_INTF_MAC2=FA:16:3E:D3:6A:FC
+
.. note:: `ACTION` parameter is not mandatory but will permit to start NFVbench with the accurate ports (loopback or e2e).
.. note:: Set of MAC parameters cannot be used in parallel as only one NFVbench/TRex process is running.
.. note:: Switching from `loopback` to `e2e` action can be done manually using `/nfvbench/start-nfvbench.sh <action>` with the accurate keyword for `action` parameter. This script will restart NFVbench with the good set of MAC.
@@ -185,6 +210,7 @@ Using pre-created direct-physical ports on openstack, mac addresses value are on
INTF_MGMT_CIDR=172.20.56.228/2
INTF_MGMT_IP_GW=172.20.56.225
DNS_SERVERS=8.8.8.8,dns.server.com
+
.. note:: A management interface is required to automatically find the virtual interface to use according to the MAC address provided (see `INTF_MAC_MGMT` parameter).
.. note:: NFVbench VM will call openstack API through the management interface to retrieve mac address for these ports
.. note:: If openstack API required a host name resolution, add the parameter DNS_SERVERS to add IP or DNS server names (multiple servers can be added separated by a `,`)
diff --git a/nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.generator b/nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.generator
index 0746fd6..633403c 100644
--- a/nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.generator
+++ b/nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.generator
@@ -4,7 +4,6 @@ touch /var/lock/subsys/local
# Waiting for cloud-init to generate $NFVBENCH_CONF, retry 60 seconds
NFVBENCH_CONF=/etc/nfvbenchvm.conf
-OPENRC=/etc/nfvbench/openrc
retry=30
until [ $retry -eq 0 ]; do
if [ -f $NFVBENCH_CONF ]; then break; fi
@@ -20,10 +19,6 @@ echo "Generating configurations for NFVbench and TRex..."
eval $(cat $NFVBENCH_CONF)
touch /nfvbench_configured.flag
-if [ -f $OPENRC ]; then
- source $OPENRC
-fi
-
# Add DNS entry
if [ $DNS_SERVERS ]; then
IFS="," read -a dns <<< $DNS_SERVERS
@@ -80,8 +75,8 @@ get_eth_port() {
if [ $INTF_MGMT_CIDR ] && [ $INTF_MGMT_IP_GW ]; then
if [ $INTF_MAC_MGMT ]; then
ETH_PORT=$(get_eth_port $INTF_MAC_MGMT)
- elif [ -f $OPENRC ] && [ "$PORT_MGMT_NAME" ]; then
- $INTF_MAC_MGMT=$(openstack port list | grep $PORT_MGMT_NAME | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
+ elif [ "$CLOUD_DETAIL" ] && [ "$PORT_MGMT_NAME" ]; then
+ $INTF_MAC_MGMT=$(openstack --os-cloud $CLOUD_DETAIL port list | grep $PORT_MGMT_NAME | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
ETH_PORT=$(get_eth_port $INTF_MAC_MGMT)
else
ETH_PORT=""
diff --git a/nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.loopvm b/nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.loopvm
index bc14902..ecc8b05 100644
--- a/nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.loopvm
+++ b/nfvbenchvm/dib/elements/nfvbenchvm/static/etc/rc.d/rc.local.loopvm
@@ -167,10 +167,11 @@ fi
if [ $PCI_ADDRESS_1 ] && [ $PCI_ADDRESS_2 ]; then
logger "NFVBENCHVM: Using pci $PCI_ADDRESS_1 ($INTF_MAC1)"
logger "NFVBENCHVM: Using pci $PCI_ADDRESS_2 ($INTF_MAC2)"
+ # active uio_pci_generic driver
+ modprobe uio_pci_generic
# Configure the forwarder
if [ "$FORWARDER" == "testpmd" ]; then
echo "Configuring testpmd..."
- modprobe uio_pci_generic
mkdir /dpdk
echo "set promisc all off" > /dpdk/testpmd_cmd.txt
# Binding ports to DPDK VFIO or UIO
diff --git a/nfvbenchvm/dib/elements/nfvbenchvm/static/nfvbench/configure-nfvbench.sh b/nfvbenchvm/dib/elements/nfvbenchvm/static/nfvbench/configure-nfvbench.sh
index 5ec584b..3bf1d8d 100644
--- a/nfvbenchvm/dib/elements/nfvbenchvm/static/nfvbench/configure-nfvbench.sh
+++ b/nfvbenchvm/dib/elements/nfvbenchvm/static/nfvbench/configure-nfvbench.sh
@@ -6,15 +6,10 @@ NFVBENCH_CONF=/etc/nfvbenchvm.conf
E2E_CFG=/etc/nfvbench/e2e.cfg
LOOPBACK_CFG=/etc/nfvbench/loopback.cfg
NFVBENCH_CFG=/etc/nfvbench/nfvbench.cfg
-OPENRC=/etc/nfvbench/openrc
# Parse and obtain all configurations
eval $(cat $NFVBENCH_CONF)
-if [ -f $OPENRC ]; then
- source $OPENRC
-fi
-
# WE assume there are at least 2 cores available for the VM
CPU_CORES=$(grep -c ^processor /proc/cpuinfo)
@@ -88,21 +83,21 @@ get_interfaces_mac_values(){
# Set dynamically interfaces mac values, if VM is spawn with SRIOV PF ports
# and openstack API are accessible
if [ -z "$LOOPBACK_INTF_MAC1" ] && [ -z "$LOOPBACK_INTF_MAC2" ]; then
- if [ -f $OPENRC ] && [ "$LOOPBACK_PORT_NAME1" ] && [ "$LOOPBACK_PORT_NAME2" ]; then
- LOOPBACK_INTF_MAC1=$(openstack port list | grep $LOOPBACK_PORT_NAME1 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
- LOOPBACK_INTF_MAC2=$(openstack port list | grep $LOOPBACK_PORT_NAME2 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
+ if [ "$CLOUD_DETAIL" ] && [ "$LOOPBACK_PORT_NAME1" ] && [ "$LOOPBACK_PORT_NAME2" ]; then
+ LOOPBACK_INTF_MAC1=$(openstack --os-cloud $CLOUD_DETAIL port list | grep $LOOPBACK_PORT_NAME1 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
+ LOOPBACK_INTF_MAC2=$(openstack --os-cloud $CLOUD_DETAIL port list | grep $LOOPBACK_PORT_NAME2 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
fi
fi
if [ -z "$E2E_INTF_MAC1" ] && [ -z "$E2E_INTF_MAC2" ]; then
- if [ -f $OPENRC ] && [ "$E2E_PORT_NAME1" ] && [ "$E2E_PORT_NAME2" ]; then
- E2E_INTF_MAC1=$(openstack port list | grep $E2E_PORT_NAME1 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
- E2E_INTF_MAC2=$(openstack port list | grep $E2E_PORT_NAME2 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
+ if [ "$CLOUD_DETAIL" ] && [ "$E2E_PORT_NAME1" ] && [ "$E2E_PORT_NAME2" ]; then
+ E2E_INTF_MAC1=$(openstack --os-cloud $CLOUD_DETAIL port list | grep $E2E_PORT_NAME1 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
+ E2E_INTF_MAC2=$(openstack --os-cloud $CLOUD_DETAIL port list | grep $E2E_PORT_NAME2 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
fi
fi
if [ -z "$INTF_MAC1" ] && [ -z "$INTF_MAC2" ]; then
- if [ -f $OPENRC ] && [ "$PORT_NAME1" ] && [ "$PORT_NAME2" ]; then
- INTF_MAC1=$(openstack port list | grep $PORT_NAME1 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
- INTF_MAC2=$(openstack port list | grep $PORT_NAME2 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
+ if [ "$CLOUD_DETAIL" ] && [ "$PORT_NAME1" ] && [ "$PORT_NAME2" ]; then
+ INTF_MAC1=$(openstack --os-cloud $CLOUD_DETAIL port list | grep $PORT_NAME1 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
+ INTF_MAC2=$(openstack --os-cloud $CLOUD_DETAIL port list | grep $PORT_NAME2 | grep -o -Ei '([a-fA-F0-9:]{17}|[a-fA-F0-9]{12}$)' | head -1)
fi
fi
}
diff --git a/nfvbenchvm/dib/elements/nfvbenchvm/static/vpp/startup.conf b/nfvbenchvm/dib/elements/nfvbenchvm/static/vpp/startup.conf
index d174299..874f6cb 100644
--- a/nfvbenchvm/dib/elements/nfvbenchvm/static/vpp/startup.conf
+++ b/nfvbenchvm/dib/elements/nfvbenchvm/static/vpp/startup.conf
@@ -19,7 +19,7 @@ dpdk {
socket-mem 1024
dev {{PCI_ADDRESS_1}}
dev {{PCI_ADDRESS_2}}
- uio-driver igb_uio
+ uio-driver uio_pci_generic
num-mbufs {{NUM_MBUFS}}
}
diff --git a/requirements.txt b/requirements.txt
index 7c74119..a333380 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -22,7 +22,7 @@ tabulate>=0.7.5
flask>=0.12
fluent-logger>=0.5.3
netaddr>=0.7.19
-xtesting>=0.87.0
+xtesting>=0.92.0
hdrhistogram>=0.8.0
behave>=1.2.6
retry>=0.9.2 \ No newline at end of file
diff --git a/test/test_nfvbench.py b/test/test_nfvbench.py
index e53a586..360e3bd 100644
--- a/test/test_nfvbench.py
+++ b/test/test_nfvbench.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
#
+import openstack
+from keystoneauth1.exceptions import HTTPClientError
from mock import patch
import pytest
@@ -139,13 +141,41 @@ def test_load_from_rate():
# =========================================================================
def test_no_credentials():
- cred = Credentials('/completely/wrong/path/openrc', None, False)
- if cred.rc_auth_url:
- # shouldn't get valid data unless user set environment variables
+ with patch.object(openstack, 'connect') as mock:
+ cred = Credentials('/completely/wrong/path/openrc', None, None, False)
+ if cred.rc_auth_url:
+ # shouldn't get valid data unless user set environment variables
+ assert False
+ else:
+ assert True
+ mock.assert_not_called()
+
+
+def test_clouds_file_credentials():
+ with patch.object(openstack, 'connect') as mock:
+ Credentials(None, 'openstack', None, False)
+ mock.assert_called_once()
+
+
+@patch('nfvbench.nfvbench.credentials')
+def test_is_not_admin(mock_session):
+ mock_session.Session.return_value.get.return_value.raiseError.side_effect = HTTPClientError
+ cred = Credentials(None, 'openstack', None, False)
+ if cred.is_admin:
assert False
else:
assert True
+
+def test_is_admin():
+ with patch.object(openstack, 'connect'):
+ cred = Credentials(None, 'openstack', None, False)
+ if cred.is_admin:
+ assert True
+ else:
+ assert False
+
+
def test_ip_block():
ipb = IpBlock('10.0.0.0', '0.0.0.1', 256)
assert ipb.get_ip() == '10.0.0.0'
diff --git a/xtesting/behaveframework.py b/xtesting/behaveframework.py
deleted file mode 100644
index 651240d..0000000
--- a/xtesting/behaveframework.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2021 Orange
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-"""Define classes required to run any Behave test suites."""
-
-from __future__ import division
-
-import logging
-import os
-import time
-
-import json
-import six
-
-from behave.__main__ import main as behave_main
-
-from xtesting.core import testcase
-
-__author__ = "Deepak Chandella <deepak.chandella@orange.com>"
-
-
-class BehaveFramework(testcase.TestCase):
- """BehaveFramework runner."""
- # pylint: disable=too-many-instance-attributes
-
- __logger = logging.getLogger(__name__)
- dir_results = "/var/lib/xtesting/results"
-
- def __init__(self, **kwargs):
- super().__init__(**kwargs)
- self.json_file = os.path.join(self.res_dir, 'output.json')
- self.total_tests = 0
- self.pass_tests = 0
- self.fail_tests = 0
- self.skip_tests = 0
- self.response = None
-
- def parse_results(self):
- """Parse output.json and get the details in it."""
- with open(self.json_file) as stream_:
- self.response = json.load(stream_)
- if self.response:
- self.total_tests = len(self.response)
- for item in self.response:
- if item['status'] == 'passed':
- self.pass_tests += 1
- elif item['status'] == 'failed':
- self.fail_tests += 1
- elif item['status'] == 'skipped':
- self.skip_tests += 1
- self.result = 100 * (
- self.pass_tests / self.total_tests)
- self.details = {}
- self.details['total_tests'] = self.total_tests
- self.details['pass_tests'] = self.pass_tests
- self.details['fail_tests'] = self.fail_tests
- self.details['skip_tests'] = self.skip_tests
- self.details['tests'] = self.response
-
- def run(self, **kwargs):
- """Run the BehaveFramework feature files
-
- Here are the steps:
- * create the output directories if required,
- * run behave features with parameters
- * get the results in output.json,
-
- Args:
- kwargs: Arbitrary keyword arguments.
-
- Returns:
- EX_OK if all suites ran well.
- EX_RUN_ERROR otherwise.
- """
- try:
- suites = kwargs["suites"]
- tags = kwargs.get("tags", [])
- console = kwargs["console"] if "console" in kwargs else False
- except KeyError:
- self.__logger.exception("Mandatory args were not passed")
- return self.EX_RUN_ERROR
- if not os.path.exists(self.res_dir):
- try:
- os.makedirs(self.res_dir)
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot create %s", self.res_dir)
- return self.EX_RUN_ERROR
- config = ['--tags=' + ','.join(tags),
- '--junit', '--junit-directory={}'.format(self.res_dir),
- '--format=json', '--outfile={}'.format(self.json_file)]
- if six.PY3:
- html_file = os.path.join(self.res_dir, 'output.html')
- config += ['--format=behave_html_formatter:HTMLFormatter',
- '--outfile={}'.format(html_file)]
- if console:
- config += ['--format=pretty',
- '--outfile=-']
- for feature in suites:
- config.append(feature)
- self.start_time = time.time()
- behave_main(config)
- self.stop_time = time.time()
-
- try:
- self.parse_results()
- self.__logger.info("Results were successfully parsed")
- except Exception: # pylint: disable=broad-except
- self.__logger.exception("Cannot parse results")
- return self.EX_RUN_ERROR
- return self.EX_OK