blob: 1177d424e1e7ee483073034e5045d3c688f7a419 [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$"
tierno5f79a262017-11-28 11:53:01 +010046__version__ = "0.5.22-r538"
garciadeblas259459f2017-11-14 16:27:31 +010047version_date = "Nov 2017"
48database_version = 22 #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
tierno5f79a262017-11-28 11:53:01 +0100664 if network.get('enable_dhcp'):
mirabal65ba8f82017-02-15 12:36:33 +0100665 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)
tierno5f79a262017-11-28 11:53:01 +0100675 if result >= 0: # and dhcp_integrity:
mirabal65ba8f82017-02-15 12:36:33 +0100676 if bridge_net:
677 bridge_net[3] = content
tierno5f79a262017-11-28 11:53:01 +0100678 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:
tierno5f79a262017-11-28 11:53:01 +0100687 raise ovimException("Error creating network: {}".format(content), -result)
688
mirabale9f6f1a2017-02-16 17:57:35 +0100689# TODO kei change update->edit
mirabal65ba8f82017-02-15 12:36:33 +0100690
mirabale9f6f1a2017-02-16 17:57:35 +0100691 def edit_network(self, network_id, network):
mirabal65ba8f82017-02-15 12:36:33 +0100692 """
mirabale9f6f1a2017-02-16 17:57:35 +0100693 Update entwork data byt id
mirabal65ba8f82017-02-15 12:36:33 +0100694 :return:
695 """
mirabale9f6f1a2017-02-16 17:57:35 +0100696 # Look for the previous data
697 where_ = {'uuid': network_id}
698 result, network_old = self.db.get_table(FROM='nets', WHERE=where_)
699 if result < 0:
700 raise ovimException("Error updating network %s" % network_old, HTTP_Internal_Server_Error)
701 elif result == 0:
702 raise ovimException('network %s not found' % network_id, HTTP_Not_Found)
703 # get ports
704 nbports, content = self.db.get_table(FROM='ports', SELECT=('uuid as port_id',),
705 WHERE={'net_id': network_id}, LIMIT=100)
706 if result < 0:
707 raise ovimException("http_put_network_id error %d %s" % (result, network_old), HTTP_Internal_Server_Error)
708 if nbports > 0:
709 if 'type' in network and network['type'] != network_old[0]['type']:
710 raise ovimException("Can not change type of network while having ports attached",
711 HTTP_Method_Not_Allowed)
712 if 'vlan' in network and network['vlan'] != network_old[0]['vlan']:
713 raise ovimException("Can not change vlan of network while having ports attached",
714 HTTP_Method_Not_Allowed)
mirabal65ba8f82017-02-15 12:36:33 +0100715
mirabale9f6f1a2017-02-16 17:57:35 +0100716 # check valid params
717 net_provider = network.get('provider', network_old[0]['provider'])
718 net_type = network.get('type', network_old[0]['type'])
719 net_bind_net = network.get("bind_net")
720 net_bind_type = network.get("bind_type")
721 if net_bind_net:
722 # look for a valid net
723 if self._check_valid_uuid(net_bind_net):
724 net_bind_key = "uuid"
725 else:
726 net_bind_key = "name"
727 result, content = self.db.get_table(FROM='nets', WHERE={net_bind_key: net_bind_net})
728 if result < 0:
729 raise ovimException('Getting nets from db ' + content, HTTP_Internal_Server_Error)
730 elif result == 0:
731 raise ovimException("bind_net %s '%s'not found" % (net_bind_key, net_bind_net), HTTP_Bad_Request)
732 elif result > 1:
733 raise ovimException("More than one bind_net %s '%s' found, use uuid" % (net_bind_key, net_bind_net),
734 HTTP_Bad_Request)
735 network["bind_net"] = content[0]["uuid"]
736 if net_bind_type:
737 if net_bind_type[0:5] != "vlan:":
738 raise ovimException("Bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request)
739 if int(net_bind_type[5:]) > 4095 or int(net_bind_type[5:]) <= 0:
740 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
741 HTTP_Bad_Request)
742 if net_provider:
743 if net_provider[:9] == "openflow:":
744 if net_type != "ptp" and net_type != "data":
745 raise ovimException("Only 'ptp' or 'data' net types can be bound to 'openflow'", HTTP_Bad_Request)
746 else:
747 if net_type != "bridge_man" and net_type != "bridge_data":
748 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound to "
749 "'bridge', 'macvtap' or 'default", HTTP_Bad_Request)
mirabal65ba8f82017-02-15 12:36:33 +0100750
mirabale9f6f1a2017-02-16 17:57:35 +0100751 # insert in data base
752 result, content = self.db.update_rows('nets', network, WHERE={'uuid': network_id}, log=True)
753 if result >= 0:
754 # if result > 0 and nbports>0 and 'admin_state_up' in network
755 # and network['admin_state_up'] != network_old[0]['admin_state_up']:
756 if result > 0:
mirabal7bbf50e2017-03-13 15:15:18 +0100757
758 try:
tiernoaa941462017-03-29 15:10:28 +0200759 if nbports:
760 self.net_update_ofc_thread(network_id)
mirabal7bbf50e2017-03-13 15:15:18 +0100761 except ovimException as e:
762 raise ovimException("Error while launching openflow rules in network '{}' {}"
763 .format(network_id, str(e)), HTTP_Internal_Server_Error)
764 except Exception as e:
765 raise ovimException("Error while launching openflow rules in network '{}' {}"
766 .format(network_id, str(e)), HTTP_Internal_Server_Error)
767
mirabale9f6f1a2017-02-16 17:57:35 +0100768 if self.config.get("dhcp_server"):
769 if network_id in self.config["dhcp_nets"]:
770 self.config["dhcp_nets"].remove(network_id)
mirabal7bbf50e2017-03-13 15:15:18 +0100771 if network.get("name", network_old[0]["name"]) in self.config["dhcp_server"].get("nets", ()):
mirabale9f6f1a2017-02-16 17:57:35 +0100772 self.config["dhcp_nets"].append(network_id)
773 else:
mirabal7bbf50e2017-03-13 15:15:18 +0100774 net_bind = network.get("bind_type", network_old[0]["bind_type"])
775 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 +0100776 "bridge_ifaces", ()):
777 self.config["dhcp_nets"].append(network_id)
778 return network_id
mirabal65ba8f82017-02-15 12:36:33 +0100779 else:
mirabale9f6f1a2017-02-16 17:57:35 +0100780 raise ovimException(content, -result)
mirabal65ba8f82017-02-15 12:36:33 +0100781
mirabale9f6f1a2017-02-16 17:57:35 +0100782 def delete_network(self, network_id):
mirabal9e194592017-02-17 11:03:25 +0100783 """
784 Delete network by network id
785 :param network_id: network id
786 :return:
787 """
mirabal0ec17ec2017-07-19 08:43:09 -0500788 net_data = self.show_network(network_id)
mirabale9f6f1a2017-02-16 17:57:35 +0100789
790 # delete from the data base
791 result, content = self.db.delete_row('nets', network_id)
792
793 if result == 0:
794 raise ovimException("Network %s not found " % network_id, HTTP_Not_Found)
795 elif result > 0:
796 for brnet in self.config['bridge_nets']:
797 if brnet[3] == network_id:
798 brnet[3] = None
799 break
800 if self.config.get("dhcp_server") and network_id in self.config["dhcp_nets"]:
801 self.config["dhcp_nets"].remove(network_id)
mirabal0ec17ec2017-07-19 08:43:09 -0500802
803 if net_data.get('enable_dhcp'):
804 dhcp_path = self.config['ovs_controller_file_path']
805 dhcp_controller = self.get_dhcp_controller()
806 dhcp_controller.delete_dhcp_server(net_data['vlan'], network_id, dhcp_path)
807 dhcp_controller.delete_dhcp_port(net_data['vlan'], network_id, dhcp_path)
808 links = yaml.load(net_data.get('links'))
809 if links:
810 links = yaml.load(net_data.get('links'))
811 self.delete_link_bridge_to_ovs(net_data['vlan'], links)
812
813 return content
mirabale9f6f1a2017-02-16 17:57:35 +0100814 else:
tierno11c45e72017-05-17 12:04:05 +0000815 raise ovimException("Error deleting network '{}': {}".format(network_id, content), -result)
mirabal65ba8f82017-02-15 12:36:33 +0100816
817 def get_openflow_rules(self, network_id=None):
818 """
819 Get openflow id from DB
820 :param network_id: Network id, if none all networks will be retrieved
821 :return: Return a list with Openflow rules per net
822 """
823 # ignore input data
824 if not network_id:
825 where_ = {}
826 else:
827 where_ = {"net_id": network_id}
mirabal65ba8f82017-02-15 12:36:33 +0100828 result, content = self.db.get_table(
mirabalf9a1a8d2017-03-15 12:42:27 +0100829 SELECT=("name", "net_id", "ofc_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
mirabal65ba8f82017-02-15 12:36:33 +0100830 WHERE=where_, FROM='of_flows')
831
832 if result < 0:
833 raise ovimException(str(content), -result)
834 return content
835
mirabale9f6f1a2017-02-16 17:57:35 +0100836 def edit_openflow_rules(self, network_id=None):
mirabal65ba8f82017-02-15 12:36:33 +0100837
838 """
839 To make actions over the net. The action is to reinstall the openflow rules
840 network_id can be 'all'
841 :param network_id: Network id, if none all networks will be retrieved
842 :return : Number of nets updated
843 """
844
845 # ignore input data
846 if not network_id:
847 where_ = {}
848 else:
849 where_ = {"uuid": network_id}
850 result, content = self.db.get_table(SELECT=("uuid", "type"), WHERE=where_, FROM='nets')
851
852 if result < 0:
853 raise ovimException(str(content), -result)
854
855 for net in content:
856 if net["type"] != "ptp" and net["type"] != "data":
857 result -= 1
858 continue
mirabal7bbf50e2017-03-13 15:15:18 +0100859
860 try:
861 self.net_update_ofc_thread(net['uuid'])
862 except ovimException as e:
863 raise ovimException("Error updating network'{}' {}".format(net['uuid'], str(e)),
864 HTTP_Internal_Server_Error)
865 except Exception as e:
866 raise ovimException("Error updating network '{}' {}".format(net['uuid'], str(e)),
867 HTTP_Internal_Server_Error)
868
mirabal65ba8f82017-02-15 12:36:33 +0100869 return result
870
mirabalf9a1a8d2017-03-15 12:42:27 +0100871 def delete_openflow_rules(self, ofc_id=None):
mirabal65ba8f82017-02-15 12:36:33 +0100872 """
873 To make actions over the net. The action is to delete ALL openflow rules
874 :return: return operation result
875 """
mirabalf9a1a8d2017-03-15 12:42:27 +0100876
877 if not ofc_id:
878 if 'Default' in self.config['ofcs_thread']:
879 r, c = self.config['ofcs_thread']['Default'].insert_task("clear-all")
880 else:
881 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found)
882
883 elif ofc_id in self.config['ofcs_thread']:
884 r, c = self.config['ofcs_thread'][ofc_id].insert_task("clear-all")
885
886 # ignore input data
887 if r < 0:
888 raise ovimException(str(c), -r)
889 else:
890 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id), HTTP_Not_Found)
mirabal65ba8f82017-02-15 12:36:33 +0100891 return r
892
mirabalf9a1a8d2017-03-15 12:42:27 +0100893 def get_openflow_ports(self, ofc_id=None):
mirabal65ba8f82017-02-15 12:36:33 +0100894 """
895 Obtain switch ports names of openflow controller
896 :return: Return flow ports in DB
897 """
mirabalf9a1a8d2017-03-15 12:42:27 +0100898 if not ofc_id:
899 if 'Default' in self.config['ofcs_thread']:
900 conn = self.config['ofcs_thread']['Default'].OF_connector
901 else:
902 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found)
903
tierno11c45e72017-05-17 12:04:05 +0000904 elif ofc_id in self.config['ofcs_thread']:
mirabalf9a1a8d2017-03-15 12:42:27 +0100905 conn = self.config['ofcs_thread'][ofc_id].OF_connector
906 else:
907 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id), HTTP_Not_Found)
908 return conn.pp2ofi
tierno57f7bda2017-02-09 12:01:55 +0100909
910 def get_ports(self, columns=None, filter={}, limit=None):
911 # result, content = my.db.get_ports(where_)
912 result, content = self.db.get_table(SELECT=columns, WHERE=filter, FROM='ports', LIMIT=limit)
913 if result < 0:
914 self.logger.error("http_get_ports Error %d %s", result, content)
915 raise ovimException(str(content), -result)
916 else:
917 convert_boolean(content, ('admin_state_up',))
918 return content
919
tierno57f7bda2017-02-09 12:01:55 +0100920 def new_port(self, port_data):
921 port_data['type'] = 'external'
922 if port_data.get('net_id'):
923 # check that new net has the correct type
924 result, new_net = self.db.check_target_net(port_data['net_id'], None, 'external')
925 if result < 0:
926 raise ovimException(str(new_net), -result)
927 # insert in data base
928 result, uuid = self.db.new_row('ports', port_data, True, True)
929 if result > 0:
930 if 'net_id' in port_data:
mirabal7bbf50e2017-03-13 15:15:18 +0100931 try:
932 self.net_update_ofc_thread(port_data['net_id'])
933 except ovimException as e:
934 raise ovimException("Cannot insert a task for updating network '{}' {}"
935 .format(port_data['net_id'], str(e)), HTTP_Internal_Server_Error)
936 except Exception as e:
937 raise ovimException("Cannot insert a task for updating network '{}' {}"
938 .format(port_data['net_id'], str(e)), HTTP_Internal_Server_Error)
939
tierno57f7bda2017-02-09 12:01:55 +0100940 return uuid
941 else:
942 raise ovimException(str(uuid), -result)
943
mirabal37829452017-03-09 14:41:21 +0100944 def new_external_port(self, port_data):
945 """
946 Create new external port and check port mapping correspondence
947 :param port_data: port_data = {
948 'region': 'datacenter region',
949 'compute_node': 'compute node id',
950 'pci': 'pci port address',
951 'vlan': 'net vlan',
952 'net_id': 'net id',
953 'tenant_id': 'tenant id',
954 'mac': 'switch mac',
955 'name': 'port name'
956 'ip_address': 'ip address - optional'}
957 :return:
958 """
959
960 port_data['type'] = 'external'
961
962 if port_data.get('net_id'):
963 # check that new net has the correct type
964 result, new_net = self.db.check_target_net(port_data['net_id'], None, 'external')
965 if result < 0:
966 raise ovimException(str(new_net), -result)
967 # insert in data base
968 db_filter = {}
969
970 if port_data.get('region'):
971 db_filter['region'] = port_data['region']
972 if port_data.get('pci'):
973 db_filter['pci'] = port_data['pci']
974 if port_data.get('compute_node'):
975 db_filter['compute_node'] = port_data['compute_node']
976
977 columns = ['ofc_id', 'switch_dpid', 'switch_port', 'switch_mac', 'pci']
978 port_mapping_data = self.get_of_port_mappings(columns, db_filter)
979
980 if not len(port_mapping_data):
tierno16007502017-03-27 16:48:32 +0200981 raise ovimException("No port mapping founded for '{}'".format(str(db_filter)),
mirabal37829452017-03-09 14:41:21 +0100982 HTTP_Not_Found)
983 elif len(port_mapping_data) > 1:
984 raise ovimException("Wrong port data was given, please check pci, region & compute id data",
985 HTTP_Conflict)
986
987 port_data['ofc_id'] = port_mapping_data[0]['ofc_id']
988 port_data['switch_dpid'] = port_mapping_data[0]['switch_dpid']
989 port_data['switch_port'] = port_mapping_data[0]['switch_port']
990 port_data['switch_mac'] = port_mapping_data[0]['switch_mac']
991
992 # remove from compute_node, region and pci of_port_data to adapt to 'ports' structure
montesmoreno275b1992017-03-28 15:45:02 +0200993 if 'region' in port_data:
994 del port_data['region']
995 if 'pci' in port_data:
996 del port_data['pci']
997 if 'compute_node' in port_data:
998 del port_data['compute_node']
mirabal37829452017-03-09 14:41:21 +0100999
1000 result, uuid = self.db.new_row('ports', port_data, True, True)
1001 if result > 0:
mirabal7bbf50e2017-03-13 15:15:18 +01001002 try:
1003 self.net_update_ofc_thread(port_data['net_id'], port_data['ofc_id'])
1004 except ovimException as e:
1005 raise ovimException("Cannot insert a task for updating network '{}' {}".
1006 format(port_data['net_id'], str(e)), HTTP_Internal_Server_Error)
1007 except Exception as e:
1008 raise ovimException("Cannot insert a task for updating network '{}' {}"
1009 .format(port_data['net_id'], e), HTTP_Internal_Server_Error)
mirabal37829452017-03-09 14:41:21 +01001010 return uuid
1011 else:
1012 raise ovimException(str(uuid), -result)
1013
tiernoaa941462017-03-29 15:10:28 +02001014 def net_update_ofc_thread(self, net_id, ofc_id=None, switch_dpid=None):
mirabal7bbf50e2017-03-13 15:15:18 +01001015 """
1016 Insert a update net task by net id or ofc_id for each ofc thread
1017 :param net_id: network id
1018 :param ofc_id: openflow controller id
tiernoaa941462017-03-29 15:10:28 +02001019 :param switch_dpid: switch dpid
mirabal7bbf50e2017-03-13 15:15:18 +01001020 :return:
1021 """
1022 if not net_id:
1023 raise ovimException("No net_id received", HTTP_Internal_Server_Error)
1024
mirabal7bbf50e2017-03-13 15:15:18 +01001025 r = -1
1026 c = 'No valid ofc_id or switch_dpid received'
1027
1028 if not ofc_id:
1029 ports = self.get_ports(filter={"net_id": net_id})
1030 for port in ports:
1031 port_ofc_id = port.get('ofc_id', None)
1032 if port_ofc_id:
1033 ofc_id = port['ofc_id']
1034 switch_dpid = port['switch_dpid']
1035 break
tiernoaa941462017-03-29 15:10:28 +02001036 #TODO if not ofc_id: look at database table ofcs
1037
mirabal7bbf50e2017-03-13 15:15:18 +01001038
1039 # If no ofc_id found it, default ofc_id is used.
1040 if not ofc_id and not switch_dpid:
1041 ofc_id = "Default"
1042
1043 if ofc_id and ofc_id in self.config['ofcs_thread']:
1044 r, c = self.config['ofcs_thread'][ofc_id].insert_task("update-net", net_id)
1045 elif switch_dpid:
1046
1047 ofcs_dpid_list = self.config['ofcs_thread_dpid']
1048 for ofc_t in ofcs_dpid_list:
1049 if switch_dpid in ofc_t:
1050 r, c = ofc_t[switch_dpid].insert_task("update-net", net_id)
1051
1052 if r < 0:
tierno82232582017-03-15 18:09:16 +01001053 message = "Cannot insert a task for updating network '{}', {}".format(net_id, c)
mirabal7bbf50e2017-03-13 15:15:18 +01001054 self.logger.error(message)
1055 raise ovimException(message, HTTP_Internal_Server_Error)
1056
tierno57f7bda2017-02-09 12:01:55 +01001057 def delete_port(self, port_id):
1058 # Look for the previous port data
1059 result, ports = self.db.get_table(WHERE={'uuid': port_id, "type": "external"}, FROM='ports')
1060 if result < 0:
1061 raise ovimException("Cannot get port info from database: {}".format(ports), http_code=-result)
1062 # delete from the data base
1063 result, content = self.db.delete_row('ports', port_id)
1064 if result == 0:
1065 raise ovimException("External port '{}' not found".format(port_id), http_code=HTTP_Not_Found)
1066 elif result < 0:
1067 raise ovimException("Cannot delete port from database: {}".format(content), http_code=-result)
1068 # update network
1069 network = ports[0].get('net_id', None)
1070 if network:
1071 # change of net.
mirabal7bbf50e2017-03-13 15:15:18 +01001072
1073 try:
tiernoaa941462017-03-29 15:10:28 +02001074 self.net_update_ofc_thread(network, ofc_id=ports[0]["ofc_id"], switch_dpid=ports[0]["switch_dpid"])
mirabal7bbf50e2017-03-13 15:15:18 +01001075 except ovimException as e:
1076 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network, str(e)),
1077 HTTP_Internal_Server_Error)
1078 except Exception as e:
1079 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network, str(e)),
1080 HTTP_Internal_Server_Error)
1081
tierno57f7bda2017-02-09 12:01:55 +01001082 return content
1083
tierno57f7bda2017-02-09 12:01:55 +01001084 def edit_port(self, port_id, port_data, admin=True):
1085 # Look for the previous port data
1086 result, content = self.db.get_table(FROM="ports", WHERE={'uuid': port_id})
1087 if result < 0:
1088 raise ovimException("Cannot get port info from database: {}".format(content), http_code=-result)
1089 elif result == 0:
1090 raise ovimException("Port '{}' not found".format(port_id), http_code=HTTP_Not_Found)
1091 port = content[0]
1092 nets = []
1093 host_id = None
1094 result = 1
1095 if 'net_id' in port_data:
1096 # change of net.
1097 old_net = port.get('net_id', None)
1098 new_net = port_data['net_id']
1099 if old_net != new_net:
1100
1101 if new_net:
1102 nets.append(new_net) # put first the new net, so that new openflow rules are created before removing the old ones
1103 if old_net:
1104 nets.append(old_net)
1105 if port['type'] == 'instance:bridge' or port['type'] == 'instance:ovs':
1106 raise ovimException("bridge interfaces cannot be attached to a different net", http_code=HTTP_Forbidden)
1107 elif port['type'] == 'external' and not admin:
1108 raise ovimException("Needed admin privileges",http_code=HTTP_Unauthorized)
1109 if new_net:
1110 # check that new net has the correct type
1111 result, new_net_dict = self.db.check_target_net(new_net, None, port['type'])
1112 if result < 0:
1113 raise ovimException("Error {}".format(new_net_dict), http_code=HTTP_Conflict)
1114 # change VLAN for SR-IOV ports
1115 if result >= 0 and port["type"] == "instance:data" and port["model"] == "VF": # TODO consider also VFnotShared
1116 if new_net:
1117 port_data["vlan"] = None
1118 else:
1119 port_data["vlan"] = new_net_dict["vlan"]
1120 # get host where this VM is allocated
1121 result, content = self.db.get_table(FROM="instances", WHERE={"uuid": port["instance_id"]})
1122 if result > 0:
1123 host_id = content[0]["host_id"]
1124
1125 # insert in data base
1126 if result >= 0:
1127 result, content = self.db.update_rows('ports', port_data, WHERE={'uuid': port_id}, log=False)
tiernoaa941462017-03-29 15:10:28 +02001128 port.update(port_data)
tierno57f7bda2017-02-09 12:01:55 +01001129
1130 # Insert task to complete actions
1131 if result > 0:
1132 for net_id in nets:
mirabal7bbf50e2017-03-13 15:15:18 +01001133 try:
tiernoaa941462017-03-29 15:10:28 +02001134 self.net_update_ofc_thread(net_id, port["ofc_id"], switch_dpid=port["switch_dpid"])
mirabal7bbf50e2017-03-13 15:15:18 +01001135 except ovimException as e:
1136 raise ovimException("Error updating network'{}' {}".format(net_id, str(e)),
1137 HTTP_Internal_Server_Error)
1138 except Exception as e:
1139 raise ovimException("Error updating network '{}' {}".format(net_id, str(e)),
1140 HTTP_Internal_Server_Error)
1141
tierno57f7bda2017-02-09 12:01:55 +01001142 if host_id:
1143 r, v = self.config['host_threads'][host_id].insert_task("edit-iface", port_id, old_net, new_net)
1144 if r < 0:
1145 self.logger.error("Error updating network '{}' {}".format(r,v))
1146 # TODO Do something if fails
1147 if result >= 0:
1148 return port_id
1149 else:
1150 raise ovimException("Error {}".format(content), http_code=-result)
mirabalb716ac52017-02-10 14:47:53 +01001151
mirabal9e194592017-02-17 11:03:25 +01001152 def new_of_controller(self, ofc_data):
1153 """
1154 Create a new openflow controller into DB
1155 :param ofc_data: Dict openflow controller data
1156 :return: openflow controller dpid
1157 """
1158
mirabal580435e2017-03-01 16:17:10 +01001159 result, ofc_uuid = self.db.new_row('ofcs', ofc_data, True, True)
mirabal9e194592017-02-17 11:03:25 +01001160 if result < 0:
mirabal580435e2017-03-01 16:17:10 +01001161 raise ovimException("New ofc Error %s" % ofc_uuid, HTTP_Internal_Server_Error)
1162
1163 ofc_data['uuid'] = ofc_uuid
1164 of_conn = self._load_of_module(ofc_data)
1165 self._create_ofc_task(ofc_uuid, ofc_data['dpid'], of_conn)
1166
1167 return ofc_uuid
mirabal9e194592017-02-17 11:03:25 +01001168
1169 def edit_of_controller(self, of_id, ofc_data):
1170 """
1171 Edit an openflow controller entry from DB
1172 :return:
1173 """
1174 if not ofc_data:
1175 raise ovimException("No data received during uptade OF contorller", http_code=HTTP_Internal_Server_Error)
1176
1177 old_of_controller = self.show_of_controller(of_id)
1178
1179 if old_of_controller:
1180 result, content = self.db.update_rows('ofcs', ofc_data, WHERE={'uuid': of_id}, log=False)
1181 if result >= 0:
1182 return ofc_data
1183 else:
1184 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id),
1185 http_code=-result)
1186 else:
1187 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id),
1188 http_code=HTTP_Internal_Server_Error)
1189
1190 def delete_of_controller(self, of_id):
1191 """
1192 Delete an openflow controller from DB.
1193 :param of_id: openflow controller dpid
1194 :return:
1195 """
1196
mirabal580435e2017-03-01 16:17:10 +01001197 ofc = self.show_of_controller(of_id)
1198
Pablo Montes Moreno5b6f7492017-03-02 16:18:36 +01001199 result, content = self.db.delete_row("ofcs", of_id)
mirabal9e194592017-02-17 11:03:25 +01001200 if result < 0:
1201 raise ovimException("Cannot delete ofc from database: {}".format(content), http_code=-result)
1202 elif result == 0:
1203 raise ovimException("ofc {} not found ".format(content), http_code=HTTP_Not_Found)
mirabal580435e2017-03-01 16:17:10 +01001204
1205 ofc_thread = self.config['ofcs_thread'][of_id]
1206 del self.config['ofcs_thread'][of_id]
1207 for ofc_th in self.config['ofcs_thread_dpid']:
1208 if ofc['dpid'] in ofc_th:
1209 self.config['ofcs_thread_dpid'].remove(ofc_th)
1210
1211 ofc_thread.insert_task("exit")
1212 #ofc_thread.join()
1213
mirabal9e194592017-02-17 11:03:25 +01001214 return content
1215
1216 def show_of_controller(self, uuid):
1217 """
1218 Show an openflow controller by dpid from DB.
1219 :param db_filter: List with where query parameters
1220 :return:
1221 """
1222
1223 result, content = self.db.get_table(FROM='ofcs', WHERE={"uuid": uuid}, LIMIT=100)
1224
1225 if result == 0:
1226 raise ovimException("Openflow controller with uuid '{}' not found".format(uuid),
1227 http_code=HTTP_Not_Found)
1228 elif result < 0:
1229 raise ovimException("Openflow controller with uuid '{}' error".format(uuid),
1230 http_code=HTTP_Internal_Server_Error)
Pablo Montes Moreno5b6f7492017-03-02 16:18:36 +01001231 return content[0]
mirabal9e194592017-02-17 11:03:25 +01001232
mirabalfbfb7972017-02-27 17:36:17 +01001233 def get_of_controllers(self, columns=None, db_filter={}, limit=None):
mirabal9e194592017-02-17 11:03:25 +01001234 """
1235 Show an openflow controllers from DB.
1236 :param columns: List with SELECT query parameters
1237 :param db_filter: List with where query parameters
mirabalfbfb7972017-02-27 17:36:17 +01001238 :param limit: result Limit
mirabal9e194592017-02-17 11:03:25 +01001239 :return:
1240 """
mirabalfbfb7972017-02-27 17:36:17 +01001241 result, content = self.db.get_table(SELECT=columns, FROM='ofcs', WHERE=db_filter, LIMIT=limit)
mirabal9e194592017-02-17 11:03:25 +01001242
1243 if result < 0:
1244 raise ovimException(str(content), -result)
1245
1246 return content
1247
mirabalfbfb7972017-02-27 17:36:17 +01001248 def get_tenants(self, columns=None, db_filter={}, limit=None):
1249 """
1250 Retrieve tenant list from DB
1251 :param columns: List with SELECT query parameters
1252 :param db_filter: List with where query parameters
1253 :param limit: result limit
1254 :return:
1255 """
1256 result, content = self.db.get_table(FROM='tenants', SELECT=columns, WHERE=db_filter, LIMIT=limit)
1257 if result < 0:
1258 raise ovimException('get_tenatns Error {}'.format(str(content)), -result)
1259 else:
1260 convert_boolean(content, ('enabled',))
1261 return content
1262
1263 def show_tenant_id(self, tenant_id):
1264 """
1265 Get tenant from DB by id
1266 :param tenant_id: tenant id
1267 :return:
1268 """
1269 result, content = self.db.get_table(FROM='tenants', SELECT=('uuid', 'name', 'description', 'enabled'),
1270 WHERE={"uuid": tenant_id})
1271 if result < 0:
1272 raise ovimException(str(content), -result)
1273 elif result == 0:
1274 raise ovimException("tenant with uuid='{}' not found".format(tenant_id), HTTP_Not_Found)
1275 else:
1276 convert_boolean(content, ('enabled',))
1277 return content[0]
1278
1279 def new_tentant(self, tenant):
1280 """
1281 Create a tenant and store in DB
1282 :param tenant: Dictionary with tenant data
1283 :return: the uuid of created tenant. Raise exception upon error
1284 """
1285
1286 # insert in data base
1287 result, tenant_uuid = self.db.new_tenant(tenant)
1288
1289 if result >= 0:
1290 return tenant_uuid
1291 else:
1292 raise ovimException(str(tenant_uuid), -result)
1293
1294 def delete_tentant(self, tenant_id):
1295 """
1296 Delete a tenant from the database.
1297 :param tenant_id: Tenant id
1298 :return: delete tenant id
1299 """
1300
1301 # check permissions
1302 r, tenants_flavors = self.db.get_table(FROM='tenants_flavors', SELECT=('flavor_id', 'tenant_id'),
1303 WHERE={'tenant_id': tenant_id})
1304 if r <= 0:
1305 tenants_flavors = ()
1306 r, tenants_images = self.db.get_table(FROM='tenants_images', SELECT=('image_id', 'tenant_id'),
1307 WHERE={'tenant_id': tenant_id})
1308 if r <= 0:
1309 tenants_images = ()
1310
1311 result, content = self.db.delete_row('tenants', tenant_id)
1312 if result == 0:
1313 raise ovimException("tenant '%s' not found" % tenant_id, HTTP_Not_Found)
1314 elif result > 0:
1315 for flavor in tenants_flavors:
1316 self.db.delete_row_by_key("flavors", "uuid", flavor['flavor_id'])
1317 for image in tenants_images:
1318 self.db.delete_row_by_key("images", "uuid", image['image_id'])
1319 return content
1320 else:
1321 raise ovimException("Error deleting tenant '%s' " % tenant_id, HTTP_Internal_Server_Error)
1322
1323 def edit_tenant(self, tenant_id, tenant_data):
1324 """
1325 Update a tenant data identified by tenant id
1326 :param tenant_id: tenant id
1327 :param tenant_data: Dictionary with tenant data
1328 :return:
1329 """
1330
1331 # Look for the previous data
1332 result, tenant_data_old = self.db.get_table(FROM='tenants', WHERE={'uuid': tenant_id})
1333 if result < 0:
1334 raise ovimException("Error updating tenant with uuid='{}': {}".format(tenant_id, tenant_data_old),
1335 HTTP_Internal_Server_Error)
1336 elif result == 0:
1337 raise ovimException("tenant with uuid='{}' not found".format(tenant_id), HTTP_Not_Found)
1338
1339 # insert in data base
1340 result, content = self.db.update_rows('tenants', tenant_data, WHERE={'uuid': tenant_id}, log=True)
1341 if result >= 0:
1342 return content
1343 else:
1344 raise ovimException(str(content), -result)
1345
mirabal6045a9d2017-03-06 11:36:55 +01001346 def set_of_port_mapping(self, of_maps, ofc_id=None, switch_dpid=None, region=None):
1347 """
1348 Create new port mapping entry
1349 :param of_maps: List with port mapping information
1350 # maps =[{"ofc_id": <ofc_id>,"region": datacenter region,"compute_node": compute uuid,"pci": pci adress,
1351 "switch_dpid": swith dpid,"switch_port": port name,"switch_mac": mac}]
1352 :param ofc_id: ofc id
1353 :param switch_dpid: switch dpid
1354 :param region: datacenter region id
1355 :return:
1356 """
1357
1358 for map in of_maps:
1359 if ofc_id:
1360 map['ofc_id'] = ofc_id
1361 if switch_dpid:
1362 map['switch_dpid'] = switch_dpid
1363 if region:
1364 map['region'] = region
tierno338e9982017-09-08 12:44:15 +02001365 if map.get("pci"):
1366 map["pci"] = map["pci"].lower()
mirabal6045a9d2017-03-06 11:36:55 +01001367
1368 for of_map in of_maps:
1369 result, uuid = self.db.new_row('of_port_mappings', of_map, True)
1370 if result > 0:
1371 of_map["uuid"] = uuid
1372 else:
1373 raise ovimException(str(uuid), -result)
1374 return of_maps
1375
1376 def clear_of_port_mapping(self, db_filter={}):
1377 """
1378 Clear port mapping filtering using db_filter dict
1379 :param db_filter: Parameter to filter during remove process
1380 :return:
1381 """
1382 result, content = self.db.delete_row_by_dict(FROM='of_port_mappings', WHERE=db_filter)
1383 # delete_row_by_key
1384 if result >= 0:
1385 return content
1386 else:
1387 raise ovimException("Error deleting of_port_mappings with filter='{}'".format(str(db_filter)),
1388 HTTP_Internal_Server_Error)
1389
1390 def get_of_port_mappings(self, column=None, db_filter=None, db_limit=None):
1391 """
1392 Retrive port mapping from DB
1393 :param column:
1394 :param db_filter:
1395 :return:
1396 """
1397 result, content = self.db.get_table(SELECT=column, WHERE=db_filter, FROM='of_port_mappings', LIMIT=db_limit)
1398
1399 if result < 0:
1400 self.logger.error("get_of_port_mappings Error %d %s", result, content)
1401 raise ovimException(str(content), -result)
1402 else:
1403 return content
1404
mirabalb716ac52017-02-10 14:47:53 +01001405 def get_dhcp_controller(self):
1406 """
1407 Create an host_thread object for manage openvim controller and not create a thread for itself
1408 :return: dhcp_host openvim controller object
1409 """
1410
1411 if 'openvim_controller' in self.config['host_threads']:
1412 return self.config['host_threads']['openvim_controller']
1413
1414 bridge_ifaces = []
1415 controller_ip = self.config['ovs_controller_ip']
tiernoa6933042017-05-24 16:54:33 +02001416 ovs_controller_user = self.config.get('ovs_controller_user')
mirabalb716ac52017-02-10 14:47:53 +01001417
1418 host_test_mode = True if self.config['mode'] == 'test' or self.config['mode'] == "OF only" else False
1419 host_develop_mode = True if self.config['mode'] == 'development' else False
1420
1421 dhcp_host = ht.host_thread(name='openvim_controller', user=ovs_controller_user, host=controller_ip,
tiernoa6933042017-05-24 16:54:33 +02001422 password=self.config.get('ovs_controller_password'),
1423 keyfile=self.config.get('ovs_controller_keyfile'),
tiernoe0c28c12017-05-04 18:44:40 +02001424 db=self.config["db"], db_lock=self.config["db_lock"], test=host_test_mode,
tiernoa6933042017-05-24 16:54:33 +02001425 image_path=self.config['host_image_path'], version=self.config['version'],
mirabalb716ac52017-02-10 14:47:53 +01001426 host_id='openvim_controller', develop_mode=host_develop_mode,
tiernoe0c28c12017-05-04 18:44:40 +02001427 develop_bridge_iface=bridge_ifaces,
1428 logger_name=self.logger_name + ".host.controller",
tiernof135eff2017-04-19 19:11:53 +02001429 debug=self.config.get('log_level_host'))
tiernoa6933042017-05-24 16:54:33 +02001430 # dhcp_host.start()
mirabalb716ac52017-02-10 14:47:53 +01001431 self.config['host_threads']['openvim_controller'] = dhcp_host
mirabal42ca0092017-06-14 05:42:30 -05001432 try:
1433 dhcp_host.check_connectivity()
1434 except Exception as e:
1435 pass
1436
mirabalb716ac52017-02-10 14:47:53 +01001437 return dhcp_host
1438
mirabal6878e3f2017-06-05 09:19:26 -05001439 def launch_dhcp_server(self, vlan, first_ip, last_ip, cidr, gateway, dns, routes):
mirabalb716ac52017-02-10 14:47:53 +01001440 """
1441 Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
1442 :param vlan: vlan identifier
1443 :param first_ip: First dhcp range ip
1444 :param last_ip: Last dhcp range ip
1445 :param cidr: net cidr
mirabale9f6f1a2017-02-16 17:57:35 +01001446 :param gateway: net gateway
mirabalb716ac52017-02-10 14:47:53 +01001447 :return:
1448 """
1449 ip_tools = IPNetwork(cidr)
1450 dhcp_netmask = str(ip_tools.netmask)
1451 ip_range = [first_ip, last_ip]
1452
1453 dhcp_path = self.config['ovs_controller_file_path']
1454
1455 controller_host = self.get_dhcp_controller()
mirabale16a6362017-07-10 05:45:56 -05001456
mirabal6878e3f2017-06-05 09:19:26 -05001457 # controller_host.create_linux_bridge(vlan)
1458 controller_host.create_dhcp_interfaces(vlan, first_ip, dhcp_netmask)
1459 dhcp_path = self.config['ovs_controller_file_path']
1460 controller_host.launch_dhcp_server(vlan, ip_range, dhcp_netmask, dhcp_path, gateway, dns, routes)
1461
1462 def launch_link_bridge_to_ovs(self, vlan, gateway, dhcp_cidr, links=None, routes=None):
1463 """
1464 Launch creating of connections (veth) between user bridge (link) and OVS
1465 :param vlan:
1466 :param gateway:
1467 :param links:
1468 :return:
1469 """
1470
1471 if links:
1472 controller_host = self.get_dhcp_controller()
1473 for link in links:
1474 if 'iface' in link and 'nat' not in link:
1475 controller_host.create_link_bridge_to_ovs(vlan, link['iface'])
1476 elif 'nat' in link:
1477 controller_host.create_qrouter_ovs_connection(vlan, gateway, dhcp_cidr)
1478 controller_host.create_qrouter_br_connection(vlan, dhcp_cidr, link)
1479
1480 if len(routes):
1481 controller_host.add_ns_routes(vlan, routes)
1482
1483 def delete_link_bridge_to_ovs(self, vlan, links=None):
1484 """
1485 Delete connections (veth) between user bridge (link) and OVS
1486 :param vlan:
1487 :param links:
1488 :return:
1489 """
1490 if links:
1491 controller_host = self.get_dhcp_controller()
1492
1493 for link in links:
1494 if 'iface' in link and 'nat' not in link:
1495 controller_host.remove_link_bridge_to_ovs(vlan, link['iface'])
1496 elif 'nat' in link:
1497 controller_host.delete_qrouter_connection(vlan, link['iface'])
1498
mirabalb716ac52017-02-10 14:47:53 +01001499
mirabald87877c2017-03-31 15:15:52 +02001500if __name__ == "__main__":
1501
1502 parser = argparse.ArgumentParser()
tierno46ca3a92017-04-05 19:49:24 +02001503 parser.add_argument("-v","--version", help="show ovim library version", action="store_true")
1504 parser.add_argument("--database-version", help="show required database version", action="store_true")
mirabald87877c2017-03-31 15:15:52 +02001505 args = parser.parse_args()
1506 if args.version:
1507 print ('openvimd version {} {}'.format(ovim.get_version(), ovim.get_version_date()))
1508 print ('(c) Copyright Telefonica')
tierno46ca3a92017-04-05 19:49:24 +02001509 elif args.database_version:
1510 print ('required database version: {}'.format(ovim.get_database_version()))
mirabalb716ac52017-02-10 14:47:53 +01001511