blob: fe2748ff5b4c903032c0dbecc59376ef20dd17fb [file] [log] [blame]
mirabald87877c2017-03-31 15:15:52 +02001#!/usr/bin/env python
tierno57f7bda2017-02-09 12:01:55 +01002# -*- coding: utf-8 -*-
3
4##
5# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
6# This file is part of openvim
7# All Rights Reserved.
8#
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
12#
13# http://www.apache.org/licenses/LICENSE-2.0
14#
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
19# under the License.
20#
21# For those usages not covered by the Apache License, Version 2.0 please
22# contact with: nfvlabs@tid.es
23##
24
tierno51068952017-04-26 15:09:48 +020025"""
tierno57f7bda2017-02-09 12:01:55 +010026This is the thread for the http server North API.
27Two thread will be launched, with normal and administrative permissions.
tierno51068952017-04-26 15:09:48 +020028"""
tierno57f7bda2017-02-09 12:01:55 +010029
30import threading
mirabal6878e3f2017-06-05 09:19:26 -050031import yaml
garciadeblas071df952017-04-21 11:12:50 +020032import vim_db
tierno57f7bda2017-02-09 12:01:55 +010033import logging
tierno29d80242017-04-25 18:07:08 +020034# import imp
tierno95a9e832017-04-27 18:49:37 +020035import os.path
mirabal9f657102017-04-10 20:05:40 +020036import argparse
mirabal65ba8f82017-02-15 12:36:33 +010037from netaddr import IPNetwork
38from jsonschema import validate as js_v, exceptions as js_e
garciadeblas071df952017-04-21 11:12:50 +020039import host_thread as ht
40import dhcp_thread as dt
41import openflow_thread as oft
42import openflow_conn
mirabal9f657102017-04-10 20:05:40 +020043
tierno51068952017-04-26 15:09:48 +020044__author__ = "Alfonso Tierno, Leonardo Mirabal"
45__date__ = "$06-Feb-2017 12:07:15$"
mirabal6878e3f2017-06-05 09:19:26 -050046__version__ = "0.5.18-r534"
mirabalcaeb2242017-05-31 10:52:22 -050047version_date = "Jun 2017"
mirabal6878e3f2017-06-05 09:19:26 -050048database_version = 21 #needed database schema version
tierno57f7bda2017-02-09 12:01:55 +010049
50HTTP_Bad_Request = 400
51HTTP_Unauthorized = 401
52HTTP_Not_Found = 404
53HTTP_Forbidden = 403
54HTTP_Method_Not_Allowed = 405
55HTTP_Not_Acceptable = 406
56HTTP_Request_Timeout = 408
57HTTP_Conflict = 409
58HTTP_Service_Unavailable = 503
59HTTP_Internal_Server_Error= 500
60
61
62def 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
65 Attributes:
66 'data': dictionary bottle.FormsDict variable to be checked. None or empty is consideted valid
67 'items': tuple of keys to convert
68 Return:
69 None
70 '''
71 if type(data) is dict:
72 for k in data.keys():
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)
75 if k in items:
76 if type(data[k]) is str:
77 if data[k] == "false":
78 data[k] = False
79 elif data[k] == "true":
80 data[k] = True
81 if type(data) is tuple or type(data) is list:
82 for k in data:
83 if type(k) is dict or type(k) is tuple or type(k) is list:
84 convert_boolean(k, items)
85
86
87
88class ovimException(Exception):
89 def __init__(self, message, http_code=HTTP_Bad_Request):
90 self.http_code = http_code
91 Exception.__init__(self, message)
92
93
94class ovim():
95 running_info = {} #TODO OVIM move the info of running threads from config_dic to this static variable
mirabal580435e2017-03-01 16:17:10 +010096 of_module = {}
97
tierno57f7bda2017-02-09 12:01:55 +010098 def __init__(self, configuration):
99 self.config = configuration
tierno46ca3a92017-04-05 19:49:24 +0200100 self.logger_name = configuration.get("logger_name", "openvim")
101 self.logger = logging.getLogger(self.logger_name)
tierno57f7bda2017-02-09 12:01:55 +0100102 self.db = None
tierno46ca3a92017-04-05 19:49:24 +0200103 self.db = self._create_database_connection()
mirabal580435e2017-03-01 16:17:10 +0100104 self.of_test_mode = False
tierno57f7bda2017-02-09 12:01:55 +0100105
106 def _create_database_connection(self):
107 db = vim_db.vim_db((self.config["network_vlan_range_start"], self.config["network_vlan_range_end"]),
tierno46ca3a92017-04-05 19:49:24 +0200108 self.logger_name + ".db", self.config.get('log_level_db'))
tierno57f7bda2017-02-09 12:01:55 +0100109 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']) )
116 return db
117
mirabale9f6f1a2017-02-16 17:57:35 +0100118 @staticmethod
mirabal50a052f2017-03-27 18:08:07 +0200119 def get_version():
120 return __version__
121
122 @staticmethod
123 def get_version_date():
124 return version_date
125
126 @staticmethod
127 def get_database_version():
128 return database_version
129
130 @staticmethod
mirabale9f6f1a2017-02-16 17:57:35 +0100131 def _check_dhcp_data_integrity(network):
132 """
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
135 :return:
136 """
137 if "cidr" in network:
138 cidr = network["cidr"]
139 ip_tools = IPNetwork(cidr)
140 cidr_len = ip_tools.prefixlen
141 if cidr_len > 29:
142 return False
143
144 ips = IPNetwork(cidr)
145 if "dhcp_first_ip" not in network:
mirabal72fcda72017-05-09 11:01:06 +0200146 network["dhcp_first_ip"] = str(ips[3])
mirabale9f6f1a2017-02-16 17:57:35 +0100147 if "dhcp_last_ip" not in network:
148 network["dhcp_last_ip"] = str(ips[-2])
149 if "gateway_ip" not in network:
mirabal6878e3f2017-06-05 09:19:26 -0500150 network["gateway_ip"] = str(ips[1])
mirabale9f6f1a2017-02-16 17:57:35 +0100151
152 return True
153 else:
154 return False
155
156 @staticmethod
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}$"}
159 try:
160 js_v(uuid, id_schema)
161 return True
162 except js_e.ValidationError:
163 return False
tierno57f7bda2017-02-09 12:01:55 +0100164
165 def start_service(self):
mirabal580435e2017-03-01 16:17:10 +0100166 """
167 Start ovim services
168 :return:
169 """
tierno2db743b2017-03-28 17:23:15 +0200170 global database_version
mirabal580435e2017-03-01 16:17:10 +0100171 # if self.running_info:
tierno57f7bda2017-02-09 12:01:55 +0100172 # return #TODO service can be checked and rebuild broken threads
173 r = self.db.get_db_version()
tierno95a9e832017-04-27 18:49:37 +0200174 db_path = __file__
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"
178 else:
179 db_path += "/../database_utils"
180
mirabal580435e2017-03-01 16:17:10 +0100181 if r[0] < 0:
tierno95a9e832017-04-27 18:49:37 +0200182 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))
tierno46ca3a92017-04-05 19:49:24 +0200188 self.logger.critical("Starting ovim server version: '{} {}' database version '{}'".format(
189 self.get_version(), self.get_version_date(), self.get_database_version()))
tierno57f7bda2017-02-09 12:01:55 +0100190 # create database connection for openflow threads
tiernoe0c28c12017-05-04 18:44:40 +0200191 self.config["db"] = self._create_database_connection()
192 self.config["db_lock"] = threading.Lock()
tierno57f7bda2017-02-09 12:01:55 +0100193
mirabal580435e2017-03-01 16:17:10 +0100194 self.of_test_mode = False if self.config['mode'] == 'normal' or self.config['mode'] == "OF only" else True
mirabal42ca0092017-06-14 05:42:30 -0500195
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)
200
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'})
204 if r < 0:
205 raise ovimException("Cannot get hosts from database {}".format(hosts))
206
207 self.config['host_threads'] = {}
208
209 for host in hosts:
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'))
220
221 try:
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']))
mirabald48f4f92017-06-29 10:04:21 -0500226 thread.start()
mirabal42ca0092017-06-14 05:42:30 -0500227 self.config['host_threads'][host['uuid']] = thread
228
mirabal580435e2017-03-01 16:17:10 +0100229 # precreate interfaces; [bridge:<host_bridge_name>, VLAN used at Host, uuid of network camping in this bridge,
230 # speed in Gbit/s
231
tierno57f7bda2017-02-09 12:01:55 +0100232 self.config['dhcp_nets'] = []
233 self.config['bridge_nets'] = []
234 for bridge, vlan_speed in self.config["bridge_ifaces"].items():
mirabal580435e2017-03-01 16:17:10 +0100235 # skip 'development_bridge'
tierno57f7bda2017-02-09 12:01:55 +0100236 if self.config['mode'] == 'development' and self.config['development_bridge'] == bridge:
237 continue
238 self.config['bridge_nets'].append([bridge, vlan_speed[0], vlan_speed[1], None])
239
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']:
tierno686b3952017-03-10 13:57:24 +0100243 r, nets = self.db.get_table(SELECT=('uuid',), FROM='nets', WHERE={'provider': "bridge:" + brnet[0]})
tierno57f7bda2017-02-09 12:01:55 +0100244 if r > 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", ()):
tierno686b3952017-03-10 13:57:24 +0100255 r, nets = self.db.get_table(SELECT=('uuid',), FROM='nets', WHERE={'name': net})
tierno57f7bda2017-02-09 12:01:55 +0100256 if r > 0:
257 self.config['dhcp_nets'].append(nets[0]['uuid'])
258
mirabal580435e2017-03-01 16:17:10 +0100259 # OFC default
260 self._start_ofc_default_task()
tierno57f7bda2017-02-09 12:01:55 +0100261
mirabal580435e2017-03-01 16:17:10 +0100262 # OFC per tenant in DB
263 self._start_of_db_tasks()
tierno57f7bda2017-02-09 12:01:55 +0100264
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")
268 if dhcp_params:
269 thread = dt.dhcp_thread(dhcp_params=dhcp_params, test=host_test_mode, dhcp_nets=self.config["dhcp_nets"],
tiernoe0c28c12017-05-04 18:44:40 +0200270 db=self.config["db"], db_lock=self.config["db_lock"],
271 logger_name=self.logger_name + ".dhcp",
tierno43044b02017-04-06 18:58:24 +0200272 debug=self.config.get('log_level_of'))
tierno57f7bda2017-02-09 12:01:55 +0100273 thread.start()
274 self.config['dhcp_thread'] = thread
275
mirabal580435e2017-03-01 16:17:10 +0100276
tierno57f7bda2017-02-09 12:01:55 +0100277
mirabalb716ac52017-02-10 14:47:53 +0100278 # create ovs dhcp thread
279 result, content = self.db.get_table(FROM='nets')
280 if result < 0:
281 self.logger.error("http_get_ports Error %d %s", result, content)
282 raise ovimException(str(content), -result)
283
284 for net in content:
285 net_type = net['type']
tierno1d5c2292017-07-13 17:50:59 +0200286 if net['status'] != "INACTIVE" and (net_type == 'bridge_data' or net_type == 'bridge_man') and \
tiernoa6933042017-05-24 16:54:33 +0200287 net["provider"][:4] == 'OVS:' and net["enable_dhcp"] == "true":
288 try:
mirabale16a6362017-07-10 05:45:56 -0500289 config_routes = net.get('routes')
290 if config_routes:
291 routes = yaml.safe_load(config_routes)
292 else:
293 routes = None
294
295 config_dns = net.get('dns')
296 if config_dns:
297 dns = yaml.safe_load(config_dns)
298 else:
299 dns = None
300
301 links = net.get('links')
302 if links:
303 links = yaml.safe_load(net.get('links'))
mirabal0ec17ec2017-07-19 08:43:09 -0500304 if net.get('enable_dhcp'):
305 self.launch_dhcp_server(net.get('vlan'),
306 net.get('dhcp_first_ip'),
307 net.get('dhcp_last_ip'),
308 net.get('cidr'),
309 net.get('gateway_ip'),
310 dns,
311 routes)
mirabale16a6362017-07-10 05:45:56 -0500312 self.launch_link_bridge_to_ovs(net['vlan'], net.get('gateway_ip'), net.get('cidr'), links, routes)
tierno1d5c2292017-07-13 17:50:59 +0200313 if net["status"] == "ERROR":
314 self.db.update_rows("nets", UPDATE={"status": "ACTIVE", "last_error": None},
315 WHERE={"uuid": net["uuid"]})
tiernoa6933042017-05-24 16:54:33 +0200316 except Exception as e:
317 self.logger.error("Fail at launching dhcp server for net_id='%s' net_name='%s': %s",
318 net["uuid"], net["name"], str(e))
tierno1d5c2292017-07-13 17:50:59 +0200319 self.db.update_rows("nets", UPDATE={"status": "ERROR",
tiernoa6933042017-05-24 16:54:33 +0200320 "last_error": "Fail at launching dhcp server: " + str(e)},
tierno1d5c2292017-07-13 17:50:59 +0200321 WHERE={"uuid": net["uuid"]})
mirabalb716ac52017-02-10 14:47:53 +0100322
mirabal580435e2017-03-01 16:17:10 +0100323 def _start_of_db_tasks(self):
324 """
325 Start ofc task for existing ofcs in database
326 :param db_of:
327 :param db_lock:
328 :return:
329 """
330 ofcs = self.get_of_controllers()
331
332 for ofc in ofcs:
333 of_conn = self._load_of_module(ofc)
334 # create ofc thread per of controller
335 self._create_ofc_task(ofc['uuid'], ofc['dpid'], of_conn)
336
337 def _create_ofc_task(self, ofc_uuid, dpid, of_conn):
338 """
339 Create an ofc thread for handle each sdn controllers
340 :param ofc_uuid: sdn controller uuid
341 :param dpid: sdn controller dpid
342 :param of_conn: OF_conn module
343 :return:
344 """
345 if 'ofcs_thread' not in self.config and 'ofcs_thread_dpid' not in self.config:
346 ofcs_threads = {}
347 ofcs_thread_dpid = []
348 else:
349 ofcs_threads = self.config['ofcs_thread']
350 ofcs_thread_dpid = self.config['ofcs_thread_dpid']
351
352 if ofc_uuid not in ofcs_threads:
353 ofc_thread = self._create_ofc_thread(of_conn, ofc_uuid)
354 if ofc_uuid == "Default":
355 self.config['of_thread'] = ofc_thread
356
357 ofcs_threads[ofc_uuid] = ofc_thread
358 self.config['ofcs_thread'] = ofcs_threads
359
360 ofcs_thread_dpid.append({dpid: ofc_thread})
361 self.config['ofcs_thread_dpid'] = ofcs_thread_dpid
362
363 def _start_ofc_default_task(self):
364 """
365 Create default ofc thread
366 """
367 if 'of_controller' not in self.config \
368 and 'of_controller_ip' not in self.config \
369 and 'of_controller_port' not in self.config \
370 and 'of_controller_dpid' not in self.config:
371 return
372
373 # OF THREAD
374 db_config = {}
375 db_config['ip'] = self.config.get('of_controller_ip')
376 db_config['port'] = self.config.get('of_controller_port')
377 db_config['dpid'] = self.config.get('of_controller_dpid')
378 db_config['type'] = self.config.get('of_controller')
379 db_config['user'] = self.config.get('of_user')
380 db_config['password'] = self.config.get('of_password')
381
382 # create connector to the openflow controller
383 # load other parameters starting by of_ from config dict in a temporal dict
384
385 of_conn = self._load_of_module(db_config)
386 # create openflow thread
387 self._create_ofc_task("Default", db_config['dpid'], of_conn)
388
389 def _load_of_module(self, db_config):
390 """
391 import python module for each SDN controller supported
mirabalf9a1a8d2017-03-15 12:42:27 +0100392 :param db_config: SDN dn information
mirabal580435e2017-03-01 16:17:10 +0100393 :return: Module
394 """
395 if not db_config:
396 raise ovimException("No module found it", HTTP_Internal_Server_Error)
397
398 module_info = None
399
400 try:
401 if self.of_test_mode:
mirabal6c600652017-03-16 17:22:57 +0100402 return openflow_conn.OfTestConnector({"name": db_config['type'],
403 "dpid": db_config['dpid'],
404 "of_debug": self.config['log_level_of']})
mirabal580435e2017-03-01 16:17:10 +0100405 temp_dict = {}
406
407 if db_config:
408 temp_dict['of_ip'] = db_config['ip']
409 temp_dict['of_port'] = db_config['port']
410 temp_dict['of_dpid'] = db_config['dpid']
411 temp_dict['of_controller'] = db_config['type']
montesmorenoba1862b2017-04-06 10:07:44 +0000412 temp_dict['of_user'] = db_config.get('user')
413 temp_dict['of_password'] = db_config.get('password')
mirabal580435e2017-03-01 16:17:10 +0100414
415 temp_dict['of_debug'] = self.config['log_level_of']
416
417 if temp_dict['of_controller'] == 'opendaylight':
418 module = "ODL"
419 else:
420 module = temp_dict['of_controller']
421
422 if module not in ovim.of_module:
garciadeblas7fa5a652017-04-26 17:55:43 +0200423 try:
424 pkg = __import__("osm_openvim." + module)
425 of_conn_module = getattr(pkg, module)
426 ovim.of_module[module] = of_conn_module
427 self.logger.debug("Module load from {}".format("osm_openvim." + module))
428 except Exception as e:
tierno29d80242017-04-25 18:07:08 +0200429 self.logger.error("Cannot open openflow controller module of type '%s'", module)
430 raise ovimException("Cannot open openflow controller of type module '{}'"
431 "Revise it is installed".format(module),
432 HTTP_Internal_Server_Error)
mirabal580435e2017-03-01 16:17:10 +0100433 else:
434 of_conn_module = ovim.of_module[module]
tierno29d80242017-04-25 18:07:08 +0200435 return of_conn_module.OF_conn(temp_dict)
436 except Exception as e:
437 self.logger.error("Cannot open the Openflow controller '%s': %s", type(e).__name__, str(e))
438 raise ovimException("Cannot open the Openflow controller '{}': '{}'".format(type(e).__name__, str(e)),
mirabal580435e2017-03-01 16:17:10 +0100439 HTTP_Internal_Server_Error)
440
441 def _create_ofc_thread(self, of_conn, ofc_uuid="Default"):
442 """
443 Create and launch a of thread
444 :return: thread obj
445 """
446 # create openflow thread
447
montesmoreno92827552017-03-30 13:24:17 +0200448 #if 'of_controller_nets_with_same_vlan' in self.config:
449 # ofc_net_same_vlan = self.config['of_controller_nets_with_same_vlan']
450 #else:
451 # ofc_net_same_vlan = False
452 ofc_net_same_vlan = False
mirabal580435e2017-03-01 16:17:10 +0100453
tiernoe0c28c12017-05-04 18:44:40 +0200454 thread = oft.openflow_thread(ofc_uuid, of_conn, of_test=self.of_test_mode, db=self.config["db"],
455 db_lock=self.config["db_lock"],
456 pmp_with_same_vlan=ofc_net_same_vlan,
457 logger_name=self.logger_name + ".ofc." + ofc_uuid,
458 debug=self.config.get('log_level_of'))
mirabal580435e2017-03-01 16:17:10 +0100459 #r, c = thread.OF_connector.obtain_port_correspondence()
460 #if r < 0:
461 # raise ovimException("Cannot get openflow information %s", c)
462 thread.start()
463 return thread
464
tierno57f7bda2017-02-09 12:01:55 +0100465 def stop_service(self):
466 threads = self.config.get('host_threads', {})
467 if 'of_thread' in self.config:
468 threads['of'] = (self.config['of_thread'])
mirabal580435e2017-03-01 16:17:10 +0100469 if 'ofcs_thread' in self.config:
470 ofcs_thread = self.config['ofcs_thread']
471 for ofc in ofcs_thread:
472 threads[ofc] = ofcs_thread[ofc]
473
tierno57f7bda2017-02-09 12:01:55 +0100474 if 'dhcp_thread' in self.config:
475 threads['dhcp'] = (self.config['dhcp_thread'])
476
tiernoa6933042017-05-24 16:54:33 +0200477 for thread_id, thread in threads.items():
478 if thread_id == 'openvim_controller':
479 continue
tierno57f7bda2017-02-09 12:01:55 +0100480 thread.insert_task("exit")
tiernoa6933042017-05-24 16:54:33 +0200481 for thread_id, thread in threads.items():
482 if thread_id == 'openvim_controller':
483 continue
tierno57f7bda2017-02-09 12:01:55 +0100484 thread.join()
tierno57f7bda2017-02-09 12:01:55 +0100485
mirabal9e194592017-02-17 11:03:25 +0100486 def get_networks(self, columns=None, db_filter={}, limit=None):
mirabal65ba8f82017-02-15 12:36:33 +0100487 """
488 Retreive networks available
mirabale9f6f1a2017-02-16 17:57:35 +0100489 :param columns: List with select query parameters
mirabal9e194592017-02-17 11:03:25 +0100490 :param db_filter: List with where query parameters
mirabale9f6f1a2017-02-16 17:57:35 +0100491 :param limit: Query limit result
mirabal65ba8f82017-02-15 12:36:33 +0100492 :return:
493 """
mirabal9e194592017-02-17 11:03:25 +0100494 result, content = self.db.get_table(SELECT=columns, FROM='nets', WHERE=db_filter, LIMIT=limit)
mirabal65ba8f82017-02-15 12:36:33 +0100495
496 if result < 0:
497 raise ovimException(str(content), -result)
498
499 convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
500
501 return content
502
mirabal9e194592017-02-17 11:03:25 +0100503 def show_network(self, network_id, db_filter={}):
mirabal65ba8f82017-02-15 12:36:33 +0100504 """
mirabale9f6f1a2017-02-16 17:57:35 +0100505 Get network from DB by id
506 :param network_id: net Id
mirabal9e194592017-02-17 11:03:25 +0100507 :param db_filter: List with where query parameters
mirabal65ba8f82017-02-15 12:36:33 +0100508 :return:
509 """
510 # obtain data
mirabale9f6f1a2017-02-16 17:57:35 +0100511 if not network_id:
512 raise ovimException("Not network id was not found")
mirabal9e194592017-02-17 11:03:25 +0100513 db_filter['uuid'] = network_id
mirabal65ba8f82017-02-15 12:36:33 +0100514
mirabal9e194592017-02-17 11:03:25 +0100515 result, content = self.db.get_table(FROM='nets', WHERE=db_filter, LIMIT=100)
mirabal65ba8f82017-02-15 12:36:33 +0100516
517 if result < 0:
518 raise ovimException(str(content), -result)
519 elif result == 0:
mirabale9f6f1a2017-02-16 17:57:35 +0100520 raise ovimException("show_network network '%s' not found" % network_id, -result)
mirabal65ba8f82017-02-15 12:36:33 +0100521 else:
522 convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
mirabale9f6f1a2017-02-16 17:57:35 +0100523 # get ports from DB
mirabal65ba8f82017-02-15 12:36:33 +0100524 result, ports = self.db.get_table(FROM='ports', SELECT=('uuid as port_id',),
mirabale9f6f1a2017-02-16 17:57:35 +0100525 WHERE={'net_id': network_id}, LIMIT=100)
mirabal65ba8f82017-02-15 12:36:33 +0100526 if len(ports) > 0:
527 content[0]['ports'] = ports
mirabal65ba8f82017-02-15 12:36:33 +0100528
mirabale9f6f1a2017-02-16 17:57:35 +0100529 convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp'))
530 return content[0]
531
532 def new_network(self, network):
mirabal65ba8f82017-02-15 12:36:33 +0100533 """
mirabale9f6f1a2017-02-16 17:57:35 +0100534 Create a net in DB
mirabal65ba8f82017-02-15 12:36:33 +0100535 :return:
536 """
537 tenant_id = network.get('tenant_id')
538
539 if tenant_id:
540 result, _ = self.db.get_table(FROM='tenants', SELECT=('uuid',), WHERE={'uuid': tenant_id, "enabled": True})
541 if result <= 0:
542 raise ovimException("set_network error, no tenant founded", -result)
543
544 bridge_net = None
545 # check valid params
546 net_provider = network.get('provider')
547 net_type = network.get('type')
mirabal65ba8f82017-02-15 12:36:33 +0100548 net_vlan = network.get("vlan")
549 net_bind_net = network.get("bind_net")
550 net_bind_type = network.get("bind_type")
tiernoa290d8f2017-05-03 17:42:52 +0200551 net_region = network.get("region")
mirabal65ba8f82017-02-15 12:36:33 +0100552 name = network["name"]
553
554 # check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
555 vlan_index = name.rfind(":")
556 if not net_bind_net and not net_bind_type and vlan_index > 1:
557 try:
558 vlan_tag = int(name[vlan_index + 1:])
559 if not vlan_tag and vlan_tag < 4096:
560 net_bind_net = name[:vlan_index]
561 net_bind_type = "vlan:" + name[vlan_index + 1:]
562 except:
563 pass
564
565 if net_bind_net:
566 # look for a valid net
567 if self._check_valid_uuid(net_bind_net):
568 net_bind_key = "uuid"
569 else:
570 net_bind_key = "name"
571 result, content = self.db.get_table(FROM='nets', WHERE={net_bind_key: net_bind_net})
572 if result < 0:
573 raise ovimException(' getting nets from db ' + content, HTTP_Internal_Server_Error)
574 elif result == 0:
575 raise ovimException(" bind_net %s '%s'not found" % (net_bind_key, net_bind_net), HTTP_Bad_Request)
576 elif result > 1:
577 raise ovimException(" more than one bind_net %s '%s' found, use uuid" % (net_bind_key, net_bind_net), HTTP_Bad_Request)
578 network["bind_net"] = content[0]["uuid"]
579
580 if net_bind_type:
581 if net_bind_type[0:5] != "vlan:":
582 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request)
583 if int(net_bind_type[5:]) > 4095 or int(net_bind_type[5:]) <= 0:
584 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
585 HTTP_Bad_Request)
586 network["bind_type"] = net_bind_type
587
588 if net_provider:
589 if net_provider[:9] == "openflow:":
590 if net_type:
591 if net_type != "ptp" and net_type != "data":
592 raise ovimException(" only 'ptp' or 'data' net types can be bound to 'openflow'",
593 HTTP_Bad_Request)
594 else:
595 net_type = 'data'
596 else:
597 if net_type:
598 if net_type != "bridge_man" and net_type != "bridge_data":
599 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound "
600 "to 'bridge', 'macvtap' or 'default", HTTP_Bad_Request)
601 else:
602 net_type = 'bridge_man'
603
604 if not net_type:
605 net_type = 'bridge_man'
606
607 if net_provider:
608 if net_provider[:7] == 'bridge:':
609 # check it is one of the pre-provisioned bridges
610 bridge_net_name = net_provider[7:]
611 for brnet in self.config['bridge_nets']:
612 if brnet[0] == bridge_net_name: # free
tierno11c45e72017-05-17 12:04:05 +0000613 if brnet[3]:
mirabal65ba8f82017-02-15 12:36:33 +0100614 raise ovimException("invalid 'provider:physical', "
615 "bridge '%s' is already used" % bridge_net_name, HTTP_Conflict)
616 bridge_net = brnet
617 net_vlan = brnet[1]
618 break
mirabale9f6f1a2017-02-16 17:57:35 +0100619 # if bridge_net==None:
620 # bottle.abort(HTTP_Bad_Request, "invalid 'provider:physical', bridge '%s' is not one of the
621 # provisioned 'bridge_ifaces' in the configuration file" % bridge_net_name)
622 # return
623
mirabal65ba8f82017-02-15 12:36:33 +0100624 elif self.config['network_type'] == 'bridge' and (net_type == 'bridge_data' or net_type == 'bridge_man'):
625 # look for a free precreated nets
626 for brnet in self.config['bridge_nets']:
627 if not brnet[3]: # free
628 if not bridge_net:
629 if net_type == 'bridge_man': # look for the smaller speed
630 if brnet[2] < bridge_net[2]:
631 bridge_net = brnet
632 else: # look for the larger speed
633 if brnet[2] > bridge_net[2]:
634 bridge_net = brnet
635 else:
636 bridge_net = brnet
637 net_vlan = brnet[1]
638 if not bridge_net:
639 raise ovimException("Max limits of bridge networks reached. Future versions of VIM "
640 "will overcome this limit", HTTP_Bad_Request)
641 else:
mirabale9f6f1a2017-02-16 17:57:35 +0100642 self.logger.debug("using net " + bridge_net)
mirabal65ba8f82017-02-15 12:36:33 +0100643 net_provider = "bridge:" + bridge_net[0]
644 net_vlan = bridge_net[1]
645 elif net_type == 'bridge_data' or net_type == 'bridge_man' and self.config['network_type'] == 'ovs':
646 net_provider = 'OVS'
tiernoa290d8f2017-05-03 17:42:52 +0200647 if not net_region:
648 if net_type == "data" or net_type == "ptp":
649 net_region = "__DATA__"
650 elif net_provider == "OVS":
651 net_region = "__OVS__"
mirabal65ba8f82017-02-15 12:36:33 +0100652 if not net_vlan and (net_type == "data" or net_type == "ptp" or net_provider == "OVS"):
tiernoa290d8f2017-05-03 17:42:52 +0200653 net_vlan = self.db.get_free_net_vlan(net_region)
mirabal65ba8f82017-02-15 12:36:33 +0100654 if net_vlan < 0:
655 raise ovimException("Error getting an available vlan", HTTP_Internal_Server_Error)
656 if net_provider == 'OVS':
657 net_provider = 'OVS' + ":" + str(net_vlan)
658
659 network['provider'] = net_provider
660 network['type'] = net_type
661 network['vlan'] = net_vlan
tiernoa290d8f2017-05-03 17:42:52 +0200662 network['region'] = net_region
mirabal65ba8f82017-02-15 12:36:33 +0100663 dhcp_integrity = True
664 if 'enable_dhcp' in network and network['enable_dhcp']:
665 dhcp_integrity = self._check_dhcp_data_integrity(network)
mirabal6878e3f2017-06-05 09:19:26 -0500666
667 if network.get('links'):
668 network['links'] = yaml.safe_dump(network['links'], default_flow_style=True, width=256)
669 if network.get('dns'):
670 network['dns'] = yaml.safe_dump(network['dns'], default_flow_style=True, width=256)
671 if network.get('routes'):
672 network['routes'] = yaml.safe_dump(network['routes'], default_flow_style=True, width=256)
mirabal65ba8f82017-02-15 12:36:33 +0100673
674 result, content = self.db.new_row('nets', network, True, True)
mirabal65ba8f82017-02-15 12:36:33 +0100675 if result >= 0 and dhcp_integrity:
676 if bridge_net:
677 bridge_net[3] = content
mirabal0ec17ec2017-07-19 08:43:09 -0500678 if self.config.get("dhcp_server") and self.config['network_type'] == 'bridge': # \
mirabal65ba8f82017-02-15 12:36:33 +0100679 if network["name"] in self.config["dhcp_server"].get("nets", ()):
680 self.config["dhcp_nets"].append(content)
mirabale9f6f1a2017-02-16 17:57:35 +0100681 self.logger.debug("dhcp_server: add new net", content)
tierno11c45e72017-05-17 12:04:05 +0000682 elif bridge_net and bridge_net[0] in self.config["dhcp_server"].get("bridge_ifaces", ()):
mirabal65ba8f82017-02-15 12:36:33 +0100683 self.config["dhcp_nets"].append(content)
mirabale9f6f1a2017-02-16 17:57:35 +0100684 self.logger.debug("dhcp_server: add new net", content, content)
mirabal65ba8f82017-02-15 12:36:33 +0100685 return content
686 else:
mirabal65ba8f82017-02-15 12:36:33 +0100687 raise ovimException("Error posting network", HTTP_Internal_Server_Error)
mirabale9f6f1a2017-02-16 17:57:35 +0100688# TODO kei change update->edit
mirabal65ba8f82017-02-15 12:36:33 +0100689
mirabale9f6f1a2017-02-16 17:57:35 +0100690 def edit_network(self, network_id, network):
mirabal65ba8f82017-02-15 12:36:33 +0100691 """
mirabale9f6f1a2017-02-16 17:57:35 +0100692 Update entwork data byt id
mirabal65ba8f82017-02-15 12:36:33 +0100693 :return:
694 """
mirabale9f6f1a2017-02-16 17:57:35 +0100695 # Look for the previous data
696 where_ = {'uuid': network_id}
697 result, network_old = self.db.get_table(FROM='nets', WHERE=where_)
698 if result < 0:
699 raise ovimException("Error updating network %s" % network_old, HTTP_Internal_Server_Error)
700 elif result == 0:
701 raise ovimException('network %s not found' % network_id, HTTP_Not_Found)
702 # get ports
703 nbports, content = self.db.get_table(FROM='ports', SELECT=('uuid as port_id',),
704 WHERE={'net_id': network_id}, LIMIT=100)
705 if result < 0:
706 raise ovimException("http_put_network_id error %d %s" % (result, network_old), HTTP_Internal_Server_Error)
707 if nbports > 0:
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)
mirabal65ba8f82017-02-15 12:36:33 +0100714
mirabale9f6f1a2017-02-16 17:57:35 +0100715 # check valid params
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")
720 if net_bind_net:
721 # look for a valid net
722 if self._check_valid_uuid(net_bind_net):
723 net_bind_key = "uuid"
724 else:
725 net_bind_key = "name"
726 result, content = self.db.get_table(FROM='nets', WHERE={net_bind_key: net_bind_net})
727 if result < 0:
728 raise ovimException('Getting nets from db ' + content, HTTP_Internal_Server_Error)
729 elif result == 0:
730 raise ovimException("bind_net %s '%s'not found" % (net_bind_key, net_bind_net), HTTP_Bad_Request)
731 elif result > 1:
732 raise ovimException("More than one bind_net %s '%s' found, use uuid" % (net_bind_key, net_bind_net),
733 HTTP_Bad_Request)
734 network["bind_net"] = content[0]["uuid"]
735 if net_bind_type:
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",
740 HTTP_Bad_Request)
741 if net_provider:
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)
745 else:
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)
mirabal65ba8f82017-02-15 12:36:33 +0100749
mirabale9f6f1a2017-02-16 17:57:35 +0100750 # insert in data base
751 result, content = self.db.update_rows('nets', network, WHERE={'uuid': network_id}, log=True)
752 if result >= 0:
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']:
755 if result > 0:
mirabal7bbf50e2017-03-13 15:15:18 +0100756
757 try:
tiernoaa941462017-03-29 15:10:28 +0200758 if nbports:
759 self.net_update_ofc_thread(network_id)
mirabal7bbf50e2017-03-13 15:15:18 +0100760 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)
766
mirabale9f6f1a2017-02-16 17:57:35 +0100767 if self.config.get("dhcp_server"):
768 if network_id in self.config["dhcp_nets"]:
769 self.config["dhcp_nets"].remove(network_id)
mirabal7bbf50e2017-03-13 15:15:18 +0100770 if network.get("name", network_old[0]["name"]) in self.config["dhcp_server"].get("nets", ()):
mirabale9f6f1a2017-02-16 17:57:35 +0100771 self.config["dhcp_nets"].append(network_id)
772 else:
mirabal7bbf50e2017-03-13 15:15:18 +0100773 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(
mirabale9f6f1a2017-02-16 17:57:35 +0100775 "bridge_ifaces", ()):
776 self.config["dhcp_nets"].append(network_id)
777 return network_id
mirabal65ba8f82017-02-15 12:36:33 +0100778 else:
mirabale9f6f1a2017-02-16 17:57:35 +0100779 raise ovimException(content, -result)
mirabal65ba8f82017-02-15 12:36:33 +0100780
mirabale9f6f1a2017-02-16 17:57:35 +0100781 def delete_network(self, network_id):
mirabal9e194592017-02-17 11:03:25 +0100782 """
783 Delete network by network id
784 :param network_id: network id
785 :return:
786 """
mirabal0ec17ec2017-07-19 08:43:09 -0500787 net_data = self.show_network(network_id)
mirabale9f6f1a2017-02-16 17:57:35 +0100788
789 # delete from the data base
790 result, content = self.db.delete_row('nets', network_id)
791
792 if result == 0:
793 raise ovimException("Network %s not found " % network_id, HTTP_Not_Found)
794 elif result > 0:
795 for brnet in self.config['bridge_nets']:
796 if brnet[3] == network_id:
797 brnet[3] = None
798 break
799 if self.config.get("dhcp_server") and network_id in self.config["dhcp_nets"]:
800 self.config["dhcp_nets"].remove(network_id)
mirabal0ec17ec2017-07-19 08:43:09 -0500801
802 if net_data.get('enable_dhcp'):
803 dhcp_path = self.config['ovs_controller_file_path']
804 dhcp_controller = self.get_dhcp_controller()
805 dhcp_controller.delete_dhcp_server(net_data['vlan'], network_id, dhcp_path)
806 dhcp_controller.delete_dhcp_port(net_data['vlan'], network_id, dhcp_path)
807 links = yaml.load(net_data.get('links'))
808 if links:
809 links = yaml.load(net_data.get('links'))
810 self.delete_link_bridge_to_ovs(net_data['vlan'], links)
811
812 return content
mirabale9f6f1a2017-02-16 17:57:35 +0100813 else:
tierno11c45e72017-05-17 12:04:05 +0000814 raise ovimException("Error deleting network '{}': {}".format(network_id, content), -result)
mirabal65ba8f82017-02-15 12:36:33 +0100815
816 def get_openflow_rules(self, network_id=None):
817 """
818 Get openflow id from DB
819 :param network_id: Network id, if none all networks will be retrieved
820 :return: Return a list with Openflow rules per net
821 """
822 # ignore input data
823 if not network_id:
824 where_ = {}
825 else:
826 where_ = {"net_id": network_id}
mirabal65ba8f82017-02-15 12:36:33 +0100827 result, content = self.db.get_table(
mirabalf9a1a8d2017-03-15 12:42:27 +0100828 SELECT=("name", "net_id", "ofc_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
mirabal65ba8f82017-02-15 12:36:33 +0100829 WHERE=where_, FROM='of_flows')
830
831 if result < 0:
832 raise ovimException(str(content), -result)
833 return content
834
mirabale9f6f1a2017-02-16 17:57:35 +0100835 def edit_openflow_rules(self, network_id=None):
mirabal65ba8f82017-02-15 12:36:33 +0100836
837 """
838 To make actions over the net. The action is to reinstall the openflow rules
839 network_id can be 'all'
840 :param network_id: Network id, if none all networks will be retrieved
841 :return : Number of nets updated
842 """
843
844 # ignore input data
845 if not network_id:
846 where_ = {}
847 else:
848 where_ = {"uuid": network_id}
849 result, content = self.db.get_table(SELECT=("uuid", "type"), WHERE=where_, FROM='nets')
850
851 if result < 0:
852 raise ovimException(str(content), -result)
853
854 for net in content:
855 if net["type"] != "ptp" and net["type"] != "data":
856 result -= 1
857 continue
mirabal7bbf50e2017-03-13 15:15:18 +0100858
859 try:
860 self.net_update_ofc_thread(net['uuid'])
861 except ovimException as e:
862 raise ovimException("Error updating network'{}' {}".format(net['uuid'], str(e)),
863 HTTP_Internal_Server_Error)
864 except Exception as e:
865 raise ovimException("Error updating network '{}' {}".format(net['uuid'], str(e)),
866 HTTP_Internal_Server_Error)
867
mirabal65ba8f82017-02-15 12:36:33 +0100868 return result
869
mirabalf9a1a8d2017-03-15 12:42:27 +0100870 def delete_openflow_rules(self, ofc_id=None):
mirabal65ba8f82017-02-15 12:36:33 +0100871 """
872 To make actions over the net. The action is to delete ALL openflow rules
873 :return: return operation result
874 """
mirabalf9a1a8d2017-03-15 12:42:27 +0100875
876 if not ofc_id:
877 if 'Default' in self.config['ofcs_thread']:
878 r, c = self.config['ofcs_thread']['Default'].insert_task("clear-all")
879 else:
880 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found)
881
882 elif ofc_id in self.config['ofcs_thread']:
883 r, c = self.config['ofcs_thread'][ofc_id].insert_task("clear-all")
884
885 # ignore input data
886 if r < 0:
887 raise ovimException(str(c), -r)
888 else:
889 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id), HTTP_Not_Found)
mirabal65ba8f82017-02-15 12:36:33 +0100890 return r
891
mirabalf9a1a8d2017-03-15 12:42:27 +0100892 def get_openflow_ports(self, ofc_id=None):
mirabal65ba8f82017-02-15 12:36:33 +0100893 """
894 Obtain switch ports names of openflow controller
895 :return: Return flow ports in DB
896 """
mirabalf9a1a8d2017-03-15 12:42:27 +0100897 if not ofc_id:
898 if 'Default' in self.config['ofcs_thread']:
899 conn = self.config['ofcs_thread']['Default'].OF_connector
900 else:
901 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found)
902
tierno11c45e72017-05-17 12:04:05 +0000903 elif ofc_id in self.config['ofcs_thread']:
mirabalf9a1a8d2017-03-15 12:42:27 +0100904 conn = self.config['ofcs_thread'][ofc_id].OF_connector
905 else:
906 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id), HTTP_Not_Found)
907 return conn.pp2ofi
tierno57f7bda2017-02-09 12:01:55 +0100908
909 def get_ports(self, columns=None, filter={}, limit=None):
910 # result, content = my.db.get_ports(where_)
911 result, content = self.db.get_table(SELECT=columns, WHERE=filter, FROM='ports', LIMIT=limit)
912 if result < 0:
913 self.logger.error("http_get_ports Error %d %s", result, content)
914 raise ovimException(str(content), -result)
915 else:
916 convert_boolean(content, ('admin_state_up',))
917 return content
918
tierno57f7bda2017-02-09 12:01:55 +0100919 def new_port(self, port_data):
920 port_data['type'] = 'external'
921 if port_data.get('net_id'):
922 # check that new net has the correct type
923 result, new_net = self.db.check_target_net(port_data['net_id'], None, 'external')
924 if result < 0:
925 raise ovimException(str(new_net), -result)
926 # insert in data base
927 result, uuid = self.db.new_row('ports', port_data, True, True)
928 if result > 0:
929 if 'net_id' in port_data:
mirabal7bbf50e2017-03-13 15:15:18 +0100930 try:
931 self.net_update_ofc_thread(port_data['net_id'])
932 except ovimException as e:
933 raise ovimException("Cannot insert a task for updating network '{}' {}"
934 .format(port_data['net_id'], str(e)), HTTP_Internal_Server_Error)
935 except Exception as e:
936 raise ovimException("Cannot insert a task for updating network '{}' {}"
937 .format(port_data['net_id'], str(e)), HTTP_Internal_Server_Error)
938
tierno57f7bda2017-02-09 12:01:55 +0100939 return uuid
940 else:
941 raise ovimException(str(uuid), -result)
942
mirabal37829452017-03-09 14:41:21 +0100943 def new_external_port(self, port_data):
944 """
945 Create new external port and check port mapping correspondence
946 :param port_data: port_data = {
947 'region': 'datacenter region',
948 'compute_node': 'compute node id',
949 'pci': 'pci port address',
950 'vlan': 'net vlan',
951 'net_id': 'net id',
952 'tenant_id': 'tenant id',
953 'mac': 'switch mac',
954 'name': 'port name'
955 'ip_address': 'ip address - optional'}
956 :return:
957 """
958
959 port_data['type'] = 'external'
960
961 if port_data.get('net_id'):
962 # check that new net has the correct type
963 result, new_net = self.db.check_target_net(port_data['net_id'], None, 'external')
964 if result < 0:
965 raise ovimException(str(new_net), -result)
966 # insert in data base
967 db_filter = {}
968
969 if port_data.get('region'):
970 db_filter['region'] = port_data['region']
971 if port_data.get('pci'):
972 db_filter['pci'] = port_data['pci']
973 if port_data.get('compute_node'):
974 db_filter['compute_node'] = port_data['compute_node']
975
976 columns = ['ofc_id', 'switch_dpid', 'switch_port', 'switch_mac', 'pci']
977 port_mapping_data = self.get_of_port_mappings(columns, db_filter)
978
979 if not len(port_mapping_data):
tierno16007502017-03-27 16:48:32 +0200980 raise ovimException("No port mapping founded for '{}'".format(str(db_filter)),
mirabal37829452017-03-09 14:41:21 +0100981 HTTP_Not_Found)
982 elif len(port_mapping_data) > 1:
983 raise ovimException("Wrong port data was given, please check pci, region & compute id data",
984 HTTP_Conflict)
985
986 port_data['ofc_id'] = port_mapping_data[0]['ofc_id']
987 port_data['switch_dpid'] = port_mapping_data[0]['switch_dpid']
988 port_data['switch_port'] = port_mapping_data[0]['switch_port']
989 port_data['switch_mac'] = port_mapping_data[0]['switch_mac']
990
991 # remove from compute_node, region and pci of_port_data to adapt to 'ports' structure
montesmoreno275b1992017-03-28 15:45:02 +0200992 if 'region' in port_data:
993 del port_data['region']
994 if 'pci' in port_data:
995 del port_data['pci']
996 if 'compute_node' in port_data:
997 del port_data['compute_node']
mirabal37829452017-03-09 14:41:21 +0100998
999 result, uuid = self.db.new_row('ports', port_data, True, True)
1000 if result > 0:
mirabal7bbf50e2017-03-13 15:15:18 +01001001 try:
1002 self.net_update_ofc_thread(port_data['net_id'], port_data['ofc_id'])
1003 except ovimException as e:
1004 raise ovimException("Cannot insert a task for updating network '{}' {}".
1005 format(port_data['net_id'], str(e)), HTTP_Internal_Server_Error)
1006 except Exception as e:
1007 raise ovimException("Cannot insert a task for updating network '{}' {}"
1008 .format(port_data['net_id'], e), HTTP_Internal_Server_Error)
mirabal37829452017-03-09 14:41:21 +01001009 return uuid
1010 else:
1011 raise ovimException(str(uuid), -result)
1012
tiernoaa941462017-03-29 15:10:28 +02001013 def net_update_ofc_thread(self, net_id, ofc_id=None, switch_dpid=None):
mirabal7bbf50e2017-03-13 15:15:18 +01001014 """
1015 Insert a update net task by net id or ofc_id for each ofc thread
1016 :param net_id: network id
1017 :param ofc_id: openflow controller id
tiernoaa941462017-03-29 15:10:28 +02001018 :param switch_dpid: switch dpid
mirabal7bbf50e2017-03-13 15:15:18 +01001019 :return:
1020 """
1021 if not net_id:
1022 raise ovimException("No net_id received", HTTP_Internal_Server_Error)
1023
mirabal7bbf50e2017-03-13 15:15:18 +01001024 r = -1
1025 c = 'No valid ofc_id or switch_dpid received'
1026
1027 if not ofc_id:
1028 ports = self.get_ports(filter={"net_id": net_id})
1029 for port in ports:
1030 port_ofc_id = port.get('ofc_id', None)
1031 if port_ofc_id:
1032 ofc_id = port['ofc_id']
1033 switch_dpid = port['switch_dpid']
1034 break
tiernoaa941462017-03-29 15:10:28 +02001035 #TODO if not ofc_id: look at database table ofcs
1036
mirabal7bbf50e2017-03-13 15:15:18 +01001037
1038 # If no ofc_id found it, default ofc_id is used.
1039 if not ofc_id and not switch_dpid:
1040 ofc_id = "Default"
1041
1042 if ofc_id and ofc_id in self.config['ofcs_thread']:
1043 r, c = self.config['ofcs_thread'][ofc_id].insert_task("update-net", net_id)
1044 elif switch_dpid:
1045
1046 ofcs_dpid_list = self.config['ofcs_thread_dpid']
1047 for ofc_t in ofcs_dpid_list:
1048 if switch_dpid in ofc_t:
1049 r, c = ofc_t[switch_dpid].insert_task("update-net", net_id)
1050
1051 if r < 0:
tierno82232582017-03-15 18:09:16 +01001052 message = "Cannot insert a task for updating network '{}', {}".format(net_id, c)
mirabal7bbf50e2017-03-13 15:15:18 +01001053 self.logger.error(message)
1054 raise ovimException(message, HTTP_Internal_Server_Error)
1055
tierno57f7bda2017-02-09 12:01:55 +01001056 def delete_port(self, port_id):
1057 # Look for the previous port data
1058 result, ports = self.db.get_table(WHERE={'uuid': port_id, "type": "external"}, FROM='ports')
1059 if result < 0:
1060 raise ovimException("Cannot get port info from database: {}".format(ports), http_code=-result)
1061 # delete from the data base
1062 result, content = self.db.delete_row('ports', port_id)
1063 if result == 0:
1064 raise ovimException("External port '{}' not found".format(port_id), http_code=HTTP_Not_Found)
1065 elif result < 0:
1066 raise ovimException("Cannot delete port from database: {}".format(content), http_code=-result)
1067 # update network
1068 network = ports[0].get('net_id', None)
1069 if network:
1070 # change of net.
mirabal7bbf50e2017-03-13 15:15:18 +01001071
1072 try:
tiernoaa941462017-03-29 15:10:28 +02001073 self.net_update_ofc_thread(network, ofc_id=ports[0]["ofc_id"], switch_dpid=ports[0]["switch_dpid"])
mirabal7bbf50e2017-03-13 15:15:18 +01001074 except ovimException as e:
1075 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network, str(e)),
1076 HTTP_Internal_Server_Error)
1077 except Exception as e:
1078 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network, str(e)),
1079 HTTP_Internal_Server_Error)
1080
tierno57f7bda2017-02-09 12:01:55 +01001081 return content
1082
tierno57f7bda2017-02-09 12:01:55 +01001083 def edit_port(self, port_id, port_data, admin=True):
1084 # Look for the previous port data
1085 result, content = self.db.get_table(FROM="ports", WHERE={'uuid': port_id})
1086 if result < 0:
1087 raise ovimException("Cannot get port info from database: {}".format(content), http_code=-result)
1088 elif result == 0:
1089 raise ovimException("Port '{}' not found".format(port_id), http_code=HTTP_Not_Found)
1090 port = content[0]
1091 nets = []
1092 host_id = None
1093 result = 1
1094 if 'net_id' in port_data:
1095 # change of net.
1096 old_net = port.get('net_id', None)
1097 new_net = port_data['net_id']
1098 if old_net != new_net:
1099
1100 if new_net:
1101 nets.append(new_net) # put first the new net, so that new openflow rules are created before removing the old ones
1102 if old_net:
1103 nets.append(old_net)
1104 if port['type'] == 'instance:bridge' or port['type'] == 'instance:ovs':
1105 raise ovimException("bridge interfaces cannot be attached to a different net", http_code=HTTP_Forbidden)
1106 elif port['type'] == 'external' and not admin:
1107 raise ovimException("Needed admin privileges",http_code=HTTP_Unauthorized)
1108 if new_net:
1109 # check that new net has the correct type
1110 result, new_net_dict = self.db.check_target_net(new_net, None, port['type'])
1111 if result < 0:
1112 raise ovimException("Error {}".format(new_net_dict), http_code=HTTP_Conflict)
1113 # change VLAN for SR-IOV ports
1114 if result >= 0 and port["type"] == "instance:data" and port["model"] == "VF": # TODO consider also VFnotShared
1115 if new_net:
1116 port_data["vlan"] = None
1117 else:
1118 port_data["vlan"] = new_net_dict["vlan"]
1119 # get host where this VM is allocated
1120 result, content = self.db.get_table(FROM="instances", WHERE={"uuid": port["instance_id"]})
1121 if result > 0:
1122 host_id = content[0]["host_id"]
1123
1124 # insert in data base
1125 if result >= 0:
1126 result, content = self.db.update_rows('ports', port_data, WHERE={'uuid': port_id}, log=False)
tiernoaa941462017-03-29 15:10:28 +02001127 port.update(port_data)
tierno57f7bda2017-02-09 12:01:55 +01001128
1129 # Insert task to complete actions
1130 if result > 0:
1131 for net_id in nets:
mirabal7bbf50e2017-03-13 15:15:18 +01001132 try:
tiernoaa941462017-03-29 15:10:28 +02001133 self.net_update_ofc_thread(net_id, port["ofc_id"], switch_dpid=port["switch_dpid"])
mirabal7bbf50e2017-03-13 15:15:18 +01001134 except ovimException as e:
1135 raise ovimException("Error updating network'{}' {}".format(net_id, str(e)),
1136 HTTP_Internal_Server_Error)
1137 except Exception as e:
1138 raise ovimException("Error updating network '{}' {}".format(net_id, str(e)),
1139 HTTP_Internal_Server_Error)
1140
tierno57f7bda2017-02-09 12:01:55 +01001141 if host_id:
1142 r, v = self.config['host_threads'][host_id].insert_task("edit-iface", port_id, old_net, new_net)
1143 if r < 0:
1144 self.logger.error("Error updating network '{}' {}".format(r,v))
1145 # TODO Do something if fails
1146 if result >= 0:
1147 return port_id
1148 else:
1149 raise ovimException("Error {}".format(content), http_code=-result)
mirabalb716ac52017-02-10 14:47:53 +01001150
mirabal9e194592017-02-17 11:03:25 +01001151 def new_of_controller(self, ofc_data):
1152 """
1153 Create a new openflow controller into DB
1154 :param ofc_data: Dict openflow controller data
1155 :return: openflow controller dpid
1156 """
1157
mirabal580435e2017-03-01 16:17:10 +01001158 result, ofc_uuid = self.db.new_row('ofcs', ofc_data, True, True)
mirabal9e194592017-02-17 11:03:25 +01001159 if result < 0:
mirabal580435e2017-03-01 16:17:10 +01001160 raise ovimException("New ofc Error %s" % ofc_uuid, HTTP_Internal_Server_Error)
1161
1162 ofc_data['uuid'] = ofc_uuid
1163 of_conn = self._load_of_module(ofc_data)
1164 self._create_ofc_task(ofc_uuid, ofc_data['dpid'], of_conn)
1165
1166 return ofc_uuid
mirabal9e194592017-02-17 11:03:25 +01001167
1168 def edit_of_controller(self, of_id, ofc_data):
1169 """
1170 Edit an openflow controller entry from DB
1171 :return:
1172 """
1173 if not ofc_data:
1174 raise ovimException("No data received during uptade OF contorller", http_code=HTTP_Internal_Server_Error)
1175
1176 old_of_controller = self.show_of_controller(of_id)
1177
1178 if old_of_controller:
1179 result, content = self.db.update_rows('ofcs', ofc_data, WHERE={'uuid': of_id}, log=False)
1180 if result >= 0:
1181 return ofc_data
1182 else:
1183 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id),
1184 http_code=-result)
1185 else:
1186 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id),
1187 http_code=HTTP_Internal_Server_Error)
1188
1189 def delete_of_controller(self, of_id):
1190 """
1191 Delete an openflow controller from DB.
1192 :param of_id: openflow controller dpid
1193 :return:
1194 """
1195
mirabal580435e2017-03-01 16:17:10 +01001196 ofc = self.show_of_controller(of_id)
1197
Pablo Montes Moreno5b6f7492017-03-02 16:18:36 +01001198 result, content = self.db.delete_row("ofcs", of_id)
mirabal9e194592017-02-17 11:03:25 +01001199 if result < 0:
1200 raise ovimException("Cannot delete ofc from database: {}".format(content), http_code=-result)
1201 elif result == 0:
1202 raise ovimException("ofc {} not found ".format(content), http_code=HTTP_Not_Found)
mirabal580435e2017-03-01 16:17:10 +01001203
1204 ofc_thread = self.config['ofcs_thread'][of_id]
1205 del self.config['ofcs_thread'][of_id]
1206 for ofc_th in self.config['ofcs_thread_dpid']:
1207 if ofc['dpid'] in ofc_th:
1208 self.config['ofcs_thread_dpid'].remove(ofc_th)
1209
1210 ofc_thread.insert_task("exit")
1211 #ofc_thread.join()
1212
mirabal9e194592017-02-17 11:03:25 +01001213 return content
1214
1215 def show_of_controller(self, uuid):
1216 """
1217 Show an openflow controller by dpid from DB.
1218 :param db_filter: List with where query parameters
1219 :return:
1220 """
1221
1222 result, content = self.db.get_table(FROM='ofcs', WHERE={"uuid": uuid}, LIMIT=100)
1223
1224 if result == 0:
1225 raise ovimException("Openflow controller with uuid '{}' not found".format(uuid),
1226 http_code=HTTP_Not_Found)
1227 elif result < 0:
1228 raise ovimException("Openflow controller with uuid '{}' error".format(uuid),
1229 http_code=HTTP_Internal_Server_Error)
Pablo Montes Moreno5b6f7492017-03-02 16:18:36 +01001230 return content[0]
mirabal9e194592017-02-17 11:03:25 +01001231
mirabalfbfb7972017-02-27 17:36:17 +01001232 def get_of_controllers(self, columns=None, db_filter={}, limit=None):
mirabal9e194592017-02-17 11:03:25 +01001233 """
1234 Show an openflow controllers from DB.
1235 :param columns: List with SELECT query parameters
1236 :param db_filter: List with where query parameters
mirabalfbfb7972017-02-27 17:36:17 +01001237 :param limit: result Limit
mirabal9e194592017-02-17 11:03:25 +01001238 :return:
1239 """
mirabalfbfb7972017-02-27 17:36:17 +01001240 result, content = self.db.get_table(SELECT=columns, FROM='ofcs', WHERE=db_filter, LIMIT=limit)
mirabal9e194592017-02-17 11:03:25 +01001241
1242 if result < 0:
1243 raise ovimException(str(content), -result)
1244
1245 return content
1246
mirabalfbfb7972017-02-27 17:36:17 +01001247 def get_tenants(self, columns=None, db_filter={}, limit=None):
1248 """
1249 Retrieve tenant list from DB
1250 :param columns: List with SELECT query parameters
1251 :param db_filter: List with where query parameters
1252 :param limit: result limit
1253 :return:
1254 """
1255 result, content = self.db.get_table(FROM='tenants', SELECT=columns, WHERE=db_filter, LIMIT=limit)
1256 if result < 0:
1257 raise ovimException('get_tenatns Error {}'.format(str(content)), -result)
1258 else:
1259 convert_boolean(content, ('enabled',))
1260 return content
1261
1262 def show_tenant_id(self, tenant_id):
1263 """
1264 Get tenant from DB by id
1265 :param tenant_id: tenant id
1266 :return:
1267 """
1268 result, content = self.db.get_table(FROM='tenants', SELECT=('uuid', 'name', 'description', 'enabled'),
1269 WHERE={"uuid": tenant_id})
1270 if result < 0:
1271 raise ovimException(str(content), -result)
1272 elif result == 0:
1273 raise ovimException("tenant with uuid='{}' not found".format(tenant_id), HTTP_Not_Found)
1274 else:
1275 convert_boolean(content, ('enabled',))
1276 return content[0]
1277
1278 def new_tentant(self, tenant):
1279 """
1280 Create a tenant and store in DB
1281 :param tenant: Dictionary with tenant data
1282 :return: the uuid of created tenant. Raise exception upon error
1283 """
1284
1285 # insert in data base
1286 result, tenant_uuid = self.db.new_tenant(tenant)
1287
1288 if result >= 0:
1289 return tenant_uuid
1290 else:
1291 raise ovimException(str(tenant_uuid), -result)
1292
1293 def delete_tentant(self, tenant_id):
1294 """
1295 Delete a tenant from the database.
1296 :param tenant_id: Tenant id
1297 :return: delete tenant id
1298 """
1299
1300 # check permissions
1301 r, tenants_flavors = self.db.get_table(FROM='tenants_flavors', SELECT=('flavor_id', 'tenant_id'),
1302 WHERE={'tenant_id': tenant_id})
1303 if r <= 0:
1304 tenants_flavors = ()
1305 r, tenants_images = self.db.get_table(FROM='tenants_images', SELECT=('image_id', 'tenant_id'),
1306 WHERE={'tenant_id': tenant_id})
1307 if r <= 0:
1308 tenants_images = ()
1309
1310 result, content = self.db.delete_row('tenants', tenant_id)
1311 if result == 0:
1312 raise ovimException("tenant '%s' not found" % tenant_id, HTTP_Not_Found)
1313 elif result > 0:
1314 for flavor in tenants_flavors:
1315 self.db.delete_row_by_key("flavors", "uuid", flavor['flavor_id'])
1316 for image in tenants_images:
1317 self.db.delete_row_by_key("images", "uuid", image['image_id'])
1318 return content
1319 else:
1320 raise ovimException("Error deleting tenant '%s' " % tenant_id, HTTP_Internal_Server_Error)
1321
1322 def edit_tenant(self, tenant_id, tenant_data):
1323 """
1324 Update a tenant data identified by tenant id
1325 :param tenant_id: tenant id
1326 :param tenant_data: Dictionary with tenant data
1327 :return:
1328 """
1329
1330 # Look for the previous data
1331 result, tenant_data_old = self.db.get_table(FROM='tenants', WHERE={'uuid': tenant_id})
1332 if result < 0:
1333 raise ovimException("Error updating tenant with uuid='{}': {}".format(tenant_id, tenant_data_old),
1334 HTTP_Internal_Server_Error)
1335 elif result == 0:
1336 raise ovimException("tenant with uuid='{}' not found".format(tenant_id), HTTP_Not_Found)
1337
1338 # insert in data base
1339 result, content = self.db.update_rows('tenants', tenant_data, WHERE={'uuid': tenant_id}, log=True)
1340 if result >= 0:
1341 return content
1342 else:
1343 raise ovimException(str(content), -result)
1344
mirabal6045a9d2017-03-06 11:36:55 +01001345 def set_of_port_mapping(self, of_maps, ofc_id=None, switch_dpid=None, region=None):
1346 """
1347 Create new port mapping entry
1348 :param of_maps: List with port mapping information
1349 # maps =[{"ofc_id": <ofc_id>,"region": datacenter region,"compute_node": compute uuid,"pci": pci adress,
1350 "switch_dpid": swith dpid,"switch_port": port name,"switch_mac": mac}]
1351 :param ofc_id: ofc id
1352 :param switch_dpid: switch dpid
1353 :param region: datacenter region id
1354 :return:
1355 """
1356
1357 for map in of_maps:
1358 if ofc_id:
1359 map['ofc_id'] = ofc_id
1360 if switch_dpid:
1361 map['switch_dpid'] = switch_dpid
1362 if region:
1363 map['region'] = region
1364
1365 for of_map in of_maps:
1366 result, uuid = self.db.new_row('of_port_mappings', of_map, True)
1367 if result > 0:
1368 of_map["uuid"] = uuid
1369 else:
1370 raise ovimException(str(uuid), -result)
1371 return of_maps
1372
1373 def clear_of_port_mapping(self, db_filter={}):
1374 """
1375 Clear port mapping filtering using db_filter dict
1376 :param db_filter: Parameter to filter during remove process
1377 :return:
1378 """
1379 result, content = self.db.delete_row_by_dict(FROM='of_port_mappings', WHERE=db_filter)
1380 # delete_row_by_key
1381 if result >= 0:
1382 return content
1383 else:
1384 raise ovimException("Error deleting of_port_mappings with filter='{}'".format(str(db_filter)),
1385 HTTP_Internal_Server_Error)
1386
1387 def get_of_port_mappings(self, column=None, db_filter=None, db_limit=None):
1388 """
1389 Retrive port mapping from DB
1390 :param column:
1391 :param db_filter:
1392 :return:
1393 """
1394 result, content = self.db.get_table(SELECT=column, WHERE=db_filter, FROM='of_port_mappings', LIMIT=db_limit)
1395
1396 if result < 0:
1397 self.logger.error("get_of_port_mappings Error %d %s", result, content)
1398 raise ovimException(str(content), -result)
1399 else:
1400 return content
1401
mirabalb716ac52017-02-10 14:47:53 +01001402 def get_dhcp_controller(self):
1403 """
1404 Create an host_thread object for manage openvim controller and not create a thread for itself
1405 :return: dhcp_host openvim controller object
1406 """
1407
1408 if 'openvim_controller' in self.config['host_threads']:
1409 return self.config['host_threads']['openvim_controller']
1410
1411 bridge_ifaces = []
1412 controller_ip = self.config['ovs_controller_ip']
tiernoa6933042017-05-24 16:54:33 +02001413 ovs_controller_user = self.config.get('ovs_controller_user')
mirabalb716ac52017-02-10 14:47:53 +01001414
1415 host_test_mode = True if self.config['mode'] == 'test' or self.config['mode'] == "OF only" else False
1416 host_develop_mode = True if self.config['mode'] == 'development' else False
1417
1418 dhcp_host = ht.host_thread(name='openvim_controller', user=ovs_controller_user, host=controller_ip,
tiernoa6933042017-05-24 16:54:33 +02001419 password=self.config.get('ovs_controller_password'),
1420 keyfile=self.config.get('ovs_controller_keyfile'),
tiernoe0c28c12017-05-04 18:44:40 +02001421 db=self.config["db"], db_lock=self.config["db_lock"], test=host_test_mode,
tiernoa6933042017-05-24 16:54:33 +02001422 image_path=self.config['host_image_path'], version=self.config['version'],
mirabalb716ac52017-02-10 14:47:53 +01001423 host_id='openvim_controller', develop_mode=host_develop_mode,
tiernoe0c28c12017-05-04 18:44:40 +02001424 develop_bridge_iface=bridge_ifaces,
1425 logger_name=self.logger_name + ".host.controller",
tiernof135eff2017-04-19 19:11:53 +02001426 debug=self.config.get('log_level_host'))
tiernoa6933042017-05-24 16:54:33 +02001427 # dhcp_host.start()
mirabalb716ac52017-02-10 14:47:53 +01001428 self.config['host_threads']['openvim_controller'] = dhcp_host
mirabal42ca0092017-06-14 05:42:30 -05001429 try:
1430 dhcp_host.check_connectivity()
1431 except Exception as e:
1432 pass
1433
mirabalb716ac52017-02-10 14:47:53 +01001434 return dhcp_host
1435
mirabal6878e3f2017-06-05 09:19:26 -05001436 def launch_dhcp_server(self, vlan, first_ip, last_ip, cidr, gateway, dns, routes):
mirabalb716ac52017-02-10 14:47:53 +01001437 """
1438 Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
1439 :param vlan: vlan identifier
1440 :param first_ip: First dhcp range ip
1441 :param last_ip: Last dhcp range ip
1442 :param cidr: net cidr
mirabale9f6f1a2017-02-16 17:57:35 +01001443 :param gateway: net gateway
mirabalb716ac52017-02-10 14:47:53 +01001444 :return:
1445 """
1446 ip_tools = IPNetwork(cidr)
1447 dhcp_netmask = str(ip_tools.netmask)
1448 ip_range = [first_ip, last_ip]
1449
1450 dhcp_path = self.config['ovs_controller_file_path']
1451
1452 controller_host = self.get_dhcp_controller()
mirabale16a6362017-07-10 05:45:56 -05001453
mirabal6878e3f2017-06-05 09:19:26 -05001454 # controller_host.create_linux_bridge(vlan)
1455 controller_host.create_dhcp_interfaces(vlan, first_ip, dhcp_netmask)
1456 dhcp_path = self.config['ovs_controller_file_path']
1457 controller_host.launch_dhcp_server(vlan, ip_range, dhcp_netmask, dhcp_path, gateway, dns, routes)
1458
1459 def launch_link_bridge_to_ovs(self, vlan, gateway, dhcp_cidr, links=None, routes=None):
1460 """
1461 Launch creating of connections (veth) between user bridge (link) and OVS
1462 :param vlan:
1463 :param gateway:
1464 :param links:
1465 :return:
1466 """
1467
1468 if links:
1469 controller_host = self.get_dhcp_controller()
1470 for link in links:
1471 if 'iface' in link and 'nat' not in link:
1472 controller_host.create_link_bridge_to_ovs(vlan, link['iface'])
1473 elif 'nat' in link:
1474 controller_host.create_qrouter_ovs_connection(vlan, gateway, dhcp_cidr)
1475 controller_host.create_qrouter_br_connection(vlan, dhcp_cidr, link)
1476
1477 if len(routes):
1478 controller_host.add_ns_routes(vlan, routes)
1479
1480 def delete_link_bridge_to_ovs(self, vlan, links=None):
1481 """
1482 Delete connections (veth) between user bridge (link) and OVS
1483 :param vlan:
1484 :param links:
1485 :return:
1486 """
1487 if links:
1488 controller_host = self.get_dhcp_controller()
1489
1490 for link in links:
1491 if 'iface' in link and 'nat' not in link:
1492 controller_host.remove_link_bridge_to_ovs(vlan, link['iface'])
1493 elif 'nat' in link:
1494 controller_host.delete_qrouter_connection(vlan, link['iface'])
1495
mirabalb716ac52017-02-10 14:47:53 +01001496
mirabald87877c2017-03-31 15:15:52 +02001497if __name__ == "__main__":
1498
1499 parser = argparse.ArgumentParser()
tierno46ca3a92017-04-05 19:49:24 +02001500 parser.add_argument("-v","--version", help="show ovim library version", action="store_true")
1501 parser.add_argument("--database-version", help="show required database version", action="store_true")
mirabald87877c2017-03-31 15:15:52 +02001502 args = parser.parse_args()
1503 if args.version:
1504 print ('openvimd version {} {}'.format(ovim.get_version(), ovim.get_version_date()))
1505 print ('(c) Copyright Telefonica')
tierno46ca3a92017-04-05 19:49:24 +02001506 elif args.database_version:
1507 print ('required database version: {}'.format(ovim.get_database_version()))
mirabalb716ac52017-02-10 14:47:53 +01001508