aboutsummaryrefslogtreecommitdiffstats
path: root/functest
diff options
context:
space:
mode:
Diffstat (limited to 'functest')
-rwxr-xr-xfunctest/ci/config_functest.yaml44
-rwxr-xr-xfunctest/ci/exec_test.sh8
-rwxr-xr-xfunctest/ci/prepare_env.py6
-rwxr-xr-xfunctest/ci/run_tests.py4
-rwxr-xr-xfunctest/ci/testcases.yaml30
-rw-r--r--functest/core/feature_base.py1
-rw-r--r--functest/core/vnf_base.py26
-rwxr-xr-xfunctest/opnfv_tests/features/security_scan.py24
-rw-r--r--functest/opnfv_tests/openstack/rally/rally.py9
-rw-r--r--functest/opnfv_tests/openstack/snaps/health_check.py34
-rw-r--r--functest/opnfv_tests/openstack/tempest/conf_utils.py56
-rw-r--r--functest/opnfv_tests/openstack/tempest/tempest.py67
-rw-r--r--functest/opnfv_tests/security_scan/config.ini29
-rw-r--r--functest/opnfv_tests/security_scan/connect.py245
-rw-r--r--functest/opnfv_tests/security_scan/examples/xccdf-rhel7-server-upstream.ini29
-rw-r--r--functest/opnfv_tests/security_scan/examples/xccdf-standard.ini29
-rw-r--r--functest/opnfv_tests/security_scan/scripts/createfiles.py26
-rw-r--r--functest/opnfv_tests/security_scan/scripts/internet_check.py27
-rwxr-xr-xfunctest/opnfv_tests/security_scan/security_scan.py220
-rw-r--r--functest/opnfv_tests/vnf/ims/cloudify_ims.py212
-rw-r--r--functest/opnfv_tests/vnf/ims/cloudify_ims.yaml39
-rw-r--r--functest/tests/unit/utils/test_openstack_utils.py36
-rwxr-xr-xfunctest/utils/openstack_utils.py15
23 files changed, 384 insertions, 832 deletions
diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml
index f6cb14cb..d0442cf9 100755
--- a/functest/ci/config_functest.yaml
+++ b/functest/ci/config_functest.yaml
@@ -5,7 +5,6 @@ general:
dir_odl: functest/opnfv_tests/sdn/odl
rally: functest/opnfv_tests/openstack/rally
tempest_cases: functest/opnfv_tests/openstack/tempest/custom_tests
- dir_vIMS: functest/opnfv_tests/vnf/ims
dir_onos: functest/opnfv_tests/sdn/onos/teston
dir_onos_sfc: functest/opnfv_tests/sdn/onos/sfc
@@ -27,13 +26,14 @@ general:
repo_parser: /home/opnfv/repos/parser
repo_domino: /home/opnfv/repos/domino
repo_snaps: /home/opnfv/repos/snaps
+ repo_securityscan: /home/opnfv/repos/securityscanning
functest: /home/opnfv/functest
functest_test: /home/opnfv/repos/functest/functest/opnfv_tests
results: /home/opnfv/functest/results
functest_logging_cfg: /home/opnfv/repos/functest/functest/ci/logging.json
functest_conf: /home/opnfv/functest/conf
functest_data: /home/opnfv/functest/data
- dir_vIMS_data: /home/opnfv/functest/data/vIMS/
+ ims_data: /home/opnfv/functest/data/ims/
rally_inst: /home/opnfv/.rally
openstack:
@@ -125,45 +125,7 @@ vnf:
cloudify_ims:
tenant_name: cloudify_ims
tenant_description: vIMS
- tenant_images:
- ubuntu_14.04: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img
- centos_7: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1510.qcow2
- cloudify:
- blueprint:
- url: https://github.com/boucherv-orange/cloudify-manager-blueprints.git
- branch: "3.3.1-build"
- requierments:
- ram_min: 3000
- os_image: centos_7
- inputs:
- keystone_username: ""
- keystone_password: ""
- keystone_tenant_name: ""
- keystone_url: ""
- manager_public_key_name: 'manager-kp'
- agent_public_key_name: 'agent-kp'
- image_id: ""
- flavor_id: "3"
- external_network_name: ""
- ssh_user: centos
- agents_user: ubuntu
- clearwater:
- blueprint:
- file_name: 'openstack-blueprint.yaml'
- name: "clearwater-opnfv"
- destination_folder: "opnfv-cloudify-clearwater"
- url: https://github.com/Orange-OpenSource/opnfv-cloudify-clearwater.git
- branch: "stable"
- deployment_name: 'clearwater-opnfv'
- requirements:
- ram_min: 1700
- os_image: ubuntu_14.04
- inputs:
- image_id: ''
- flavor_id: ''
- agent_user: 'ubuntu'
- external_network_name: ''
- public_domain: clearwater.opnfv
+ config: cloudify_ims.yaml
orchestra_ims:
tenant_name: orchestra_ims
tenant_description: ims deployed with openbaton
diff --git a/functest/ci/exec_test.sh b/functest/ci/exec_test.sh
index 6a2b55a2..aa0cfaf7 100755
--- a/functest/ci/exec_test.sh
+++ b/functest/ci/exec_test.sh
@@ -105,14 +105,6 @@ function run_test(){
# no need to run anything until refactoring done
# ${REPOS_DIR}/ovno/Testcases/RunTests.sh
;;
- "security_scan")
- echo "Sourcing Credentials ${FUNCTEST_CONF_DIR}/stackrc for undercloud .."
- source ${FUNCTEST_CONF_DIR}/stackrc
- python ${FUNCTEST_TEST_DIR}/security_scan/security_scan.py --config ${FUNCTEST_TEST_DIR}/security_scan/config.ini
- ;;
- "moon")
- python ${REPOS_DIR}/moon/tests/run_tests.py $report
- ;;
*)
echo "The test case '${test_name}' does not exist."
exit 1
diff --git a/functest/ci/prepare_env.py b/functest/ci/prepare_env.py
index b3e59020..cca9ac73 100755
--- a/functest/ci/prepare_env.py
+++ b/functest/ci/prepare_env.py
@@ -170,12 +170,10 @@ def source_rc_file():
sys.exit(1)
logger.info("Sourcing the OpenStack RC file...")
- creds = os_utils.source_credentials(
+ os_utils.source_credentials(
CONST.openstack_creds)
- str = ""
- for key, value in creds.iteritems():
+ for key, value in os.environ.iteritems():
if re.search("OS_", key):
- str += "\n\t\t\t\t\t\t " + key + "=" + value
if key == 'OS_AUTH_URL':
CONST.OS_AUTH_URL = value
elif key == 'OS_USERNAME':
diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py
index 320102dd..6a6516ab 100755
--- a/functest/ci/run_tests.py
+++ b/functest/ci/run_tests.py
@@ -78,8 +78,8 @@ def source_rc_file():
logger.error("RC file %s does not exist..." % rc_file)
sys.exit(1)
logger.debug("Sourcing the OpenStack RC file...")
- creds = os_utils.source_credentials(rc_file)
- for key, value in creds.iteritems():
+ os_utils.source_credentials(rc_file)
+ for key, value in os.environ.iteritems():
if re.search("OS_", key):
if key == 'OS_AUTH_URL':
ft_constants.OS_AUTH_URL = value
diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml
index 6397f764..6007f972 100755
--- a/functest/ci/testcases.yaml
+++ b/functest/ci/testcases.yaml
@@ -19,6 +19,22 @@ tiers:
installer: ''
scenario: '^((?!lxd).)*$'
-
+ name: snaps_health_check
+ criteria: 'status == "PASS"'
+ 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.
+
+ dependencies:
+ installer: ''
+ scenario: '^((?!lxd).)*$'
+ run:
+ module: 'functest.opnfv_tests.openstack.snaps.health_check'
+ class: 'HealthCheck'
+ -
name: connection_check
criteria: 'status == "PASS"'
blocking: true
@@ -223,10 +239,13 @@ tiers:
criteria: 'status == "PASS"'
blocking: false
description: >-
- Simple security Scan
+ Simple Security Scan
dependencies:
installer: 'apex'
scenario: '^((?!fdio).)*$'
+ run:
+ module: 'functest.opnfv_tests.features.security_scan'
+ class: 'SecurityScan'
# -
# name: copper
# criteria: 'status == "PASS"'
@@ -240,15 +259,6 @@ tiers:
# module: 'functest.opnfv_tests.features.copper'
# class: 'Copper'
-
- name: moon
- criteria: 'status == "PASS"'
- blocking: false
- description: >-
- Security management system for OPNFV
- dependencies:
- installer: 'compass'
- scenario: '(odl)*(moon)'
- -
name: multisite
criteria: 'success_rate == 100%'
blocking: false
diff --git a/functest/core/feature_base.py b/functest/core/feature_base.py
index 873e21da..fe9a9998 100644
--- a/functest/core/feature_base.py
+++ b/functest/core/feature_base.py
@@ -24,6 +24,7 @@ class FeatureBase(base.TestcaseBase):
self.post()
self.parse_results(ret)
self.log_results()
+ self.logger.info("Test result is stored in '%s'" % self.result_file)
return base.TestcaseBase.EX_OK
def prepare(self, **kwargs):
diff --git a/functest/core/vnf_base.py b/functest/core/vnf_base.py
index 4d019858..44b4ae04 100644
--- a/functest/core/vnf_base.py
+++ b/functest/core/vnf_base.py
@@ -7,12 +7,10 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
-import os
import time
import inspect
-
import functest.utils.functest_logger as ft_logger
import functest.utils.openstack_utils as os_utils
import functest.utils.functest_utils as ft_utils
@@ -161,30 +159,6 @@ class VnfOnBoardingBase(base.TestcaseBase):
"username": self.tenant_name,
"password": self.tenant_name,
})
- self.glance_client = os_utils.get_glance_client(self.creds)
- self.logger.info("Upload some OS images if it doesn't exist")
-
- temp_dir = os.path.join(self.data_dir, "tmp/")
- for image_name, image_url in self.images.iteritems():
- image_id = os_utils.get_image_id(self.glance_client, image_name)
-
- if image_id == '':
- self.logger.info("""%s image doesn't exist on glance repository. Try
- downloading this image and upload on glance !""" % image_name)
- image_id = os_utils.download_and_add_image_on_glance(
- self.glance_client, image_name, image_url, temp_dir)
-
- if image_id == '':
- self.step_failure(
- "Failed to find or upload required OS "
- "image for this deployment")
-
- self.logger.info("Update security group quota for this tenant")
-
- if not os_utils.update_sg_quota(self.neutron_client,
- tenant_id, 50, 100):
- self.step_failure("Failed to update security group quota" +
- " for tenant " + self.tenant_name)
# orchestrator is not mandatory to dpeloy and test VNF
def deploy_orchestrator(self, **kwargs):
diff --git a/functest/opnfv_tests/features/security_scan.py b/functest/opnfv_tests/features/security_scan.py
new file mode 100755
index 00000000..bcae516b
--- /dev/null
+++ b/functest/opnfv_tests/features/security_scan.py
@@ -0,0 +1,24 @@
+#!/usr/bin/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
+#
+
+import functest.core.feature_base as base
+from functest.utils.constants import CONST
+
+
+class SecurityScan(base.FeatureBase):
+ def __init__(self):
+ super(SecurityScan, self).__init__(project='security_scan',
+ case='security_scan',
+ repo='dir_repo_securityscan')
+ self.cmd = ('bash {0} && '
+ 'cd {1} && '
+ 'python security_scan.py --config config.ini && '
+ 'cd -'.format(CONST.openstack_creds,
+ self.repo))
diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py
index 16a872fc..46d6a570 100644
--- a/functest/opnfv_tests/openstack/rally/rally.py
+++ b/functest/opnfv_tests/openstack/rally/rally.py
@@ -526,14 +526,13 @@ class RallyBase(testcase_base.TestcaseBase):
self._run_tests()
self._generate_report()
self._clean_up()
+ res = testcase_base.TestcaseBase.EX_OK
except Exception as e:
logger.error('Error with run: %s' % e)
- return testcase_base.TestcaseBase.EX_RUN_ERROR
- self.stop_time = time.time()
+ res = testcase_base.TestcaseBase.EX_RUN_ERROR
- # If we are here, it means that the test case was successfully executed
- # criteria is managed by the criteria Field
- return testcase_base.TestcaseBase.EX_OK
+ self.stop_time = time.time()
+ return res
class RallySanity(RallyBase):
diff --git a/functest/opnfv_tests/openstack/snaps/health_check.py b/functest/opnfv_tests/openstack/snaps/health_check.py
new file mode 100644
index 00000000..993c1000
--- /dev/null
+++ b/functest/opnfv_tests/openstack/snaps/health_check.py
@@ -0,0 +1,34 @@
+# 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
+
+import unittest
+
+from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
+from snaps.openstack.tests.create_instance_tests import SimpleHealthCheck
+
+from functest.core.pytest_suite_runner import PyTestSuiteRunner
+from functest.opnfv_tests.openstack.snaps import snaps_utils
+from functest.utils.constants import CONST
+
+
+class HealthCheck(PyTestSuiteRunner):
+ """
+ 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):
+ super(HealthCheck, self).__init__()
+
+ self.suite = unittest.TestSuite()
+ self.case_name = "snaps_health_check"
+ ext_net_name = snaps_utils.get_ext_net_name()
+
+ self.suite.addTest(
+ OSIntegrationTestCase.parameterize(
+ SimpleHealthCheck, CONST.openstack_creds, ext_net_name,
+ use_keystone=CONST.snaps_use_keystone))
diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py
index 91a5bb4b..03735baa 100644
--- a/functest/opnfv_tests/openstack/tempest/conf_utils.py
+++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py
@@ -13,8 +13,6 @@ import re
import shutil
import subprocess
-import opnfv.utils.constants as releng_constants
-
from functest.utils.constants import CONST
import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
@@ -110,24 +108,19 @@ def get_verifier_deployment_dir(verifier_id, deployment_id):
def configure_tempest(deployment_dir, IMAGE_ID=None, FLAVOR_ID=None):
"""
- Add/update needed parameters into tempest.conf file generated by Rally
+ Calls rally verify and updates the generated tempest.conf with
+ given parameters
"""
- tempest_conf_file = os.path.join(deployment_dir, "tempest.conf")
- if os.path.isfile(tempest_conf_file):
- logger.debug("Verifier is already configured.")
- logger.debug("Reconfiguring the current verifier...")
- cmd = "rally verify configure-verifier --reconfigure"
- else:
- logger.info("Configuring the verifier...")
- cmd = "rally verify configure-verifier"
- ft_utils.execute_command(cmd)
+ conf_verifier_result = configure_verifier(deployment_dir)
+ configure_tempest_update_params(conf_verifier_result,
+ IMAGE_ID, FLAVOR_ID)
- logger.debug("Looking for tempest.conf file...")
- if not os.path.isfile(tempest_conf_file):
- logger.error("Tempest configuration file %s NOT found."
- % tempest_conf_file)
- return releng_constants.EXIT_RUN_ERROR
+def configure_tempest_update_params(tempest_conf_file,
+ IMAGE_ID=None, FLAVOR_ID=None):
+ """
+ Add/update needed parameters into tempest.conf file
+ """
logger.debug("Updating selected tempest.conf parameters...")
config = ConfigParser.RawConfigParser()
config.read(tempest_conf_file)
@@ -178,7 +171,27 @@ def configure_tempest(deployment_dir, IMAGE_ID=None, FLAVOR_ID=None):
shutil.copyfile(tempest_conf_file,
os.path.join(TEMPEST_RESULTS_DIR, 'tempest.conf'))
- return releng_constants.EXIT_OK
+
+def configure_verifier(deployment_dir):
+ """
+ Execute rally verify configure-verifier, which generates tempest.conf
+ """
+ tempest_conf_file = os.path.join(deployment_dir, "tempest.conf")
+ if os.path.isfile(tempest_conf_file):
+ logger.debug("Verifier is already configured.")
+ logger.debug("Reconfiguring the current verifier...")
+ cmd = "rally verify configure-verifier --reconfigure"
+ else:
+ logger.info("Configuring the verifier...")
+ cmd = "rally verify configure-verifier"
+ ft_utils.execute_command(cmd)
+
+ logger.debug("Looking for tempest.conf file...")
+ 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)
def configure_tempest_multisite(deployment_dir):
@@ -191,9 +204,8 @@ def configure_tempest_multisite(deployment_dir):
logger.debug("Finding tempest.conf file...")
tempest_conf_old = os.path.join(deployment_dir, 'tempest.conf')
if not os.path.isfile(tempest_conf_old):
- logger.error("Tempest configuration file %s NOT found."
- % tempest_conf_old)
- return releng_constants.EXIT_RUN_ERROR
+ raise Exception("Tempest configuration file %s NOT found."
+ % tempest_conf_old)
# Copy tempest.conf to /home/opnfv/functest/results/tempest/
cur_path = os.path.split(os.path.realpath(__file__))[0]
@@ -265,5 +277,3 @@ def configure_tempest_multisite(deployment_dir):
config.set('kingbird', 'api_version', kingbird_api_version)
with open(tempest_conf_file, 'wb') as config_file:
config.write(config_file)
-
- return releng_constants.EXIT_OK
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
index e1a223a7..13d9e4e6 100644
--- a/functest/opnfv_tests/openstack/tempest/tempest.py
+++ b/functest/opnfv_tests/openstack/tempest/tempest.py
@@ -57,7 +57,7 @@ class TempestCommon(testcase_base.TestcaseBase):
CONST.tempest_identity_tenant_name,
CONST.tempest_identity_tenant_description)
if not tenant_id:
- logger.error("Error : Failed to create %s tenant"
+ logger.error("Failed to create %s tenant"
% CONST.tempest_identity_tenant_name)
user_id = os_utils.create_user(keystone_client,
@@ -65,7 +65,7 @@ class TempestCommon(testcase_base.TestcaseBase):
CONST.tempest_identity_user_password,
None, tenant_id)
if not user_id:
- logger.error("Error : Failed to create %s user" %
+ logger.error("Failed to create %s user" %
CONST.tempest_identity_user_name)
logger.debug("Creating private network for Tempest suite")
@@ -74,8 +74,8 @@ class TempestCommon(testcase_base.TestcaseBase):
CONST.tempest_private_subnet_name,
CONST.tempest_router_name,
CONST.tempest_private_subnet_cidr)
- if not network_dic:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ if network_dic is None:
+ raise Exception('Failed to create private network')
if CONST.tempest_use_custom_images:
# adding alternative image should be trivial should we need it
@@ -83,8 +83,8 @@ class TempestCommon(testcase_base.TestcaseBase):
_, self.IMAGE_ID = os_utils.get_or_create_image(
CONST.openstack_image_name, conf_utils.GLANCE_IMAGE_PATH,
CONST.openstack_image_disk_format)
- if not self.IMAGE_ID:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ if self.IMAGE_ID is None:
+ raise Exception('Failed to create image')
if CONST.tempest_use_custom_flavors:
# adding alternative flavor should be trivial should we need it
@@ -94,10 +94,8 @@ class TempestCommon(testcase_base.TestcaseBase):
CONST.openstack_flavor_ram,
CONST.openstack_flavor_disk,
CONST.openstack_flavor_vcpus)
- if not self.FLAVOR_ID:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
-
- return testcase_base.TestcaseBase.EX_OK
+ if self.FLAVOR_ID is None:
+ raise Exception('Failed to create flavor')
def generate_test_list(self, verifier_repo_dir):
logger.debug("Generating test case list...")
@@ -109,9 +107,8 @@ class TempestCommon(testcase_base.TestcaseBase):
shutil.copyfile(
conf_utils.TEMPEST_CUSTOM, conf_utils.TEMPEST_RAW_LIST)
else:
- logger.error("Tempest test list file %s NOT found."
- % conf_utils.TEMPEST_CUSTOM)
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ raise Exception("Tempest test list file %s NOT found."
+ % conf_utils.TEMPEST_CUSTOM)
else:
if self.MODE == 'smoke':
testr_mode = "smoke"
@@ -128,8 +125,6 @@ class TempestCommon(testcase_base.TestcaseBase):
conf_utils.TEMPEST_RAW_LIST))
ft_utils.execute_command(cmd)
- return testcase_base.TestcaseBase.EX_OK
-
def apply_tempest_blacklist(self):
logger.debug("Applying tempest blacklist...")
cases_file = self.read_file(conf_utils.TEMPEST_RAW_LIST)
@@ -164,7 +159,6 @@ class TempestCommon(testcase_base.TestcaseBase):
else:
result_file.write(str(cases_line) + '\n')
result_file.close()
- return testcase_base.TestcaseBase.EX_OK
def _parse_verification_id(line):
first_pos = line.index("UUID=") + len("UUID=")
@@ -217,7 +211,7 @@ class TempestCommon(testcase_base.TestcaseBase):
f_env.close()
def parse_verifier_result(self):
- if not self.VERIFICATION_ID:
+ if self.VERIFICATION_ID is None:
raise Exception('Verification UUID not found')
cmd_line = "rally verify show --uuid {}".format(self.VERIFICATION_ID)
@@ -274,33 +268,22 @@ class TempestCommon(testcase_base.TestcaseBase):
if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR):
os.makedirs(conf_utils.TEMPEST_RESULTS_DIR)
- # Pre-configuration
- res = self.create_tempest_resources()
- if res != testcase_base.TestcaseBase.EX_OK:
- return res
-
- res = conf_utils.configure_tempest(self.DEPLOYMENT_DIR,
- self.IMAGE_ID,
- self.FLAVOR_ID)
- if res != testcase_base.TestcaseBase.EX_OK:
- return res
-
- res = self.generate_test_list(self.VERIFIER_REPO_DIR)
- if res != testcase_base.TestcaseBase.EX_OK:
- return res
-
- res = self.apply_tempest_blacklist()
- if res != testcase_base.TestcaseBase.EX_OK:
- return res
-
- self.run_verifier_tests()
- self.parse_verifier_result()
+ try:
+ self.create_tempest_resources()
+ conf_utils.configure_tempest(self.DEPLOYMENT_DIR,
+ self.IMAGE_ID,
+ self.FLAVOR_ID)
+ self.generate_test_list(self.VERIFIER_REPO_DIR)
+ self.apply_tempest_blacklist()
+ self.run_verifier_tests()
+ self.parse_verifier_result()
+ res = testcase_base.TestcaseBase.EX_OK
+ except Exception as e:
+ logger.error('Error with run: %s' % e)
+ res = testcase_base.TestcaseBase.EX_RUN_ERROR
self.stop_time = time.time()
-
- # If we are here, it means that the test case was successfully executed
- # criteria is managed by the criteria Field
- return testcase_base.TestcaseBase.EX_OK
+ return res
class TempestSmokeSerial(TempestCommon):
diff --git a/functest/opnfv_tests/security_scan/config.ini b/functest/opnfv_tests/security_scan/config.ini
deleted file mode 100644
index b97de80f..00000000
--- a/functest/opnfv_tests/security_scan/config.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-[undercloud]
-port = 22
-user = stack
-remotekey = /home/stack/.ssh/id_rsa
-localkey = /root/.ssh/overCloudKey
-
-[controller]
-port = 22
-user = heat-admin
-scantype = xccdf
-secpolicy = /usr/share/xml/scap/ssg/content/ssg-centos7-xccdf.xml
-cpe = /usr/share/xml/scap/ssg/content/ssg-rhel7-cpe-dictionary.xml
-profile = stig-rhel7-server-upstream
-report = report.html
-results = results.xml
-reports_dir=/home/opnfv/functest/results/security_scan/
-clean = True
-
-[compute]
-port = 22
-user = heat-admin
-scantype = xccdf
-secpolicy = /usr/share/xml/scap/ssg/content/ssg-centos7-xccdf.xml
-cpe = /usr/share/xml/scap/ssg/content/ssg-rhel7-cpe-dictionary.xml
-profile = sstig-rhel7-server-upstream
-report = report.html
-results = results.xml
-reports_dir=/home/opnfv/functest/results/security_scan/
-clean = True
diff --git a/functest/opnfv_tests/security_scan/connect.py b/functest/opnfv_tests/security_scan/connect.py
deleted file mode 100644
index 3d5456c5..00000000
--- a/functest/opnfv_tests/security_scan/connect.py
+++ /dev/null
@@ -1,245 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 Red Hat
-# Luke Hinds (lhinds@redhat.com)
-# 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
-#
-# 0.1: OpenSCAP paramiko connection functions
-
-import os
-import socket
-import paramiko
-
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_constants as ft_constants
-
-# add installer IP from env
-INSTALLER_IP = ft_constants.CI_INSTALLER_IP
-
-# Set up loggers
-logger = ft_logger.Logger("security_scan").getLogger()
-paramiko.util.log_to_file("/var/log/paramiko.log")
-
-
-class SetUp:
- def __init__(self, *args):
- self.args = args
-
- def keystonepass(self):
- com = self.args[0]
- client = paramiko.SSHClient()
- privatekeyfile = os.path.expanduser('/root/.ssh/id_rsa')
- selectedkey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
- client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- try:
- client.connect(INSTALLER_IP, port=22, username='stack',
- pkey=selectedkey)
- except paramiko.SSHException:
- logger.error("Password is invalid for "
- "undercloud host: {0}".format(INSTALLER_IP))
- except paramiko.AuthenticationException:
- logger.error("Authentication failed for "
- "undercloud host: {0}".format(INSTALLER_IP))
- except socket.error:
- logger.error("Socker Connection failed for "
- "undercloud host: {0}".format(INSTALLER_IP))
- stdin, stdout, stderr = client.exec_command(com)
- return stdout.read()
- client.close()
-
- def getockey(self):
- remotekey = self.args[0]
- localkey = self.args[1]
- privatekeyfile = os.path.expanduser('/root/.ssh/id_rsa')
- selectedkey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
- transport = paramiko.Transport((INSTALLER_IP, 22))
- transport.connect(username='stack', pkey=selectedkey)
- try:
- sftp = paramiko.SFTPClient.from_transport(transport)
- except paramiko.SSHException:
- logger.error("Authentication failed for "
- "host: {0}".format(INSTALLER_IP))
- except paramiko.AuthenticationException:
- logger.error("Authentication failed for "
- "host: {0}".format(INSTALLER_IP))
- except socket.error:
- logger.error("Socker Connection failed for "
- "undercloud host: {0}".format(INSTALLER_IP))
- sftp.get(remotekey, localkey)
- sftp.close()
- transport.close()
-
-
-class ConnectionManager:
- def __init__(self, host, port, user, localkey, *args):
- self.host = host
- self.port = port
- self.user = user
- self.localkey = localkey
- self.args = args
-
- def remotescript(self):
- localpath = self.args[0]
- remotepath = self.args[1]
- com = self.args[2]
-
- client = paramiko.SSHClient()
- privatekeyfile = os.path.expanduser('/root/.ssh/id_rsa')
- selectedkey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
- client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- # Connection to undercloud
- try:
- client.connect(INSTALLER_IP, port=22, username='stack',
- pkey=selectedkey)
- except paramiko.SSHException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except paramiko.AuthenticationException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except socket.error:
- logger.error("Socker Connection failed for "
- "undercloud host: {0}".format(self.host))
-
- transport = client.get_transport()
- local_addr = ('127.0.0.1', 0)
- channel = transport.open_channel("direct-tcpip",
- (self.host, int(self.port)),
- (local_addr))
- remote_client = paramiko.SSHClient()
- remote_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- # Tunnel to overcloud
- try:
- remote_client.connect('127.0.0.1', port=22, username=self.user,
- key_filename=self.localkey, sock=channel)
- sftp = remote_client.open_sftp()
- sftp.put(localpath, remotepath)
- except paramiko.SSHException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except paramiko.AuthenticationException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except socket.error:
- logger.error("Socker Connection failed for "
- "undercloud host: {0}".format(self.host))
-
- output = ""
- stdin, stdout, stderr = remote_client.exec_command(com)
- stdout = stdout.readlines()
- # remove script
- sftp.remove(remotepath)
- remote_client.close()
- client.close()
- # Pipe back stout
- for line in stdout:
- output = output + line
- if output != "":
- return output
-
- def remotecmd(self):
- com = self.args[0]
-
- client = paramiko.SSHClient()
- privatekeyfile = os.path.expanduser('/root/.ssh/id_rsa')
- selectedkey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
- client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- # Connection to undercloud
- try:
- client.connect(INSTALLER_IP, port=22, username='stack',
- pkey=selectedkey)
- except paramiko.SSHException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except paramiko.AuthenticationException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except socket.error:
- logger.error("Socker Connection failed for "
- "undercloud host: {0}".format(self.host))
-
- transport = client.get_transport()
- local_addr = ('127.0.0.1', 0) # 0 denotes choose random port
- channel = transport.open_channel("direct-tcpip",
- (self.host, int(self.port)),
- (local_addr))
- remote_client = paramiko.SSHClient()
- remote_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- # Tunnel to overcloud
- try:
- remote_client.connect('127.0.0.1', port=22, username=self.user,
- key_filename=self.localkey, sock=channel)
- except paramiko.SSHException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except paramiko.AuthenticationException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except socket.error:
- logger.error("Socker Connection failed for "
- "undercloud host: {0}".format(self.host))
-
- chan = remote_client.get_transport().open_session()
- chan.get_pty()
- feed = chan.makefile()
- chan.exec_command(com)
- print feed.read()
-
- remote_client.close()
- client.close()
-
- def download_reports(self):
- dl_folder = self.args[0]
- reportfile = self.args[1]
- reportname = self.args[2]
- resultsname = self.args[3]
- client = paramiko.SSHClient()
- privatekeyfile = os.path.expanduser('/root/.ssh/id_rsa')
- selectedkey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
- client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- # Connection to overcloud
- try:
- client.connect(INSTALLER_IP, port=22, username='stack',
- pkey=selectedkey)
- except paramiko.SSHException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except paramiko.AuthenticationException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except socket.error:
- logger.error("Socker Connection failed for "
- "undercloud host: {0}".format(self.host))
-
- transport = client.get_transport()
- local_addr = ('127.0.0.1', 0) # 0 denotes choose random port
- channel = transport.open_channel("direct-tcpip",
- (self.host, int(self.port)),
- (local_addr))
- remote_client = paramiko.SSHClient()
- remote_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- # Tunnel to overcloud
- try:
- remote_client.connect('127.0.0.1', port=22, username=self.user,
- key_filename=self.localkey, sock=channel)
- except paramiko.SSHException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except paramiko.AuthenticationException:
- logger.error("Authentication failed for "
- "host: {0}".format(self.host))
- except socket.error:
- logger.error("Socker Connection failed for "
- "undercloud host: {0}".format(self.host))
- # Download the reports
- sftp = remote_client.open_sftp()
- logger.info("Downloading \"{0}\"...".format(reportname))
- sftp.get(reportfile, ('{0}/{1}'.format(dl_folder, reportname)))
- logger.info("Downloading \"{0}\"...".format(resultsname))
- sftp.get(reportfile, ('{0}/{1}'.format(dl_folder, resultsname)))
- sftp.close()
- transport.close()
diff --git a/functest/opnfv_tests/security_scan/examples/xccdf-rhel7-server-upstream.ini b/functest/opnfv_tests/security_scan/examples/xccdf-rhel7-server-upstream.ini
deleted file mode 100644
index 43b2e82d..00000000
--- a/functest/opnfv_tests/security_scan/examples/xccdf-rhel7-server-upstream.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-[undercloud]
-port = 22
-user = stack
-remotekey = /home/stack/.ssh/id_rsa
-localkey = /root/.ssh/overCloudKey
-
-[controller]
-port = 22
-user = heat-admin
-scantype = xccdf
-secpolicy = /usr/share/xml/scap/ssg/content/ssg-centos7-xccdf.xml
-cpe = /usr/share/xml/scap/ssg/content/ssg-rhel7-cpe-dictionary.xml
-profile = stig-rhel7-server-upstream
-report = report.hmtl
-results = results.xml
-reports_dir=/home/opnfv/functest/results/security_scan/
-clean = True
-
-[compute]
-port = 22
-user = heat-admin
-scantype = xccdf
-secpolicy = /usr/share/xml/scap/ssg/content/ssg-centos7-xccdf.xml
-cpe = /usr/share/xml/scap/ssg/content/ssg-rhel7-cpe-dictionary.xml
-profile = stig-rhel7-server-upstream
-report = report.hmtl
-results = results.xml
-reports_dir=/home/opnfv/functest/results/security_scan/
-clean = True
diff --git a/functest/opnfv_tests/security_scan/examples/xccdf-standard.ini b/functest/opnfv_tests/security_scan/examples/xccdf-standard.ini
deleted file mode 100644
index bfbcf82d..00000000
--- a/functest/opnfv_tests/security_scan/examples/xccdf-standard.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-[undercloud]
-port = 22
-user = stack
-remotekey = /home/stack/.ssh/id_rsa
-localkey = /root/.ssh/overCloudKey
-
-[controller]
-port = 22
-user = heat-admin
-scantype = xccdf
-secpolicy = /usr/share/xml/scap/ssg/content/ssg-centos7-xccdf.xml
-cpe = /usr/share/xml/scap/ssg/content/ssg-rhel7-cpe-dictionary.xml
-profile = standard
-report = report.hmtl
-results = results.xml
-reports_dir=/home/opnfv/functest/results/security_scan/
-clean = True
-
-[compute]
-port = 22
-user = heat-admin
-scantype = xccdf
-secpolicy = /usr/share/xml/scap/ssg/content/ssg-centos7-xccdf.xml
-cpe = /usr/share/xml/scap/ssg/content/ssg-rhel7-cpe-dictionary.xml
-profile = standard
-report = report.hmtl
-results = results.xml
-reports_dir=/home/opnfv/functest/results/security_scan/
-clean = True
diff --git a/functest/opnfv_tests/security_scan/scripts/createfiles.py b/functest/opnfv_tests/security_scan/scripts/createfiles.py
deleted file mode 100644
index b828901a..00000000
--- a/functest/opnfv_tests/security_scan/scripts/createfiles.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 Red Hat
-# Luke Hinds (lhinds@redhat.com)
-# 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
-#
-# 0.1: This script creates the needed local files into a tmp directory. Should
-# '--clean' be passed, all files will be removed, post scan.
-
-
-import os
-import tempfile
-
-files = ['results.xml', 'report.html', 'syschar.xml']
-
-
-directory_name = tempfile.mkdtemp()
-
-for i in files:
- os.system("touch %s/%s" % (directory_name, i))
-
-print directory_name
diff --git a/functest/opnfv_tests/security_scan/scripts/internet_check.py b/functest/opnfv_tests/security_scan/scripts/internet_check.py
deleted file mode 100644
index d417d174..00000000
--- a/functest/opnfv_tests/security_scan/scripts/internet_check.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 Red Hat
-# Luke Hinds (lhinds@redhat.com)
-# 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
-#
-# Performs simple connection check, falls to default timeout of 10 seconds
-
-import socket
-
-TEST_HOST = "google.com"
-
-
-def is_connected():
- try:
- host = socket.gethostbyname(TEST_HOST)
- socket.create_connection((host, 80), 2)
- return True
- except:
- return False
-
-
-print is_connected()
diff --git a/functest/opnfv_tests/security_scan/security_scan.py b/functest/opnfv_tests/security_scan/security_scan.py
deleted file mode 100755
index f0673924..00000000
--- a/functest/opnfv_tests/security_scan/security_scan.py
+++ /dev/null
@@ -1,220 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 Red Hat
-# Luke Hinds (lhinds@redhat.com)
-# 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
-#
-# 0.1: This script installs OpenSCAP on the remote host, and scans the
-# nominated node. Post scan a report is downloaded and if '--clean' is passed
-# all trace of the scan is removed from the remote system.
-
-
-import datetime
-import os
-import sys
-from ConfigParser import SafeConfigParser
-
-import argparse
-from keystoneclient import session
-from keystoneclient.auth.identity import v2
-from novaclient import client
-
-import connect
-import functest.utils.functest_constants as ft_constants
-
-__version__ = 0.1
-__author__ = 'Luke Hinds (lhinds@redhat.com)'
-__url__ = 'https://wiki.opnfv.org/display/functest/Functest+Security'
-
-# Global vars
-INSTALLER_IP = ft_constants.CI_INSTALLER_IP
-oscapbin = 'sudo /bin/oscap'
-functest_dir = '%s/security_scan/' % ft_constants.FUNCTEST_TEST_DIR
-
-# Apex Spefic var needed to query Undercloud
-if ft_constants.OS_AUTH_URL is None:
- connect.logger.error(" Enviroment variable OS_AUTH_URL is not set")
- sys.exit(0)
-else:
- OS_AUTH_URL = ft_constants.OS_AUTH_URL
-
-# args
-parser = argparse.ArgumentParser(description='OPNFV OpenSCAP Scanner')
-parser.add_argument('--config', action='store', dest='cfgfile',
- help='Config file', required=True)
-args = parser.parse_args()
-
-# Config Parser
-cfgparse = SafeConfigParser()
-cfgparse.read(args.cfgfile)
-
-# Grab Undercloud key
-remotekey = cfgparse.get('undercloud', 'remotekey')
-localkey = cfgparse.get('undercloud', 'localkey')
-setup = connect.SetUp(remotekey, localkey)
-setup.getockey()
-
-
-# Configure Nova Credentials
-com = 'sudo /usr/bin/hiera admin_password'
-setup = connect.SetUp(com)
-keypass = setup.keystonepass()
-auth = v2.Password(auth_url=OS_AUTH_URL,
- username='admin',
- password=str(keypass).rstrip(),
- tenant_name='admin')
-sess = session.Session(auth=auth)
-nova = client.Client(2, session=sess)
-
-
-class GlobalVariables:
- tmpdir = ""
-
-
-def run_tests(host, nodetype):
- user = cfgparse.get(nodetype, 'user')
- port = cfgparse.get(nodetype, 'port')
- connect.logger.info("Host: {0} Selected Profile: {1}".format(host,
- nodetype))
- connect.logger.info("Checking internet for package installation...")
- if internet_check(host, nodetype):
- connect.logger.info("Internet Connection OK.")
- connect.logger.info("Creating temp file structure..")
- createfiles(host, port, user, localkey)
- connect.logger.debug("Installing OpenSCAP...")
- install_pkg(host, port, user, localkey)
- connect.logger.debug("Running scan...")
- run_scanner(host, port, user, localkey, nodetype)
- clean = cfgparse.get(nodetype, 'clean')
- connect.logger.info("Post installation tasks....")
- post_tasks(host, port, user, localkey, nodetype)
- if clean:
- connect.logger.info("Cleaning down environment....")
- connect.logger.debug("Removing OpenSCAP....")
- removepkg(host, port, user, localkey, nodetype)
- connect.logger.info("Deleting tmp file and reports (remote)...")
- cleandir(host, port, user, localkey, nodetype)
- else:
- connect.logger.error("Internet timeout. Moving on to next node..")
- pass
-
-
-def nova_iterate():
- # Find compute nodes, active with network on ctlplane
- for server in nova.servers.list():
- if server.status == 'ACTIVE' and 'compute' in server.name:
- networks = server.networks
- nodetype = 'compute'
- for host in networks['ctlplane']:
- run_tests(host, nodetype)
- # Find controller nodes, active with network on ctlplane
- elif server.status == 'ACTIVE' and 'controller' in server.name:
- networks = server.networks
- nodetype = 'controller'
- for host in networks['ctlplane']:
- run_tests(host, nodetype)
-
-
-def internet_check(host, nodetype):
- import connect
- user = cfgparse.get(nodetype, 'user')
- port = cfgparse.get(nodetype, 'port')
- localpath = functest_dir + 'scripts/internet_check.py'
- remotepath = '/tmp/internet_check.py'
- com = 'python /tmp/internet_check.py'
- testconnect = connect.ConnectionManager(host, port, user, localkey,
- localpath, remotepath, com)
- connectionresult = testconnect.remotescript()
- if connectionresult.rstrip() == 'True':
- return True
- else:
- return False
-
-
-def createfiles(host, port, user, localkey):
- import connect
- localpath = functest_dir + 'scripts/createfiles.py'
- remotepath = '/tmp/createfiles.py'
- com = 'python /tmp/createfiles.py'
- connect = connect.ConnectionManager(host, port, user, localkey,
- localpath, remotepath, com)
- GlobalVariables.tmpdir = connect.remotescript()
-
-
-def install_pkg(host, port, user, localkey):
- import connect
- com = 'sudo yum -y install openscap-scanner scap-security-guide'
- connect = connect.ConnectionManager(host, port, user, localkey, com)
- connect.remotecmd()
-
-
-def run_scanner(host, port, user, localkey, nodetype):
- import connect
- scantype = cfgparse.get(nodetype, 'scantype')
- profile = cfgparse.get(nodetype, 'profile')
- results = cfgparse.get(nodetype, 'results')
- report = cfgparse.get(nodetype, 'report')
- secpolicy = cfgparse.get(nodetype, 'secpolicy')
- # Here is where we contruct the actual scan command
- if scantype == 'xccdf':
- cpe = cfgparse.get(nodetype, 'cpe')
- com = '{0} xccdf eval --profile {1} --results {2}/{3}' \
- ' --report {2}/{4}' \
- ' --cpe {5} {6}'.format(oscapbin,
- profile,
- GlobalVariables.tmpdir.rstrip(),
- results,
- report,
- cpe,
- secpolicy)
- connect = connect.ConnectionManager(host, port, user, localkey, com)
- connect.remotecmd()
- elif scantype == 'oval':
- com = '{0} oval eval --results {1}/{2} '
- '--report {1}/{3} {4}'.format(oscapbin,
- GlobalVariables.tmpdir.rstrip(),
- results, report, secpolicy)
- connect = connect.ConnectionManager(host, port, user, localkey, com)
- connect.remotecmd()
- else:
- com = '{0} oval-collect '.format(oscapbin)
- connect = connect.ConnectionManager(host, port, user, localkey, com)
- connect.remotecmd()
-
-
-def post_tasks(host, port, user, localkey, nodetype):
- import connect
- # Create the download folder for functest dashboard and download reports
- reports_dir = cfgparse.get(nodetype, 'reports_dir')
- dl_folder = os.path.join(reports_dir, host + "_" +
- datetime.datetime.
- now().strftime('%Y-%m-%d_%H-%M-%S'))
- os.makedirs(dl_folder, 0755)
- report = cfgparse.get(nodetype, 'report')
- results = cfgparse.get(nodetype, 'results')
- reportfile = '{0}/{1}'.format(GlobalVariables.tmpdir.rstrip(), report)
- connect = connect.ConnectionManager(host, port, user, localkey, dl_folder,
- reportfile, report, results)
- connect.download_reports()
-
-
-def removepkg(host, port, user, localkey, nodetype):
- import connect
- com = 'sudo yum -y remove openscap-scanner scap-security-guide'
- connect = connect.ConnectionManager(host, port, user, localkey, com)
- connect.remotecmd()
-
-
-def cleandir(host, port, user, localkey, nodetype):
- import connect
- com = 'sudo rm -r {0}'.format(GlobalVariables.tmpdir.rstrip())
- connect = connect.ConnectionManager(host, port, user, localkey, com)
- connect.remotecmd()
-
-
-if __name__ == '__main__':
- nova_iterate()
diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.py b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
index 13a5af4f..e2508c22 100644
--- a/functest/opnfv_tests/vnf/ims/cloudify_ims.py
+++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
@@ -11,7 +11,9 @@ import json
import os
import requests
import subprocess
+import sys
import time
+import yaml
import functest.core.vnf_base as vnf_base
import functest.utils.functest_logger as ft_logger
@@ -29,57 +31,127 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
repo='', cmd=''):
super(ImsVnf, self).__init__(project, case, repo, cmd)
self.logger = ft_logger.Logger("vIMS").getLogger()
- self.case_dir = os.path.join(CONST.functest_test, 'vnf/ims/')
- self.data_dir = CONST.dir_vIMS_data
+ self.case_dir = os.path.join(CONST.dir_functest_test, 'vnf/ims/')
+ self.data_dir = CONST.dir_ims_data
self.test_dir = CONST.dir_repo_vims_test
+ # Retrieve the configuration
+ try:
+ self.config = CONST.__getattribute__(
+ 'vnf_{}_config'.format(self.case_name))
+ except:
+ raise Exception("VNF config file not found")
+
+ config_file = self.case_dir + self.config
self.orchestrator = dict(
- requirements=CONST.cloudify_requirements,
- blueprint=CONST.cloudify_blueprint,
- inputs=CONST.cloudify_inputs
+ requirements=get_config("cloudify.requirements", config_file),
+ blueprint=get_config("cloudify.blueprint", config_file),
+ inputs=get_config("cloudify.inputs", config_file)
)
-
+ self.logger.debug("Orchestrator configuration: %s" % self.orchestrator)
self.vnf = dict(
- blueprint=CONST.clearwater_blueprint,
- deployment_name=CONST.clearwater_deployment_name,
- inputs=CONST.clearwater_inputs,
- requirements=CONST.clearwater_requirements
+ blueprint=get_config("clearwater.blueprint", config_file),
+ deployment_name=get_config("clearwater.deployment_name",
+ config_file),
+ inputs=get_config("clearwater.inputs", config_file),
+ requirements=get_config("clearwater.requirements", config_file)
)
+ self.logger.debug("VNF configuration: %s" % self.vnf)
+
+ self.images = get_config("tenant_images", config_file)
+ self.logger.info("Images needed for vIMS: %s" % self.images)
# vIMS Data directory creation
if not os.path.exists(self.data_dir):
os.makedirs(self.data_dir)
def deploy_orchestrator(self, **kwargs):
+
+ self.logger.info("Additional pre-configuration steps")
+ self.neutron_client = os_utils.get_neutron_client(self.creds)
+ self.glance_client = os_utils.get_glance_client(self.creds)
+ self.keystone_client = os_utils.get_keystone_client(self.creds)
+ self.nova_client = os_utils.get_nova_client(self.creds)
+
+ # needs some images
+ self.logger.info("Upload some OS images if it doesn't exist")
+ temp_dir = os.path.join(self.data_dir, "tmp/")
+ for image_name, image_url in self.images.iteritems():
+ self.logger.info("image: %s, url: %s" % (image_name, image_url))
+ try:
+ image_id = os_utils.get_image_id(self.glance_client,
+ image_name)
+ self.logger.debug("image_id: %s" % image_id)
+ except:
+ self.logger.error("Unexpected error: %s" % sys.exc_info()[0])
+
+ if image_id == '':
+ self.logger.info("""%s image doesn't exist on glance repository. Try
+ downloading this image and upload on glance !""" % image_name)
+ image_id = download_and_add_image_on_glance(self.glance_client,
+ image_name,
+ image_url,
+ temp_dir)
+ if image_id == '':
+ self.step_failure(
+ "Failed to find or upload required OS "
+ "image for this deployment")
+ # Need to extend quota
+ self.logger.info("Update security group quota for this tenant")
+ tenant_id = os_utils.get_tenant_id(self.keystone_client,
+ self.tenant_name)
+ self.logger.debug("Tenant id found %s" % tenant_id)
+ if not os_utils.update_sg_quota(self.neutron_client,
+ tenant_id, 50, 100):
+ self.step_failure("Failed to update security group quota" +
+ " for tenant " + self.tenant_name)
+ self.logger.debug("group quota extended")
+
+ # start the deployment of cloudify
public_auth_url = os_utils.get_endpoint('identity')
- cfy = Orchestrator(self.data_dir, self.orchestrator.inputs)
- self.orchestrator.object = cfy
+ self.logger.debug("CFY inputs: %s" % self.orchestrator['inputs'])
+ cfy = Orchestrator(self.data_dir, self.orchestrator['inputs'])
+ self.orchestrator['object'] = cfy
+ self.logger.debug("Orchestrator object created")
- if 'tenant_name' in self.creds.keys():
- tenant_name = self.creds['tenant_name']
- elif 'project_name' in self.creds.keys():
- tenant_name = self.creds['project_name']
+ self.logger.debug("Tenant name: %s" % self.tenant_name)
- cfy.set_credentials(username=self.creds['username'],
- password=self.creds['password'],
- tenant_name=tenant_name,
+ cfy.set_credentials(username=self.tenant_name,
+ password=self.tenant_name,
+ tenant_name=self.tenant_name,
auth_url=public_auth_url)
+ self.logger.info("Credentials set in CFY")
# orchestrator VM flavor
- flavor_id = self.get_flavor("m1.large", self.orchestrator.requirements)
+ self.logger.info("Check Flavor is available, if not create one")
+ self.logger.debug("Flavor details %s " %
+ self.orchestrator['requirements']['ram_min'])
+ flavor_exist, flavor_id = os_utils.get_or_create_flavor(
+ "m1.large",
+ self.orchestrator['requirements']['ram_min'],
+ '1',
+ '1',
+ public=True)
+ self.logger.debug("Flavor id: %s" % flavor_id)
+
if not flavor_id:
self.logger.info("Available flavors are: ")
- self.pMsg(self.nova_client.flavor.list())
+ self.logger.info(self.nova_client.flavor.list())
self.step_failure("Failed to find required flavor"
"for this deployment")
cfy.set_flavor_id(flavor_id)
+ self.logger.debug("Flavor OK")
# orchestrator VM image
- if 'os_image' in self.orchestrator.requirements.keys():
+ self.logger.debug("Orchestrator image")
+ if 'os_image' in self.orchestrator['requirements'].keys():
image_id = os_utils.get_image_id(
- self.glance_client, self.orchestrator.requirements['os_image'])
+ self.glance_client,
+ self.orchestrator['requirements']['os_image'])
+ self.logger.debug("Orchestrator image id: %s" % image_id)
if image_id == '':
+ self.logger.error("CFY image not found")
self.step_failure("Failed to find required OS image"
" for cloudify manager")
else:
@@ -87,16 +159,22 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
" for cloudify manager")
cfy.set_image_id(image_id)
+ self.logger.debug("Orchestrator image set")
+ self.logger.debug("Get External network")
ext_net = os_utils.get_external_net(self.neutron_client)
+ self.logger.debug("External network: %s" % ext_net)
if not ext_net:
self.step_failure("Failed to get external network")
cfy.set_external_network_name(ext_net)
+ self.logger.debug("CFY External network set")
+ self.logger.debug("get resolvconf")
ns = ft_utils.get_resolvconf_ns()
if ns:
cfy.set_nameservers(ns)
+ self.logger.debug("Resolvconf set")
if 'compute' in self.nova_client.client.services_url:
cfy.set_nova_url(self.nova_client.client.services_url['compute'])
@@ -110,8 +188,9 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
cmd = self.case_dir + "create_venv.sh " + self.data_dir
ft_utils.execute_command(cmd)
- cfy.download_manager_blueprint(self.orchestrator.blueprint['url'],
- self.orchestrator.blueprint['branch'])
+ cfy.download_manager_blueprint(
+ self.orchestrator['blueprint']['url'],
+ self.orchestrator['blueprint']['branch'])
cfy.deploy_manager()
return {'status': 'PASS', 'result': ''}
@@ -121,10 +200,16 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
self.vnf.object = cw
self.logger.info("Collect flavor id for all clearwater vm")
- flavor_id = self.get_flavor("m1.small", self.vnf.requirements)
+ flavor_exist, flavor_id = os_utils.get_or_create_flavor(
+ "m1.small",
+ self.vnf['requirements']['ram_min'],
+ '1',
+ '1',
+ public=True)
+ self.logger.debug("Flavor id: %s" % flavor_id)
if not flavor_id:
self.logger.info("Available flavors are: ")
- self.pMsg(self.nova_client.flavor.list())
+ self.logger.info(self.nova_client.flavor.list())
self.step_failure("Failed to find required flavor"
" for this deployment")
@@ -133,7 +218,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
# VMs image
if 'os_image' in self.vnf.requirements.keys():
image_id = os_utils.get_image_id(
- self.glance_client, self.vnf.requirements['os_image'])
+ self.glance_client, self.vnf['requirements']['os_image'])
if image_id == '':
self.step_failure("Failed to find required OS image"
" for clearwater VMs")
@@ -256,23 +341,54 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
self.orchestrator.object.undeploy_manager()
super(ImsVnf, self).clean()
- def get_flavor(self, flavor_name, requirements):
- try:
- flavor_id = os_utils.get_flavor_id(self.nova_client, flavor_name)
- if 'ram_min' in requirements.keys():
- flavor_id = os_utils.get_flavor_id_by_ram_range(
- self.nova_client, requirements['ram_min'], 7500)
-
- if flavor_id == '':
- self.logger.error(
- "Failed to find %s flavor. "
- "Try with ram range default requirement !" % flavor_name)
- flavor_id = os_utils.get_flavor_id_by_ram_range(
- self.nova_client,
- 4000, 10000)
- return flavor_id
- except:
- self.logger.error("Flavor '%s' not found." % self.flavor_name)
- self.logger.info("Available flavors are: ")
- self.pMsg(self.nova_client.flavor.list())
- return None
+ def main(self, **kwargs):
+ self.logger.info("Cloudify IMS VNF onboarding test starting")
+ self.execute()
+ self.logger.info("Cloudify IMS VNF onboarding test executed")
+ if self.criteria is "PASS":
+ return self.EX_OK
+ else:
+ return self.EX_RUN_ERROR
+
+ def run(self):
+ kwargs = {}
+ return self.main(**kwargs)
+
+
+# ----------------------------------------------------------
+#
+# YAML UTILS
+#
+# -----------------------------------------------------------
+def get_config(parameter, file):
+ """
+ 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) as f:
+ file_yaml = yaml.safe_load(f)
+ f.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 download_and_add_image_on_glance(glance, image_name, image_url, data_dir):
+ dest_path = data_dir
+ if not os.path.exists(dest_path):
+ os.makedirs(dest_path)
+ file_name = image_url.rsplit('/')[-1]
+ if not ft_utils.download_url(image_url, dest_path):
+ return False
+
+ image = os_utils.create_glance_image(
+ glance, image_name, dest_path + file_name)
+ if not image:
+ return False
+
+ return image
diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml b/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml
new file mode 100644
index 00000000..c5918087
--- /dev/null
+++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml
@@ -0,0 +1,39 @@
+tenant_images:
+ ubuntu_14.04: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img
+ centos_7: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1510.qcow2
+cloudify:
+ blueprint:
+ url: https://github.com/boucherv-orange/cloudify-manager-blueprints.git
+ branch: '3.3.1-build'
+ requirements:
+ ram_min: 3000
+ os_image: centos_7
+ inputs:
+ keystone_username: ""
+ keystone_password: ""
+ keystone_tenant_name: ""
+ keystone_url: ""
+ manager_public_key_name: 'manager-kp'
+ agent_public_key_name: 'agent-kp'
+ image_id: ""
+ flavor_id: "3"
+ external_network_name: ""
+ ssh_user: centos
+ agents_user: ubuntu
+clearwater:
+ blueprint:
+ file_name: openstack-blueprint.yaml
+ name: clearwater-opnfv
+ destination_folder: opnfv-cloudify-clearwater
+ url: https://github.com/Orange-OpenSource/opnfv-cloudify-clearwater.git
+ branch: stable
+ deployment_name: clearwater-opnfv
+ requirements:
+ ram_min: 1700
+ os_image: ubuntu_14.04
+ inputs:
+ image_id: ''
+ flavor_id: ''
+ agent_user: ubuntu
+ external_network_name: ''
+ public_domain: clearwaterfv
diff --git a/functest/tests/unit/utils/test_openstack_utils.py b/functest/tests/unit/utils/test_openstack_utils.py
index 0f510414..0971b4e8 100644
--- a/functest/tests/unit/utils/test_openstack_utils.py
+++ b/functest/tests/unit/utils/test_openstack_utils.py
@@ -7,6 +7,7 @@
import copy
import logging
+import os
import unittest
import mock
@@ -353,18 +354,31 @@ class OSUtilsTesting(unittest.TestCase):
def test_get_credentials_missing_endpoint_type(self):
self._get_credentials_missing_env('OS_ENDPOINT_TYPE')
+ def _test_source_credentials(self, msg, key='OS_TENANT_NAME',
+ value='admin'):
+ try:
+ del os.environ[key]
+ except:
+ pass
+ f = 'rc_file'
+ with mock.patch('__builtin__.open', mock.mock_open(read_data=msg),
+ create=True) as m:
+ m.return_value.__iter__ = lambda self: iter(self.readline, '')
+ openstack_utils.source_credentials(f)
+ m.assert_called_once_with(f, 'r')
+ self.assertEqual(os.environ[key], value)
+
def test_source_credentials(self):
- with mock.patch('functest.utils.openstack_utils.subprocess.Popen') \
- as mock_subproc_popen, \
- mock.patch('functest.utils.openstack_utils.os.environ'):
- process_mock = mock.Mock()
- attrs = {'communicate.return_value': ('OS_USER_NAME=test_name',
- 'success')}
- process_mock.configure_mock(**attrs)
- mock_subproc_popen.return_value = process_mock
-
- self.assertDictEqual(openstack_utils.source_credentials('rc_file'),
- {'OS_USER_NAME': 'test_name'})
+ self._test_source_credentials('OS_TENANT_NAME=admin')
+ self._test_source_credentials('OS_TENANT_NAME= admin')
+ self._test_source_credentials('OS_TENANT_NAME = admin')
+ self._test_source_credentials('OS_TENANT_NAME = "admin"')
+ self._test_source_credentials('export OS_TENANT_NAME=admin')
+ self._test_source_credentials('export OS_TENANT_NAME =admin')
+ self._test_source_credentials('export OS_TENANT_NAME = admin')
+ self._test_source_credentials('export OS_TENANT_NAME = "admin"')
+ self._test_source_credentials('OS_TENANT_NAME', value='')
+ self._test_source_credentials('export OS_TENANT_NAME', value='')
@mock.patch('functest.utils.openstack_utils.os.getenv',
return_value=None)
diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py
index 64f18504..c21ed818 100755
--- a/functest/utils/openstack_utils.py
+++ b/functest/utils/openstack_utils.py
@@ -10,7 +10,7 @@
import os
import os.path
-import subprocess
+import re
import sys
import time
@@ -112,12 +112,13 @@ def get_credentials(other_creds={}):
def source_credentials(rc_file):
- pipe = subprocess.Popen(". %s; env" % rc_file, stdout=subprocess.PIPE,
- shell=True)
- output = pipe.communicate()[0]
- env = dict((line.split("=", 1) for line in output.splitlines()))
- os.environ.update(env)
- return env
+ with open(rc_file, "r") as f:
+ for line in f:
+ var = line.rstrip('"\n').replace(
+ 'export ', '').replace("'", "").split("=")
+ key = re.sub(r'^ *| *$', '', var[0])
+ value = re.sub(r'^[" ]*|[ "]*$', '', "".join(var[1:]))
+ os.environ[key] = value
def get_credentials_for_rally():