2 # -*- coding: utf-8 -*-
5 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
6 # This file is part of openvim
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact with: nfvlabs@tid.es
26 This is the thread for the http server North API.
27 Two thread will be launched, with normal and administrative permissions.
37 from netaddr
import IPNetwork
38 from jsonschema
import validate
as js_v
, exceptions
as js_e
39 import host_thread
as ht
40 import dhcp_thread
as dt
41 import openflow_thread
as oft
44 __author__
= "Alfonso Tierno, Leonardo Mirabal"
45 __date__
= "$06-Feb-2017 12:07:15$"
46 __version__
= "0.5.18-r534"
47 version_date
= "Jun 2017"
48 database_version
= 21 #needed database schema version
50 HTTP_Bad_Request
= 400
51 HTTP_Unauthorized
= 401
54 HTTP_Method_Not_Allowed
= 405
55 HTTP_Not_Acceptable
= 406
56 HTTP_Request_Timeout
= 408
58 HTTP_Service_Unavailable
= 503
59 HTTP_Internal_Server_Error
= 500
62 def convert_boolean(data
, items
):
63 '''Check recursively the content of data, and if there is an key contained in items, convert value from string to boolean
64 It assumes that bandwidth is well formed
66 'data': dictionary bottle.FormsDict variable to be checked. None or empty is consideted valid
67 'items': tuple of keys to convert
71 if type(data
) is dict:
73 if type(data
[k
]) is dict or type(data
[k
]) is tuple or type(data
[k
]) is list:
74 convert_boolean(data
[k
], items
)
76 if type(data
[k
]) is str:
77 if data
[k
] == "false":
79 elif data
[k
] == "true":
81 if type(data
) is tuple or type(data
) is list:
83 if type(k
) is dict or type(k
) is tuple or type(k
) is list:
84 convert_boolean(k
, items
)
88 class ovimException(Exception):
89 def __init__(self
, message
, http_code
=HTTP_Bad_Request
):
90 self
.http_code
= http_code
91 Exception.__init
__(self
, message
)
95 running_info
= {} #TODO OVIM move the info of running threads from config_dic to this static variable
98 def __init__(self
, configuration
):
99 self
.config
= configuration
100 self
.logger_name
= configuration
.get("logger_name", "openvim")
101 self
.logger
= logging
.getLogger(self
.logger_name
)
103 self
.db
= self
._create
_database
_connection
()
104 self
.of_test_mode
= False
106 def _create_database_connection(self
):
107 db
= vim_db
.vim_db((self
.config
["network_vlan_range_start"], self
.config
["network_vlan_range_end"]),
108 self
.logger_name
+ ".db", self
.config
.get('log_level_db'))
109 if db
.connect(self
.config
['db_host'], self
.config
['db_user'], self
.config
['db_passwd'],
110 self
.config
['db_name']) == -1:
111 # self.logger.error("Cannot connect to database %s at %s@%s", self.config['db_name'], self.config['db_user'],
112 # self.config['db_host'])
113 raise ovimException("Cannot connect to database {} at {}@{}".format(self
.config
['db_name'],
114 self
.config
['db_user'],
115 self
.config
['db_host']) )
123 def get_version_date():
127 def get_database_version():
128 return database_version
131 def _check_dhcp_data_integrity(network
):
133 Check if all dhcp parameter for anet are valid, if not will be calculated from cidr value
134 :param network: list with user nets paramters
137 if "cidr" in network
:
138 cidr
= network
["cidr"]
139 ip_tools
= IPNetwork(cidr
)
140 cidr_len
= ip_tools
.prefixlen
144 ips
= IPNetwork(cidr
)
145 if "dhcp_first_ip" not in network
:
146 network
["dhcp_first_ip"] = str(ips
[3])
147 if "dhcp_last_ip" not in network
:
148 network
["dhcp_last_ip"] = str(ips
[-2])
149 if "gateway_ip" not in network
:
150 network
["gateway_ip"] = str(ips
[1])
157 def _check_valid_uuid(uuid
):
158 id_schema
= {"type": "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
160 js_v(uuid
, id_schema
)
162 except js_e
.ValidationError
:
165 def start_service(self
):
170 global database_version
171 # if self.running_info:
172 # return #TODO service can be checked and rebuild broken threads
173 r
= self
.db
.get_db_version()
175 db_path
= db_path
[:db_path
.rfind("/")]
176 if os
.path
.exists(db_path
+ "/database_utils/migrate_vim_db.sh"):
177 db_path
+= "/database_utils"
179 db_path
+= "/../database_utils"
182 raise ovimException("DATABASE is not valid. If you think it is corrupted, you can init it with"
183 " '{db_path}/init_vim_db.sh' script".format(db_path
=db_path
))
184 elif r
[0] != database_version
:
185 raise ovimException("DATABASE wrong version '{current}'. Try to upgrade/downgrade to version '{target}'"
186 " with '{db_path}/migrate_vim_db.sh {target}'".format(
187 current
=r
[0], target
=database_version
, db_path
=db_path
))
188 self
.logger
.critical("Starting ovim server version: '{} {}' database version '{}'".format(
189 self
.get_version(), self
.get_version_date(), self
.get_database_version()))
190 # create database connection for openflow threads
191 self
.config
["db"] = self
._create
_database
_connection
()
192 self
.config
["db_lock"] = threading
.Lock()
194 self
.of_test_mode
= False if self
.config
['mode'] == 'normal' or self
.config
['mode'] == "OF only" else True
196 # Create one thread for each host
197 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
198 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
199 host_develop_bridge_iface
= self
.config
.get('development_bridge', None)
201 # get host list from data base before starting threads
202 r
, hosts
= self
.db
.get_table(SELECT
=('name', 'ip_name', 'user', 'uuid', 'password', 'keyfile'),
203 FROM
='hosts', WHERE
={'status': 'ok'})
205 raise ovimException("Cannot get hosts from database {}".format(hosts
))
207 self
.config
['host_threads'] = {}
210 thread
= ht
.host_thread(name
=host
['name'], user
=host
['user'], host
=host
['ip_name'], db
=self
.config
["db"],
211 password
=host
['password'],
212 keyfile
=host
.get('keyfile', self
.config
["host_ssh_keyfile"]),
213 db_lock
=self
.config
["db_lock"], test
=host_test_mode
,
214 image_path
=self
.config
['host_image_path'],
215 version
=self
.config
['version'], host_id
=host
['uuid'],
216 develop_mode
=host_develop_mode
,
217 develop_bridge_iface
=host_develop_bridge_iface
,
218 logger_name
=self
.logger_name
+ ".host." + host
['name'],
219 debug
=self
.config
.get('log_level_host'))
222 thread
.check_connectivity()
223 except Exception as e
:
224 self
.logger
.critical('Error detected for compute = {} with ip = {}'
225 .format(host
['name'], host
['ip_name']))
227 self
.config
['host_threads'][host
['uuid']] = thread
229 # precreate interfaces; [bridge:<host_bridge_name>, VLAN used at Host, uuid of network camping in this bridge,
232 self
.config
['dhcp_nets'] = []
233 self
.config
['bridge_nets'] = []
234 for bridge
, vlan_speed
in self
.config
["bridge_ifaces"].items():
235 # skip 'development_bridge'
236 if self
.config
['mode'] == 'development' and self
.config
['development_bridge'] == bridge
:
238 self
.config
['bridge_nets'].append([bridge
, vlan_speed
[0], vlan_speed
[1], None])
240 # check if this bridge is already used (present at database) for a network)
241 used_bridge_nets
= []
242 for brnet
in self
.config
['bridge_nets']:
243 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'provider': "bridge:" + brnet
[0]})
245 brnet
[3] = nets
[0]['uuid']
246 used_bridge_nets
.append(brnet
[0])
247 if self
.config
.get("dhcp_server"):
248 if brnet
[0] in self
.config
["dhcp_server"]["bridge_ifaces"]:
249 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
250 if len(used_bridge_nets
) > 0:
251 self
.logger
.info("found used bridge nets: " + ",".join(used_bridge_nets
))
252 # get nets used by dhcp
253 if self
.config
.get("dhcp_server"):
254 for net
in self
.config
["dhcp_server"].get("nets", ()):
255 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'name': net
})
257 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
260 self
._start
_ofc
_default
_task
()
262 # OFC per tenant in DB
263 self
._start
_of
_db
_tasks
()
265 # create dhcp_server thread
266 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
267 dhcp_params
= self
.config
.get("dhcp_server")
269 thread
= dt
.dhcp_thread(dhcp_params
=dhcp_params
, test
=host_test_mode
, dhcp_nets
=self
.config
["dhcp_nets"],
270 db
=self
.config
["db"], db_lock
=self
.config
["db_lock"],
271 logger_name
=self
.logger_name
+ ".dhcp",
272 debug
=self
.config
.get('log_level_of'))
274 self
.config
['dhcp_thread'] = thread
278 # create ovs dhcp thread
279 result
, content
= self
.db
.get_table(FROM
='nets')
281 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
282 raise ovimException(str(content
), -result
)
285 net_type
= net
['type']
286 if net
['status'] != "INACTIVE" and (net_type
== 'bridge_data' or net_type
== 'bridge_man') and \
287 net
["provider"][:4] == 'OVS:' and net
["enable_dhcp"] == "true":
289 config_routes
= net
.get('routes')
291 routes
= yaml
.safe_load(config_routes
)
295 config_dns
= net
.get('dns')
297 dns
= yaml
.safe_load(config_dns
)
301 links
= net
.get('links')
303 links
= yaml
.safe_load(net
.get('links'))
304 self
.launch_dhcp_server(net
.get('vlan'),
305 net
.get('dhcp_first_ip'),
306 net
.get('dhcp_last_ip'),
308 net
.get('gateway_ip'),
311 self
.launch_link_bridge_to_ovs(net
['vlan'], net
.get('gateway_ip'), net
.get('cidr'), links
, routes
)
312 if net
["status"] == "ERROR":
313 self
.db
.update_rows("nets", UPDATE
={"status": "ACTIVE", "last_error": None},
314 WHERE
={"uuid": net
["uuid"]})
315 except Exception as e
:
316 self
.logger
.error("Fail at launching dhcp server for net_id='%s' net_name='%s': %s",
317 net
["uuid"], net
["name"], str(e
))
318 self
.db
.update_rows("nets", UPDATE
={"status": "ERROR",
319 "last_error": "Fail at launching dhcp server: " + str(e
)},
320 WHERE
={"uuid": net
["uuid"]})
322 def _start_of_db_tasks(self
):
324 Start ofc task for existing ofcs in database
329 ofcs
= self
.get_of_controllers()
332 of_conn
= self
._load
_of
_module
(ofc
)
333 # create ofc thread per of controller
334 self
._create
_ofc
_task
(ofc
['uuid'], ofc
['dpid'], of_conn
)
336 def _create_ofc_task(self
, ofc_uuid
, dpid
, of_conn
):
338 Create an ofc thread for handle each sdn controllers
339 :param ofc_uuid: sdn controller uuid
340 :param dpid: sdn controller dpid
341 :param of_conn: OF_conn module
344 if 'ofcs_thread' not in self
.config
and 'ofcs_thread_dpid' not in self
.config
:
346 ofcs_thread_dpid
= []
348 ofcs_threads
= self
.config
['ofcs_thread']
349 ofcs_thread_dpid
= self
.config
['ofcs_thread_dpid']
351 if ofc_uuid
not in ofcs_threads
:
352 ofc_thread
= self
._create
_ofc
_thread
(of_conn
, ofc_uuid
)
353 if ofc_uuid
== "Default":
354 self
.config
['of_thread'] = ofc_thread
356 ofcs_threads
[ofc_uuid
] = ofc_thread
357 self
.config
['ofcs_thread'] = ofcs_threads
359 ofcs_thread_dpid
.append({dpid
: ofc_thread
})
360 self
.config
['ofcs_thread_dpid'] = ofcs_thread_dpid
362 def _start_ofc_default_task(self
):
364 Create default ofc thread
366 if 'of_controller' not in self
.config \
367 and 'of_controller_ip' not in self
.config \
368 and 'of_controller_port' not in self
.config \
369 and 'of_controller_dpid' not in self
.config
:
374 db_config
['ip'] = self
.config
.get('of_controller_ip')
375 db_config
['port'] = self
.config
.get('of_controller_port')
376 db_config
['dpid'] = self
.config
.get('of_controller_dpid')
377 db_config
['type'] = self
.config
.get('of_controller')
378 db_config
['user'] = self
.config
.get('of_user')
379 db_config
['password'] = self
.config
.get('of_password')
381 # create connector to the openflow controller
382 # load other parameters starting by of_ from config dict in a temporal dict
384 of_conn
= self
._load
_of
_module
(db_config
)
385 # create openflow thread
386 self
._create
_ofc
_task
("Default", db_config
['dpid'], of_conn
)
388 def _load_of_module(self
, db_config
):
390 import python module for each SDN controller supported
391 :param db_config: SDN dn information
395 raise ovimException("No module found it", HTTP_Internal_Server_Error
)
400 if self
.of_test_mode
:
401 return openflow_conn
.OfTestConnector({"name": db_config
['type'],
402 "dpid": db_config
['dpid'],
403 "of_debug": self
.config
['log_level_of']})
407 temp_dict
['of_ip'] = db_config
['ip']
408 temp_dict
['of_port'] = db_config
['port']
409 temp_dict
['of_dpid'] = db_config
['dpid']
410 temp_dict
['of_controller'] = db_config
['type']
411 temp_dict
['of_user'] = db_config
.get('user')
412 temp_dict
['of_password'] = db_config
.get('password')
414 temp_dict
['of_debug'] = self
.config
['log_level_of']
416 if temp_dict
['of_controller'] == 'opendaylight':
419 module
= temp_dict
['of_controller']
421 if module
not in ovim
.of_module
:
423 pkg
= __import__("osm_openvim." + module
)
424 of_conn_module
= getattr(pkg
, module
)
425 ovim
.of_module
[module
] = of_conn_module
426 self
.logger
.debug("Module load from {}".format("osm_openvim." + module
))
427 except Exception as e
:
428 self
.logger
.error("Cannot open openflow controller module of type '%s'", module
)
429 raise ovimException("Cannot open openflow controller of type module '{}'"
430 "Revise it is installed".format(module
),
431 HTTP_Internal_Server_Error
)
433 of_conn_module
= ovim
.of_module
[module
]
434 return of_conn_module
.OF_conn(temp_dict
)
435 except Exception as e
:
436 self
.logger
.error("Cannot open the Openflow controller '%s': %s", type(e
).__name
__, str(e
))
437 raise ovimException("Cannot open the Openflow controller '{}': '{}'".format(type(e
).__name
__, str(e
)),
438 HTTP_Internal_Server_Error
)
440 def _create_ofc_thread(self
, of_conn
, ofc_uuid
="Default"):
442 Create and launch a of thread
445 # create openflow thread
447 #if 'of_controller_nets_with_same_vlan' in self.config:
448 # ofc_net_same_vlan = self.config['of_controller_nets_with_same_vlan']
450 # ofc_net_same_vlan = False
451 ofc_net_same_vlan
= False
453 thread
= oft
.openflow_thread(ofc_uuid
, of_conn
, of_test
=self
.of_test_mode
, db
=self
.config
["db"],
454 db_lock
=self
.config
["db_lock"],
455 pmp_with_same_vlan
=ofc_net_same_vlan
,
456 logger_name
=self
.logger_name
+ ".ofc." + ofc_uuid
,
457 debug
=self
.config
.get('log_level_of'))
458 #r, c = thread.OF_connector.obtain_port_correspondence()
460 # raise ovimException("Cannot get openflow information %s", c)
464 def stop_service(self
):
465 threads
= self
.config
.get('host_threads', {})
466 if 'of_thread' in self
.config
:
467 threads
['of'] = (self
.config
['of_thread'])
468 if 'ofcs_thread' in self
.config
:
469 ofcs_thread
= self
.config
['ofcs_thread']
470 for ofc
in ofcs_thread
:
471 threads
[ofc
] = ofcs_thread
[ofc
]
473 if 'dhcp_thread' in self
.config
:
474 threads
['dhcp'] = (self
.config
['dhcp_thread'])
476 for thread_id
, thread
in threads
.items():
477 if thread_id
== 'openvim_controller':
479 thread
.insert_task("exit")
480 for thread_id
, thread
in threads
.items():
481 if thread_id
== 'openvim_controller':
485 def get_networks(self
, columns
=None, db_filter
={}, limit
=None):
487 Retreive networks available
488 :param columns: List with select query parameters
489 :param db_filter: List with where query parameters
490 :param limit: Query limit result
493 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='nets', WHERE
=db_filter
, LIMIT
=limit
)
496 raise ovimException(str(content
), -result
)
498 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
502 def show_network(self
, network_id
, db_filter
={}):
504 Get network from DB by id
505 :param network_id: net Id
506 :param db_filter: List with where query parameters
511 raise ovimException("Not network id was not found")
512 db_filter
['uuid'] = network_id
514 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
=db_filter
, LIMIT
=100)
517 raise ovimException(str(content
), -result
)
519 raise ovimException("show_network network '%s' not found" % network_id
, -result
)
521 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
523 result
, ports
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
524 WHERE
={'net_id': network_id
}, LIMIT
=100)
526 content
[0]['ports'] = ports
528 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
531 def new_network(self
, network
):
536 tenant_id
= network
.get('tenant_id')
539 result
, _
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
, "enabled": True})
541 raise ovimException("set_network error, no tenant founded", -result
)
545 net_provider
= network
.get('provider')
546 net_type
= network
.get('type')
547 net_vlan
= network
.get("vlan")
548 net_bind_net
= network
.get("bind_net")
549 net_bind_type
= network
.get("bind_type")
550 net_region
= network
.get("region")
551 name
= network
["name"]
553 # check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
554 vlan_index
= name
.rfind(":")
555 if not net_bind_net
and not net_bind_type
and vlan_index
> 1:
557 vlan_tag
= int(name
[vlan_index
+ 1:])
558 if not vlan_tag
and vlan_tag
< 4096:
559 net_bind_net
= name
[:vlan_index
]
560 net_bind_type
= "vlan:" + name
[vlan_index
+ 1:]
565 # look for a valid net
566 if self
._check
_valid
_uuid
(net_bind_net
):
567 net_bind_key
= "uuid"
569 net_bind_key
= "name"
570 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
572 raise ovimException(' getting nets from db ' + content
, HTTP_Internal_Server_Error
)
574 raise ovimException(" bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
576 raise ovimException(" more than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
577 network
["bind_net"] = content
[0]["uuid"]
580 if net_bind_type
[0:5] != "vlan:":
581 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
582 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
583 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
585 network
["bind_type"] = net_bind_type
588 if net_provider
[:9] == "openflow:":
590 if net_type
!= "ptp" and net_type
!= "data":
591 raise ovimException(" only 'ptp' or 'data' net types can be bound to 'openflow'",
597 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
598 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound "
599 "to 'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
601 net_type
= 'bridge_man'
604 net_type
= 'bridge_man'
607 if net_provider
[:7] == 'bridge:':
608 # check it is one of the pre-provisioned bridges
609 bridge_net_name
= net_provider
[7:]
610 for brnet
in self
.config
['bridge_nets']:
611 if brnet
[0] == bridge_net_name
: # free
613 raise ovimException("invalid 'provider:physical', "
614 "bridge '%s' is already used" % bridge_net_name
, HTTP_Conflict
)
618 # if bridge_net==None:
619 # bottle.abort(HTTP_Bad_Request, "invalid 'provider:physical', bridge '%s' is not one of the
620 # provisioned 'bridge_ifaces' in the configuration file" % bridge_net_name)
623 elif self
.config
['network_type'] == 'bridge' and (net_type
== 'bridge_data' or net_type
== 'bridge_man'):
624 # look for a free precreated nets
625 for brnet
in self
.config
['bridge_nets']:
626 if not brnet
[3]: # free
628 if net_type
== 'bridge_man': # look for the smaller speed
629 if brnet
[2] < bridge_net
[2]:
631 else: # look for the larger speed
632 if brnet
[2] > bridge_net
[2]:
638 raise ovimException("Max limits of bridge networks reached. Future versions of VIM "
639 "will overcome this limit", HTTP_Bad_Request
)
641 self
.logger
.debug("using net " + bridge_net
)
642 net_provider
= "bridge:" + bridge_net
[0]
643 net_vlan
= bridge_net
[1]
644 elif net_type
== 'bridge_data' or net_type
== 'bridge_man' and self
.config
['network_type'] == 'ovs':
647 if net_type
== "data" or net_type
== "ptp":
648 net_region
= "__DATA__"
649 elif net_provider
== "OVS":
650 net_region
= "__OVS__"
651 if not net_vlan
and (net_type
== "data" or net_type
== "ptp" or net_provider
== "OVS"):
652 net_vlan
= self
.db
.get_free_net_vlan(net_region
)
654 raise ovimException("Error getting an available vlan", HTTP_Internal_Server_Error
)
655 if net_provider
== 'OVS':
656 net_provider
= 'OVS' + ":" + str(net_vlan
)
658 network
['provider'] = net_provider
659 network
['type'] = net_type
660 network
['vlan'] = net_vlan
661 network
['region'] = net_region
662 dhcp_integrity
= True
663 if 'enable_dhcp' in network
and network
['enable_dhcp']:
664 dhcp_integrity
= self
._check
_dhcp
_data
_integrity
(network
)
666 if network
.get('links'):
667 network
['links'] = yaml
.safe_dump(network
['links'], default_flow_style
=True, width
=256)
668 if network
.get('dns'):
669 network
['dns'] = yaml
.safe_dump(network
['dns'], default_flow_style
=True, width
=256)
670 if network
.get('routes'):
671 network
['routes'] = yaml
.safe_dump(network
['routes'], default_flow_style
=True, width
=256)
673 result
, content
= self
.db
.new_row('nets', network
, True, True)
675 if result
>= 0 and dhcp_integrity
:
677 bridge_net
[3] = content
678 if self
.config
.get("dhcp_server") and self
.config
['network_type'] == 'bridge':
679 if network
["name"] in self
.config
["dhcp_server"].get("nets", ()):
680 self
.config
["dhcp_nets"].append(content
)
681 self
.logger
.debug("dhcp_server: add new net", content
)
682 elif bridge_net
and bridge_net
[0] in self
.config
["dhcp_server"].get("bridge_ifaces", ()):
683 self
.config
["dhcp_nets"].append(content
)
684 self
.logger
.debug("dhcp_server: add new net", content
, content
)
687 raise ovimException("Error posting network", HTTP_Internal_Server_Error
)
688 # TODO kei change update->edit
690 def edit_network(self
, network_id
, network
):
692 Update entwork data byt id
695 # Look for the previous data
696 where_
= {'uuid': network_id
}
697 result
, network_old
= self
.db
.get_table(FROM
='nets', WHERE
=where_
)
699 raise ovimException("Error updating network %s" % network_old
, HTTP_Internal_Server_Error
)
701 raise ovimException('network %s not found' % network_id
, HTTP_Not_Found
)
703 nbports
, content
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
704 WHERE
={'net_id': network_id
}, LIMIT
=100)
706 raise ovimException("http_put_network_id error %d %s" % (result
, network_old
), HTTP_Internal_Server_Error
)
708 if 'type' in network
and network
['type'] != network_old
[0]['type']:
709 raise ovimException("Can not change type of network while having ports attached",
710 HTTP_Method_Not_Allowed
)
711 if 'vlan' in network
and network
['vlan'] != network_old
[0]['vlan']:
712 raise ovimException("Can not change vlan of network while having ports attached",
713 HTTP_Method_Not_Allowed
)
716 net_provider
= network
.get('provider', network_old
[0]['provider'])
717 net_type
= network
.get('type', network_old
[0]['type'])
718 net_bind_net
= network
.get("bind_net")
719 net_bind_type
= network
.get("bind_type")
721 # look for a valid net
722 if self
._check
_valid
_uuid
(net_bind_net
):
723 net_bind_key
= "uuid"
725 net_bind_key
= "name"
726 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
728 raise ovimException('Getting nets from db ' + content
, HTTP_Internal_Server_Error
)
730 raise ovimException("bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
732 raise ovimException("More than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
),
734 network
["bind_net"] = content
[0]["uuid"]
736 if net_bind_type
[0:5] != "vlan:":
737 raise ovimException("Bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
738 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
739 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
742 if net_provider
[:9] == "openflow:":
743 if net_type
!= "ptp" and net_type
!= "data":
744 raise ovimException("Only 'ptp' or 'data' net types can be bound to 'openflow'", HTTP_Bad_Request
)
746 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
747 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound to "
748 "'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
750 # insert in data base
751 result
, content
= self
.db
.update_rows('nets', network
, WHERE
={'uuid': network_id
}, log
=True)
753 # if result > 0 and nbports>0 and 'admin_state_up' in network
754 # and network['admin_state_up'] != network_old[0]['admin_state_up']:
759 self
.net_update_ofc_thread(network_id
)
760 except ovimException
as e
:
761 raise ovimException("Error while launching openflow rules in network '{}' {}"
762 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
763 except Exception as e
:
764 raise ovimException("Error while launching openflow rules in network '{}' {}"
765 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
767 if self
.config
.get("dhcp_server"):
768 if network_id
in self
.config
["dhcp_nets"]:
769 self
.config
["dhcp_nets"].remove(network_id
)
770 if network
.get("name", network_old
[0]["name"]) in self
.config
["dhcp_server"].get("nets", ()):
771 self
.config
["dhcp_nets"].append(network_id
)
773 net_bind
= network
.get("bind_type", network_old
[0]["bind_type"])
774 if net_bind
and net_bind
and net_bind
[:7] == "bridge:" and net_bind
[7:] in self
.config
["dhcp_server"].get(
775 "bridge_ifaces", ()):
776 self
.config
["dhcp_nets"].append(network_id
)
779 raise ovimException(content
, -result
)
781 def delete_network(self
, network_id
):
783 Delete network by network id
784 :param network_id: network id
788 # delete from the data base
789 result
, content
= self
.db
.delete_row('nets', network_id
)
792 raise ovimException("Network %s not found " % network_id
, HTTP_Not_Found
)
794 for brnet
in self
.config
['bridge_nets']:
795 if brnet
[3] == network_id
:
798 if self
.config
.get("dhcp_server") and network_id
in self
.config
["dhcp_nets"]:
799 self
.config
["dhcp_nets"].remove(network_id
)
802 raise ovimException("Error deleting network '{}': {}".format(network_id
, content
), -result
)
804 def get_openflow_rules(self
, network_id
=None):
806 Get openflow id from DB
807 :param network_id: Network id, if none all networks will be retrieved
808 :return: Return a list with Openflow rules per net
814 where_
= {"net_id": network_id
}
815 result
, content
= self
.db
.get_table(
816 SELECT
=("name", "net_id", "ofc_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
817 WHERE
=where_
, FROM
='of_flows')
820 raise ovimException(str(content
), -result
)
823 def edit_openflow_rules(self
, network_id
=None):
826 To make actions over the net. The action is to reinstall the openflow rules
827 network_id can be 'all'
828 :param network_id: Network id, if none all networks will be retrieved
829 :return : Number of nets updated
836 where_
= {"uuid": network_id
}
837 result
, content
= self
.db
.get_table(SELECT
=("uuid", "type"), WHERE
=where_
, FROM
='nets')
840 raise ovimException(str(content
), -result
)
843 if net
["type"] != "ptp" and net
["type"] != "data":
848 self
.net_update_ofc_thread(net
['uuid'])
849 except ovimException
as e
:
850 raise ovimException("Error updating network'{}' {}".format(net
['uuid'], str(e
)),
851 HTTP_Internal_Server_Error
)
852 except Exception as e
:
853 raise ovimException("Error updating network '{}' {}".format(net
['uuid'], str(e
)),
854 HTTP_Internal_Server_Error
)
858 def delete_openflow_rules(self
, ofc_id
=None):
860 To make actions over the net. The action is to delete ALL openflow rules
861 :return: return operation result
865 if 'Default' in self
.config
['ofcs_thread']:
866 r
, c
= self
.config
['ofcs_thread']['Default'].insert_task("clear-all")
868 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
870 elif ofc_id
in self
.config
['ofcs_thread']:
871 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("clear-all")
875 raise ovimException(str(c
), -r
)
877 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
880 def get_openflow_ports(self
, ofc_id
=None):
882 Obtain switch ports names of openflow controller
883 :return: Return flow ports in DB
886 if 'Default' in self
.config
['ofcs_thread']:
887 conn
= self
.config
['ofcs_thread']['Default'].OF_connector
889 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
891 elif ofc_id
in self
.config
['ofcs_thread']:
892 conn
= self
.config
['ofcs_thread'][ofc_id
].OF_connector
894 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
897 def get_ports(self
, columns
=None, filter={}, limit
=None):
898 # result, content = my.db.get_ports(where_)
899 result
, content
= self
.db
.get_table(SELECT
=columns
, WHERE
=filter, FROM
='ports', LIMIT
=limit
)
901 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
902 raise ovimException(str(content
), -result
)
904 convert_boolean(content
, ('admin_state_up',))
907 def new_port(self
, port_data
):
908 port_data
['type'] = 'external'
909 if port_data
.get('net_id'):
910 # check that new net has the correct type
911 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
913 raise ovimException(str(new_net
), -result
)
914 # insert in data base
915 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
917 if 'net_id' in port_data
:
919 self
.net_update_ofc_thread(port_data
['net_id'])
920 except ovimException
as e
:
921 raise ovimException("Cannot insert a task for updating network '{}' {}"
922 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
923 except Exception as e
:
924 raise ovimException("Cannot insert a task for updating network '{}' {}"
925 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
929 raise ovimException(str(uuid
), -result
)
931 def new_external_port(self
, port_data
):
933 Create new external port and check port mapping correspondence
934 :param port_data: port_data = {
935 'region': 'datacenter region',
936 'compute_node': 'compute node id',
937 'pci': 'pci port address',
940 'tenant_id': 'tenant id',
943 'ip_address': 'ip address - optional'}
947 port_data
['type'] = 'external'
949 if port_data
.get('net_id'):
950 # check that new net has the correct type
951 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
953 raise ovimException(str(new_net
), -result
)
954 # insert in data base
957 if port_data
.get('region'):
958 db_filter
['region'] = port_data
['region']
959 if port_data
.get('pci'):
960 db_filter
['pci'] = port_data
['pci']
961 if port_data
.get('compute_node'):
962 db_filter
['compute_node'] = port_data
['compute_node']
964 columns
= ['ofc_id', 'switch_dpid', 'switch_port', 'switch_mac', 'pci']
965 port_mapping_data
= self
.get_of_port_mappings(columns
, db_filter
)
967 if not len(port_mapping_data
):
968 raise ovimException("No port mapping founded for '{}'".format(str(db_filter
)),
970 elif len(port_mapping_data
) > 1:
971 raise ovimException("Wrong port data was given, please check pci, region & compute id data",
974 port_data
['ofc_id'] = port_mapping_data
[0]['ofc_id']
975 port_data
['switch_dpid'] = port_mapping_data
[0]['switch_dpid']
976 port_data
['switch_port'] = port_mapping_data
[0]['switch_port']
977 port_data
['switch_mac'] = port_mapping_data
[0]['switch_mac']
979 # remove from compute_node, region and pci of_port_data to adapt to 'ports' structure
980 if 'region' in port_data
:
981 del port_data
['region']
982 if 'pci' in port_data
:
984 if 'compute_node' in port_data
:
985 del port_data
['compute_node']
987 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
990 self
.net_update_ofc_thread(port_data
['net_id'], port_data
['ofc_id'])
991 except ovimException
as e
:
992 raise ovimException("Cannot insert a task for updating network '{}' {}".
993 format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
994 except Exception as e
:
995 raise ovimException("Cannot insert a task for updating network '{}' {}"
996 .format(port_data
['net_id'], e
), HTTP_Internal_Server_Error
)
999 raise ovimException(str(uuid
), -result
)
1001 def net_update_ofc_thread(self
, net_id
, ofc_id
=None, switch_dpid
=None):
1003 Insert a update net task by net id or ofc_id for each ofc thread
1004 :param net_id: network id
1005 :param ofc_id: openflow controller id
1006 :param switch_dpid: switch dpid
1010 raise ovimException("No net_id received", HTTP_Internal_Server_Error
)
1013 c
= 'No valid ofc_id or switch_dpid received'
1016 ports
= self
.get_ports(filter={"net_id": net_id
})
1018 port_ofc_id
= port
.get('ofc_id', None)
1020 ofc_id
= port
['ofc_id']
1021 switch_dpid
= port
['switch_dpid']
1023 #TODO if not ofc_id: look at database table ofcs
1026 # If no ofc_id found it, default ofc_id is used.
1027 if not ofc_id
and not switch_dpid
:
1030 if ofc_id
and ofc_id
in self
.config
['ofcs_thread']:
1031 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("update-net", net_id
)
1034 ofcs_dpid_list
= self
.config
['ofcs_thread_dpid']
1035 for ofc_t
in ofcs_dpid_list
:
1036 if switch_dpid
in ofc_t
:
1037 r
, c
= ofc_t
[switch_dpid
].insert_task("update-net", net_id
)
1040 message
= "Cannot insert a task for updating network '{}', {}".format(net_id
, c
)
1041 self
.logger
.error(message
)
1042 raise ovimException(message
, HTTP_Internal_Server_Error
)
1044 def delete_port(self
, port_id
):
1045 # Look for the previous port data
1046 result
, ports
= self
.db
.get_table(WHERE
={'uuid': port_id
, "type": "external"}, FROM
='ports')
1048 raise ovimException("Cannot get port info from database: {}".format(ports
), http_code
=-result
)
1049 # delete from the data base
1050 result
, content
= self
.db
.delete_row('ports', port_id
)
1052 raise ovimException("External port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
1054 raise ovimException("Cannot delete port from database: {}".format(content
), http_code
=-result
)
1056 network
= ports
[0].get('net_id', None)
1061 self
.net_update_ofc_thread(network
, ofc_id
=ports
[0]["ofc_id"], switch_dpid
=ports
[0]["switch_dpid"])
1062 except ovimException
as e
:
1063 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1064 HTTP_Internal_Server_Error
)
1065 except Exception as e
:
1066 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1067 HTTP_Internal_Server_Error
)
1071 def edit_port(self
, port_id
, port_data
, admin
=True):
1072 # Look for the previous port data
1073 result
, content
= self
.db
.get_table(FROM
="ports", WHERE
={'uuid': port_id
})
1075 raise ovimException("Cannot get port info from database: {}".format(content
), http_code
=-result
)
1077 raise ovimException("Port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
1082 if 'net_id' in port_data
:
1084 old_net
= port
.get('net_id', None)
1085 new_net
= port_data
['net_id']
1086 if old_net
!= new_net
:
1089 nets
.append(new_net
) # put first the new net, so that new openflow rules are created before removing the old ones
1091 nets
.append(old_net
)
1092 if port
['type'] == 'instance:bridge' or port
['type'] == 'instance:ovs':
1093 raise ovimException("bridge interfaces cannot be attached to a different net", http_code
=HTTP_Forbidden
)
1094 elif port
['type'] == 'external' and not admin
:
1095 raise ovimException("Needed admin privileges",http_code
=HTTP_Unauthorized
)
1097 # check that new net has the correct type
1098 result
, new_net_dict
= self
.db
.check_target_net(new_net
, None, port
['type'])
1100 raise ovimException("Error {}".format(new_net_dict
), http_code
=HTTP_Conflict
)
1101 # change VLAN for SR-IOV ports
1102 if result
>= 0 and port
["type"] == "instance:data" and port
["model"] == "VF": # TODO consider also VFnotShared
1104 port_data
["vlan"] = None
1106 port_data
["vlan"] = new_net_dict
["vlan"]
1107 # get host where this VM is allocated
1108 result
, content
= self
.db
.get_table(FROM
="instances", WHERE
={"uuid": port
["instance_id"]})
1110 host_id
= content
[0]["host_id"]
1112 # insert in data base
1114 result
, content
= self
.db
.update_rows('ports', port_data
, WHERE
={'uuid': port_id
}, log
=False)
1115 port
.update(port_data
)
1117 # Insert task to complete actions
1121 self
.net_update_ofc_thread(net_id
, port
["ofc_id"], switch_dpid
=port
["switch_dpid"])
1122 except ovimException
as e
:
1123 raise ovimException("Error updating network'{}' {}".format(net_id
, str(e
)),
1124 HTTP_Internal_Server_Error
)
1125 except Exception as e
:
1126 raise ovimException("Error updating network '{}' {}".format(net_id
, str(e
)),
1127 HTTP_Internal_Server_Error
)
1130 r
, v
= self
.config
['host_threads'][host_id
].insert_task("edit-iface", port_id
, old_net
, new_net
)
1132 self
.logger
.error("Error updating network '{}' {}".format(r
,v
))
1133 # TODO Do something if fails
1137 raise ovimException("Error {}".format(content
), http_code
=-result
)
1139 def new_of_controller(self
, ofc_data
):
1141 Create a new openflow controller into DB
1142 :param ofc_data: Dict openflow controller data
1143 :return: openflow controller dpid
1146 result
, ofc_uuid
= self
.db
.new_row('ofcs', ofc_data
, True, True)
1148 raise ovimException("New ofc Error %s" % ofc_uuid
, HTTP_Internal_Server_Error
)
1150 ofc_data
['uuid'] = ofc_uuid
1151 of_conn
= self
._load
_of
_module
(ofc_data
)
1152 self
._create
_ofc
_task
(ofc_uuid
, ofc_data
['dpid'], of_conn
)
1156 def edit_of_controller(self
, of_id
, ofc_data
):
1158 Edit an openflow controller entry from DB
1162 raise ovimException("No data received during uptade OF contorller", http_code
=HTTP_Internal_Server_Error
)
1164 old_of_controller
= self
.show_of_controller(of_id
)
1166 if old_of_controller
:
1167 result
, content
= self
.db
.update_rows('ofcs', ofc_data
, WHERE
={'uuid': of_id
}, log
=False)
1171 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1174 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1175 http_code
=HTTP_Internal_Server_Error
)
1177 def delete_of_controller(self
, of_id
):
1179 Delete an openflow controller from DB.
1180 :param of_id: openflow controller dpid
1184 ofc
= self
.show_of_controller(of_id
)
1186 result
, content
= self
.db
.delete_row("ofcs", of_id
)
1188 raise ovimException("Cannot delete ofc from database: {}".format(content
), http_code
=-result
)
1190 raise ovimException("ofc {} not found ".format(content
), http_code
=HTTP_Not_Found
)
1192 ofc_thread
= self
.config
['ofcs_thread'][of_id
]
1193 del self
.config
['ofcs_thread'][of_id
]
1194 for ofc_th
in self
.config
['ofcs_thread_dpid']:
1195 if ofc
['dpid'] in ofc_th
:
1196 self
.config
['ofcs_thread_dpid'].remove(ofc_th
)
1198 ofc_thread
.insert_task("exit")
1203 def show_of_controller(self
, uuid
):
1205 Show an openflow controller by dpid from DB.
1206 :param db_filter: List with where query parameters
1210 result
, content
= self
.db
.get_table(FROM
='ofcs', WHERE
={"uuid": uuid
}, LIMIT
=100)
1213 raise ovimException("Openflow controller with uuid '{}' not found".format(uuid
),
1214 http_code
=HTTP_Not_Found
)
1216 raise ovimException("Openflow controller with uuid '{}' error".format(uuid
),
1217 http_code
=HTTP_Internal_Server_Error
)
1220 def get_of_controllers(self
, columns
=None, db_filter
={}, limit
=None):
1222 Show an openflow controllers from DB.
1223 :param columns: List with SELECT query parameters
1224 :param db_filter: List with where query parameters
1225 :param limit: result Limit
1228 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='ofcs', WHERE
=db_filter
, LIMIT
=limit
)
1231 raise ovimException(str(content
), -result
)
1235 def get_tenants(self
, columns
=None, db_filter
={}, limit
=None):
1237 Retrieve tenant list from DB
1238 :param columns: List with SELECT query parameters
1239 :param db_filter: List with where query parameters
1240 :param limit: result limit
1243 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=columns
, WHERE
=db_filter
, LIMIT
=limit
)
1245 raise ovimException('get_tenatns Error {}'.format(str(content
)), -result
)
1247 convert_boolean(content
, ('enabled',))
1250 def show_tenant_id(self
, tenant_id
):
1252 Get tenant from DB by id
1253 :param tenant_id: tenant id
1256 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid', 'name', 'description', 'enabled'),
1257 WHERE
={"uuid": tenant_id
})
1259 raise ovimException(str(content
), -result
)
1261 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1263 convert_boolean(content
, ('enabled',))
1266 def new_tentant(self
, tenant
):
1268 Create a tenant and store in DB
1269 :param tenant: Dictionary with tenant data
1270 :return: the uuid of created tenant. Raise exception upon error
1273 # insert in data base
1274 result
, tenant_uuid
= self
.db
.new_tenant(tenant
)
1279 raise ovimException(str(tenant_uuid
), -result
)
1281 def delete_tentant(self
, tenant_id
):
1283 Delete a tenant from the database.
1284 :param tenant_id: Tenant id
1285 :return: delete tenant id
1289 r
, tenants_flavors
= self
.db
.get_table(FROM
='tenants_flavors', SELECT
=('flavor_id', 'tenant_id'),
1290 WHERE
={'tenant_id': tenant_id
})
1292 tenants_flavors
= ()
1293 r
, tenants_images
= self
.db
.get_table(FROM
='tenants_images', SELECT
=('image_id', 'tenant_id'),
1294 WHERE
={'tenant_id': tenant_id
})
1298 result
, content
= self
.db
.delete_row('tenants', tenant_id
)
1300 raise ovimException("tenant '%s' not found" % tenant_id
, HTTP_Not_Found
)
1302 for flavor
in tenants_flavors
:
1303 self
.db
.delete_row_by_key("flavors", "uuid", flavor
['flavor_id'])
1304 for image
in tenants_images
:
1305 self
.db
.delete_row_by_key("images", "uuid", image
['image_id'])
1308 raise ovimException("Error deleting tenant '%s' " % tenant_id
, HTTP_Internal_Server_Error
)
1310 def edit_tenant(self
, tenant_id
, tenant_data
):
1312 Update a tenant data identified by tenant id
1313 :param tenant_id: tenant id
1314 :param tenant_data: Dictionary with tenant data
1318 # Look for the previous data
1319 result
, tenant_data_old
= self
.db
.get_table(FROM
='tenants', WHERE
={'uuid': tenant_id
})
1321 raise ovimException("Error updating tenant with uuid='{}': {}".format(tenant_id
, tenant_data_old
),
1322 HTTP_Internal_Server_Error
)
1324 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1326 # insert in data base
1327 result
, content
= self
.db
.update_rows('tenants', tenant_data
, WHERE
={'uuid': tenant_id
}, log
=True)
1331 raise ovimException(str(content
), -result
)
1333 def set_of_port_mapping(self
, of_maps
, ofc_id
=None, switch_dpid
=None, region
=None):
1335 Create new port mapping entry
1336 :param of_maps: List with port mapping information
1337 # maps =[{"ofc_id": <ofc_id>,"region": datacenter region,"compute_node": compute uuid,"pci": pci adress,
1338 "switch_dpid": swith dpid,"switch_port": port name,"switch_mac": mac}]
1339 :param ofc_id: ofc id
1340 :param switch_dpid: switch dpid
1341 :param region: datacenter region id
1347 map['ofc_id'] = ofc_id
1349 map['switch_dpid'] = switch_dpid
1351 map['region'] = region
1353 for of_map
in of_maps
:
1354 result
, uuid
= self
.db
.new_row('of_port_mappings', of_map
, True)
1356 of_map
["uuid"] = uuid
1358 raise ovimException(str(uuid
), -result
)
1361 def clear_of_port_mapping(self
, db_filter
={}):
1363 Clear port mapping filtering using db_filter dict
1364 :param db_filter: Parameter to filter during remove process
1367 result
, content
= self
.db
.delete_row_by_dict(FROM
='of_port_mappings', WHERE
=db_filter
)
1372 raise ovimException("Error deleting of_port_mappings with filter='{}'".format(str(db_filter
)),
1373 HTTP_Internal_Server_Error
)
1375 def get_of_port_mappings(self
, column
=None, db_filter
=None, db_limit
=None):
1377 Retrive port mapping from DB
1382 result
, content
= self
.db
.get_table(SELECT
=column
, WHERE
=db_filter
, FROM
='of_port_mappings', LIMIT
=db_limit
)
1385 self
.logger
.error("get_of_port_mappings Error %d %s", result
, content
)
1386 raise ovimException(str(content
), -result
)
1390 def get_dhcp_controller(self
):
1392 Create an host_thread object for manage openvim controller and not create a thread for itself
1393 :return: dhcp_host openvim controller object
1396 if 'openvim_controller' in self
.config
['host_threads']:
1397 return self
.config
['host_threads']['openvim_controller']
1400 controller_ip
= self
.config
['ovs_controller_ip']
1401 ovs_controller_user
= self
.config
.get('ovs_controller_user')
1403 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
1404 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
1406 dhcp_host
= ht
.host_thread(name
='openvim_controller', user
=ovs_controller_user
, host
=controller_ip
,
1407 password
=self
.config
.get('ovs_controller_password'),
1408 keyfile
=self
.config
.get('ovs_controller_keyfile'),
1409 db
=self
.config
["db"], db_lock
=self
.config
["db_lock"], test
=host_test_mode
,
1410 image_path
=self
.config
['host_image_path'], version
=self
.config
['version'],
1411 host_id
='openvim_controller', develop_mode
=host_develop_mode
,
1412 develop_bridge_iface
=bridge_ifaces
,
1413 logger_name
=self
.logger_name
+ ".host.controller",
1414 debug
=self
.config
.get('log_level_host'))
1416 self
.config
['host_threads']['openvim_controller'] = dhcp_host
1418 dhcp_host
.check_connectivity()
1419 except Exception as e
:
1424 def launch_dhcp_server(self
, vlan
, first_ip
, last_ip
, cidr
, gateway
, dns
, routes
):
1426 Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
1427 :param vlan: vlan identifier
1428 :param first_ip: First dhcp range ip
1429 :param last_ip: Last dhcp range ip
1430 :param cidr: net cidr
1431 :param gateway: net gateway
1434 ip_tools
= IPNetwork(cidr
)
1435 dhcp_netmask
= str(ip_tools
.netmask
)
1436 ip_range
= [first_ip
, last_ip
]
1438 dhcp_path
= self
.config
['ovs_controller_file_path']
1440 controller_host
= self
.get_dhcp_controller()
1442 # controller_host.create_linux_bridge(vlan)
1443 controller_host
.create_dhcp_interfaces(vlan
, first_ip
, dhcp_netmask
)
1444 dhcp_path
= self
.config
['ovs_controller_file_path']
1445 controller_host
.launch_dhcp_server(vlan
, ip_range
, dhcp_netmask
, dhcp_path
, gateway
, dns
, routes
)
1447 def launch_link_bridge_to_ovs(self
, vlan
, gateway
, dhcp_cidr
, links
=None, routes
=None):
1449 Launch creating of connections (veth) between user bridge (link) and OVS
1457 controller_host
= self
.get_dhcp_controller()
1459 if 'iface' in link
and 'nat' not in link
:
1460 controller_host
.create_link_bridge_to_ovs(vlan
, link
['iface'])
1462 controller_host
.create_qrouter_ovs_connection(vlan
, gateway
, dhcp_cidr
)
1463 controller_host
.create_qrouter_br_connection(vlan
, dhcp_cidr
, link
)
1466 controller_host
.add_ns_routes(vlan
, routes
)
1468 def delete_link_bridge_to_ovs(self
, vlan
, links
=None):
1470 Delete connections (veth) between user bridge (link) and OVS
1476 controller_host
= self
.get_dhcp_controller()
1479 if 'iface' in link
and 'nat' not in link
:
1480 controller_host
.remove_link_bridge_to_ovs(vlan
, link
['iface'])
1482 controller_host
.delete_qrouter_connection(vlan
, link
['iface'])
1485 if __name__
== "__main__":
1487 parser
= argparse
.ArgumentParser()
1488 parser
.add_argument("-v","--version", help="show ovim library version", action
="store_true")
1489 parser
.add_argument("--database-version", help="show required database version", action
="store_true")
1490 args
= parser
.parse_args()
1492 print ('openvimd version {} {}'.format(ovim
.get_version(), ovim
.get_version_date()))
1493 print ('(c) Copyright Telefonica')
1494 elif args
.database_version
:
1495 print ('required database version: {}'.format(ovim
.get_database_version()))