Move openflow logic to ovim.py from httpserver.py 19/1119/2
authormirabal <leonardo.mirabal@altran.com>
Wed, 15 Feb 2017 11:36:33 +0000 (12:36 +0100)
committermirabal <leonardo.mirabal@altran.com>
Thu, 16 Feb 2017 11:17:07 +0000 (12:17 +0100)
Change-Id: I8bd095ed85fb15579c3c1ec34bfe5513c7c41452
Signed-off-by: mirabal <leonardo.mirabal@altran.com>
httpserver.py
ovim.py

index f991bc4..8f203dc 100644 (file)
@@ -458,15 +458,6 @@ def check_valid_tenant(my, tenant_id):
             return HTTP_Not_Found, "tenant '%s' not found" % tenant_id
     return 0, None
 
-def check_valid_uuid(uuid):
-    id_schema = {"type" : "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
-    try:
-        js_v(uuid, id_schema)
-        return True
-    except js_e.ValidationError:
-        return False
-
-
 def is_url(url):
     '''
     Check if string value is a well-wormed url
@@ -1848,235 +1839,82 @@ def http_post_server_action(tenant_id, server_id):
 
 @bottle.route(url_base + '/networks', method='GET')
 def http_get_networks():
-    my = config_dic['http_threads'][ threading.current_thread().name ]
-    #obtain data
-    select_,where_,limit_ = filter_query_string(bottle.request.query, http2db_network,
-            ('id','name','tenant_id','type',
-             'shared','provider:vlan','status','last_error','admin_state_up','provider:physical') )
-    #TODO temporally remove tenant_id
-    if "tenant_id" in where_:
-        del where_["tenant_id"]
-    result, content = my.db.get_table(SELECT=select_, FROM='nets', WHERE=where_, LIMIT=limit_)
-    if result < 0:
-        print "http_get_networks error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    else:
-        convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
-        delete_nulls(content)      
-        change_keys_http2db(content, http2db_network, reverse=True)  
-        data={'networks' : content}
+    try:
+        my = config_dic['http_threads'][threading.current_thread().name]
+        # obtain data
+        select_, where_, limit_ = filter_query_string(bottle.request.query, http2db_network,
+                                                      ('id', 'name', 'tenant_id', 'type',
+                                                       'shared', 'provider:vlan', 'status', 'last_error',
+                                                       'admin_state_up', 'provider:physical'))
+        if "tenant_id" in where_:
+            del where_["tenant_id"]
+        content = my.ovim.get_networks(select_, where_, limit_)
+
+        delete_nulls(content)
+        change_keys_http2db(content, http2db_network, reverse=True)
+        data = {'networks': 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>', method='GET')
 def http_get_network_id(network_id):
         data = get_network_id(network_id)
         return format_out(data)
 
+
 def get_network_id(network_id):
-    my = config_dic['http_threads'][threading.current_thread().name]
-    # obtain data
-    where_ = bottle.request.query
-    where_['uuid'] = network_id
-    result, content = my.db.get_table(FROM='nets', WHERE=where_, LIMIT=100)
+    try:
+        my = config_dic['http_threads'][threading.current_thread().name]
+        # obtain data
+        where_ = bottle.request.query
+        where_['uuid'] = network_id
+        content = my.ovim.get_network_by_id(where_)
 
-    if result < 0:
-        print "http_get_networks_id error %d %s" % (result, content)
-        bottle.abort(-result, content)
-    elif result==0:
-        print "http_get_networks_id network '%s' not found" % network_id
-        bottle.abort(HTTP_Not_Found, 'network %s not found' % network_id)
-    else:
         convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
-        change_keys_http2db(content, http2db_network, reverse=True)        
-        #get ports
-        result, ports = my.db.get_table(FROM='ports', SELECT=('uuid as port_id',), 
-                                              WHERE={'net_id': network_id}, LIMIT=100)
-        if len(ports) > 0:
-            content[0]['ports'] = ports
-        delete_nulls(content[0])      
-        data={'network' : content[0]}
+        change_keys_http2db(content, http2db_network, reverse=True)
+
+        # content[0]['ports'] = delete_nulls(content[0]['ports'])
+        delete_nulls(content[0])
+        data = {'network': content[0]}
         return 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', method='POST')
 def http_post_networks():
-    '''insert a network into the database.'''
-    my = config_dic['http_threads'][ threading.current_thread().name ]
-    #parse input data
-    http_content = format_in( network_new_schema )
-    r = remove_extra_items(http_content, network_new_schema)
-    if r is not None: print "http_post_networks: Warning: remove extra items ", r
-    change_keys_http2db(http_content['network'], http2db_network)
-    network=http_content['network']
-    #check valid tenant_id
-    tenant_id= network.get('tenant_id')
-    if tenant_id!=None:
-        result, _ = my.db.get_table(FROM='tenants', SELECT=('uuid',), WHERE={'uuid': tenant_id,"enabled":True})
-        if result<=0:
-            bottle.abort(HTTP_Not_Found, 'tenant %s not found or not enabled' % tenant_id)
-            return
-    bridge_net = None
-    #check valid params
-    net_provider = network.get('provider')
-    net_type =     network.get('type')
-    net_enable_dhcp = network.get('enable_dhcp')
-    if net_enable_dhcp:
-        net_cidr = network.get('cidr')
-
-    net_vlan =     network.get("vlan")
-    net_bind_net = network.get("bind_net")
-    net_bind_type= network.get("bind_type")
-    name = network["name"]
-    
-    #check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
-    vlan_index =name.rfind(":")
-    if net_bind_net==None and net_bind_type==None and vlan_index > 1: 
-        try:
-            vlan_tag = int(name[vlan_index+1:])
-            if vlan_tag >0 and vlan_tag < 4096:
-                net_bind_net = name[:vlan_index]
-                net_bind_type = "vlan:" + name[vlan_index+1:]
-        except:
-            pass 
-        
-    if net_bind_net != None:
-        #look for a valid net
-        if check_valid_uuid(net_bind_net):
-            net_bind_key = "uuid"
-        else:
-            net_bind_key = "name"
-        result, content = my.db.get_table(FROM='nets', WHERE={net_bind_key: net_bind_net} )
-        if result<0:
-            bottle.abort(HTTP_Internal_Server_Error, 'getting nets from db ' + content)
-            return
-        elif result==0:
-            bottle.abort(HTTP_Bad_Request, "bind_net %s '%s'not found" % (net_bind_key, net_bind_net) )
-            return
-        elif result>1:
-            bottle.abort(HTTP_Bad_Request, "more than one bind_net %s '%s' found, use uuid" % (net_bind_key, net_bind_net) )
-            return
-        network["bind_net"] = content[0]["uuid"]
-    if net_bind_type != None:
-        if net_bind_type[0:5] != "vlan:":
-            bottle.abort(HTTP_Bad_Request, "bad format for 'bind_type', must be 'vlan:<tag>'")
-            return
-        if int(net_bind_type[5:]) > 4095 or int(net_bind_type[5:])<=0 :
-            bottle.abort(HTTP_Bad_Request, "bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095")
-            return
-        network["bind_type"] = net_bind_type
-    
-    if net_provider!=None:
-        if net_provider[:9]=="openflow:":
-            if net_type!=None:
-                if net_type!="ptp" and net_type!="data":
-                    bottle.abort(HTTP_Bad_Request, "Only 'ptp' or 'data' net types can be bound to 'openflow'")
-            else:
-                net_type='data'
-        else:
-            if net_type!=None:
-                if net_type!="bridge_man" and net_type!="bridge_data":
-                    bottle.abort(HTTP_Bad_Request, "Only 'bridge_man' or 'bridge_data' net types can be bound to 'bridge', 'macvtap' or 'default")
-            else:
-                net_type='bridge_man'
-    
-    if net_type==None:
-        net_type='bridge_man' 
-        
-    if net_provider != None:
-        if net_provider[:7]=='bridge:':
-            #check it is one of the pre-provisioned bridges
-            bridge_net_name = net_provider[7:]
-            for brnet in config_dic['bridge_nets']:
-                if brnet[0]==bridge_net_name: # free
-                    if brnet[3] != None:
-                        bottle.abort(HTTP_Conflict, "invalid 'provider:physical', bridge '%s' is already used" % bridge_net_name)
-                        return
-                    bridge_net=brnet
-                    net_vlan = brnet[1]
-                    break
-#            if bridge_net==None:     
-#                bottle.abort(HTTP_Bad_Request, "invalid 'provider:physical', bridge '%s' is not one of the provisioned 'bridge_ifaces' in the configuration file" % bridge_net_name)
-#                return
-    elif config_dic['network_type'] == 'bridge' and ( net_type =='bridge_data' or net_type ==  'bridge_man' ):
-        #look for a free precreated nets
-        for brnet in config_dic['bridge_nets']:
-            if brnet[3]==None: # free
-                if bridge_net != None:
-                    if net_type=='bridge_man': #look for the smaller speed
-                        if brnet[2] < bridge_net[2]:   bridge_net = brnet
-                    else: #look for the larger speed
-                        if brnet[2] > bridge_net[2]:   bridge_net = brnet
-                else:
-                    bridge_net = brnet
-                    net_vlan = brnet[1]
-        if bridge_net==None:
-            bottle.abort(HTTP_Bad_Request, "Max limits of bridge networks reached. Future versions of VIM will overcome this limit")
-            return
-        else:
-            print "using net", bridge_net
-            net_provider = "bridge:"+bridge_net[0]
-            net_vlan = bridge_net[1]
-    elif net_type == 'bridge_data' or net_type == 'bridge_man' and config_dic['network_type'] == 'ovs':
-        net_provider = 'OVS'
-    if not net_vlan and (net_type == "data" or net_type == "ptp" or net_provider == "OVS"):
-        net_vlan = my.db.get_free_net_vlan()
-        if net_vlan < 0:
-            bottle.abort(HTTP_Internal_Server_Error, "Error getting an available vlan")
-            return
-    if net_provider == 'OVS':
-        net_provider = 'OVS' + ":" + str(net_vlan)
-
-    network['provider'] = net_provider
-    network['type']     = net_type
-    network['vlan']     = net_vlan
-    dhcp_integrity = True
-    if 'enable_dhcp' in network and network['enable_dhcp']:
-        dhcp_integrity = check_dhcp_data_integrity(network)
-
-    result, content = my.db.new_row('nets', network, True, True)
-    
-    if result >= 0 and dhcp_integrity:
-        if bridge_net!=None:
-            bridge_net[3] = content
-        if config_dic.get("dhcp_server") and config_dic['network_type'] == 'bridge':
-            if network["name"] in config_dic["dhcp_server"].get("nets", () ):
-                config_dic["dhcp_nets"].append(content)
-                print "dhcp_server: add new net", content
-            elif bridge_net != None and bridge_net[0] in config_dic["dhcp_server"].get("bridge_ifaces", () ):
-                config_dic["dhcp_nets"].append(content)
-                print "dhcp_server: add new net", content
-        return http_get_network_id(content)
-    else:
-        print "http_post_networks error %d %s" % (result, content)
-        bottle.abort(-result, content)
-        return
-
-
-def check_dhcp_data_integrity(network):
     """
-    Check if all dhcp parameter for anet are valid, if not will be calculated from cidr value
-    :param network: list with user nets paramters
+    Insert a network into the database.
     :return:
     """
-    control_iface = []
-
-    if "cidr" in network:
-        cidr = network["cidr"]
-        ip_tools = IPNetwork(cidr)
-        cidr_len = ip_tools.prefixlen
-        if cidr_len > 29:
-            return False
-
-        ips = IPNetwork(cidr)
-        if "dhcp_first_ip" not in network:
-            network["dhcp_first_ip"] = str(ips[2])
-        if "dhcp_last_ip" not in network:
-            network["dhcp_last_ip"] = str(ips[-2])
-        if "gateway_ip" not in network:
-            network["gateway_ip"] = str(ips[1])
-
-        return True
-    else:
-        return False
+    try:
+        my = config_dic['http_threads'][threading.current_thread().name]
+        # parse input data
+        http_content = format_in(network_new_schema )
+        r = remove_extra_items(http_content, network_new_schema)
+        if r is not None:
+            print "http_post_networks: Warning: remove extra items ", r
+        change_keys_http2db(http_content['network'], http2db_network)
+        network = http_content['network']
+        content = my.ovim.set_network(network)
+        return http_get_network_id(content)
+    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>', method='PUT')
@@ -2203,85 +2041,100 @@ def http_delete_network_id(network_id):
 #
 # OPENFLOW
 #
+
+
 @bottle.route(url_base + '/networks/<network_id>/openflow', method='GET')
 def http_get_openflow_id(network_id):
-    '''To obtain the list of openflow rules of a network
-    '''
-    my = config_dic['http_threads'][ threading.current_thread().name ]
-    #ignore input data
-    if network_id=='all':
-        where_={}
-    else:
-        where_={"net_id": network_id}
-    result, content = my.db.get_table(SELECT=("name","net_id","priority","vlan_id","ingress_port","src_mac","dst_mac","actions"),
-            WHERE=where_, FROM='of_flows')
-    if result < 0:
-        bottle.abort(-result, content)
-        return
-    data={'openflow-rules' : content}
+    """
+    To obtain the list of openflow rules of a network
+    :param network_id: network id
+    :return:
+    """
+
+    # ignore input data
+    if network_id == 'all':
+        network_id = None
+    try:
+        my = config_dic['http_threads'][threading.current_thread().name]
+        content = my.ovim.get_openflow_rules(network_id)
+        data = {'openflow-rules': content}
+    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)
 
+
 @bottle.route(url_base + '/networks/<network_id>/openflow', method='PUT')
 def http_put_openflow_id(network_id):
-    '''To make actions over the net. The action is to reinstall the openflow rules
+    """
+    To make actions over the net. The action is to reinstall the openflow rules
     network_id can be 'all'
-    '''
-    my = config_dic['http_threads'][ threading.current_thread().name ]
+    :param network_id: network id
+    :return:
+    """
+    my = config_dic['http_threads'][threading.current_thread().name]
+
     if not my.admin:
         bottle.abort(HTTP_Unauthorized, "Needed admin privileges")
-        return
-    #ignore input data
-    if network_id=='all':
-        where_={}
-    else:
-        where_={"uuid": network_id}
-    result, content = my.db.get_table(SELECT=("uuid","type"), WHERE=where_, FROM='nets')
-    if result < 0:
-        bottle.abort(-result, content)
-        return
-    
-    for net in content:
-        if net["type"]!="ptp" and net["type"]!="data":
-            result-=1
-            continue
-        r,c = config_dic['of_thread'].insert_task("update-net", net['uuid'])
-        if r  < 0:
-            print "http_put_openflow_id error while launching openflow rules"
-            bottle.abort(HTTP_Internal_Server_Error, c)
-    data={'result' : str(result)+" nets updates"}
+
+    if network_id == 'all':
+        network_id = None
+
+    try:
+        result = my.ovim.update_openflow_rules(network_id)
+    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))
+
+    data = {'result': str(result) + " nets updates"}
     return format_out(data)
 
-@bottle.route(url_base + '/networks/openflow/clear', method='DELETE')
+
 @bottle.route(url_base + '/networks/clear/openflow', method='DELETE')
 def http_clear_openflow_rules():
-    '''To make actions over the net. The action is to delete ALL openflow rules
-    '''
-    my = config_dic['http_threads'][ threading.current_thread().name ]
+    """
+    To make actions over the net. The action is to delete ALL openflow rules
+    :return:
+    """
+    my = config_dic['http_threads'][ threading.current_thread().name]
+
     if not my.admin:
         bottle.abort(HTTP_Unauthorized, "Needed admin privileges")
-        return
-    #ignore input data
-    r,c = config_dic['of_thread'].insert_task("clear-all")
-    if r  < 0:
-        print "http_delete_openflow_id error while launching openflow rules"
-        bottle.abort(HTTP_Internal_Server_Error, c)
-        return
+    try:
+        my.ovim.clear_openflow_rules()
+    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))
 
-    data={'result' : " Clearing openflow rules in process"}
+    data = {'result': " Clearing openflow rules in process"}
     return format_out(data)
 
+
 @bottle.route(url_base + '/networks/openflow/ports', method='GET')
 def http_get_openflow_ports():
-    '''Obtain switch ports names of openflow controller
-    '''
-    data={'ports' : config_dic['of_thread'].OF_connector.pp2ofi}
+    """
+    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}
     return format_out(data)
-
-
 #
 # PORTS
 #
 
+
 @bottle.route(url_base + '/ports', method='GET')
 def http_get_ports():
     #obtain data
diff --git a/ovim.py b/ovim.py
index 286a4d0..922e122 100644 (file)
--- a/ovim.py
+++ b/ovim.py
@@ -37,7 +37,8 @@ import imp
 import host_thread as ht
 import dhcp_thread as dt
 import openflow_thread as oft
-from netaddr import IPNetwork, IPAddress, all_matching_cidrs
+from netaddr import IPNetwork
+from jsonschema import validate as js_v, exceptions as js_e
 
 HTTP_Bad_Request =          400
 HTTP_Unauthorized =         401
@@ -238,9 +239,13 @@ class ovim():
 
         for net in content:
             net_type = net['type']
-            if net_type == 'bridge_data' or net_type == 'bridge_man' and net["provider"][:4]=="OVS:" and net["enable_dhcp"] == "true":
-                if net['enable_dhcp'] == 'true':
-                    self.launch_dhcp_server(net['vlan'], net['dhcp_first_ip'], net['dhcp_last_ip'], net['cidr'])
+            if net_type == 'bridge_data' or net_type == 'bridge_man' \
+                    and net["provider"][:4] =="OVS:" and net["enable_dhcp"] == "true":
+                    self.launch_dhcp_server(net['vlan'],
+                                            net['dhcp_first_ip'],
+                                            net['dhcp_last_ip'],
+                                            net['cidr'],
+                                            net['gateway_ip'])
 
     def stop_service(self):
         threads = self.config.get('host_threads', {})
@@ -254,6 +259,300 @@ class ovim():
         for thread in threads.values():
             thread.join()
 
+    def get_networks(self, select_=None, where_=None, limit_=100):
+        """
+        Retreive networks available
+        :param select_: List with select query parameters
+        :param where_: List with where query parameters
+        :param limit_: Query limit result
+        :return:
+        """
+        result, content = self.db.get_table(SELECT=select_, FROM='nets', WHERE=where_, LIMIT=limit_)
+
+        if result < 0:
+            raise ovimException(str(content), -result)
+
+        convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
+
+        return content
+
+    def get_network_by_id(self, where_, limit_=100):
+        """
+
+        :param where_:
+        :param limit_:
+        :return:
+        """
+        # obtain data
+        if 'uuid' not in where_:
+            raise ovimException("Not network id was not found" )
+        result, content = self.db.get_table(FROM='nets', WHERE=where_, LIMIT=limit_)
+
+        network_id = where_['uuid']
+
+        if result < 0:
+            raise ovimException(str(content), -result)
+        elif result == 0:
+            raise ovimException("http_get_networks_id network '%s' not found" % network_id, -result)
+        else:
+            convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
+            # get ports
+            result, ports = self.db.get_table(FROM='ports', SELECT=('uuid as port_id',),
+                                            WHERE={'net_id': network_id}, LIMIT=100)
+            if len(ports) > 0:
+                content[0]['ports'] = ports
+            return content
+
+    def set_network(self, network):
+        """
+
+        :return:
+        """
+        tenant_id = network.get('tenant_id')
+
+        if tenant_id:
+            result, _ = self.db.get_table(FROM='tenants', SELECT=('uuid',), WHERE={'uuid': tenant_id, "enabled": True})
+            if result <= 0:
+                raise ovimException("set_network error, no tenant founded", -result)
+
+        bridge_net = None
+        # check valid params
+        net_provider = network.get('provider')
+        net_type = network.get('type')
+        net_enable_dhcp = network.get('enable_dhcp')
+        if net_enable_dhcp:
+            net_cidr = network.get('cidr')
+
+        net_vlan = network.get("vlan")
+        net_bind_net = network.get("bind_net")
+        net_bind_type = network.get("bind_type")
+        name = network["name"]
+
+        # check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
+        vlan_index = name.rfind(":")
+        if not net_bind_net and not net_bind_type and vlan_index > 1:
+            try:
+                vlan_tag = int(name[vlan_index + 1:])
+                if not vlan_tag and vlan_tag < 4096:
+                    net_bind_net = name[:vlan_index]
+                    net_bind_type = "vlan:" + name[vlan_index + 1:]
+            except:
+                pass
+
+        if net_bind_net:
+            # look for a valid net
+            if self._check_valid_uuid(net_bind_net):
+                net_bind_key = "uuid"
+            else:
+                net_bind_key = "name"
+            result, content = self.db.get_table(FROM='nets', WHERE={net_bind_key: net_bind_net})
+            if result < 0:
+                raise ovimException(' getting nets from db ' + content, HTTP_Internal_Server_Error)
+            elif result == 0:
+                raise ovimException(" bind_net %s '%s'not found" % (net_bind_key, net_bind_net), HTTP_Bad_Request)
+            elif result > 1:
+                raise ovimException(" more than one bind_net %s '%s' found, use uuid" % (net_bind_key, net_bind_net), HTTP_Bad_Request)
+            network["bind_net"] = content[0]["uuid"]
+
+        if net_bind_type:
+            if net_bind_type[0:5] != "vlan:":
+                raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request)
+            if int(net_bind_type[5:]) > 4095 or int(net_bind_type[5:]) <= 0:
+                raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
+                                    HTTP_Bad_Request)
+            network["bind_type"] = net_bind_type
+
+        if net_provider:
+            if net_provider[:9] == "openflow:":
+                if net_type:
+                    if net_type != "ptp" and net_type != "data":
+                        raise ovimException(" only 'ptp' or 'data' net types can be bound to 'openflow'",
+                                            HTTP_Bad_Request)
+                else:
+                    net_type = 'data'
+            else:
+                if net_type:
+                    if net_type != "bridge_man" and net_type != "bridge_data":
+                        raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound "
+                                            "to 'bridge', 'macvtap' or 'default", HTTP_Bad_Request)
+                else:
+                    net_type = 'bridge_man'
+
+        if not net_type:
+            net_type = 'bridge_man'
+
+        if net_provider:
+            if net_provider[:7] == 'bridge:':
+                # check it is one of the pre-provisioned bridges
+                bridge_net_name = net_provider[7:]
+                for brnet in self.config['bridge_nets']:
+                    if brnet[0] == bridge_net_name:  # free
+                        if not brnet[3]:
+                            raise ovimException("invalid 'provider:physical', "
+                                                "bridge '%s' is already used" % bridge_net_name, HTTP_Conflict)
+                        bridge_net = brnet
+                        net_vlan = brnet[1]
+                        break
+                        #            if bridge_net==None:
+                        #                bottle.abort(HTTP_Bad_Request, "invalid 'provider:physical', bridge '%s' is not one of the provisioned 'bridge_ifaces' in the configuration file" % bridge_net_name)
+                        #                return
+        elif self.config['network_type'] == 'bridge' and (net_type == 'bridge_data' or net_type == 'bridge_man'):
+            # look for a free precreated nets
+            for brnet in self.config['bridge_nets']:
+                if not brnet[3]:  # free
+                    if not bridge_net:
+                        if net_type == 'bridge_man':  # look for the smaller speed
+                            if brnet[2] < bridge_net[2]:
+                                bridge_net = brnet
+                        else:  # look for the larger speed
+                            if brnet[2] > bridge_net[2]:
+                                bridge_net = brnet
+                    else:
+                        bridge_net = brnet
+                        net_vlan = brnet[1]
+            if not bridge_net:
+                raise ovimException("Max limits of bridge networks reached. Future versions of VIM "
+                                    "will overcome this limit", HTTP_Bad_Request)
+            else:
+                print "using net", bridge_net
+                net_provider = "bridge:" + bridge_net[0]
+                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_vlan and (net_type == "data" or net_type == "ptp" or net_provider == "OVS"):
+            net_vlan = self.db.get_free_net_vlan()
+            if net_vlan < 0:
+                raise ovimException("Error getting an available vlan", HTTP_Internal_Server_Error)
+        if net_provider == 'OVS':
+            net_provider = 'OVS' + ":" + str(net_vlan)
+
+        network['provider'] = net_provider
+        network['type'] = net_type
+        network['vlan'] = net_vlan
+        dhcp_integrity = True
+        if 'enable_dhcp' in network and network['enable_dhcp']:
+            dhcp_integrity = self._check_dhcp_data_integrity(network)
+
+        result, content = self.db.new_row('nets', network, True, True)
+
+        if result >= 0 and dhcp_integrity:
+            if bridge_net:
+                bridge_net[3] = content
+            if self.config.get("dhcp_server") and self.config['network_type'] == 'bridge':
+                if network["name"] in self.config["dhcp_server"].get("nets", ()):
+                    self.config["dhcp_nets"].append(content)
+                    print "dhcp_server: add new net", content
+                elif not bridge_net and bridge_net[0] in self.config["dhcp_server"].get("bridge_ifaces", ()):
+                    self.config["dhcp_nets"].append(content)
+                    print "dhcp_server: add new net", content
+            return content
+        else:
+            print "http_post_networks error %d %s" % (result, content)
+            raise ovimException("Error posting network", HTTP_Internal_Server_Error)
+
+    @staticmethod
+    def _check_dhcp_data_integrity(network):
+        """
+        Check if all dhcp parameter for anet are valid, if not will be calculated from cidr value
+        :param network: list with user nets paramters
+        :return:
+        """
+        control_iface = []
+
+        if "cidr" in network:
+            cidr = network["cidr"]
+            ip_tools = IPNetwork(cidr)
+            cidr_len = ip_tools.prefixlen
+            if cidr_len > 29:
+                return False
+
+            ips = IPNetwork(cidr)
+            if "dhcp_first_ip" not in network:
+                network["dhcp_first_ip"] = str(ips[2])
+            if "dhcp_last_ip" not in network:
+                network["dhcp_last_ip"] = str(ips[-2])
+            if "gateway_ip" not in network:
+                network["gateway_ip"] = str(ips[1])
+
+            return True
+        else:
+            return False
+
+    @staticmethod
+    def _check_valid_uuid( uuid):
+        id_schema = {"type": "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
+        try:
+            js_v(uuid, id_schema)
+            return True
+        except js_e.ValidationError:
+            return False
+
+    def get_openflow_rules(self, network_id=None):
+        """
+        Get openflow id from DB
+        :param network_id: Network id, if none all networks will be retrieved
+        :return: Return a list with Openflow rules per net
+        """
+        # ignore input data
+        if not network_id:
+            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"),
+            WHERE=where_, FROM='of_flows')
+
+        if result < 0:
+            raise ovimException(str(content), -result)
+        return content
+
+    def update_openflow_rules(self, network_id=None):
+
+        """
+        To make actions over the net. The action is to reinstall the openflow rules
+        network_id can be 'all'
+        :param network_id: Network id, if none all networks will be retrieved
+        :return : Number of nets updated
+        """
+
+        # ignore input data
+        if not network_id:
+            where_ = {}
+        else:
+            where_ = {"uuid": network_id}
+        result, content = self.db.get_table(SELECT=("uuid", "type"), WHERE=where_, FROM='nets')
+
+        if result < 0:
+            raise ovimException(str(content), -result)
+
+        for net in content:
+            if net["type"] != "ptp" and net["type"] != "data":
+                result -= 1
+                continue
+            r, c = self.config['of_thread'].insert_task("update-net", net['uuid'])
+            if r < 0:
+                raise ovimException(str(c), -r)
+        return result
+
+    def clear_openflow_rules(self):
+        """
+        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)
+        return r
+
+    def get_openflow_ports(self):
+        """
+        Obtain switch ports names of openflow controller
+        :return: Return flow ports in DB
+        """
+        data = {'ports': self.config['of_thread'].OF_connector.pp2ofi}
+        return data
 
     def get_ports(self, columns=None, filter={}, limit=None):
         # result, content = my.db.get_ports(where_)
@@ -265,7 +564,6 @@ class ovim():
             convert_boolean(content, ('admin_state_up',))
             return content
 
-
     def new_port(self, port_data):
         port_data['type'] = 'external'
         if port_data.get('net_id'):