Merge "remove specific node label" into v2.0
authorMike Marchetti <mmarchetti@sandvine.com>
Wed, 21 Jun 2017 00:40:03 +0000 (02:40 +0200)
committerGerrit Code Review <root@osm.etsi.org>
Wed, 21 Jun 2017 00:40:03 +0000 (02:40 +0200)
14 files changed:
Dockerfile
osm_ro/nfvo.py
osm_ro/nfvo_db.py
osm_ro/openmano_schemas.py
osm_ro/vim_thread.py
osm_ro/vimconn_aws.py
osm_ro/vimconn_openstack.py
osm_ro/vimconn_openvim.py
osm_ro/vimconn_vmware.py
requirements.txt
scripts/install-openmano.sh
setup.py
stdeb.cfg
test/test_RO.py

index 84144a8..82c3ca9 100644 (file)
@@ -6,5 +6,5 @@ RUN  apt-get update && \
   DEBIAN_FRONTEND=noninteractive apt-get -y install python-pip libmysqlclient-dev libssl-dev libffi-dev && \
   DEBIAN_FRONTEND=noninteractive pip install --upgrade pip && \
   DEBIAN_FRONTEND=noninteractive pip install --upgrade setuptools && \
-  DEBIAN_FRONTEND=noninteractive apt-get -y install python-argcomplete python-boto python-bottle python-jsonschema python-logutils python-cinderclient python-glanceclient python-keystoneclient python-neutronclient python-novaclient python-mysqldb
+  DEBIAN_FRONTEND=noninteractive apt-get -y install python-argcomplete python-boto python-bottle python-jsonschema python-logutils python-cinderclient python-glanceclient python-keystoneclient python-neutronclient python-novaclient python-openstackclient python-mysqldb
 
index 9330047..d45a3c7 100644 (file)
@@ -2041,20 +2041,23 @@ def create_instance(mydb, tenant_id, instance_dict):
             for scenario_net in scenarioDict['nets']:
                 if net_name == scenario_net["name"]:
                     if 'ip-profile' in net_instance_desc:
-                        ipprofile = net_instance_desc['ip-profile']
-                        ipprofile['subnet_address'] = ipprofile.pop('subnet-address',None)
-                        ipprofile['ip_version'] = ipprofile.pop('ip-version','IPv4')
-                        ipprofile['gateway_address'] = ipprofile.pop('gateway-address',None)
-                        ipprofile['dns_address'] = ipprofile.pop('dns-address',None)
-                        if 'dhcp' in ipprofile:
-                            ipprofile['dhcp_start_address'] = ipprofile['dhcp'].get('start-address',None)
-                            ipprofile['dhcp_enabled'] = ipprofile['dhcp'].get('enabled',True)
-                            ipprofile['dhcp_count'] = ipprofile['dhcp'].get('count',None)
-                            del ipprofile['dhcp']
+                        # translate from input format to database format
+                        ipprofile_in = net_instance_desc['ip-profile']
+                        ipprofile_db = {}
+                        ipprofile_db['subnet_address'] = ipprofile_in.get('subnet-address')
+                        ipprofile_db['ip_version'] = ipprofile_in.get('ip-version', 'IPv4')
+                        ipprofile_db['gateway_address'] = ipprofile_in.get('gateway-address')
+                        ipprofile_db['dns_address'] = ipprofile_in.get('dns-address')
+                        if isinstance(ipprofile_db['dns_address'], (list, tuple)):
+                            ipprofile_db['dns_address'] = ";".join(ipprofile_db['dns_address'])
+                        if 'dhcp' in ipprofile_in:
+                            ipprofile_db['dhcp_start_address'] = ipprofile_in['dhcp'].get('start-address')
+                            ipprofile_db['dhcp_enabled'] = ipprofile_in['dhcp'].get('enabled', True)
+                            ipprofile_db['dhcp_count'] = ipprofile_in['dhcp'].get('count' )
                         if 'ip_profile' not in scenario_net:
-                            scenario_net['ip_profile'] = ipprofile
+                            scenario_net['ip_profile'] = ipprofile_db
                         else:
-                            update(scenario_net['ip_profile'],ipprofile)
+                            update(scenario_net['ip_profile'], ipprofile_db)
             for interface in net_instance_desc.get('interfaces', () ):
                 if 'ip_address' in interface:
                     for vnf in scenarioDict['vnfs']:
index ea6d339..ac392c6 100644 (file)
@@ -107,7 +107,7 @@ class nfvo_db(db_base.db_base):
                                 created_time += 0.00001
                                 db_base._convert_bandwidth(dataiface, logger=self.logger)
                                 dataifacesDict[vm['name']][dataiface['name']] = {}
-                                dataifacesDict[vm['name']][dataiface['name']]['vpci'] = dataiface['vpci']
+                                dataifacesDict[vm['name']][dataiface['name']]['vpci'] = dataiface.get('vpci')
                                 dataifacesDict[vm['name']][dataiface['name']]['bw'] = dataiface['bandwidth']
                                 dataifacesDict[vm['name']][dataiface['name']]['model'] = "PF" if dataiface[
                                                                                                      'dedicated'] == "yes" else (
@@ -258,7 +258,7 @@ class nfvo_db(db_base.db_base):
                                 created_time += 0.00001
                                 db_base._convert_bandwidth(dataiface, logger=self.logger)
                                 ifaceDict = {}
-                                ifaceDict['vpci'] = dataiface['vpci']
+                                ifaceDict['vpci'] = dataiface.get('vpci')
                                 ifaceDict['bw'] = dataiface['bandwidth']
                                 ifaceDict['model'] = "PF" if dataiface['dedicated'] == "yes" else \
                                     ("VF" if dataiface['dedicated'] == "no" else "VFnotShared")
index 765c05f..7d218ec 100644 (file)
@@ -316,10 +316,11 @@ ip_profile_schema = {
     "$schema": "http://json-schema.org/draft-04/schema#",
     "type":"object",
     "properties":{
-        "ip-version": {"type":"string", "enum":["IPv4","IPv6"]},
+        "ip-version": {"type": "string", "enum": ["IPv4","IPv6"]},
         "subnet-address": ip_prefix_schema,
         "gateway-address": ip_schema,
-        "dns-address": ip_schema,
+        "dns-address": {"oneOf": [ip_schema,     # for backward compatibility
+                                  {"type": "array", "items": ip_schema}]},
         "dhcp": dhcp_schema
     },
 }
index 67bef44..9f396a2 100644 (file)
@@ -412,7 +412,7 @@ class vim_thread(threading.Thread):
             sdn_net_id = None
             sdn_controller = self.vim.config.get('sdn-controller')
             if sdn_controller and (net_type == "data" or net_type == "ptp"):
-                network = {"name": net_name, "type": net_type}
+                network = {"name": net_name, "type": net_type, "region": self.vim["config"]["datacenter_id"]}
 
                 vim_net = self.vim.get_network(net_id)
                 if vim_net.get('encapsulation') != 'vlan':
index dbe9acb..f0eebb6 100644 (file)
@@ -117,7 +117,7 @@ class vimconnector(vimconn.vimconnector):
                 except IOError as e:
                     raise vimconn.vimconnException("Error reading file '{}': {}".format(flavor_data[1:], e))
             elif isinstance(flavor_data, dict):
-                self.flavor_data = flavor_data
+                self.flavor_info = flavor_data
 
         self.logger = logging.getLogger('openmano.vim.aws')
         if log_level:
index de94fff..3182dbe 100644 (file)
@@ -322,9 +322,7 @@ class vimconnector(vimconn.vimconnector):
             if 'gateway_address' in ip_profile:
                 subnet['gateway_ip'] = ip_profile['gateway_address']
             if ip_profile.get('dns_address'):
-                #TODO: manage dns_address as a list of addresses separated by commas 
-                subnet['dns_nameservers'] = []
-                subnet['dns_nameservers'].append(ip_profile['dns_address'])
+                subnet['dns_nameservers'] = ip_profile['dns_address'].split(";")
             if 'dhcp_enabled' in ip_profile:
                 subnet['enable_dhcp'] = False if ip_profile['dhcp_enabled']=="false" else True
             if 'dhcp_start_address' in ip_profile:
@@ -472,11 +470,19 @@ class vimconnector(vimconn.vimconnector):
     def get_flavor_id_from_data(self, flavor_dict):
         """Obtain flavor id that match the flavor description
            Returns the flavor_id or raises a vimconnNotFoundException
+           flavor_dict: contains the required ram, vcpus, disk
+           If 'use_existing_flavors' is set to True at config, the closer flavor that provides same or more ram, vcpus
+                and disk is returned. Otherwise a flavor with exactly same ram, vcpus and disk is returned or a
+                vimconnNotFoundException is raised
         """
+        exact_match = False if self.config.get('use_existing_flavors') else True
         try:
             self._reload_connection()
-            numa=None
-            numas = flavor_dict.get("extended",{}).get("numas")
+            flavor_candidate_id = None
+            flavor_candidate_data = (10000, 10000, 10000)
+            flavor_target = (flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"])
+            # numa=None
+            numas = flavor_dict.get("extended", {}).get("numas")
             if numas:
                 #TODO
                 raise vimconn.vimconnNotFoundException("Flavor with EPA still not implemted")
@@ -488,14 +494,15 @@ class vimconnector(vimconn.vimconnector):
                 epa = flavor.get_keys()
                 if epa:
                     continue
-                    #TODO 
-                if flavor.ram != flavor_dict["ram"]:
-                    continue
-                if flavor.vcpus != flavor_dict["vcpus"]:
-                    continue
-                if flavor.disk != flavor_dict["disk"]:
-                    continue
-                return flavor.id
+                    # TODO
+                flavor_data = (flavor.ram, flavor.vcpus, flavor.disk)
+                if flavor_data == flavor_target:
+                    return flavor.id
+                elif not exact_match and flavor_target < flavor_data < flavor_candidate_data:
+                    flavor_candidate_id = flavor.id
+                    flavor_candidate_data = flavor_data
+            if not exact_match and flavor_candidate_id:
+                return flavor_candidate_id
             raise vimconn.vimconnNotFoundException("Cannot find any flavor matching '{}'".format(str(flavor_dict)))
         except (nvExceptions.NotFound, nvExceptions.ClientException, ksExceptions.ClientException, ConnectionError) as e:
             self._format_exception(e)
index e86b54d..e722dc8 100644 (file)
@@ -596,6 +596,9 @@ class vimconnector(vimconn.vimconnector):
         '''Returns the flavor identifier'''
         try:
             new_flavor_dict = flavor_data.copy()
+            for device in new_flavor_dict.get('extended', {}).get('devices', ()):
+                if 'image name' in device:
+                    del device['image name']
             new_flavor_dict["name"] = flavor_data["name"][:64]
             self._get_my_tenant()
             payload_req = json.dumps({'flavor': new_flavor_dict})
index 910387d..43ffba8 100644 (file)
@@ -2751,6 +2751,11 @@ class vimconnector(vimconn.vimconnector):
             #Unused in case of Underlay (data/ptp) network interface.
             fence_mode="bridged"
             is_inherited='false'
+            dns_list = dns_address.split(";")
+            dns1 = dns_list[0]
+            dns2_text = ""
+            if len(dns_list) >= 2:
+                dns2_text = "\n                                                <Dns2>{}</Dns2>\n".format(dns_list[1])
             data = """ <OrgVdcNetwork name="{0:s}" xmlns="http://www.vmware.com/vcloud/v1.5">
                             <Description>Openmano created</Description>
                                     <Configuration>
@@ -2759,22 +2764,22 @@ class vimconnector(vimconn.vimconnector):
                                                 <IsInherited>{1:s}</IsInherited>
                                                 <Gateway>{2:s}</Gateway>
                                                 <Netmask>{3:s}</Netmask>
-                                                <Dns1>{4:s}</Dns1>
-                                                <IsEnabled>{5:s}</IsEnabled>
+                                                <Dns1>{4:s}</Dns1>{5:s}
+                                                <IsEnabled>{6:s}</IsEnabled>
                                                 <IpRanges>
                                                     <IpRange>
-                                                        <StartAddress>{6:s}</StartAddress>
-                                                        <EndAddress>{7:s}</EndAddress>
+                                                        <StartAddress>{7:s}</StartAddress>
+                                                        <EndAddress>{8:s}</EndAddress>
                                                     </IpRange>
                                                 </IpRanges>
                                             </IpScope>
                                         </IpScopes>
-                                        <ParentNetwork href="{8:s}"/>
-                                        <FenceMode>{9:s}</FenceMode>
+                                        <ParentNetwork href="{9:s}"/>
+                                        <FenceMode>{10:s}</FenceMode>
                                     </Configuration>
-                                    <IsShared>{10:s}</IsShared>
+                                    <IsShared>{11:s}</IsShared>
                         </OrgVdcNetwork> """.format(escape(network_name), is_inherited, gateway_address,
-                                                    subnet_address, dns_address, dhcp_enabled,
+                                                    subnet_address, dns1, dns2_text, dhcp_enabled,
                                                     dhcp_start_address, dhcp_end_address, available_networks,
                                                     fence_mode, isshared)
 
index eb92478..0d6c432 100644 (file)
@@ -6,6 +6,7 @@ paramiko
 argcomplete
 requests
 logutils
+python-openstackclient
 python-novaclient
 python-keystoneclient
 python-glanceclient
index 0323cb4..624dce3 100755 (executable)
@@ -249,8 +249,11 @@ then
     [ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "python-boto"  #TODO check if at Centos it exists with this name, or PIP should be used
 
     # install openstack client needed for using openstack as a VIM
-    [ "$_DISTRO" == "Ubuntu" ] && install_packages "python-novaclient python-keystoneclient python-glanceclient python-neutronclient python-cinderclient"
-    [ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "python-devel" && easy_install python-novaclient python-keystoneclient python-glanceclient python-neutronclient python-cinderclient #TODO revise if gcc python-pip is needed
+    [ "$_DISTRO" == "Ubuntu" ] && install_packages "python-novaclient python-keystoneclient python-glanceclient "\
+                                                   "python-neutronclient python-cinderclient python-openstackclient"
+    [ "$_DISTRO" == "CentOS" -o "$_DISTRO" == "Red" ] && install_packages "python-devel" && easy_install \
+        python-novaclient python-keystoneclient python-glanceclient python-neutronclient python-cinderclient \
+        python-openstackclient #TODO revise if gcc python-pip is needed
 fi  # [[ -z "$NO_PACKAGES" ]]
 
 if [[ -z $NOCLONE ]]; then
index 5f1382d..303a652 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -24,6 +24,7 @@ _requirements = [
     "argcomplete",
     "requests",
     "logutils",
+    "python-openstackclient",
     "python-novaclient",
     "python-keystoneclient",
     "python-glanceclient",
index 7fc8a8e..a0c20ec 100644 (file)
--- a/stdeb.cfg
+++ b/stdeb.cfg
@@ -2,5 +2,5 @@
 Suite: xenial
 XS-Python-Version: >= 2.7
 Maintainer: Gerardo Garcia <gerardo.garciadeblas@telefonica.com>
-Depends: python-pip, libmysqlclient-dev, libssl-dev, libffi-dev, python-argcomplete, python-boto, python-bottle, python-jsonschema, python-logutils, python-cinderclient, python-glanceclient, python-keystoneclient, python-neutronclient, python-novaclient, python-mysqldb
+Depends: python-pip, libmysqlclient-dev, libssl-dev, libffi-dev, python-argcomplete, python-boto, python-bottle, python-jsonschema, python-logutils, python-cinderclient, python-glanceclient, python-keystoneclient, python-neutronclient, python-novaclient, python-openstackclient, python-mysqldb
 
index b1e2459..0d5e624 100755 (executable)
 '''
 Module for testing openmano functionality. It uses openmanoclient.py for invoking openmano
 '''
-__author__="Pablo Montes, Alfonso Tierno"
-__date__ ="$16-Feb-2017 17:08:16$"
-__version__="0.0.3"
-version_date="May 2017"
+__author__ = "Pablo Montes, Alfonso Tierno"
+__date__ = "$16-Feb-2017 17:08:16$"
+__version__ = "0.0.4"
+version_date = "Jun 2017"
 
 import logging
 import os
@@ -47,6 +47,26 @@ import uuid
 global test_config   #  used for global variables with the test configuration
 test_config = {}
 
+class test_base(unittest.TestCase):
+    test_index = 1
+    test_text = None
+
+    @classmethod
+    def setUpClass(cls):
+        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
+
+    @classmethod
+    def tearDownClass(cls):
+        test_config["test_number"] += 1
+
+    def tearDown(self):
+        exec_info = sys.exc_info()
+        if exec_info == (None, None, None):
+            logger.info(self.__class__.test_text+" -> TEST OK")
+        else:
+            logger.warning(self.__class__.test_text+" -> TEST NOK")
+            logger.critical("Traceback error",exc_info=True)
+
 
 def check_instance_scenario_active(uuid):
     instance = test_config["client"].get_instance(uuid=uuid)
@@ -69,30 +89,8 @@ def check_instance_scenario_active(uuid):
 IMPORTANT NOTE
 All unittest classes for code based tests must have prefix 'test_' in order to be taken into account for tests
 '''
-class test_VIM_datacenter_tenant_operations(unittest.TestCase):
-    test_index = 1
+class test_VIM_datacenter_tenant_operations(test_base):
     tenant_name = None
-    test_text = None
-
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
-
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text+" -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text+" -> TEST NOK")
-            error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
-            msg = ""
-            for line in error_trace:
-                msg = msg + line
-            logger.critical("{}".format(msg))
 
     def test_000_create_RO_tenant(self):
         self.__class__.tenant_name = _get_random_string(20)
@@ -121,30 +119,8 @@ class test_VIM_datacenter_tenant_operations(unittest.TestCase):
         assert('deleted' in tenant.get('result',""))
 
 
-class test_VIM_datacenter_operations(unittest.TestCase):
-    test_index = 1
+class test_VIM_datacenter_operations(test_base):
     datacenter_name = None
-    test_text = None
-
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
-
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text+" -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text+" -> TEST NOK")
-            error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
-            msg = ""
-            for line in error_trace:
-                msg = msg + line
-            logger.critical("{}".format(msg))
 
     def test_000_create_datacenter(self):
         self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"], self.__class__.test_index,
@@ -203,32 +179,10 @@ class test_VIM_datacenter_operations(unittest.TestCase):
         assert('deleted' in self.datacenter.get('result',""))
 
 
-class test_VIM_network_operations(unittest.TestCase):
-    test_index = 1
+class test_VIM_network_operations(test_base):
     vim_network_name = None
-    test_text = None
     vim_network_uuid = None
 
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
-
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text + " -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text + " -> TEST NOK")
-            error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
-            msg = ""
-            for line in error_trace:
-                msg = msg + line
-            logger.critical("{}".format(msg))
-
     def test_000_create_VIM_network(self):
         self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"], self.__class__.test_index,
                                                            inspect.currentframe().f_code.co_name)
@@ -265,29 +219,7 @@ class test_VIM_network_operations(unittest.TestCase):
         assert ('deleted' in network.get('result', ""))
 
 
-class test_VIM_image_operations(unittest.TestCase):
-    test_index = 1
-    test_text = None
-
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
-
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
-
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text + " -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text + " -> TEST NOK")
-            error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
-            msg = ""
-            for line in error_trace:
-                msg = msg + line
-            logger.critical("{}".format(msg))
+class test_VIM_image_operations(test_base):
 
     def test_000_list_VIM_images(self):
         self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"], self.__class__.test_index,
@@ -301,34 +233,16 @@ The following is a non critical test that will fail most of the times.
 In case of OpenStack datacenter these tests will only success if RO has access to the admin endpoint
 This test will only be executed in case it is specifically requested by the user
 '''
-class test_VIM_tenant_operations(unittest.TestCase):
-    test_index = 1
+class test_VIM_tenant_operations(test_base):
     vim_tenant_name = None
-    test_text = None
     vim_tenant_uuid = None
 
     @classmethod
     def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
+        test_base.setUpClass(cls)
         logger.warning("In case of OpenStack datacenter these tests will only success "
                        "if RO has access to the admin endpoint")
 
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
-
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text + " -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text + " -> TEST NOK")
-            error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
-            msg = ""
-            for line in error_trace:
-                msg = msg + line
-            logger.critical("{}".format(msg))
-
     def test_000_create_VIM_tenant(self):
         self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"], self.__class__.test_index,
                                                            inspect.currentframe().f_code.co_name)
@@ -364,25 +278,25 @@ class test_VIM_tenant_operations(unittest.TestCase):
         logger.debug("{}".format(tenant))
         assert ('deleted' in tenant.get('result', ""))
 
-class test_vimconn_connect(unittest.TestCase):
-    test_index = 1
-    test_text = None
+class test_vimconn_connect(test_base):
+    test_index = 1
+    test_text = None
 
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
+    @classmethod
+    def setUpClass(cls):
+        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
 
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
+    @classmethod
+    def tearDownClass(cls):
+        test_config["test_number"] += 1
 
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text+" -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text+" -> TEST NOK")
-            logger.critical("Traceback error",exc_info=True)
+    def tearDown(self):
+        exec_info = sys.exc_info()
+        if exec_info == (None, None, None):
+            logger.info(self.__class__.test_text+" -> TEST OK")
+        else:
+            logger.warning(self.__class__.test_text+" -> TEST NOK")
+            logger.critical("Traceback error",exc_info=True)
 
     def test_000_connect(self):
         self.__class__.test_text = "{}.{}. TEST {}".format(test_config["test_number"],
@@ -396,26 +310,26 @@ class test_vimconn_connect(unittest.TestCase):
             self.assertIsInstance(vca_object, VCA)
 
 
-class test_vimconn_new_network(unittest.TestCase):
-    test_index = 1
+class test_vimconn_new_network(test_base):
+    test_index = 1
     network_name = None
-    test_text = None
+    test_text = None
 
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
+    @classmethod
+    def setUpClass(cls):
+        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
 
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
+    @classmethod
+    def tearDownClass(cls):
+        test_config["test_number"] += 1
 
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text+" -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text+" -> TEST NOK")
-            logger.critical("Traceback error",exc_info=True)
+    def tearDown(self):
+        exec_info = sys.exc_info()
+        if exec_info == (None, None, None):
+            logger.info(self.__class__.test_text+" -> TEST OK")
+        else:
+            logger.warning(self.__class__.test_text+" -> TEST NOK")
+            logger.critical("Traceback error",exc_info=True)
 
     def test_000_new_network(self):
         self.__class__.network_name = _get_random_string(20)
@@ -570,18 +484,18 @@ class test_vimconn_new_network(unittest.TestCase):
         else:
             logger.info("Failed to delete network id {}".format(self.__class__.network_id))
 
-class test_vimconn_get_network_list(unittest.TestCase):
-    test_index = 1
+class test_vimconn_get_network_list(test_base):
+    test_index = 1
     network_name = None
-    test_text = None
 
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
+    # test_text = None
+    # @classmethod
+    # def setUpClass(cls):
+    #     logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
 
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
+    @classmethod
+    def tearDownClass(cls):
+        test_config["test_number"] += 1
 
     def setUp(self):
         # creating new network
@@ -593,12 +507,13 @@ class test_vimconn_get_network_list(unittest.TestCase):
         logger.debug("{}".format(network))
 
     def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text+" -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text+" -> TEST NOK")
-            logger.critical("Traceback error",exc_info=True)
+        test_base.tearDown(self)
+        # exec_info = sys.exc_info()
+        # if exec_info == (None, None, None):
+        #     logger.info(self.__class__.test_text+" -> TEST OK")
+        # else:
+        #     logger.warning(self.__class__.test_text+" -> TEST NOK")
+        #     logger.critical("Traceback error",exc_info=True)
 
         # Deleting created network
         result = test_config["vim_conn"].delete_network(self.__class__.network_id)
@@ -715,18 +630,18 @@ class test_vimconn_get_network_list(unittest.TestCase):
         network_list = test_config["vim_conn"].get_network_list({'name': 'unknown_name'})
         self.assertEqual(network_list, [])
 
-class test_vimconn_get_network(unittest.TestCase):
-    test_index = 1
+class test_vimconn_get_network(test_base):
+    test_index = 1
     network_name = None
-    test_text = None
+    test_text = None
 
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
+    @classmethod
+    def setUpClass(cls):
+        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
 
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
+    @classmethod
+    def tearDownClass(cls):
+        test_config["test_number"] += 1
 
     def setUp(self):
         # creating new network
@@ -738,12 +653,13 @@ class test_vimconn_get_network(unittest.TestCase):
         logger.debug("{}".format(network))
 
     def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text+" -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text+" -> TEST NOK")
-            logger.critical("Traceback error",exc_info=True)
+        test_base.tearDown(self)
+        # exec_info = sys.exc_info()
+        # if exec_info == (None, None, None):
+        #     logger.info(self.__class__.test_text+" -> TEST OK")
+        # else:
+        #     logger.warning(self.__class__.test_text+" -> TEST NOK")
+        #     logger.critical("Traceback error",exc_info=True)
 
         # Deleting created network
         result = test_config["vim_conn"].delete_network(self.__class__.network_id)
@@ -774,26 +690,26 @@ class test_vimconn_get_network(unittest.TestCase):
         network_info = test_config["vim_conn"].get_network(Non_exist_id)
         self.assertEqual(network_info, {})
 
-class test_vimconn_delete_network(unittest.TestCase):
-    test_index = 1
+class test_vimconn_delete_network(test_base):
+    test_index = 1
     network_name = None
-    test_text = None
+    test_text = None
 
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
+    @classmethod
+    def setUpClass(cls):
+        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
 
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
+    @classmethod
+    def tearDownClass(cls):
+        test_config["test_number"] += 1
 
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text+" -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text+" -> TEST NOK")
-            logger.critical("Traceback error",exc_info=True)
+    def tearDown(self):
+        exec_info = sys.exc_info()
+        if exec_info == (None, None, None):
+            logger.info(self.__class__.test_text+" -> TEST OK")
+        else:
+            logger.warning(self.__class__.test_text+" -> TEST NOK")
+            logger.critical("Traceback error",exc_info=True)
 
     def test_000_delete_network(self):
         # Creating network
@@ -832,25 +748,25 @@ class test_vimconn_delete_network(unittest.TestCase):
 
         self.assertEqual((context.exception).http_code, 400)
 
-class test_vimconn_get_flavor(unittest.TestCase):
-    test_index = 1
-    test_text = None
+class test_vimconn_get_flavor(test_base):
+    test_index = 1
+    test_text = None
 
-    @classmethod
-    def setUpClass(cls):
-        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
+    @classmethod
+    def setUpClass(cls):
+        logger.info("{}. {}".format(test_config["test_number"], cls.__name__))
 
-    @classmethod
-    def tearDownClass(cls):
-        test_config["test_number"] += 1
+    @classmethod
+    def tearDownClass(cls):
+        test_config["test_number"] += 1
 
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text+" -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text+" -> TEST NOK")
-            logger.critical("Traceback error",exc_info=True)
+    def tearDown(self):
+        exec_info = sys.exc_info()
+        if exec_info == (None, None, None):
+            logger.info(self.__class__.test_text+" -> TEST OK")
+        else:
+            logger.warning(self.__class__.test_text+" -> TEST NOK")
+            logger.critical("Traceback error",exc_info=True)
 
     def test_000_get_flavor(self):
         test_directory_content = os.listdir(test_config["test_directory"])
@@ -915,9 +831,8 @@ IMPORTANT NOTE
 The following unittest class does not have the 'test_' on purpose. This test is the one used for the
 scenario based tests.
 '''
-class descriptor_based_scenario_test(unittest.TestCase):
+class descriptor_based_scenario_test(test_base):
     test_index = 0
-    test_text = None
     scenario_test_path = None
     scenario_uuid = None
     instance_scenario_uuid = None
@@ -934,19 +849,6 @@ class descriptor_based_scenario_test(unittest.TestCase):
     def tearDownClass(cls):
          test_config["test_number"] += 1
 
-    def tearDown(self):
-        exec_info = sys.exc_info()
-        if exec_info == (None, None, None):
-            logger.info(self.__class__.test_text + " -> TEST OK")
-        else:
-            logger.warning(self.__class__.test_text + " -> TEST NOK")
-            error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
-            msg = ""
-            for line in error_trace:
-                msg = msg + line
-            logger.critical("{}".format(msg))
-
-
     def test_000_load_scenario(self):
         self.__class__.test_text = "{}.{}. TEST {} {}".format(test_config["test_number"], self.__class__.test_index,
                                                            inspect.currentframe().f_code.co_name,
@@ -1223,9 +1125,9 @@ def test_deploy(args):
     test_directory_content = os.listdir(test_config["test_directory"])
     # If only want to obtain a tests list print it and exit
     if args.list_tests:
-        msg = "he 'deploy' set tests are:\n\t" + ', '.join(sorted(test_directory_content))
+        msg = "the 'deploy' set tests are:\n\t" + ', '.join(sorted(test_directory_content))
         print(msg)
-        logger.info(msg)
+        logger.info(msg)
         sys.exit(0)
 
     descriptor_based_tests = []