aboutsummaryrefslogtreecommitdiffstats
path: root/functest/opnfv_tests
diff options
context:
space:
mode:
Diffstat (limited to 'functest/opnfv_tests')
-rw-r--r--functest/opnfv_tests/features/barometer.py4
-rw-r--r--functest/opnfv_tests/features/copper.py4
-rw-r--r--functest/opnfv_tests/features/doctor.py4
-rw-r--r--functest/opnfv_tests/features/domino.py4
-rw-r--r--functest/opnfv_tests/features/netready.py4
-rw-r--r--functest/opnfv_tests/features/odl_sfc.py10
-rw-r--r--functest/opnfv_tests/features/promise.py4
-rw-r--r--functest/opnfv_tests/features/sdnvpn.py4
-rw-r--r--functest/opnfv_tests/features/security_scan.py4
-rw-r--r--functest/opnfv_tests/mano/orchestra.py4
-rw-r--r--functest/opnfv_tests/openstack/rally/rally.py8
-rwxr-xr-xfunctest/opnfv_tests/openstack/refstack_client/refstack_client.py69
-rwxr-xr-xfunctest/opnfv_tests/openstack/refstack_client/tempest_conf.py53
-rw-r--r--functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt12
-rw-r--r--functest/opnfv_tests/openstack/tempest/tempest.py8
-rw-r--r--functest/opnfv_tests/openstack/vping/vping_base.py22
-rwxr-xr-xfunctest/opnfv_tests/openstack/vping/vping_ssh.py8
-rwxr-xr-xfunctest/opnfv_tests/sdn/odl/odl.py133
-rw-r--r--functest/opnfv_tests/sdn/onos/onos.py8
-rwxr-xr-xfunctest/opnfv_tests/vnf/aaa/aaa.py6
-rw-r--r--functest/opnfv_tests/vnf/ims/clearwater_ims_base.py149
-rw-r--r--functest/opnfv_tests/vnf/ims/cloudify_ims.py142
-rw-r--r--[-rwxr-xr-x]functest/opnfv_tests/vnf/ims/opera_ims.py457
-rw-r--r--functest/opnfv_tests/vnf/rnc/parser.py4
-rw-r--r--functest/opnfv_tests/vnf/router/vyos_vrouter.py6
25 files changed, 530 insertions, 601 deletions
diff --git a/functest/opnfv_tests/features/barometer.py b/functest/opnfv_tests/features/barometer.py
index 32067284..6011340f 100644
--- a/functest/opnfv_tests/features/barometer.py
+++ b/functest/opnfv_tests/features/barometer.py
@@ -8,10 +8,10 @@
from baro_tests import collectd
-import functest.core.feature_base as base
+import functest.core.feature as base
-class BarometerCollectd(base.FeatureBase):
+class BarometerCollectd(base.Feature):
'''
Class for executing barometercollectd testcase.
'''
diff --git a/functest/opnfv_tests/features/copper.py b/functest/opnfv_tests/features/copper.py
index 735b315d..689341ea 100644
--- a/functest/opnfv_tests/features/copper.py
+++ b/functest/opnfv_tests/features/copper.py
@@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-import functest.core.feature_base as base
+import functest.core.feature as base
-class Copper(base.FeatureBase):
+class Copper(base.Feature):
def __init__(self):
super(Copper, self).__init__(project='copper',
case='copper-notification',
diff --git a/functest/opnfv_tests/features/doctor.py b/functest/opnfv_tests/features/doctor.py
index 4d295a67..d32bbfc9 100644
--- a/functest/opnfv_tests/features/doctor.py
+++ b/functest/opnfv_tests/features/doctor.py
@@ -13,10 +13,10 @@
# 0.2: measure test duration and publish results under json format
#
#
-import functest.core.feature_base as base
+import functest.core.feature as base
-class Doctor(base.FeatureBase):
+class Doctor(base.Feature):
def __init__(self):
super(Doctor, self).__init__(project='doctor',
case='doctor-notification',
diff --git a/functest/opnfv_tests/features/domino.py b/functest/opnfv_tests/features/domino.py
index b36220fa..e34429bc 100644
--- a/functest/opnfv_tests/features/domino.py
+++ b/functest/opnfv_tests/features/domino.py
@@ -14,10 +14,10 @@
# 0.3: add report flag to push results when needed
# 0.4: refactoring to match Test abstraction class
-import functest.core.feature_base as base
+import functest.core.feature as base
-class Domino(base.FeatureBase):
+class Domino(base.Feature):
def __init__(self):
super(Domino, self).__init__(project='domino',
case='domino-multinode',
diff --git a/functest/opnfv_tests/features/netready.py b/functest/opnfv_tests/features/netready.py
index dec2a23c..88f377c2 100644
--- a/functest/opnfv_tests/features/netready.py
+++ b/functest/opnfv_tests/features/netready.py
@@ -8,10 +8,10 @@
#
#
-import functest.core.feature_base as base
+import functest.core.feature as base
-class GluonVping(base.FeatureBase):
+class GluonVping(base.Feature):
def __init__(self):
super(GluonVping, self).__init__(project='netready',
diff --git a/functest/opnfv_tests/features/odl_sfc.py b/functest/opnfv_tests/features/odl_sfc.py
index 431cd47e..fff7f2b0 100644
--- a/functest/opnfv_tests/features/odl_sfc.py
+++ b/functest/opnfv_tests/features/odl_sfc.py
@@ -7,16 +7,14 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
#
-import functest.core.feature_base as base
-from sfc.tests.functest import run_tests
+import functest.core.feature as base
-class OpenDaylightSFC(base.FeatureBase):
+class OpenDaylightSFC(base.Feature):
def __init__(self):
super(OpenDaylightSFC, self).__init__(project='sfc',
case='functest-odl-sfc',
repo='dir_repo_sfc')
-
- def execute(self):
- return run_tests.main()
+ dir_sfc_functest = '{}/sfc/tests/functest'.format(self.repo)
+ self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest
diff --git a/functest/opnfv_tests/features/promise.py b/functest/opnfv_tests/features/promise.py
index 15636fbf..a7f4e628 100644
--- a/functest/opnfv_tests/features/promise.py
+++ b/functest/opnfv_tests/features/promise.py
@@ -12,10 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-import functest.core.feature_base as base
+import functest.core.feature as base
-class Promise(base.FeatureBase):
+class Promise(base.Feature):
def __init__(self):
super(Promise, self).__init__(project='promise',
case='promise',
diff --git a/functest/opnfv_tests/features/sdnvpn.py b/functest/opnfv_tests/features/sdnvpn.py
index 1919a03c..10e3146c 100644
--- a/functest/opnfv_tests/features/sdnvpn.py
+++ b/functest/opnfv_tests/features/sdnvpn.py
@@ -7,10 +7,10 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
#
-import functest.core.feature_base as base
+import functest.core.feature as base
-class SdnVpnTests(base.FeatureBase):
+class SdnVpnTests(base.Feature):
def __init__(self):
super(SdnVpnTests, self).__init__(project='sdnvpn',
diff --git a/functest/opnfv_tests/features/security_scan.py b/functest/opnfv_tests/features/security_scan.py
index 58f0ec74..2374b39f 100644
--- a/functest/opnfv_tests/features/security_scan.py
+++ b/functest/opnfv_tests/features/security_scan.py
@@ -8,11 +8,11 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
-import functest.core.feature_base as base
+import functest.core.feature as base
from functest.utils.constants import CONST
-class SecurityScan(base.FeatureBase):
+class SecurityScan(base.Feature):
def __init__(self):
super(SecurityScan, self).__init__(project='securityscanning',
case='security_scan',
diff --git a/functest/opnfv_tests/mano/orchestra.py b/functest/opnfv_tests/mano/orchestra.py
index fd5e40d0..a9cf0ae6 100644
--- a/functest/opnfv_tests/mano/orchestra.py
+++ b/functest/opnfv_tests/mano/orchestra.py
@@ -12,10 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-import functest.core.feature_base as base
+import functest.core.feature as base
-class Orchestra(base.FeatureBase):
+class Orchestra(base.Feature):
def __init__(self):
super(Orchestra, self).__init__(project='orchestra',
case='orchestra',
diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py
index 46d6a570..8c6abc15 100644
--- a/functest/opnfv_tests/openstack/rally/rally.py
+++ b/functest/opnfv_tests/openstack/rally/rally.py
@@ -17,7 +17,7 @@ import time
import iniparse
import yaml
-from functest.core import testcase_base
+from functest.core import testcase
from functest.utils.constants import CONST
import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
@@ -26,7 +26,7 @@ import functest.utils.openstack_utils as os_utils
logger = ft_logger.Logger('Rally').getLogger()
-class RallyBase(testcase_base.TestcaseBase):
+class RallyBase(testcase.TestCase):
TESTS = ['authenticate', 'glance', 'cinder', 'heat', 'keystone',
'neutron', 'nova', 'quotas', 'requests', 'vm', 'all']
GLANCE_IMAGE_NAME = CONST.openstack_image_name
@@ -526,10 +526,10 @@ class RallyBase(testcase_base.TestcaseBase):
self._run_tests()
self._generate_report()
self._clean_up()
- res = testcase_base.TestcaseBase.EX_OK
+ res = testcase.TestCase.EX_OK
except Exception as e:
logger.error('Error with run: %s' % e)
- res = testcase_base.TestcaseBase.EX_RUN_ERROR
+ res = testcase.TestCase.EX_RUN_ERROR
self.stop_time = time.time()
return res
diff --git a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
index 4312b7f9..37aa9e39 100755
--- a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
+++ b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
@@ -12,18 +12,18 @@ import sys
import subprocess
import time
-from functest.core import testcase_base
+from functest.core import testcase
from functest.opnfv_tests.openstack.tempest import conf_utils
-from functest.utils import openstack_utils
from functest.utils.constants import CONST
import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
+from tempest_conf import TempestConf
""" logging configuration """
logger = ft_logger.Logger("refstack_defcore").getLogger()
-class RefstackClient(testcase_base.TestcaseBase):
+class RefstackClient(testcase.TestCase):
def __init__(self):
super(RefstackClient, self).__init__()
@@ -35,12 +35,6 @@ class RefstackClient(testcase_base.TestcaseBase):
self.CONF_PATH)
self.defcorelist = os.path.join(self.FUNCTEST_TEST,
self.DEFCORE_LIST)
- 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)
def source_venv(self):
@@ -143,59 +137,62 @@ class RefstackClient(testcase_base.TestcaseBase):
logger.info("Testcase %s success_rate is %s%%, is marked as %s"
% (self.case_name, success_rate, self.criteria))
- def defcore_env_prepare(self):
- try:
- img_flavor_dict = conf_utils.create_tempest_resources(
- use_custom_images=True, use_custom_flavors=True)
- conf_utils.configure_tempest_defcore(
- self.DEPLOYMENT_DIR, img_flavor_dict)
- self.source_venv()
- res = testcase_base.TestcaseBase.EX_OK
- except KeyError as e:
- logger.error("defcore prepare env error with: %s", e)
- res = testcase_base.TestcaseBase.EX_RUN_ERROR
-
- return res
-
def run(self):
+ '''used for functest command line,
+ functest testcase run refstack_defcore'''
self.start_time = time.time()
if not os.path.exists(conf_utils.REFSTACK_RESULTS_DIR):
os.makedirs(conf_utils.REFSTACK_RESULTS_DIR)
try:
- self.defcore_env_prepare()
+ tempestconf = TempestConf()
+ tempestconf.generate_tempestconf()
+ self.source_venv()
self.run_defcore_default()
self.parse_refstack_result()
- res = testcase_base.TestcaseBase.EX_OK
+ res = testcase.TestCase.EX_OK
except Exception as e:
logger.error('Error with run: %s', e)
- res = testcase_base.TestcaseBase.EX_RUN_ERROR
+ res = testcase.TestCase.EX_RUN_ERROR
self.stop_time = time.time()
return res
+ def _prep_test(self):
+ '''Check that the config file exists.'''
+ if not os.path.isfile(self.confpath):
+ logger.error("Conf file not valid: %s" % self.confpath)
+ if not os.path.isfile(self.testlist):
+ logger.error("testlist file not valid: %s" % self.testlist)
+
def main(self, **kwargs):
+ '''used for manually running,
+ python refstack_client.py -c <tempest_conf_path>
+ --testlist <testlist_path>
+ can generate a reference tempest.conf by
+ python tempest_conf.py
+ '''
try:
- tempestconf = kwargs['config']
- testlist = kwargs['testlist']
+ self.confpath = kwargs['config']
+ self.testlist = kwargs['testlist']
except KeyError as e:
logger.error("Cannot run refstack client. Please check "
"%s", e)
return self.EX_RUN_ERROR
try:
- openstack_utils.source_credentials(CONST.openstack_creds)
- self.defcore_env_prepare()
- self.run_defcore(tempestconf, testlist)
- res = testcase_base.TestcaseBase.EX_OK
+ self.source_venv()
+ self._prep_test()
+ self.run_defcore(self.confpath, self.testlist)
+ res = testcase.TestCase.EX_OK
except Exception as e:
logger.error('Error with run: %s', e)
- res = testcase_base.TestcaseBase.EX_RUN_ERROR
+ res = testcase.TestCase.EX_RUN_ERROR
return res
-class RefstackClientParser(testcase_base.TestcaseBase):
+class RefstackClientParser(testcase.TestCase):
def __init__(self):
super(RefstackClientParser, self).__init__()
@@ -228,7 +225,7 @@ if __name__ == '__main__':
args = parser.parse_args(sys.argv[1:])
try:
result = refstackclient.main(**args)
- if result != testcase_base.TestcaseBase.EX_OK:
+ if result != testcase.TestCase.EX_OK:
sys.exit(result)
except Exception:
- sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR)
+ sys.exit(testcase.TestCase.EX_RUN_ERROR)
diff --git a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
new file mode 100755
index 00000000..5624ed79
--- /dev/null
+++ b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+# matthew.lijun@huawei.com
+# 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 sys
+
+from functest.core import testcase
+from functest.opnfv_tests.openstack.tempest import conf_utils
+from functest.utils import openstack_utils
+from functest.utils.constants import CONST
+import functest.utils.functest_logger as ft_logger
+
+""" logging configuration """
+logger = ft_logger.Logger("refstack_defcore").getLogger()
+
+
+class TempestConf(object):
+ def __init__(self):
+ 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)
+
+ def generate_tempestconf(self):
+ try:
+ openstack_utils.source_credentials(CONST.openstack_creds)
+ img_flavor_dict = conf_utils.create_tempest_resources(
+ use_custom_images=True, use_custom_flavors=True)
+ conf_utils.configure_tempest_defcore(
+ self.DEPLOYMENT_DIR, img_flavor_dict)
+ except KeyError as e:
+ logger.error("defcore prepare env error with: %s", e)
+
+ def main(self):
+ try:
+ self.generate_tempestconf()
+ res = testcase.TestCase.EX_OK
+ except Exception as e:
+ logger.error('Error with run: %s', e)
+ res = testcase.TestCase.EX_RUN_ERROR
+
+ return res
+
+if __name__ == '__main__':
+ tempestconf = TempestConf()
+ result = tempestconf.main()
+ if result != testcase.TestCase.EX_OK:
+ sys.exit(result)
diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
index 43edabc1..75bbd749 100644
--- a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
+++ b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
@@ -71,3 +71,15 @@
- fuel
tests:
- tempest.scenario.test_server_basic_ops.TestServerBasicOps.test_server_basic_ops
+
+
+ # https://bugs.opendaylight.org/show_bug.cgi?id=5586
+ scenarios:
+ - os-odl-bgpvpn-ha
+ - os-odl-gluon-noha
+ - os-odl_l2-bgpvpn-ha
+ installers:
+ - apex
+ - fuel
+ tests:
+ - tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
index 54556a32..0addbd17 100644
--- a/functest/opnfv_tests/openstack/tempest/tempest.py
+++ b/functest/opnfv_tests/openstack/tempest/tempest.py
@@ -16,7 +16,7 @@ import time
import yaml
-from functest.core import testcase_base
+from functest.core import testcase
from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils.constants import CONST
import functest.utils.functest_logger as ft_logger
@@ -26,7 +26,7 @@ import functest.utils.functest_utils as ft_utils
logger = ft_logger.Logger("Tempest").getLogger()
-class TempestCommon(testcase_base.TestcaseBase):
+class TempestCommon(testcase.TestCase):
def __init__(self):
super(TempestCommon, self).__init__()
@@ -223,10 +223,10 @@ class TempestCommon(testcase_base.TestcaseBase):
self.apply_tempest_blacklist()
self.run_verifier_tests()
self.parse_verifier_result()
- res = testcase_base.TestcaseBase.EX_OK
+ res = testcase.TestCase.EX_OK
except Exception as e:
logger.error('Error with run: %s' % e)
- res = testcase_base.TestcaseBase.EX_RUN_ERROR
+ res = testcase.TestCase.EX_RUN_ERROR
self.stop_time = time.time()
return res
diff --git a/functest/opnfv_tests/openstack/vping/vping_base.py b/functest/opnfv_tests/openstack/vping/vping_base.py
index 9d57cfae..584ded38 100644
--- a/functest/opnfv_tests/openstack/vping/vping_base.py
+++ b/functest/opnfv_tests/openstack/vping/vping_base.py
@@ -12,12 +12,12 @@ import pprint
import time
from datetime import datetime
-import functest.core.testcase_base as testcase_base
+import functest.core.testcase as testcase
import functest.utils.openstack_utils as os_utils
from functest.utils.constants import CONST
-class VPingBase(testcase_base.TestcaseBase):
+class VPingBase(testcase.TestCase):
def __init__(self):
super(VPingBase, self).__init__()
self.logger = None
@@ -52,23 +52,23 @@ class VPingBase(testcase_base.TestcaseBase):
def run(self, **kwargs):
if not self.check_repo_exist():
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
image_id = self.create_image()
if not image_id:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
flavor = self.get_flavor()
if not flavor:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
network_id = self.create_network_full()
if not network_id:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
sg_id = self.create_security_group()
if not sg_id:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
self.delete_exist_vms()
@@ -84,7 +84,7 @@ class VPingBase(testcase_base.TestcaseBase):
None,
sg_id)
if not vm1:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
test_ip = self.get_test_ip(vm1)
vm2 = self.boot_vm(self.vm2_name,
@@ -94,17 +94,17 @@ class VPingBase(testcase_base.TestcaseBase):
test_ip,
sg_id)
if not vm2:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
EXIT_CODE = self.do_vping(vm2, test_ip)
- if EXIT_CODE == testcase_base.TestcaseBase.EX_RUN_ERROR:
+ if EXIT_CODE == testcase.TestCase.EX_RUN_ERROR:
return EXIT_CODE
self.stop_time = time.time()
self.parse_result(EXIT_CODE,
self.start_time,
self.stop_time)
- return testcase_base.TestcaseBase.EX_OK
+ return testcase.TestCase.EX_OK
def boot_vm_preparation(self, config, vmname, test_ip):
pass
diff --git a/functest/opnfv_tests/openstack/vping/vping_ssh.py b/functest/opnfv_tests/openstack/vping/vping_ssh.py
index 7a58a41f..fc2f01c6 100755
--- a/functest/opnfv_tests/openstack/vping/vping_ssh.py
+++ b/functest/opnfv_tests/openstack/vping/vping_ssh.py
@@ -19,7 +19,7 @@ from scp import SCPClient
import functest.utils.functest_logger as ft_logger
import functest.utils.openstack_utils as os_utils
import vping_base
-import functest.core.testcase_base as testcase_base
+import functest.core.testcase as testcase
class VPingSSH(vping_base.VPingBase):
@@ -32,12 +32,12 @@ class VPingSSH(vping_base.VPingBase):
def do_vping(self, vm, test_ip):
floatip = self.add_float_ip(vm)
if not floatip:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
ssh = self.establish_ssh(vm, floatip)
if not ssh:
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
if not self.transfer_ping_script(ssh, floatip):
- return testcase_base.TestcaseBase.EX_RUN_ERROR
+ return testcase.TestCase.EX_RUN_ERROR
return self.do_vping_ssh(ssh, test_ip)
def add_float_ip(self, vm):
diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py
index c8e9c492..ccc1101a 100755
--- a/functest/opnfv_tests/sdn/odl/odl.py
+++ b/functest/opnfv_tests/sdn/odl/odl.py
@@ -7,6 +7,15 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
+"""Define classes required to run ODL suites.
+
+It has been designed for any context. But helpers are given for
+running test suites in OPNFV environment.
+
+Example:
+ $ python odl.py
+"""
+
import argparse
import errno
import fileinput
@@ -20,12 +29,15 @@ from robot.errors import RobotError
import robot.run
from robot.utils.robottime import timestamp_to_secs
-from functest.core import testcase_base
+from functest.core import testcase
import functest.utils.functest_logger as ft_logger
import functest.utils.openstack_utils as op_utils
+__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
+
class ODLResultVisitor(robot.api.ResultVisitor):
+ """Visitor to get result details."""
def __init__(self):
self._data = []
@@ -43,10 +55,12 @@ class ODLResultVisitor(robot.api.ResultVisitor):
self._data.append(output)
def get_data(self):
+ """Get the details of the result."""
return self._data
-class ODLTests(testcase_base.TestcaseBase):
+class ODLTests(testcase.TestCase):
+ """ODL test runner."""
repos = "/home/opnfv/repos/"
odl_test_repo = os.path.join(repos, "odl_test")
@@ -59,11 +73,17 @@ class ODLTests(testcase_base.TestcaseBase):
logger = ft_logger.Logger("opendaylight").getLogger()
def __init__(self):
- testcase_base.TestcaseBase.__init__(self)
+ testcase.TestCase.__init__(self)
self.case_name = "odl"
@classmethod
def set_robotframework_vars(cls, odlusername="admin", odlpassword="admin"):
+ """Set credentials in csit/variables/Variables.py.
+
+ Returns:
+ True if credentials are set.
+ False otherwise.
+ """
odl_variables_files = os.path.join(cls.odl_test_repo,
'csit/variables/Variables.py')
try:
@@ -74,11 +94,12 @@ class ODLTests(testcase_base.TestcaseBase):
odlpassword + "']"),
line.rstrip())
return True
- except Exception as e:
- cls.logger.error("Cannot set ODL creds: %s" % str(e))
+ except Exception as ex: # pylint: disable=broad-except
+ cls.logger.error("Cannot set ODL creds: %s", str(ex))
return False
def parse_results(self):
+ """Parse output.xml and get the details in it."""
xml_file = os.path.join(self.res_dir, 'output.xml')
result = robot.api.ExecutionResult(xml_file)
visitor = ODLResultVisitor()
@@ -90,8 +111,38 @@ class ODLTests(testcase_base.TestcaseBase):
self.details['description'] = result.suite.name
self.details['tests'] = visitor.get_data()
- def main(self, suites=default_suites, **kwargs):
+ def main(self, suites=None, **kwargs):
+ """Run the test suites
+
+ It has been designed to be called in any context.
+ It requires the following keyword arguments:
+ * odlusername,
+ * odlpassword,
+ * osauthurl,
+ * neutronip,
+ * osusername,
+ * ostenantname,
+ * ospassword,
+ * odlip,
+ * odlwebport,
+ * odlrestconfport.
+
+ Here are the steps:
+ * set all RobotFramework_variables,
+ * create the output directories if required,
+ * get the results in output.xml,
+ * delete temporary files.
+
+ Args:
+ **kwargs: Arbitrary keyword arguments.
+
+ Returns:
+ EX_OK if all suites ran well.
+ EX_RUN_ERROR otherwise.
+ """
try:
+ if not suites:
+ suites = self.default_suites
odlusername = kwargs['odlusername']
odlpassword = kwargs['odlpassword']
osauthurl = kwargs['osauthurl']
@@ -105,17 +156,17 @@ class ODLTests(testcase_base.TestcaseBase):
'ODL_SYSTEM_IP:' + kwargs['odlip'],
'PORT:' + kwargs['odlwebport'],
'RESTCONFPORT:' + kwargs['odlrestconfport']]
- except KeyError as e:
+ except KeyError as ex:
self.logger.error("Cannot run ODL testcases. Please check "
- "%s" % str(e))
+ "%s", str(ex))
return self.EX_RUN_ERROR
if self.set_robotframework_vars(odlusername, odlpassword):
try:
os.makedirs(self.res_dir)
- except OSError as e:
- if e.errno != errno.EEXIST:
+ except OSError as ex:
+ if ex.errno != errno.EEXIST:
self.logger.exception(
- "Cannot create {}".format(self.res_dir))
+ "Cannot create %s", self.res_dir)
return self.EX_RUN_ERROR
stdout_file = os.path.join(self.res_dir, 'stdout.txt')
output_dir = os.path.join(self.res_dir, 'output.xml')
@@ -131,19 +182,31 @@ class ODLTests(testcase_base.TestcaseBase):
try:
self.parse_results()
self.logger.info("ODL results were successfully parsed")
- except RobotError as e:
- self.logger.error("Run tests before publishing: %s" %
- e.message)
+ except RobotError as ex:
+ self.logger.error("Run tests before publishing: %s",
+ ex.message)
return self.EX_RUN_ERROR
try:
os.remove(stdout_file)
except OSError:
- self.logger.warning("Cannot remove {}".format(stdout_file))
+ self.logger.warning("Cannot remove %s", stdout_file)
return self.EX_OK
else:
return self.EX_RUN_ERROR
def run(self, **kwargs):
+ """Run suites in OPNFV environment
+
+ It basically check env vars to call main() with the keywords
+ required.
+
+ Args:
+ **kwargs: Arbitrary keyword arguments.
+
+ Returns:
+ EX_OK if all suites ran well.
+ EX_RUN_ERROR otherwise.
+ """
try:
suites = self.default_suites
try:
@@ -176,19 +239,20 @@ class ODLTests(testcase_base.TestcaseBase):
kwargs['odlwebport'] = '8181'
else:
kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP']
- except KeyError as e:
+ except KeyError as ex:
self.logger.error("Cannot run ODL testcases. "
"Please check env var: "
- "%s" % str(e))
+ "%s", str(ex))
return self.EX_RUN_ERROR
- except Exception:
+ except Exception: # pylint: disable=broad-except
self.logger.exception("Cannot run ODL testcases.")
return self.EX_RUN_ERROR
return self.main(suites, **kwargs)
-class ODLParser(object):
+class ODLParser(object): # pylint: disable=too-few-public-methods
+ """Parser to run ODL test suites."""
def __init__(self):
self.parser = argparse.ArgumentParser()
@@ -226,19 +290,28 @@ class ODLParser(object):
'-p', '--pushtodb', help='Push results to DB',
action='store_true')
- def parse_args(self, argv=[]):
+ def parse_args(self, argv=None):
+ """Parse arguments.
+
+ It can call sys.exit if arguments are incorrect.
+
+ Returns:
+ the arguments from cmdline
+ """
+ if not argv:
+ argv = []
return vars(self.parser.parse_args(argv))
if __name__ == '__main__':
- odl = ODLTests()
- parser = ODLParser()
- args = parser.parse_args(sys.argv[1:])
+ ODL = ODLTests()
+ PARSER = ODLParser()
+ ARGS = PARSER.parse_args(sys.argv[1:])
try:
- result = odl.main(ODLTests.default_suites, **args)
- if result != testcase_base.TestcaseBase.EX_OK:
- sys.exit(result)
- if args['pushtodb']:
- sys.exit(odl.push_to_db())
- except Exception:
- sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR)
+ RESULT = ODL.main(ODLTests.default_suites, **ARGS)
+ if RESULT != testcase.TestCase.EX_OK:
+ sys.exit(RESULT)
+ if ARGS['pushtodb']:
+ sys.exit(ODL.push_to_db())
+ except Exception: # pylint: disable=broad-except
+ sys.exit(testcase.TestCase.EX_RUN_ERROR)
diff --git a/functest/opnfv_tests/sdn/onos/onos.py b/functest/opnfv_tests/sdn/onos/onos.py
index 8bc73832..d482ae32 100644
--- a/functest/opnfv_tests/sdn/onos/onos.py
+++ b/functest/opnfv_tests/sdn/onos/onos.py
@@ -14,7 +14,7 @@ import shutil
import time
import urlparse
-from functest.core import testcase_base
+from functest.core import testcase
from functest.utils.constants import CONST
import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
@@ -24,7 +24,7 @@ import functest.utils.openstack_utils as openstack_utils
logger = ft_logger.Logger(__name__).getLogger()
-class OnosBase(testcase_base.TestcaseBase):
+class OnosBase(testcase.TestCase):
onos_repo_path = CONST.dir_repo_onos
onos_sfc_image_name = CONST.onos_sfc_image_name
onos_sfc_image_path = os.path.join(CONST.dir_functest_data,
@@ -39,10 +39,10 @@ class OnosBase(testcase_base.TestcaseBase):
self.start_time = time.time()
try:
self._run()
- res = testcase_base.TestcaseBase.EX_OK
+ res = testcase.TestCase.EX_OK
except Exception as e:
logger.error('Error with run: %s', e)
- res = testcase_base.TestcaseBase.EX_RUN_ERROR
+ res = testcase.TestCase.EX_RUN_ERROR
self.stop_time = time.time()
return res
diff --git a/functest/opnfv_tests/vnf/aaa/aaa.py b/functest/opnfv_tests/vnf/aaa/aaa.py
index f1c265f4..bdedcf7c 100755
--- a/functest/opnfv_tests/vnf/aaa/aaa.py
+++ b/functest/opnfv_tests/vnf/aaa/aaa.py
@@ -11,7 +11,7 @@ import sys
import argparse
-import functest.core.testcase_base as testcase_base
+import functest.core.testcase as testcase
import functest.core.vnf_base as vnf_base
import functest.utils.functest_logger as ft_logger
@@ -62,9 +62,9 @@ if __name__ == '__main__':
aaa_vnf = AaaVnf()
try:
result = aaa_vnf.main(**args)
- if result != testcase_base.TestcaseBase.EX_OK:
+ if result != testcase.TestCase.EX_OK:
sys.exit(result)
if args['pushtodb']:
sys.exit(aaa_vnf.push_to_db())
except Exception:
- sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR)
+ sys.exit(testcase.TestCase.EX_RUN_ERROR)
diff --git a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
new file mode 100644
index 00000000..f21ce3f9
--- /dev/null
+++ b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
@@ -0,0 +1,149 @@
+#!/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
+import json
+import os
+import shutil
+
+import requests
+
+import functest.core.vnf_base as vnf_base
+from functest.utils.constants import CONST
+import functest.utils.functest_logger as ft_logger
+import functest.utils.functest_utils as ft_utils
+
+
+class ClearwaterOnBoardingBase(vnf_base.VnfOnBoardingBase):
+
+ def __init__(self, project='functest', case='', repo='', cmd=''):
+ self.logger = ft_logger.Logger(__name__).getLogger()
+ super(ClearwaterOnBoardingBase, self).__init__(
+ project, case, repo, cmd)
+ self.case_dir = os.path.join(CONST.dir_functest_test, 'vnf', 'ims')
+ self.data_dir = CONST.dir_ims_data
+ self.result_dir = os.path.join(CONST.dir_results, case)
+ self.test_dir = CONST.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):
+ output_dict = {}
+ self.logger.info('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}
+ rq = requests.post(account_url, data=params)
+ output_dict['login'] = params
+ if rq.status_code != 201 and rq.status_code != 409:
+ raise Exception("Unable to create an account for number"
+ " provision: %s" % rq.json()['reason'])
+ self.logger.info('Account is created on Ellis: %s', params)
+
+ session_url = 'http://{0}/session'.format(ellis_ip)
+ session_data = {
+ 'username': params['email'],
+ 'password': params['password'],
+ 'email': params['email']
+ }
+ rq = requests.post(session_url, data=session_data)
+ if rq.status_code != 201:
+ raise Exception('Failed to get cookie for Ellis')
+ cookies = rq.cookies
+ self.logger.info('Cookies: %s' % cookies)
+
+ number_url = 'http://{0}/accounts/{1}/numbers'.format(
+ ellis_ip,
+ params['email'])
+ self.logger.info('Create 1st calling number on Ellis')
+ number_res = self.create_ellis_number(number_url, cookies)
+ output_dict['number'] = number_res
+
+ if two_numbers:
+ self.logger.info('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):
+ rq = requests.post(number_url, cookies=cookies)
+
+ if rq.status_code != 200:
+ if rq and rq.json():
+ reason = rq.json()['reason']
+ else:
+ reason = rq
+ raise Exception("Unable to create a number: %s" % reason)
+ number_res = rq.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'):
+ self.logger.info('Run Clearwater live test')
+ nameservers = ft_utils.get_resolvconf_ns()
+ resolvconf = ['{0}{1}{2}'.format(os.linesep, 'nameserver ', ns)
+ for ns in nameservers]
+ self.logger.debug('resolvconf: %s', resolvconf)
+ dns_file = '/etc/resolv.conf'
+ dns_file_bak = '/etc/resolv.conf.bak'
+ shutil.copy(dns_file, dns_file_bak)
+ script = ('echo -e "nameserver {0}{1}" > {2};'
+ 'source /etc/profile.d/rvm.sh;'
+ 'cd {3};'
+ 'rake test[{4}] SIGNUP_CODE={5}'
+ .format(dns_ip,
+ ''.join(resolvconf),
+ 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.info('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(dns_file_bak, 'r') as bak_file:
+ result = bak_file.read()
+ with open(dns_file, 'w') as f:
+ f.write(result)
+
+ f = open(output_file, 'r')
+ result = f.read()
+ if result != "":
+ self.logger.debug(result)
+
+ vims_test_result = ""
+ tempFile = os.path.join(self.test_dir, "temp.json")
+ try:
+ self.logger.debug("Trying to load test results")
+ with open(tempFile) as f:
+ vims_test_result = json.load(f)
+ f.close()
+ except Exception:
+ self.logger.error("Unable to retrieve test results")
+
+ try:
+ os.remove(tempFile)
+ except Exception:
+ self.logger.error("Deleting file failed")
+
+ 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 f7dfd532..404f208e 100644
--- a/functest/opnfv_tests/vnf/ims/cloudify_ims.py
+++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
@@ -7,42 +7,37 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
-import json
import os
-import requests
-import subprocess
import sys
import time
+
+import requests
import yaml
-import functest.core.vnf_base as vnf_base
+from functest.opnfv_tests.vnf.ims.clearwater import Clearwater
+import functest.opnfv_tests.vnf.ims.clearwater_ims_base as clearwater_ims_base
+from functest.opnfv_tests.vnf.ims.orchestrator_cloudify import Orchestrator
+from functest.utils.constants import CONST
import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_utils as os_utils
-from clearwater import Clearwater
-from functest.utils.constants import CONST
-from orchestrator_cloudify import Orchestrator
-
-class ImsVnf(vnf_base.VnfOnBoardingBase):
+class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
def __init__(self, project='functest', case='cloudify_ims',
repo='', cmd=''):
- super(ImsVnf, self).__init__(project, case, repo, cmd)
- self.logger = ft_logger.Logger("vIMS").getLogger()
- 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
+ super(CloudifyIms, self).__init__(project, case, repo, cmd)
+ self.logger = ft_logger.Logger(__name__).getLogger()
# Retrieve the configuration
try:
self.config = CONST.__getattribute__(
'vnf_{}_config'.format(self.case_name))
- except:
+ except Exception:
raise Exception("VNF config file not found")
- config_file = self.case_dir + self.config
+ config_file = os.path.join(self.case_dir, self.config)
self.orchestrator = dict(
requirements=get_config("cloudify.requirements", config_file),
blueprint=get_config("cloudify.blueprint", config_file),
@@ -61,10 +56,6 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
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")
@@ -82,7 +73,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
image_id = os_utils.get_image_id(self.glance_client,
image_name)
self.logger.debug("image_id: %s" % image_id)
- except:
+ except Exception:
self.logger.error("Unexpected error: %s" % sys.exc_info()[0])
if image_id == '':
@@ -177,10 +168,11 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
self.logger.debug("Resolvconf set")
self.logger.info("Prepare virtualenv for cloudify-cli")
- cmd = "chmod +x " + self.case_dir + "create_venv.sh"
+ venv_scrit_dir = os.path.join(self.case_dir, "create_venv.sh")
+ cmd = "chmod +x " + venv_scrit_dir
ft_utils.execute_command(cmd)
time.sleep(3)
- cmd = self.case_dir + "create_venv.sh " + self.data_dir
+ cmd = venv_scrit_dir + " " + self.data_dir
ft_utils.execute_command(cmd)
cfy.download_manager_blueprint(
@@ -251,99 +243,25 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
self.logger.debug("Trying to get clearwater manager IP ... ")
mgr_ip = os.popen(cmd).read()
mgr_ip = mgr_ip.splitlines()[0]
- except:
+ except Exception:
self.step_failure("Unable to retrieve the IP of the "
"cloudify manager server !")
- api_url = "http://" + mgr_ip + "/api/v2"
- dep_outputs = requests.get(api_url + "/deployments/" +
- self.vnf['deployment_name'] + "/outputs")
- dns_ip = dep_outputs.json()['outputs']['dns_ip']
- ellis_ip = dep_outputs.json()['outputs']['ellis_ip']
-
- self.logger.debug("DNS ip : %s" % dns_ip)
- self.logger.debug("ELLIS ip : %s" % ellis_ip)
-
- ellis_url = "http://" + ellis_ip + "/"
- url = ellis_url + "accounts"
-
- params = {"password": "functest",
- "full_name": "opnfv functest user",
- "email": "functest@opnfv.fr",
- "signup_code": "secret"}
-
- rq = requests.post(url, data=params)
- i = 30
- while rq.status_code != 201 and i > 0:
- rq = requests.post(url, data=params)
- self.logger.debug("Account creation http status code: %s"
- % rq.status_code)
- i = i - 1
- time.sleep(10)
-
- if rq.status_code == 201:
- url = ellis_url + "session"
- rq = requests.post(url, data=params)
- cookies = rq.cookies
- else:
- self.step_failure("Unable to create an account")
-
- url = ellis_url + "accounts/" + params['email'] + "/numbers"
- if cookies != "":
- rq = requests.post(url, cookies=cookies)
- i = 24
- while rq.status_code != 200 and i > 0:
- rq = requests.post(url, cookies=cookies)
- self.logger.debug("Number creation http status code: %s"
- % rq.status_code)
- i = i - 1
- time.sleep(25)
-
- if rq.status_code != 200:
- self.step_failure("Unable to create a number: %s"
- % rq.json()['reason'])
-
- nameservers = ft_utils.get_resolvconf_ns()
- resolvconf = ""
- for ns in nameservers:
- resolvconf += "\nnameserver " + ns
+ self.logger.info('Cloudify Manager: %s', mgr_ip)
+ api_url = 'http://{0}/api/v2/deployments/{1}/outputs'.format(
+ mgr_ip, self.vnf['deployment_name'])
+ dep_outputs = requests.get(api_url)
+ self.logger.info(api_url)
+ outputs = dep_outputs.json()['outputs']
+ self.logger.info("Deployment outputs: %s", outputs)
+ dns_ip = outputs['dns_ip']
+ ellis_ip = outputs['ellis_ip']
+ self.config_ellis(ellis_ip)
if dns_ip != "":
- script = ('echo -e "nameserver ' + dns_ip + resolvconf +
- '" > /etc/resolv.conf; ')
- script += 'source /etc/profile.d/rvm.sh; '
- script += 'cd {0}; '
- script += ('rake test[{1}] SIGNUP_CODE="secret"')
-
- cmd = ("/bin/bash -c '" +
- script.format(self.data_dir, self.inputs["public_domain"]) +
- "'")
- output_file = "output.txt"
- f = open(output_file, 'w+')
- subprocess.call(cmd, shell=True, stdout=f,
- stderr=subprocess.STDOUT)
- f.close()
-
- f = open(output_file, 'r')
- result = f.read()
- if result != "":
- self.logger.debug(result)
-
- vims_test_result = ""
- tempFile = os.path.join(self.test_dir, "temp.json")
- try:
- self.logger.debug("Trying to load test results")
- with open(tempFile) as f:
- vims_test_result = json.load(f)
- f.close()
- except:
- self.logger.error("Unable to retrieve test results")
-
- try:
- os.remove(tempFile)
- except:
- self.logger.error("Deleting file failed")
-
+ vims_test_result = self.run_clearwater_live_test(
+ dns_ip=dns_ip,
+ public_domain=self.inputs["public_domain"])
if vims_test_result != '':
return {'status': 'PASS', 'result': vims_test_result}
else:
@@ -352,7 +270,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
def clean(self):
self.vnf['object'].undeploy_vnf()
self.orchestrator['object'].undeploy_manager()
- super(ImsVnf, self).clean()
+ super(CloudifyIms, self).clean()
def main(self, **kwargs):
self.logger.info("Cloudify IMS VNF onboarding test starting")
diff --git a/functest/opnfv_tests/vnf/ims/opera_ims.py b/functest/opnfv_tests/vnf/ims/opera_ims.py
index 7ead401f..d022b3c7 100755..100644
--- a/functest/opnfv_tests/vnf/ims/opera_ims.py
+++ b/functest/opnfv_tests/vnf/ims/opera_ims.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-# Copyright (c) 2016 Orange and others.
+# Copyright (c) 2017 HUAWEI TECHNOLOGIES CO.,LTD and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
@@ -8,381 +8,117 @@
# http://www.apache.org/licenses/LICENSE-2.0
import json
-import socket
-import sys
+import os
import time
-import yaml
-import functest.core.vnf_base as vnf_base
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_utils as ft_utils
-import functest.utils.openstack_utils as os_utils
-import os
+from opera import openo_connect
+import requests
+
+import functest.opnfv_tests.vnf.ims.clearwater_ims_base as clearwater_ims_base
from functest.utils.constants import CONST
+import functest.utils.functest_logger as ft_logger
-from org.openbaton.cli.agents.agents import MainAgent
-from org.openbaton.cli.errors.errors import NfvoException
+class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase):
-def servertest(host, port):
- args = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM)
- for family, socktype, proto, canonname, sockaddr in args:
- s = socket.socket(family, socktype, proto)
+ def __init__(self, project='functest', case='opera_ims',
+ repo=CONST.dir_repo_opera, cmd=''):
+ super(OperaIms, self).__init__(project, case, repo, cmd)
+ self.logger = ft_logger.Logger(__name__).getLogger()
+ self.ellis_file = os.path.join(self.result_dir, 'ellis.info')
+ self.live_test_file = os.path.join(self.result_dir,
+ 'live_test_report.json')
try:
- s.connect(sockaddr)
- except socket.error:
- return False
+ self.openo_msb_endpoint = os.environ['OPENO_MSB_ENDPOINT']
+ except KeyError:
+ raise Exception('OPENO_MSB_ENDPOINT is not specified,'
+ ' put it as <OPEN-O ip>:<port>')
else:
- s.close()
- return True
-
-# ----------------------------------------------------------
-#
-# 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
-
-
-class ImsVnf(vnf_base.VnfOnBoardingBase):
-
- def __init__(self, project='functest', case='orchestra_ims',
- repo='', cmd=''):
- super(ImsVnf, self).__init__(project, case, repo, cmd)
- self.ob_password = "openbaton"
- self.ob_username = "admin"
- self.ob_https = False
- self.ob_port = "8080"
- self.ob_ip = "localhost"
- self.ob_instance_id = ""
- self.logger = ft_logger.Logger("orchestra_ims").getLogger()
- 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
- self.ob_projectid = ""
- self.keystone_client = os_utils.get_keystone_client()
- self.ob_nsr_id = ""
- self.main_agent = None
- # vIMS Data directory creation
- if not os.path.exists(self.data_dir):
- os.makedirs(self.data_dir)
- # Retrieve the configuration
- try:
- self.config = CONST.__getattribute__(
- 'vnf_{}_config'.format(self.case_name))
- except:
- raise Exception("Orchestra VNF config file not found")
- config_file = self.case_dir + self.config
- self.imagename = get_config("openbaton.imagename", config_file)
- self.market_link = get_config("openbaton.marketplace_link",
- config_file)
- self.images = get_config("tenant_images", config_file)
-
- def deploy_orchestrator(self, **kwargs):
- self.logger.info("Additional pre-configuration steps")
- nova_client = os_utils.get_nova_client()
- neutron_client = os_utils.get_neutron_client()
- glance_client = os_utils.get_glance_client()
-
- # 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(glance_client,
- image_name)
- self.logger.info("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(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")
- network_dic = os_utils.create_network_full(neutron_client,
- "openbaton_mgmt",
- "openbaton_mgmt_subnet",
- "openbaton_router",
- "192.168.100.0/24")
-
- # orchestrator VM flavor
- self.logger.info("Check medium Flavor is available, if not create one")
- flavor_exist, flavor_id = os_utils.get_or_create_flavor(
- "m1.medium",
- "4096",
- '1',
- '2',
- public=True)
- self.logger.debug("Flavor id: %s" % flavor_id)
-
- if not network_dic:
- self.logger.error("There has been a problem when creating the "
- "neutron network")
-
- network_id = network_dic["net_id"]
-
- self.logger.info("Creating floating IP for VM in advance...")
- floatip_dic = os_utils.create_floating_ip(neutron_client)
- floatip = floatip_dic['fip_addr']
-
- if floatip is None:
- self.logger.error("Cannot create floating IP.")
-
- userdata = "#!/bin/bash\n"
- userdata += "set -x\n"
- userdata += "set -e\n"
- userdata += "echo \"nameserver 8.8.8.8\" >> /etc/resolv.conf\n"
- userdata += "apt-get install curl\n"
- userdata += ("echo \"rabbitmq_broker_ip=%s\" > ./config_file\n"
- % floatip)
- userdata += "echo \"mysql=no\" >> ./config_file\n"
- userdata += ("echo \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuPXrV3"
- "geeHc6QUdyUr/1Z+yQiqLcOskiEGBiXr4z76MK4abiFmDZ18OMQlc"
- "fl0p3kS0WynVgyaOHwZkgy/DIoIplONVr2CKBKHtPK+Qcme2PVnCtv"
- "EqItl/FcD+1h5XSQGoa+A1TSGgCod/DPo+pes0piLVXP8Ph6QS1k7S"
- "ic7JDeRQ4oT1bXYpJ2eWBDMfxIWKZqcZRiGPgMIbJ1iEkxbpeaAd9O"
- "4MiM9nGCPESmed+p54uYFjwEDlAJZShcAZziiZYAvMZhvAhe6USljc"
- "7YAdalAnyD/jwCHuwIrUw/lxo7UdNCmaUxeobEYyyFA1YVXzpNFZya"
- "XPGAAYIJwEq/ openbaton@opnfv\" >> /home/ubuntu/.ssh/aut"
- "horized_keys\n")
- userdata += "cat ./config_file\n"
- userdata += ("curl -s http://get.openbaton.org/bootstrap "
- "> ./bootstrap\n")
- userdata += "export OPENBATON_COMPONENT_AUTOSTART=false\n"
- bootstrap = "sh ./bootstrap release -configFile=./config_file"
- userdata += bootstrap + "\n"
-
- userdata += ("echo \"nfvo.plugin.timeout=300000\" >> "
- "/etc/openbaton/openbaton-nfvo.properties\n")
- userdata += "service openbaton-nfvo restart\n"
- userdata += "service openbaton-vnfm-generic restart\n"
-
- sg_id = os_utils.create_security_group_full(neutron_client,
- "orchestra-sec-group",
- "allowall")
-
- os_utils.create_secgroup_rule(neutron_client, sg_id, "ingress",
- "icmp", 0, 255)
- os_utils.create_secgroup_rule(neutron_client, sg_id, "egress",
- "icmp", 0, 255)
- os_utils.create_secgroup_rule(neutron_client, sg_id, "ingress",
- "tcp", 1, 65535)
- os_utils.create_secgroup_rule(neutron_client, sg_id, "ingress",
- "udp", 1, 65535)
- os_utils.create_secgroup_rule(neutron_client, sg_id, "egress",
- "tcp", 1, 65535)
- os_utils.create_secgroup_rule(neutron_client, sg_id, "egress",
- "udp", 1, 65535)
-
- self.logger.info("Security group set")
-
- self.logger.info("Create instance....")
- self.logger.info("flavor: m1.medium\n"
- "image: %s\n"
- "network_id: %s\n"
- "userdata: %s\n"
- % (self.imagename, network_id, userdata))
-
- instance = os_utils.create_instance_and_wait_for_active(
- "m1.medium",
- os_utils.get_image_id(glance_client, self.imagename),
- network_id,
- "orchestra-openbaton",
- config_drive=False,
- userdata=userdata)
+ self.logger.info('OPEN-O endpoint is: %s', self.openo_msb_endpoint)
- self.ob_instance_id = instance.id
+ def prepare(self):
+ pass
- self.logger.info("Adding sec group to orchestra instance")
- os_utils.add_secgroup_to_instance(nova_client,
- self.ob_instance_id, sg_id)
-
- self.logger.info("Associating floating ip: '%s' to VM '%s' "
- % (floatip, "orchestra-openbaton"))
- if not os_utils.add_floating_ip(nova_client, instance.id, floatip):
- self.logger.error("Cannot associate floating IP to VM.")
- self.step_failure("Cannot associate floating IP to VM.")
-
- self.logger.info("Waiting for nfvo to be up and running...")
- x = 0
- while x < 100:
- if servertest(floatip, "8080"):
- break
- else:
- self.logger.debug("openbaton is not started yet")
- time.sleep(5)
- x += 1
-
- if x == 100:
- self.logger.error("Openbaton is not started correctly")
- self.step_failure("Openbaton is not started correctly")
-
- self.ob_ip = floatip
- self.ob_password = "openbaton"
- self.ob_username = "admin"
- self.ob_https = False
- self.ob_port = "8080"
-
- self.logger.info("Deploy orchestrator: OK")
+ def clean(self):
+ pass
def deploy_vnf(self):
- self.logger.info("vIMS Deployment")
-
- self.main_agent = MainAgent(nfvo_ip=self.ob_ip,
- nfvo_port=self.ob_port,
- https=self.ob_https,
- version=1,
- username=self.ob_username,
- password=self.ob_password)
-
- project_agent = self.main_agent.get_agent("project", self.ob_projectid)
- for p in json.loads(project_agent.find()):
- if p.get("name") == "default":
- self.ob_projectid = p.get("id")
- break
-
- self.logger.debug("project id: %s" % self.ob_projectid)
- if self.ob_projectid == "":
- self.logger.error("Default project id was not found!")
- self.step_failure("Default project id was not found!")
-
- vim_json = {
- "name": "vim-instance",
- "authUrl": os_utils.get_credentials().get("auth_url"),
- "tenant": os_utils.get_credentials().get("tenant_name"),
- "username": os_utils.get_credentials().get("username"),
- "password": os_utils.get_credentials().get("password"),
- # "keyPair": "opnfv",
- # TODO change the keypair to correct value
- # or upload a correct one or remove it
- "securityGroups": [
- "default",
- "orchestra-sec-group"
- ],
- "type": "openstack",
- "location": {
- "name": "opnfv",
- "latitude": "52.525876",
- "longitude": "13.314400"
- }
- }
-
- self.logger.debug("vim: %s" % vim_json)
-
- self.main_agent.get_agent(
- "vim",
- project_id=self.ob_projectid).create(entity=json.dumps(vim_json))
-
- market_agent = self.main_agent.get_agent("market",
- project_id=self.ob_projectid)
-
- nsd = {}
- try:
- self.logger.info("sending: %s" % self.market_link)
- nsd = market_agent.create(entity=self.market_link)
- self.logger.info("Onboarded nsd: " + nsd.get("name"))
- except NfvoException as e:
- self.step_failure(e.message)
-
- nsr_agent = self.main_agent.get_agent("nsr",
- project_id=self.ob_projectid)
- nsd_id = nsd.get('id')
- if nsd_id is None:
- self.step_failure("NSD not onboarded correctly")
-
- nsr = None
try:
- nsr = nsr_agent.create(nsd_id)
- except NfvoException as e:
- self.step_failure(e.message)
-
- if nsr.get('code') is not None:
- self.logger.error(
- "vIMS cannot be deployed: %s -> %s" %
- (nsr.get('code'), nsr.get('message')))
- self.step_failure("vIMS cannot be deployed")
-
- i = 0
- self.logger.info("waiting NSR to go to active...")
- while nsr.get("status") != 'ACTIVE' and nsr.get("status") != 'ERROR':
- i += 1
- if i == 100:
- self.step_failure("After %s sec the nsr did not go to active.."
- % 5 * 100)
- time.sleep(5)
- nsr = json.loads(nsr_agent.find(nsr.get('id')))
-
- if nsr.get("status") == 'ACTIVE':
- deploy_vnf = {'status': "PASS", 'result': nsr}
- self.logger.info("Deploy VNF: OK")
+ openo_connect.create_service(self.openo_msb_endpoint,
+ 'functest_opera',
+ 'VNF for functest testing')
+ except Exception as e:
+ self.logger.error(e)
+ return {'status': 'FAIL', 'result': e}
else:
- deploy_vnf = {'status': "FAIL", 'result': nsr}
- self.logger.error("Deploy VNF: ERROR")
- self.step_failure("Deploy vIMS failed")
- self.ob_nsr_id = nsr.get("id")
- return deploy_vnf
+ self.logger.info('vIMS deployment is kicked off')
+ return {'status': 'PASS', 'result': ''}
- def test_vnf(self):
- # Adaptations probably needed
- # code used for cloudify_ims
- # ruby client on jumphost calling the vIMS on the SUT
- return
+ def dump_info(self, info_file, result):
+ with open(info_file, 'w') as f:
+ self.logger.debug('Save information to file: %s', info_file)
+ json.dump(result, f)
- def clean(self):
- self.main_agent.get_agent(
- "nsr",
- project_id=self.ob_projectid).delete(self.ob_nsr_id)
- time.sleep(5)
- os_utils.delete_instance(nova_client=os_utils.get_nova_client(),
- instance_id=self.ob_instance_id)
- # TODO question is the clean removing also the VM?
- # I think so since is goinf to remove the tenant...
- super(ImsVnf, self).clean()
+ def test_vnf(self):
+ vnfm_ip = openo_connect.get_vnfm_ip(self.openo_msb_endpoint)
+ self.logger.info('VNFM IP: %s', vnfm_ip)
+ vnf_status_url = 'http://{0}:5000/api/v1/model/status'.format(vnfm_ip)
+ vnf_alive = False
+ retry = 15
+
+ self.logger.info('Check the VNF status')
+ while retry > 0:
+ rq = requests.get(vnf_status_url)
+ response = rq.json()
+ vnf_alive = response['vnf_alive']
+ msg = response['msg']
+ self.logger.info(msg)
+ if vnf_alive:
+ break
+ self.logger.info('check again in one minute...')
+ retry = retry - 1
+ time.sleep(60)
+
+ if not vnf_alive:
+ raise Exception('VNF failed to start: {0}'.format(msg))
+
+ ellis_config_url = ('http://{0}:5000/api/v1/model/ellis/configure'
+ .format(vnfm_ip))
+ rq = requests.get(ellis_config_url, timeout=60)
+ if rq.json() and not rq.json()['ellis_ok']:
+ self.logger.error(rq.json()['data'])
+ raise Exception('Failed to configure Ellis')
+
+ self.logger.info('Get Clearwater deployment detail')
+ vnf_info_url = ('http://{0}:5000/api/v1/model/output'
+ .format(vnfm_ip))
+ rq = requests.get(vnf_info_url, timeout=60)
+ data = rq.json()['data']
+ self.logger.info(data)
+ bono_ip = data['bono_ip']
+ ellis_ip = data['ellis_ip']
+ dns_ip = data['dns_ip']
+ result = self.config_ellis(ellis_ip, 'signup', True)
+ self.logger.debug('Ellis Result: %s', result)
+ self.dump_info(self.ellis_file, result)
+
+ if dns_ip:
+ vims_test_result = self.run_clearwater_live_test(
+ dns_ip,
+ 'clearwater.local',
+ bono_ip,
+ ellis_ip,
+ 'signup')
+ if vims_test_result != '':
+ self.dump_info(self.live_test_file, vims_test_result)
+ return {'status': 'PASS', 'result': vims_test_result}
+ else:
+ return {'status': 'FAIL', 'result': ''}
def main(self, **kwargs):
- self.logger.info("Orchestra IMS VNF onboarding test starting")
+ self.logger.info("Start to run Opera vIMS VNF onboarding test")
self.execute()
- self.logger.info("Orchestra IMS VNF onboarding test executed")
+ self.logger.info("Opera vIMS VNF onboarding test finished")
if self.criteria is "PASS":
return self.EX_OK
else:
@@ -391,10 +127,3 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
def run(self):
kwargs = {}
return self.main(**kwargs)
-
-
-if __name__ == '__main__':
- test = ImsVnf()
- test.deploy_orchestrator()
- test.deploy_vnf()
- test.clean()
diff --git a/functest/opnfv_tests/vnf/rnc/parser.py b/functest/opnfv_tests/vnf/rnc/parser.py
index 1cff7220..133145d7 100644
--- a/functest/opnfv_tests/vnf/rnc/parser.py
+++ b/functest/opnfv_tests/vnf/rnc/parser.py
@@ -15,10 +15,10 @@
# limitations under the License.
#
-import functest.core.feature_base as base
+import functest.core.feature as base
-class Parser(base.FeatureBase):
+class Parser(base.Feature):
def __init__(self):
super(Parser, self).__init__(project='parser',
case='parser-basics',
diff --git a/functest/opnfv_tests/vnf/router/vyos_vrouter.py b/functest/opnfv_tests/vnf/router/vyos_vrouter.py
index 94a3ecfd..e188c3fb 100644
--- a/functest/opnfv_tests/vnf/router/vyos_vrouter.py
+++ b/functest/opnfv_tests/vnf/router/vyos_vrouter.py
@@ -6,16 +6,16 @@
# 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
+import functest.core.feature as base
import json
import os
RESULT_DETAILS_FILE = "test_result.json"
-class VrouterVnf(base.FeatureBase):
+class VrouterVnf(base.Feature):
def __init__(self):
- super(VrouterVnf, self).__init__(project='vRouter',
+ super(VrouterVnf, self).__init__(project='functest',
case='vyos_vrouter',
repo='dir_repo_vrouter')
self.cmd = 'cd %s && ./run.sh' % self.repo