Changes to import dynamically modules in ovim.py
[osm/openvim.git] / osm_openvim / ovim.py
index 39ab578..fb34552 100755 (executable)
 # contact with: nfvlabs@tid.es
 ##
 
-'''
+"""
 This is the thread for the http server North API. 
 Two thread will be launched, with normal and administrative permissions.
-'''
-
-__author__ = "Alfonso Tierno, Leonardo Mirabal"
-__date__ = "$06-Feb-2017 12:07:15$"
-__version__ = "0.5.10-r526"
-version_date = "Apr 2017"
-database_version = "0.17"      #expected database schema version
+"""
 
 import threading
-import osm_openvim.vim_db as vim_db
+import vim_db
 import logging
-import imp
+# import imp
+import os.path
 import argparse
 from netaddr import IPNetwork
 from jsonschema import validate as js_v, exceptions as js_e
-import osm_openvim.host_thread as ht
-import osm_openvim.dhcp_thread as dt
-import osm_openvim.openflow_thread as oft
-import osm_openvim.openflow_conn as openflow_conn
+import host_thread as ht
+import dhcp_thread as dt
+import openflow_thread as oft
+import openflow_conn
 
+__author__ = "Alfonso Tierno, Leonardo Mirabal"
+__date__ = "$06-Feb-2017 12:07:15$"
+__version__ = "0.5.13-r529"
+version_date = "May 2017"
+database_version = 18      #needed database schema version
 
 HTTP_Bad_Request =          400
 HTTP_Unauthorized =         401
@@ -100,8 +100,6 @@ class ovim():
         self.logger = logging.getLogger(self.logger_name)
         self.db = None
         self.db = self._create_database_connection()
-        self.db_lock = None
-        self.db_of = None
         self.of_test_mode = False
 
     def _create_database_connection(self):
@@ -172,19 +170,25 @@ class ovim():
         # if self.running_info:
         #    return  #TODO service can be checked and rebuild broken threads
         r = self.db.get_db_version()
+        db_path = __file__
+        db_path = db_path[:db_path.rfind("/")]
+        if os.path.exists(db_path + "/database_utils/migrate_vim_db.sh"):
+            db_path += "/database_utils"
+        else:
+            db_path += "/../database_utils"
+
         if r[0] < 0:
-            raise ovimException("DATABASE is not a VIM one or it is a '0.0' version. Try to upgrade to version '{}' with "\
-                                "'./database_utils/migrate_vim_db.sh'".format(database_version) )
-        elif r[1] != database_version:
-            raise ovimException("DATABASE wrong version '{}'. Try to upgrade/downgrade to version '{}' with "\
-                                "'./database_utils/migrate_vim_db.sh'".format(r[1], database_version) )
+            raise ovimException("DATABASE is not valid. If you think it is corrupted, you can init it with"
+                                " '{db_path}/init_vim_db.sh' script".format(db_path=db_path))
+        elif r[0] != database_version:
+            raise ovimException("DATABASE wrong version '{current}'. Try to upgrade/downgrade to version '{target}'"
+                                " with '{db_path}/migrate_vim_db.sh {target}'".format(
+                                current=r[0], target=database_version,  db_path=db_path))
         self.logger.critical("Starting ovim server version: '{} {}' database version '{}'".format(
             self.get_version(), self.get_version_date(), self.get_database_version()))
         # create database connection for openflow threads
-        self.db_of = self._create_database_connection()
-        self.config["db"] = self.db_of
-        self.db_lock = threading.Lock()
-        self.config["db_lock"] = self.db_lock
+        self.config["db"] = self._create_database_connection()
+        self.config["db_lock"] = threading.Lock()
 
         self.of_test_mode = False if self.config['mode'] == 'normal' or self.config['mode'] == "OF only" else True
         # precreate interfaces; [bridge:<host_bridge_name>, VLAN used at Host, uuid of network camping in this bridge,
@@ -228,7 +232,8 @@ class ovim():
         dhcp_params = self.config.get("dhcp_server")
         if dhcp_params:
             thread = dt.dhcp_thread(dhcp_params=dhcp_params, test=host_test_mode, dhcp_nets=self.config["dhcp_nets"],
-                                    db=self.db_of, db_lock=self.db_lock, logger_name=self.logger_name + ".dhcp",
+                                    db=self.config["db"], db_lock=self.config["db_lock"],
+                                    logger_name=self.logger_name + ".dhcp",
                                     debug=self.config.get('log_level_of'))
             thread.start()
             self.config['dhcp_thread'] = thread
@@ -246,10 +251,14 @@ class ovim():
         self.config['host_threads'] = {}
         for host in hosts:
             host['image_path'] = '/opt/VNF/images/openvim'
-            thread = ht.host_thread(name=host['name'], user=host['user'], host=host['ip_name'], db=self.db_of,
-                                    db_lock=self.db_lock, test=host_test_mode, image_path=self.config['image_path'],
-                                    version=self.config['version'], host_id=host['uuid'], develop_mode=host_develop_mode,
-                                    develop_bridge_iface=host_develop_bridge_iface)
+            thread = ht.host_thread(name=host['name'], user=host['user'], host=host['ip_name'], db=self.config["db"],
+                                    db_lock=self.config["db_lock"], test=host_test_mode,
+                                    image_path=self.config['image_path'],
+                                    version=self.config['version'], host_id=host['uuid'],
+                                    develop_mode=host_develop_mode,
+                                    develop_bridge_iface=host_develop_bridge_iface,
+                                    logger_name=self.logger_name + ".host." + host['name'],
+                                    debug=self.config.get('log_level_host'))
             thread.start()
             self.config['host_threads'][host['uuid']] = thread
 
@@ -369,27 +378,22 @@ class ovim():
                 module = temp_dict['of_controller']
 
             if module not in ovim.of_module:
-                module_info = imp.find_module(module)
-                of_conn_module = imp.load_module("OF_conn", *module_info)
-                ovim.of_module[module] = of_conn_module
+                try:
+                    pkg = __import__("osm_openvim." + module)
+                    of_conn_module = getattr(pkg, module)
+                    ovim.of_module[module] = of_conn_module
+                    self.logger.debug("Module load from {}".format("osm_openvim." + module))
+                except Exception as e:
+                    self.logger.error("Cannot open openflow controller module of type '%s'", module)
+                    raise ovimException("Cannot open openflow controller of type module '{}'"
+                                        "Revise it is installed".format(module),
+                                        HTTP_Internal_Server_Error)
             else:
                 of_conn_module = ovim.of_module[module]
-
-            try:
-                return of_conn_module.OF_conn(temp_dict)
-            except Exception as e:
-                self.logger.error("Cannot open the Openflow controller '%s': %s", type(e).__name__, str(e))
-                if module_info and module_info[0]:
-                    file.close(module_info[0])
-                raise ovimException("Cannot open the Openflow controller '{}': '{}'".format(type(e).__name__, str(e)),
-                                    HTTP_Internal_Server_Error)
-        except (IOError, ImportError) as e:
-            if module_info and module_info[0]:
-                file.close(module_info[0])
-            self.logger.error("Cannot open openflow controller module '%s'; %s: %s; revise 'of_controller' "
-                              "field of configuration file.", module, type(e).__name__, str(e))
-            raise ovimException("Cannot open openflow controller module '{}'; {}: {}; revise 'of_controller' "
-                                "field of configuration file.".format(module, type(e).__name__, str(e)),
+            return of_conn_module.OF_conn(temp_dict)
+        except Exception as e:
+            self.logger.error("Cannot open the Openflow controller '%s': %s", type(e).__name__, str(e))
+            raise ovimException("Cannot open the Openflow controller '{}': '{}'".format(type(e).__name__, str(e)),
                                 HTTP_Internal_Server_Error)
 
     def _create_ofc_thread(self, of_conn, ofc_uuid="Default"):
@@ -405,8 +409,11 @@ class ovim():
         #    ofc_net_same_vlan = False
         ofc_net_same_vlan = False
 
-        thread = oft.openflow_thread(ofc_uuid, of_conn, of_test=self.of_test_mode, db=self.db_of, db_lock=self.db_lock,
-                                     pmp_with_same_vlan=ofc_net_same_vlan, debug=self.config['log_level_of'])
+        thread = oft.openflow_thread(ofc_uuid, of_conn, of_test=self.of_test_mode, db=self.config["db"],
+                                     db_lock=self.config["db_lock"],
+                                     pmp_with_same_vlan=ofc_net_same_vlan,
+                                     logger_name=self.logger_name + ".ofc." + ofc_uuid,
+                                     debug=self.config.get('log_level_of'))
         #r, c = thread.OF_connector.obtain_port_correspondence()
         #if r < 0:
         #    raise ovimException("Cannot get openflow information %s", c)
@@ -495,6 +502,7 @@ class ovim():
         net_vlan = network.get("vlan")
         net_bind_net = network.get("bind_net")
         net_bind_type = network.get("bind_type")
+        net_region = network.get("region")
         name = network["name"]
 
         # check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
@@ -590,8 +598,13 @@ class ovim():
                 net_vlan = bridge_net[1]
         elif net_type == 'bridge_data' or net_type == 'bridge_man' and self.config['network_type'] == 'ovs':
             net_provider = 'OVS'
+        if not net_region:
+            if net_type == "data" or net_type == "ptp":
+                net_region = "__DATA__"
+            elif net_provider == "OVS":
+                net_region = "__OVS__"
         if not net_vlan and (net_type == "data" or net_type == "ptp" or net_provider == "OVS"):
-            net_vlan = self.db.get_free_net_vlan()
+            net_vlan = self.db.get_free_net_vlan(net_region)
             if net_vlan < 0:
                 raise ovimException("Error getting an available vlan", HTTP_Internal_Server_Error)
         if net_provider == 'OVS':
@@ -600,6 +613,7 @@ class ovim():
         network['provider'] = net_provider
         network['type'] = net_type
         network['vlan'] = net_vlan
+        network['region'] = net_region
         dhcp_integrity = True
         if 'enable_dhcp' in network and network['enable_dhcp']:
             dhcp_integrity = self._check_dhcp_data_integrity(network)
@@ -1338,12 +1352,13 @@ class ovim():
         host_develop_mode = True if self.config['mode'] == 'development' else False
 
         dhcp_host = ht.host_thread(name='openvim_controller', user=ovs_controller_user, host=controller_ip,
-                                   db=self.db_of,
-                                   db_lock=self.db_lock, test=host_test_mode,
+                                   db=self.config["db"], db_lock=self.config["db_lock"], test=host_test_mode,
                                    image_path=self.config['image_path'], version=self.config['version'],
                                    host_id='openvim_controller', develop_mode=host_develop_mode,
-                                   develop_bridge_iface=bridge_ifaces)
-
+                                   develop_bridge_iface=bridge_ifaces,
+                                   logger_name=self.logger_name + ".host.controller",
+                                   debug=self.config.get('log_level_host'))
+        dhcp_host.start()
         self.config['host_threads']['openvim_controller'] = dhcp_host
         if not host_test_mode:
             dhcp_host.ssh_connect()