Create db entry for manage Openflow controllers 38/1138/12
authormirabal <leonardo.mirabal@altran.com>
Fri, 17 Feb 2017 10:03:25 +0000 (11:03 +0100)
committermirabal <leonardo.mirabal@altran.com>
Mon, 27 Feb 2017 16:56:02 +0000 (17:56 +0100)
Change-Id: Ie3249e72487c15ed4a9a09bc64f50589102e9162
Signed-off-by: mirabal <leonardo.mirabal@altran.com>
database_utils/migrate_vim_db.sh
httpserver.py
openvimd.py
ovim.py
templates/openflow_controller.yaml [new file with mode: 0644]
vim_schema.py

index b856db9..137bbf9 100755 (executable)
@@ -179,9 +179,9 @@ DATABASE_TARGET_VER_NUM=0
 [ $OPENVIM_VER_NUM -ge 5001 ] && DATABASE_TARGET_VER_NUM=9   #0.5.1   =>  9
 [ $OPENVIM_VER_NUM -ge 5002 ] && DATABASE_TARGET_VER_NUM=10  #0.5.2   => 10
 [ $OPENVIM_VER_NUM -ge 5004 ] && DATABASE_TARGET_VER_NUM=11  #0.5.4   => 11
+[ $OPENVIM_VER_NUM -ge 5005 ] && DATABASE_TARGET_VER_NUM=12  #0.5.5   => 12
 #TODO ... put next versions here
 
-
 function upgrade_to_1(){
     echo "    upgrade database from version 0.0 to version 0.1"
     echo "      CREATE TABLE \`schema_version\`"
@@ -495,14 +495,44 @@ function downgrade_from_11(){
     echo "ALTER TABLE nets DROP COLUMN gateway_ip;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
     echo "DELETE FROM schema_version WHERE version_int = '11';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
 }
-#TODO ... put funtions here
+function upgrade_to_12(){
+    echo "    upgrade database from version 0.11 to version 0.12"
+    echo "    Create of_controller table "
+    echo "CREATE TABLE ofcs (
+       uuid VARCHAR(36) NOT NULL,
+       name VARCHAR(255) NOT NULL,
+       dpid VARCHAR(64) NOT NULL,
+       ip VARCHAR(64) NOT NULL,
+       port INT(5) NOT NULL,
+       type VARCHAR(64) NOT NULL,
+       version VARCHAR(12) NULL DEFAULT NULL,
+       user VARCHAR(64) NULL DEFAULT NULL,
+       password VARCHAR(64) NULL DEFAULT NULL,
+       PRIMARY KEY (uuid)
+)
+COLLATE='utf8_general_ci'
+ENGINE=InnoDB;"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "    Modify user_at for uuids table"
+    echo "ALTER TABLE uuids  CHANGE COLUMN used_at used_at VARCHAR(64) NULL DEFAULT NULL COMMENT 'Table that uses this UUID' ;"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "INSERT INTO schema_version (version_int, version, openvim_ver, comments, date) VALUES (12, '0.12', '0.5.5', 'Add of_controller table', '2017-02-17');"| $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+}
 
+function downgrade_from_12(){
+    echo "    downgrade database from version 0.12 to version 0.11"
+    echo "    Delete ofcs table"
+    echo "DROP TABLE ofcs;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "ALTER TABLE uuids  CHANGE COLUMN used_at used_at ENUM('flavors', 'hosts', 'images', 'instances', 'nets', 'ports', 'tenants') NULL DEFAULT NULL COMMENT 'Table that uses this UUID' ;" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+    echo "DELETE FROM schema_version WHERE version_int = '12';" | $DBCMD || ! echo "ERROR. Aborted!" || exit -1
+}
+#TODO ... put funtions here
 
+echo "db version = "${DATABASE_VER_NUM}
 [ $DATABASE_TARGET_VER_NUM -eq $DATABASE_VER_NUM ] && echo "    current database version $DATABASE_VER is ok"
 #UPGRADE DATABASE step by step
 while [ $DATABASE_TARGET_VER_NUM -gt $DATABASE_VER_NUM ]
 do
     DATABASE_VER_NUM=$((DATABASE_VER_NUM+1))
+
     upgrade_to_${DATABASE_VER_NUM}
     #FILE_="${DIRNAME}/upgrade_to_${DATABASE_VER_NUM}.sh"
     #[ ! -x "$FILE_" ] && echo "Error, can not find script '$FILE_' to upgrade" >&2 && exit -1
index 954c1d5..2380d03 100644 (file)
@@ -47,7 +47,7 @@ from vim_schema import host_new_schema, host_edit_schema, tenant_new_schema, \
     flavor_new_schema, flavor_update_schema, \
     image_new_schema, image_update_schema, \
     server_new_schema, server_action_schema, network_new_schema, network_update_schema, \
-    port_new_schema, port_update_schema
+    port_new_schema, port_update_schema, openflow_controller_schema
 import ovim
 import logging
 
@@ -153,6 +153,7 @@ http2db_flavor={'id':'uuid','imageRef':'image_id'}
 http2db_image={'id':'uuid', 'created':'created_at', 'updated':'modified_at', 'public': 'public'}
 http2db_server={'id':'uuid','hostId':'host_id','flavorRef':'flavor_id','imageRef':'image_id','created':'created_at'}
 http2db_network={'id':'uuid','provider:vlan':'vlan', 'provider:physical': 'provider'}
+http2db_ofc = {'id': 'uuid'}
 http2db_port={'id':'uuid', 'network_id':'net_id', 'mac_address':'mac', 'device_owner':'type','device_id':'instance_id','binding:switch_port':'switch_port','binding:vlan':'vlan', 'bandwidth':'Mbps'}
 
 def remove_extra_items(data, schema):
@@ -1982,6 +1983,127 @@ def http_delete_network_id(network_id):
 #
 
 
+@bottle.route(url_base + '/openflow/controller', method='GET')
+def http_get_openflow_controller():
+    """
+    Retrieve a openflow controllers list from DB.
+    :return:
+    """
+    # TODO check if show a proper list
+    my = config_dic['http_threads'][threading.current_thread().name]
+
+    try:
+        select_, where_, limit_ = filter_query_string(bottle.request.query, http2db_ofc,
+                                                      ('id', 'name', 'dpid', 'ip', 'port', 'type',
+                                                       'version', 'user', 'password'))
+
+        content = my.ovim.get_of_controllers(select_, where_)
+        delete_nulls(content)
+        change_keys_http2db(content, http2db_ofc, reverse=True)
+        data = {'ofcs': content}
+        return format_out(data)
+    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))
+
+
+@bottle.route(url_base + '/openflow/controller/<uuid>', method='GET')
+def http_get_openflow_controller_id(uuid):
+    """
+    Get an openflow controller by dpid from DB.get_of_controllers
+    """
+    my = config_dic['http_threads'][threading.current_thread().name]
+
+    try:
+
+        content = my.ovim.show_of_controller(uuid)
+        delete_nulls(content)
+        change_keys_http2db(content, http2db_ofc, reverse=True)
+        data = {'ofc': content}
+        return format_out(data)
+    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))
+
+
+@bottle.route(url_base + '/openflow/controller/', method='POST')
+def http_post_openflow_controller():
+    """
+    Create a new openflow controller into DB
+    :return:
+    """
+    my = config_dic['http_threads'][threading.current_thread().name]
+
+    try:
+        http_content = format_in(openflow_controller_schema)
+        of_c = http_content['ofc']
+        uuid = my.ovim.new_of_controller(of_c)
+        content = my.ovim.show_of_controller(uuid)
+        delete_nulls(content)
+        change_keys_http2db(content, http2db_ofc, reverse=True)
+        data = {'ofc': content}
+        return format_out(data)
+    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))
+
+
+@bottle.route(url_base + '/openflow/controller/<of_controller_id>', method='PUT')
+def http_put_openflow_controller_by_id(of_controller_id):
+    """
+    Create an openflow controller into DB
+    :param of_controller_id: openflow controller dpid
+    :return:
+    """
+    my = config_dic['http_threads'][threading.current_thread().name]
+
+    try:
+        http_content = format_in(openflow_controller_schema)
+        of_c = http_content['ofc']
+
+        content = my.ovim.edit_of_controller(of_controller_id, of_c)
+        delete_nulls(content)
+        change_keys_http2db(content, http2db_ofc, reverse=True)
+        data = {'ofc': content}
+        return format_out(data)
+    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))
+
+
+@bottle.route(url_base + '/openflow/controller/<of_controller_id>', method='DELETE')
+def http_delete_openflow_controller(of_controller_id):
+    """
+    Delete  an openflow controller from DB.
+    :param of_controller_id: openflow controller dpid
+    :return:
+    """
+    my = config_dic['http_threads'][threading.current_thread().name]
+
+    try:
+        content = my.ovim.delete_of_controller(of_controller_id)
+        data = {'result': content}
+        return format_out(data)
+    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))
+
+
 @bottle.route(url_base + '/networks/<network_id>/openflow', method='GET')
 def http_get_openflow_id(network_id):
     """
index 17a958f..923ad16 100755 (executable)
@@ -28,11 +28,11 @@ and launches the rest of threads: http clients, openflow controller
 and host controllers  
 '''
 
-__author__="Alfonso Tierno"
-__date__ ="$10-jul-2014 12:07:15$"
-__version__="0.5.4-r521"
-version_date="Jan 2017"
-database_version="0.11"      #expected database schema version
+__author__ = "Alfonso Tierno"
+__date__ = "$10-jul-2014 12:07:15$"
+__version__ = "0.5.5-r522"
+version_date = "Feb 2017"
+database_version = "0.12"      #expected database schema version
 
 import httpserver
 import auxiliary_functions as af
diff --git a/ovim.py b/ovim.py
index d15fdbd..38c49dd 100644 (file)
--- a/ovim.py
+++ b/ovim.py
@@ -292,15 +292,15 @@ class ovim():
         for thread in threads.values():
             thread.join()
 
-    def get_networks(self, columns=None, filter={}, limit=None):
+    def get_networks(self, columns=None, db_filter={}, limit=None):
         """
         Retreive networks available
         :param columns: List with select query parameters
-        :param filter: List with where query parameters
+        :param db_filter: List with where query parameters
         :param limit: Query limit result
         :return:
         """
-        result, content = self.db.get_table(SELECT=columns, FROM='nets', WHERE=filter, LIMIT=limit)
+        result, content = self.db.get_table(SELECT=columns, FROM='nets', WHERE=db_filter, LIMIT=limit)
 
         if result < 0:
             raise ovimException(str(content), -result)
@@ -309,20 +309,19 @@ class ovim():
 
         return content
 
-    def show_network(self, network_id, filter={}):
+    def show_network(self, network_id, db_filter={}):
         """
         Get network from DB by id
         :param network_id: net Id
-        :param filter:
-        :param limit:
+        :param db_filter: List with where query parameters
         :return:
         """
         # obtain data
         if not network_id:
             raise ovimException("Not network id was not found")
-        filter['uuid'] = network_id
+        db_filter['uuid'] = network_id
 
-        result, content = self.db.get_table(FROM='nets', WHERE=filter, LIMIT=100)
+        result, content = self.db.get_table(FROM='nets', WHERE=db_filter, LIMIT=100)
 
         if result < 0:
             raise ovimException(str(content), -result)
@@ -568,6 +567,11 @@ class ovim():
             raise ovimException(content, -result)
 
     def delete_network(self, network_id):
+        """
+        Delete network by network id
+        :param network_id:  network id
+        :return:
+        """
 
         # delete from the data base
         result, content = self.db.delete_row('nets', network_id)
@@ -763,6 +767,84 @@ class ovim():
         else:
             raise ovimException("Error {}".format(content), http_code=-result)
 
+    def new_of_controller(self, ofc_data):
+        """
+        Create a new openflow controller into DB
+        :param ofc_data: Dict openflow controller data
+        :return: openflow controller dpid
+        """
+
+        result, content = self.db.new_row('ofcs', ofc_data, True, True)
+        if result < 0:
+            raise ovimException("New ofc Error %s" % content, HTTP_Internal_Server_Error)
+        return content
+
+    def edit_of_controller(self, of_id, ofc_data):
+        """
+        Edit an openflow controller entry from DB
+        :return:
+        """
+        if not ofc_data:
+            raise ovimException("No data received during uptade OF contorller", http_code=HTTP_Internal_Server_Error)
+
+        old_of_controller = self.show_of_controller(of_id)
+
+        if old_of_controller:
+            result, content = self.db.update_rows('ofcs', ofc_data, WHERE={'uuid': of_id}, log=False)
+            if result >= 0:
+                return ofc_data
+            else:
+                raise ovimException("Error uptating OF contorller with uuid {}".format(of_id),
+                                    http_code=-result)
+        else:
+            raise ovimException("Error uptating OF contorller with uuid {}".format(of_id),
+                                http_code=HTTP_Internal_Server_Error)
+
+    def delete_of_controller(self, of_id):
+        """
+        Delete an openflow controller from DB.
+        :param of_id: openflow controller dpid
+        :return:
+        """
+
+        result, content = self.db.delete_row_by_key("ofcs", "uuid", of_id)
+        if result < 0:
+            raise ovimException("Cannot delete ofc from database: {}".format(content), http_code=-result)
+        elif result == 0:
+            raise ovimException("ofc {} not found ".format(content), http_code=HTTP_Not_Found)
+        return content
+
+    def show_of_controller(self, uuid):
+        """
+        Show an openflow controller by dpid from DB.
+        :param db_filter: List with where query parameters
+        :return:
+        """
+
+        result, content = self.db.get_table(FROM='ofcs', WHERE={"uuid": uuid}, LIMIT=100)
+
+        if result == 0:
+            raise ovimException("Openflow controller with uuid '{}' not found".format(uuid),
+                                http_code=HTTP_Not_Found)
+        elif result < 0:
+            raise ovimException("Openflow controller with uuid '{}' error".format(uuid),
+                                http_code=HTTP_Internal_Server_Error)
+        return content
+
+    def get_of_controllers(self, columns=None, db_filter={}):
+        """
+        Show an openflow controllers from DB.
+        :param columns:  List with SELECT query parameters
+        :param db_filter: List with where query parameters
+        :return:
+        """
+        result, content = self.db.get_table(SELECT=columns, FROM='ofcs', WHERE=db_filter, LIMIT=100)
+
+        if result < 0:
+            raise ovimException(str(content), -result)
+
+        return content
+
     def get_dhcp_controller(self):
         """
         Create an host_thread object for manage openvim controller and not create a thread for itself
diff --git a/templates/openflow_controller.yaml b/templates/openflow_controller.yaml
new file mode 100644 (file)
index 0000000..a4924cd
--- /dev/null
@@ -0,0 +1,31 @@
+##
+# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
+# This file is part of openvim
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+ofc:
+    #Openflow controller information
+    name: 'sdn'                        # SDN controller name
+    dpid: '00:01:02:03:04:05:06:07'    # Openflow Switch identifier (put here the right number)
+    ip: 127.0.0.1                      # IP address where the Openflow controller is listening
+    port: 7070                         # TCP port where the Openflow controller is listening (REST API server)
+    type: floodlight                   # Type of controller to be used. Valid controllers are 'opendaylight', 'onos', 'floodlight' or <custom>
+    version: 0.0.0                     # SDN contorller version
+    user: user                         # User credentials for the controller if needed
+    password: passwd                   # Password credentials for the controller if needed
index 6d508a6..7da3a48 100644 (file)
@@ -147,8 +147,6 @@ metadata_schema={
     }
 }
 
-
-
 tenant_new_schema = {
     "title":"tenant creation information schema",
     "$schema": "http://json-schema.org/draft-04/schema#",
@@ -613,6 +611,7 @@ network_new_schema = {
     "required": ["network"],
     "additionalProperties": False
 }
+
 network_update_schema = {
     "title":"network update information schema",
     "$schema": "http://json-schema.org/draft-04/schema#",
@@ -715,3 +714,27 @@ hostinfo_schema = {
     },
     "required": ["iface_names"]
 }
+
+openflow_controller_schema = {
+    "title": "network creation information schema",
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "type": "object",
+    "properties": {
+        "ofc": {
+            "type": "object",
+            "properties": {
+                "name": name_schema,
+                "dpid": nameshort_schema,
+                "ip": nameshort_schema,
+                "port": port_schema,
+                "type": nameshort_schema,
+                "version": nametiny_schema,
+                "user": nameshort_schema,
+                "password": nameshort_schema
+            },
+            "required": ["dpid", "type", "ip", "port", "name"]
+        }
+    },
+    "required": ["ofc"],
+    "additionalProperties": False
+}
\ No newline at end of file