Modify http get/clear openflows to handle n ofc_id

	- Add ofc_id to http_get_openflow_ports
	- Add ofc_id http_clear_openflow_rules
	- Both http service will handle multimple ofc thread and the task will be injected in a thread nu ofc_id
	- ofc_id Added to of_flow table to of_flows

Change-Id: Id9b1ec67341d70eaea8b678fa4ef34c5a81a3c21
Signed-off-by: mirabal <leonardo.mirabal@altran.com>
diff --git a/database_utils/migrate_vim_db.sh b/database_utils/migrate_vim_db.sh
index 8def5cb..a3d96e8 100755
--- a/database_utils/migrate_vim_db.sh
+++ b/database_utils/migrate_vim_db.sh
@@ -182,6 +182,7 @@
 [ $OPENVIM_VER_NUM -ge 5005 ] && DATABASE_TARGET_VER_NUM=12  #0.5.5   => 12
 [ $OPENVIM_VER_NUM -ge 5006 ] && DATABASE_TARGET_VER_NUM=13  #0.5.6   => 13
 [ $OPENVIM_VER_NUM -ge 5007 ] && DATABASE_TARGET_VER_NUM=14  #0.5.7   => 14
+[ $OPENVIM_VER_NUM -ge 5008 ] && DATABASE_TARGET_VER_NUM=15  #0.5.8   => 15
 #TODO ... put next versions here
 
 function upgrade_to_1(){
@@ -584,6 +585,24 @@
     echo "DELETE FROM schema_version WHERE version_int = '14';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
 }
 
+function upgrade_to_15(){
+    echo "    upgrade database from version 0.14 to version 0.15"
+    echo "    Add ofc_id colum to 'of_flows'"
+    echo "ALTER TABLE of_flows
+	ADD COLUMN ofc_id VARCHAR(36) NULL DEFAULT NULL AFTER net_id,
+	ADD CONSTRAINT FK_of_flows_ofcs FOREIGN KEY (ofc_id) REFERENCES ofcs (uuid) ON UPDATE CASCADE ON DELETE SET NULL;"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "INSERT INTO schema_version (version_int, version, openvim_ver, comments, date) VALUES (15, '0.15', '0.5.8', 'Add ofc_id colum to of_flows', '2017-03-15');"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+}
+
+function downgrade_from_15(){
+    echo "    downgrade database from version 0.15 to version 0.14"
+    echo "    Delete ofc_id to 'of_flows'"
+    echo "ALTER TABLE of_flows
+	DROP COLUMN ofc_id,
+	DROP FOREIGN KEY FK_of_flows_ofcs;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "DELETE FROM schema_version WHERE version_int = '15';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+}
+
 #TODO ... put funtions here
 
 echo "db version = "${DATABASE_VER_NUM}
diff --git a/httpserver.py b/httpserver.py
index e35daf0..6a16f39 100644
--- a/httpserver.py
+++ b/httpserver.py
@@ -2196,9 +2196,9 @@
     data = {'result': str(result) + " nets updates"}
     return format_out(data)
 
-
+@bottle.route(url_base + '/networks/clear/openflow/<ofc_id>', method='DELETE')
 @bottle.route(url_base + '/networks/clear/openflow', method='DELETE')
-def http_clear_openflow_rules():
+def http_clear_openflow_rules(ofc_id=None):
     """
     To make actions over the net. The action is to delete ALL openflow rules
     :return:
@@ -2208,7 +2208,7 @@
     if not my.admin:
         bottle.abort(HTTP_Unauthorized, "Needed admin privileges")
     try:
-        my.ovim.delete_openflow_rules()
+        my.ovim.delete_openflow_rules(ofc_id)
     except ovim.ovimException as e:
         my.logger.error(str(e), exc_info=True)
         bottle.abort(e.http_code, str(e))
@@ -2219,16 +2219,25 @@
     data = {'result': " Clearing openflow rules in process"}
     return format_out(data)
 
-
+@bottle.route(url_base + '/networks/openflow/ports/<ofc_id>', method='GET')
 @bottle.route(url_base + '/networks/openflow/ports', method='GET')
-def http_get_openflow_ports():
+def http_get_openflow_ports(ofc_id=None):
     """
     Obtain switch ports names of openflow controller
     :return:
     """
     my = config_dic['http_threads'][threading.current_thread().name]
-    ports = my.ovim.get_openflow_ports()
-    data = {'ports': ports}
+
+    try:
+        ports = my.ovim.get_openflow_ports(ofc_id)
+        data = {'ports': ports}
+    except ovim.ovimException as e:
+        my.logger.error(str(e), exc_info=True)
+        bottle.abort(e.http_code, str(e))
+    except Exception as e:
+        my.logger.error(str(e), exc_info=True)
+        bottle.abort(HTTP_Bad_Request, str(e))
+
     return format_out(data)
 #
 # PORTS
diff --git a/openflow_thread.py b/openflow_thread.py
index 638ab19..b797f2d 100644
--- a/openflow_thread.py
+++ b/openflow_thread.py
@@ -95,11 +95,14 @@
         self.rules= {}
         self.logger = logging.getLogger('vim.OF.TEST')
         self.logger.setLevel(getattr(logging, params.get("of_debug", "ERROR")))
+        self.pp2ofi = {}
 
     def get_of_switches(self):
         return 0, ()
+
     def obtain_port_correspondence(self):
         return 0, ()
+
     def del_flow(self, flow_name):
         if flow_name in self.rules:
             self.logger.debug("del_flow OK")
@@ -108,10 +111,12 @@
         else:
             self.logger.warning("del_flow not found")
             return -1, "flow %s not found"
+
     def new_flow(self, data):
         self.rules[ data["name"] ] = data
         self.logger.debug("new_flow OK")
         return 0, None
+
     def get_of_rules(self, translate_of_ports=True):
         return 0, self.rules
 
diff --git a/openvimd.py b/openvimd.py
index 8fe3843..6090741 100755
--- a/openvimd.py
+++ b/openvimd.py
@@ -30,9 +30,9 @@
 
 __author__ = "Alfonso Tierno"
 __date__ = "$10-jul-2014 12:07:15$"
-__version__ = "0.5.7-r524"
-version_date = "Feb 2017"
-database_version = "0.14"      #expected database schema version
+__version__ = "0.5.8-r524"
+version_date = "March 2017"
+database_version = "0.15"      #expected database schema version
 
 import httpserver
 import auxiliary_functions as af
diff --git a/ovim.py b/ovim.py
index 16b3f03..5b36b73 100644
--- a/ovim.py
+++ b/ovim.py
@@ -316,7 +316,7 @@
     def _load_of_module(self, db_config):
         """
         import python module for each SDN controller supported
-        :param default: SDN dn information
+        :param db_config: SDN dn information
         :return: Module
         """
         if not db_config:
@@ -326,8 +326,8 @@
 
         try:
             if self.of_test_mode:
-                return  oft.of_test_connector({"name": db_config['type'], "dpid": db_config['dpid'],
-                                               "of_debug": self.config['log_level_of']})
+                return oft.of_test_connector({"name": db_config['type'], "dpid": db_config['dpid'],
+                                              "of_debug": self.config['log_level_of']})
             temp_dict = {}
 
             if db_config:
@@ -719,9 +719,8 @@
             where_ = {}
         else:
             where_ = {"net_id": network_id}
-
         result, content = self.db.get_table(
-            SELECT=("name", "net_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
+            SELECT=("name", "net_id", "ofc_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
             WHERE=where_, FROM='of_flows')
 
         if result < 0:
@@ -763,24 +762,44 @@
 
         return result
 
-    def delete_openflow_rules(self):
+    def delete_openflow_rules(self, ofc_id=None):
         """
         To make actions over the net. The action is to delete ALL openflow rules
         :return: return operation result
         """
-        # ignore input data
-        r, c = self.config['of_thread'].insert_task("clear-all")
-        if r < 0:
-            raise ovimException(str(c), -r)
+
+        if not ofc_id:
+            if 'Default' in self.config['ofcs_thread']:
+                r, c = self.config['ofcs_thread']['Default'].insert_task("clear-all")
+            else:
+                raise ovimException("Default Openflow controller not not running", HTTP_Not_Found)
+
+        elif ofc_id in self.config['ofcs_thread']:
+            r, c = self.config['ofcs_thread'][ofc_id].insert_task("clear-all")
+
+            # ignore input data
+            if r < 0:
+                raise ovimException(str(c), -r)
+        else:
+            raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id), HTTP_Not_Found)
         return r
 
-    def get_openflow_ports(self):
+    def get_openflow_ports(self, ofc_id=None):
         """
         Obtain switch ports names of openflow controller
         :return: Return flow ports in DB
         """
-        data = {'ports': self.config['of_thread'].OF_connector.pp2ofi}
-        return data
+        if not ofc_id:
+            if 'Default' in self.config['ofcs_thread']:
+                conn = self.config['ofcs_thread']['Default'].OF_connector
+            else:
+                raise ovimException("Default Openflow controller not not running", HTTP_Not_Found)
+
+        if ofc_id in self.config['ofcs_thread']:
+            conn = self.config['ofcs_thread'][ofc_id].OF_connector
+        else:
+            raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id), HTTP_Not_Found)
+        return conn.pp2ofi
 
     def get_ports(self, columns=None, filter={}, limit=None):
         # result, content = my.db.get_ports(where_)