2 # -*- coding: utf-8 -*-
5 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
6 # This file is part of openvim
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact with: nfvlabs@tid.es
26 This is the thread for the http server North API.
27 Two thread will be launched, with normal and administrative permissions.
37 from netaddr
import IPNetwork
38 from jsonschema
import validate
as js_v
, exceptions
as js_e
39 import host_thread
as ht
40 import dhcp_thread
as dt
41 import openflow_thread
as oft
44 __author__
= "Alfonso Tierno, Leonardo Mirabal"
45 __date__
= "$06-Feb-2017 12:07:15$"
46 __version__
= "0.5.18-r534"
47 version_date
= "Jun 2017"
48 database_version
= 21 #needed database schema version
50 HTTP_Bad_Request
= 400
51 HTTP_Unauthorized
= 401
54 HTTP_Method_Not_Allowed
= 405
55 HTTP_Not_Acceptable
= 406
56 HTTP_Request_Timeout
= 408
58 HTTP_Service_Unavailable
= 503
59 HTTP_Internal_Server_Error
= 500
62 def convert_boolean(data
, items
):
63 '''Check recursively the content of data, and if there is an key contained in items, convert value from string to boolean
64 It assumes that bandwidth is well formed
66 'data': dictionary bottle.FormsDict variable to be checked. None or empty is consideted valid
67 'items': tuple of keys to convert
71 if type(data
) is dict:
73 if type(data
[k
]) is dict or type(data
[k
]) is tuple or type(data
[k
]) is list:
74 convert_boolean(data
[k
], items
)
76 if type(data
[k
]) is str:
77 if data
[k
] == "false":
79 elif data
[k
] == "true":
81 if type(data
) is tuple or type(data
) is list:
83 if type(k
) is dict or type(k
) is tuple or type(k
) is list:
84 convert_boolean(k
, items
)
88 class ovimException(Exception):
89 def __init__(self
, message
, http_code
=HTTP_Bad_Request
):
90 self
.http_code
= http_code
91 Exception.__init
__(self
, message
)
95 running_info
= {} #TODO OVIM move the info of running threads from config_dic to this static variable
98 def __init__(self
, configuration
):
99 self
.config
= configuration
100 self
.logger_name
= configuration
.get("logger_name", "openvim")
101 self
.logger
= logging
.getLogger(self
.logger_name
)
103 self
.db
= self
._create
_database
_connection
()
104 self
.of_test_mode
= False
106 def _create_database_connection(self
):
107 db
= vim_db
.vim_db((self
.config
["network_vlan_range_start"], self
.config
["network_vlan_range_end"]),
108 self
.logger_name
+ ".db", self
.config
.get('log_level_db'))
109 if db
.connect(self
.config
['db_host'], self
.config
['db_user'], self
.config
['db_passwd'],
110 self
.config
['db_name']) == -1:
111 # self.logger.error("Cannot connect to database %s at %s@%s", self.config['db_name'], self.config['db_user'],
112 # self.config['db_host'])
113 raise ovimException("Cannot connect to database {} at {}@{}".format(self
.config
['db_name'],
114 self
.config
['db_user'],
115 self
.config
['db_host']) )
123 def get_version_date():
127 def get_database_version():
128 return database_version
131 def _check_dhcp_data_integrity(network
):
133 Check if all dhcp parameter for anet are valid, if not will be calculated from cidr value
134 :param network: list with user nets paramters
137 if "cidr" in network
:
138 cidr
= network
["cidr"]
139 ip_tools
= IPNetwork(cidr
)
140 cidr_len
= ip_tools
.prefixlen
144 ips
= IPNetwork(cidr
)
145 if "dhcp_first_ip" not in network
:
146 network
["dhcp_first_ip"] = str(ips
[3])
147 if "dhcp_last_ip" not in network
:
148 network
["dhcp_last_ip"] = str(ips
[-2])
149 if "gateway_ip" not in network
:
150 network
["gateway_ip"] = str(ips
[1])
157 def _check_valid_uuid(uuid
):
158 id_schema
= {"type": "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
160 js_v(uuid
, id_schema
)
162 except js_e
.ValidationError
:
165 def start_service(self
):
170 global database_version
171 # if self.running_info:
172 # return #TODO service can be checked and rebuild broken threads
173 r
= self
.db
.get_db_version()
175 db_path
= db_path
[:db_path
.rfind("/")]
176 if os
.path
.exists(db_path
+ "/database_utils/migrate_vim_db.sh"):
177 db_path
+= "/database_utils"
179 db_path
+= "/../database_utils"
182 raise ovimException("DATABASE is not valid. If you think it is corrupted, you can init it with"
183 " '{db_path}/init_vim_db.sh' script".format(db_path
=db_path
))
184 elif r
[0] != database_version
:
185 raise ovimException("DATABASE wrong version '{current}'. Try to upgrade/downgrade to version '{target}'"
186 " with '{db_path}/migrate_vim_db.sh {target}'".format(
187 current
=r
[0], target
=database_version
, db_path
=db_path
))
188 self
.logger
.critical("Starting ovim server version: '{} {}' database version '{}'".format(
189 self
.get_version(), self
.get_version_date(), self
.get_database_version()))
190 # create database connection for openflow threads
191 self
.config
["db"] = self
._create
_database
_connection
()
192 self
.config
["db_lock"] = threading
.Lock()
194 self
.of_test_mode
= False if self
.config
['mode'] == 'normal' or self
.config
['mode'] == "OF only" else True
196 # Create one thread for each host
197 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
198 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
199 host_develop_bridge_iface
= self
.config
.get('development_bridge', None)
201 # get host list from data base before starting threads
202 r
, hosts
= self
.db
.get_table(SELECT
=('name', 'ip_name', 'user', 'uuid', 'password', 'keyfile'),
203 FROM
='hosts', WHERE
={'status': 'ok'})
205 raise ovimException("Cannot get hosts from database {}".format(hosts
))
207 self
.config
['host_threads'] = {}
210 thread
= ht
.host_thread(name
=host
['name'], user
=host
['user'], host
=host
['ip_name'], db
=self
.config
["db"],
211 password
=host
['password'],
212 keyfile
=host
.get('keyfile', self
.config
["host_ssh_keyfile"]),
213 db_lock
=self
.config
["db_lock"], test
=host_test_mode
,
214 image_path
=self
.config
['host_image_path'],
215 version
=self
.config
['version'], host_id
=host
['uuid'],
216 develop_mode
=host_develop_mode
,
217 develop_bridge_iface
=host_develop_bridge_iface
,
218 logger_name
=self
.logger_name
+ ".host." + host
['name'],
219 debug
=self
.config
.get('log_level_host'))
222 thread
.check_connectivity()
223 except Exception as e
:
224 self
.logger
.critical('Error detected for compute = {} with ip = {}'
225 .format(host
['name'], host
['ip_name']))
227 self
.config
['host_threads'][host
['uuid']] = thread
229 # precreate interfaces; [bridge:<host_bridge_name>, VLAN used at Host, uuid of network camping in this bridge,
232 self
.config
['dhcp_nets'] = []
233 self
.config
['bridge_nets'] = []
234 for bridge
, vlan_speed
in self
.config
["bridge_ifaces"].items():
235 # skip 'development_bridge'
236 if self
.config
['mode'] == 'development' and self
.config
['development_bridge'] == bridge
:
238 self
.config
['bridge_nets'].append([bridge
, vlan_speed
[0], vlan_speed
[1], None])
240 # check if this bridge is already used (present at database) for a network)
241 used_bridge_nets
= []
242 for brnet
in self
.config
['bridge_nets']:
243 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'provider': "bridge:" + brnet
[0]})
245 brnet
[3] = nets
[0]['uuid']
246 used_bridge_nets
.append(brnet
[0])
247 if self
.config
.get("dhcp_server"):
248 if brnet
[0] in self
.config
["dhcp_server"]["bridge_ifaces"]:
249 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
250 if len(used_bridge_nets
) > 0:
251 self
.logger
.info("found used bridge nets: " + ",".join(used_bridge_nets
))
252 # get nets used by dhcp
253 if self
.config
.get("dhcp_server"):
254 for net
in self
.config
["dhcp_server"].get("nets", ()):
255 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'name': net
})
257 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
260 self
._start
_ofc
_default
_task
()
262 # OFC per tenant in DB
263 self
._start
_of
_db
_tasks
()
265 # create dhcp_server thread
266 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
267 dhcp_params
= self
.config
.get("dhcp_server")
269 thread
= dt
.dhcp_thread(dhcp_params
=dhcp_params
, test
=host_test_mode
, dhcp_nets
=self
.config
["dhcp_nets"],
270 db
=self
.config
["db"], db_lock
=self
.config
["db_lock"],
271 logger_name
=self
.logger_name
+ ".dhcp",
272 debug
=self
.config
.get('log_level_of'))
274 self
.config
['dhcp_thread'] = thread
278 # create ovs dhcp thread
279 result
, content
= self
.db
.get_table(FROM
='nets')
281 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
282 raise ovimException(str(content
), -result
)
285 net_type
= net
['type']
286 if (net_type
== 'bridge_data' or net_type
== 'bridge_man') and \
287 net
["provider"][:4] == 'OVS:' and net
["enable_dhcp"] == "true":
289 routes
= yaml
.safe_load(net
.get('routes'))
290 dns
= yaml
.safe_load(net
.get('dns'))
291 self
.launch_dhcp_server(net
.get('vlan'),
292 net
.get('dhcp_first_ip'),
293 net
.get('dhcp_last_ip'),
295 net
.get('gateway_ip'),
298 self
.launch_link_bridge_to_ovs(net
['vlan'], net
.get('links'), net
.get('routes'))
299 except Exception as e
:
300 self
.logger
.error("Fail at launching dhcp server for net_id='%s' net_name='%s': %s",
301 net
["uuid"], net
["name"], str(e
))
302 self
.db
.update_rows("nets", {"status": "ERROR",
303 "last_error": "Fail at launching dhcp server: " + str(e
)},
304 {"uuid": net
["uuid"]})
306 def _start_of_db_tasks(self
):
308 Start ofc task for existing ofcs in database
313 ofcs
= self
.get_of_controllers()
316 of_conn
= self
._load
_of
_module
(ofc
)
317 # create ofc thread per of controller
318 self
._create
_ofc
_task
(ofc
['uuid'], ofc
['dpid'], of_conn
)
320 def _create_ofc_task(self
, ofc_uuid
, dpid
, of_conn
):
322 Create an ofc thread for handle each sdn controllers
323 :param ofc_uuid: sdn controller uuid
324 :param dpid: sdn controller dpid
325 :param of_conn: OF_conn module
328 if 'ofcs_thread' not in self
.config
and 'ofcs_thread_dpid' not in self
.config
:
330 ofcs_thread_dpid
= []
332 ofcs_threads
= self
.config
['ofcs_thread']
333 ofcs_thread_dpid
= self
.config
['ofcs_thread_dpid']
335 if ofc_uuid
not in ofcs_threads
:
336 ofc_thread
= self
._create
_ofc
_thread
(of_conn
, ofc_uuid
)
337 if ofc_uuid
== "Default":
338 self
.config
['of_thread'] = ofc_thread
340 ofcs_threads
[ofc_uuid
] = ofc_thread
341 self
.config
['ofcs_thread'] = ofcs_threads
343 ofcs_thread_dpid
.append({dpid
: ofc_thread
})
344 self
.config
['ofcs_thread_dpid'] = ofcs_thread_dpid
346 def _start_ofc_default_task(self
):
348 Create default ofc thread
350 if 'of_controller' not in self
.config \
351 and 'of_controller_ip' not in self
.config \
352 and 'of_controller_port' not in self
.config \
353 and 'of_controller_dpid' not in self
.config
:
358 db_config
['ip'] = self
.config
.get('of_controller_ip')
359 db_config
['port'] = self
.config
.get('of_controller_port')
360 db_config
['dpid'] = self
.config
.get('of_controller_dpid')
361 db_config
['type'] = self
.config
.get('of_controller')
362 db_config
['user'] = self
.config
.get('of_user')
363 db_config
['password'] = self
.config
.get('of_password')
365 # create connector to the openflow controller
366 # load other parameters starting by of_ from config dict in a temporal dict
368 of_conn
= self
._load
_of
_module
(db_config
)
369 # create openflow thread
370 self
._create
_ofc
_task
("Default", db_config
['dpid'], of_conn
)
372 def _load_of_module(self
, db_config
):
374 import python module for each SDN controller supported
375 :param db_config: SDN dn information
379 raise ovimException("No module found it", HTTP_Internal_Server_Error
)
384 if self
.of_test_mode
:
385 return openflow_conn
.OfTestConnector({"name": db_config
['type'],
386 "dpid": db_config
['dpid'],
387 "of_debug": self
.config
['log_level_of']})
391 temp_dict
['of_ip'] = db_config
['ip']
392 temp_dict
['of_port'] = db_config
['port']
393 temp_dict
['of_dpid'] = db_config
['dpid']
394 temp_dict
['of_controller'] = db_config
['type']
395 temp_dict
['of_user'] = db_config
.get('user')
396 temp_dict
['of_password'] = db_config
.get('password')
398 temp_dict
['of_debug'] = self
.config
['log_level_of']
400 if temp_dict
['of_controller'] == 'opendaylight':
403 module
= temp_dict
['of_controller']
405 if module
not in ovim
.of_module
:
407 pkg
= __import__("osm_openvim." + module
)
408 of_conn_module
= getattr(pkg
, module
)
409 ovim
.of_module
[module
] = of_conn_module
410 self
.logger
.debug("Module load from {}".format("osm_openvim." + module
))
411 except Exception as e
:
412 self
.logger
.error("Cannot open openflow controller module of type '%s'", module
)
413 raise ovimException("Cannot open openflow controller of type module '{}'"
414 "Revise it is installed".format(module
),
415 HTTP_Internal_Server_Error
)
417 of_conn_module
= ovim
.of_module
[module
]
418 return of_conn_module
.OF_conn(temp_dict
)
419 except Exception as e
:
420 self
.logger
.error("Cannot open the Openflow controller '%s': %s", type(e
).__name
__, str(e
))
421 raise ovimException("Cannot open the Openflow controller '{}': '{}'".format(type(e
).__name
__, str(e
)),
422 HTTP_Internal_Server_Error
)
424 def _create_ofc_thread(self
, of_conn
, ofc_uuid
="Default"):
426 Create and launch a of thread
429 # create openflow thread
431 #if 'of_controller_nets_with_same_vlan' in self.config:
432 # ofc_net_same_vlan = self.config['of_controller_nets_with_same_vlan']
434 # ofc_net_same_vlan = False
435 ofc_net_same_vlan
= False
437 thread
= oft
.openflow_thread(ofc_uuid
, of_conn
, of_test
=self
.of_test_mode
, db
=self
.config
["db"],
438 db_lock
=self
.config
["db_lock"],
439 pmp_with_same_vlan
=ofc_net_same_vlan
,
440 logger_name
=self
.logger_name
+ ".ofc." + ofc_uuid
,
441 debug
=self
.config
.get('log_level_of'))
442 #r, c = thread.OF_connector.obtain_port_correspondence()
444 # raise ovimException("Cannot get openflow information %s", c)
448 def stop_service(self
):
449 threads
= self
.config
.get('host_threads', {})
450 if 'of_thread' in self
.config
:
451 threads
['of'] = (self
.config
['of_thread'])
452 if 'ofcs_thread' in self
.config
:
453 ofcs_thread
= self
.config
['ofcs_thread']
454 for ofc
in ofcs_thread
:
455 threads
[ofc
] = ofcs_thread
[ofc
]
457 if 'dhcp_thread' in self
.config
:
458 threads
['dhcp'] = (self
.config
['dhcp_thread'])
460 for thread_id
, thread
in threads
.items():
461 if thread_id
== 'openvim_controller':
463 thread
.insert_task("exit")
464 for thread_id
, thread
in threads
.items():
465 if thread_id
== 'openvim_controller':
469 def get_networks(self
, columns
=None, db_filter
={}, limit
=None):
471 Retreive networks available
472 :param columns: List with select query parameters
473 :param db_filter: List with where query parameters
474 :param limit: Query limit result
477 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='nets', WHERE
=db_filter
, LIMIT
=limit
)
480 raise ovimException(str(content
), -result
)
482 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
486 def show_network(self
, network_id
, db_filter
={}):
488 Get network from DB by id
489 :param network_id: net Id
490 :param db_filter: List with where query parameters
495 raise ovimException("Not network id was not found")
496 db_filter
['uuid'] = network_id
498 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
=db_filter
, LIMIT
=100)
501 raise ovimException(str(content
), -result
)
503 raise ovimException("show_network network '%s' not found" % network_id
, -result
)
505 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
507 result
, ports
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
508 WHERE
={'net_id': network_id
}, LIMIT
=100)
510 content
[0]['ports'] = ports
512 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
515 def new_network(self
, network
):
520 tenant_id
= network
.get('tenant_id')
523 result
, _
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
, "enabled": True})
525 raise ovimException("set_network error, no tenant founded", -result
)
529 net_provider
= network
.get('provider')
530 net_type
= network
.get('type')
531 net_vlan
= network
.get("vlan")
532 net_bind_net
= network
.get("bind_net")
533 net_bind_type
= network
.get("bind_type")
534 net_region
= network
.get("region")
535 name
= network
["name"]
537 # check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
538 vlan_index
= name
.rfind(":")
539 if not net_bind_net
and not net_bind_type
and vlan_index
> 1:
541 vlan_tag
= int(name
[vlan_index
+ 1:])
542 if not vlan_tag
and vlan_tag
< 4096:
543 net_bind_net
= name
[:vlan_index
]
544 net_bind_type
= "vlan:" + name
[vlan_index
+ 1:]
549 # look for a valid net
550 if self
._check
_valid
_uuid
(net_bind_net
):
551 net_bind_key
= "uuid"
553 net_bind_key
= "name"
554 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
556 raise ovimException(' getting nets from db ' + content
, HTTP_Internal_Server_Error
)
558 raise ovimException(" bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
560 raise ovimException(" more than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
561 network
["bind_net"] = content
[0]["uuid"]
564 if net_bind_type
[0:5] != "vlan:":
565 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
566 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
567 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
569 network
["bind_type"] = net_bind_type
572 if net_provider
[:9] == "openflow:":
574 if net_type
!= "ptp" and net_type
!= "data":
575 raise ovimException(" only 'ptp' or 'data' net types can be bound to 'openflow'",
581 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
582 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound "
583 "to 'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
585 net_type
= 'bridge_man'
588 net_type
= 'bridge_man'
591 if net_provider
[:7] == 'bridge:':
592 # check it is one of the pre-provisioned bridges
593 bridge_net_name
= net_provider
[7:]
594 for brnet
in self
.config
['bridge_nets']:
595 if brnet
[0] == bridge_net_name
: # free
597 raise ovimException("invalid 'provider:physical', "
598 "bridge '%s' is already used" % bridge_net_name
, HTTP_Conflict
)
602 # if bridge_net==None:
603 # bottle.abort(HTTP_Bad_Request, "invalid 'provider:physical', bridge '%s' is not one of the
604 # provisioned 'bridge_ifaces' in the configuration file" % bridge_net_name)
607 elif self
.config
['network_type'] == 'bridge' and (net_type
== 'bridge_data' or net_type
== 'bridge_man'):
608 # look for a free precreated nets
609 for brnet
in self
.config
['bridge_nets']:
610 if not brnet
[3]: # free
612 if net_type
== 'bridge_man': # look for the smaller speed
613 if brnet
[2] < bridge_net
[2]:
615 else: # look for the larger speed
616 if brnet
[2] > bridge_net
[2]:
622 raise ovimException("Max limits of bridge networks reached. Future versions of VIM "
623 "will overcome this limit", HTTP_Bad_Request
)
625 self
.logger
.debug("using net " + bridge_net
)
626 net_provider
= "bridge:" + bridge_net
[0]
627 net_vlan
= bridge_net
[1]
628 elif net_type
== 'bridge_data' or net_type
== 'bridge_man' and self
.config
['network_type'] == 'ovs':
631 if net_type
== "data" or net_type
== "ptp":
632 net_region
= "__DATA__"
633 elif net_provider
== "OVS":
634 net_region
= "__OVS__"
635 if not net_vlan
and (net_type
== "data" or net_type
== "ptp" or net_provider
== "OVS"):
636 net_vlan
= self
.db
.get_free_net_vlan(net_region
)
638 raise ovimException("Error getting an available vlan", HTTP_Internal_Server_Error
)
639 if net_provider
== 'OVS':
640 net_provider
= 'OVS' + ":" + str(net_vlan
)
642 network
['provider'] = net_provider
643 network
['type'] = net_type
644 network
['vlan'] = net_vlan
645 network
['region'] = net_region
646 dhcp_integrity
= True
647 if 'enable_dhcp' in network
and network
['enable_dhcp']:
648 dhcp_integrity
= self
._check
_dhcp
_data
_integrity
(network
)
650 if network
.get('links'):
651 network
['links'] = yaml
.safe_dump(network
['links'], default_flow_style
=True, width
=256)
652 if network
.get('dns'):
653 network
['dns'] = yaml
.safe_dump(network
['dns'], default_flow_style
=True, width
=256)
654 if network
.get('routes'):
655 network
['routes'] = yaml
.safe_dump(network
['routes'], default_flow_style
=True, width
=256)
657 result
, content
= self
.db
.new_row('nets', network
, True, True)
659 if result
>= 0 and dhcp_integrity
:
661 bridge_net
[3] = content
662 if self
.config
.get("dhcp_server") and self
.config
['network_type'] == 'bridge':
663 if network
["name"] in self
.config
["dhcp_server"].get("nets", ()):
664 self
.config
["dhcp_nets"].append(content
)
665 self
.logger
.debug("dhcp_server: add new net", content
)
666 elif bridge_net
and bridge_net
[0] in self
.config
["dhcp_server"].get("bridge_ifaces", ()):
667 self
.config
["dhcp_nets"].append(content
)
668 self
.logger
.debug("dhcp_server: add new net", content
, content
)
671 raise ovimException("Error posting network", HTTP_Internal_Server_Error
)
672 # TODO kei change update->edit
674 def edit_network(self
, network_id
, network
):
676 Update entwork data byt id
679 # Look for the previous data
680 where_
= {'uuid': network_id
}
681 result
, network_old
= self
.db
.get_table(FROM
='nets', WHERE
=where_
)
683 raise ovimException("Error updating network %s" % network_old
, HTTP_Internal_Server_Error
)
685 raise ovimException('network %s not found' % network_id
, HTTP_Not_Found
)
687 nbports
, content
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
688 WHERE
={'net_id': network_id
}, LIMIT
=100)
690 raise ovimException("http_put_network_id error %d %s" % (result
, network_old
), HTTP_Internal_Server_Error
)
692 if 'type' in network
and network
['type'] != network_old
[0]['type']:
693 raise ovimException("Can not change type of network while having ports attached",
694 HTTP_Method_Not_Allowed
)
695 if 'vlan' in network
and network
['vlan'] != network_old
[0]['vlan']:
696 raise ovimException("Can not change vlan of network while having ports attached",
697 HTTP_Method_Not_Allowed
)
700 net_provider
= network
.get('provider', network_old
[0]['provider'])
701 net_type
= network
.get('type', network_old
[0]['type'])
702 net_bind_net
= network
.get("bind_net")
703 net_bind_type
= network
.get("bind_type")
705 # look for a valid net
706 if self
._check
_valid
_uuid
(net_bind_net
):
707 net_bind_key
= "uuid"
709 net_bind_key
= "name"
710 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
712 raise ovimException('Getting nets from db ' + content
, HTTP_Internal_Server_Error
)
714 raise ovimException("bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
716 raise ovimException("More than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
),
718 network
["bind_net"] = content
[0]["uuid"]
720 if net_bind_type
[0:5] != "vlan:":
721 raise ovimException("Bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
722 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
723 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
726 if net_provider
[:9] == "openflow:":
727 if net_type
!= "ptp" and net_type
!= "data":
728 raise ovimException("Only 'ptp' or 'data' net types can be bound to 'openflow'", HTTP_Bad_Request
)
730 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
731 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound to "
732 "'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
734 # insert in data base
735 result
, content
= self
.db
.update_rows('nets', network
, WHERE
={'uuid': network_id
}, log
=True)
737 # if result > 0 and nbports>0 and 'admin_state_up' in network
738 # and network['admin_state_up'] != network_old[0]['admin_state_up']:
743 self
.net_update_ofc_thread(network_id
)
744 except ovimException
as e
:
745 raise ovimException("Error while launching openflow rules in network '{}' {}"
746 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
747 except Exception as e
:
748 raise ovimException("Error while launching openflow rules in network '{}' {}"
749 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
751 if self
.config
.get("dhcp_server"):
752 if network_id
in self
.config
["dhcp_nets"]:
753 self
.config
["dhcp_nets"].remove(network_id
)
754 if network
.get("name", network_old
[0]["name"]) in self
.config
["dhcp_server"].get("nets", ()):
755 self
.config
["dhcp_nets"].append(network_id
)
757 net_bind
= network
.get("bind_type", network_old
[0]["bind_type"])
758 if net_bind
and net_bind
and net_bind
[:7] == "bridge:" and net_bind
[7:] in self
.config
["dhcp_server"].get(
759 "bridge_ifaces", ()):
760 self
.config
["dhcp_nets"].append(network_id
)
763 raise ovimException(content
, -result
)
765 def delete_network(self
, network_id
):
767 Delete network by network id
768 :param network_id: network id
772 # delete from the data base
773 result
, content
= self
.db
.delete_row('nets', network_id
)
776 raise ovimException("Network %s not found " % network_id
, HTTP_Not_Found
)
778 for brnet
in self
.config
['bridge_nets']:
779 if brnet
[3] == network_id
:
782 if self
.config
.get("dhcp_server") and network_id
in self
.config
["dhcp_nets"]:
783 self
.config
["dhcp_nets"].remove(network_id
)
786 raise ovimException("Error deleting network '{}': {}".format(network_id
, content
), -result
)
788 def get_openflow_rules(self
, network_id
=None):
790 Get openflow id from DB
791 :param network_id: Network id, if none all networks will be retrieved
792 :return: Return a list with Openflow rules per net
798 where_
= {"net_id": network_id
}
799 result
, content
= self
.db
.get_table(
800 SELECT
=("name", "net_id", "ofc_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
801 WHERE
=where_
, FROM
='of_flows')
804 raise ovimException(str(content
), -result
)
807 def edit_openflow_rules(self
, network_id
=None):
810 To make actions over the net. The action is to reinstall the openflow rules
811 network_id can be 'all'
812 :param network_id: Network id, if none all networks will be retrieved
813 :return : Number of nets updated
820 where_
= {"uuid": network_id
}
821 result
, content
= self
.db
.get_table(SELECT
=("uuid", "type"), WHERE
=where_
, FROM
='nets')
824 raise ovimException(str(content
), -result
)
827 if net
["type"] != "ptp" and net
["type"] != "data":
832 self
.net_update_ofc_thread(net
['uuid'])
833 except ovimException
as e
:
834 raise ovimException("Error updating network'{}' {}".format(net
['uuid'], str(e
)),
835 HTTP_Internal_Server_Error
)
836 except Exception as e
:
837 raise ovimException("Error updating network '{}' {}".format(net
['uuid'], str(e
)),
838 HTTP_Internal_Server_Error
)
842 def delete_openflow_rules(self
, ofc_id
=None):
844 To make actions over the net. The action is to delete ALL openflow rules
845 :return: return operation result
849 if 'Default' in self
.config
['ofcs_thread']:
850 r
, c
= self
.config
['ofcs_thread']['Default'].insert_task("clear-all")
852 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
854 elif ofc_id
in self
.config
['ofcs_thread']:
855 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("clear-all")
859 raise ovimException(str(c
), -r
)
861 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
864 def get_openflow_ports(self
, ofc_id
=None):
866 Obtain switch ports names of openflow controller
867 :return: Return flow ports in DB
870 if 'Default' in self
.config
['ofcs_thread']:
871 conn
= self
.config
['ofcs_thread']['Default'].OF_connector
873 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
875 elif ofc_id
in self
.config
['ofcs_thread']:
876 conn
= self
.config
['ofcs_thread'][ofc_id
].OF_connector
878 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
881 def get_ports(self
, columns
=None, filter={}, limit
=None):
882 # result, content = my.db.get_ports(where_)
883 result
, content
= self
.db
.get_table(SELECT
=columns
, WHERE
=filter, FROM
='ports', LIMIT
=limit
)
885 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
886 raise ovimException(str(content
), -result
)
888 convert_boolean(content
, ('admin_state_up',))
891 def new_port(self
, port_data
):
892 port_data
['type'] = 'external'
893 if port_data
.get('net_id'):
894 # check that new net has the correct type
895 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
897 raise ovimException(str(new_net
), -result
)
898 # insert in data base
899 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
901 if 'net_id' in port_data
:
903 self
.net_update_ofc_thread(port_data
['net_id'])
904 except ovimException
as e
:
905 raise ovimException("Cannot insert a task for updating network '{}' {}"
906 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
907 except Exception as e
:
908 raise ovimException("Cannot insert a task for updating network '{}' {}"
909 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
913 raise ovimException(str(uuid
), -result
)
915 def new_external_port(self
, port_data
):
917 Create new external port and check port mapping correspondence
918 :param port_data: port_data = {
919 'region': 'datacenter region',
920 'compute_node': 'compute node id',
921 'pci': 'pci port address',
924 'tenant_id': 'tenant id',
927 'ip_address': 'ip address - optional'}
931 port_data
['type'] = 'external'
933 if port_data
.get('net_id'):
934 # check that new net has the correct type
935 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
937 raise ovimException(str(new_net
), -result
)
938 # insert in data base
941 if port_data
.get('region'):
942 db_filter
['region'] = port_data
['region']
943 if port_data
.get('pci'):
944 db_filter
['pci'] = port_data
['pci']
945 if port_data
.get('compute_node'):
946 db_filter
['compute_node'] = port_data
['compute_node']
948 columns
= ['ofc_id', 'switch_dpid', 'switch_port', 'switch_mac', 'pci']
949 port_mapping_data
= self
.get_of_port_mappings(columns
, db_filter
)
951 if not len(port_mapping_data
):
952 raise ovimException("No port mapping founded for '{}'".format(str(db_filter
)),
954 elif len(port_mapping_data
) > 1:
955 raise ovimException("Wrong port data was given, please check pci, region & compute id data",
958 port_data
['ofc_id'] = port_mapping_data
[0]['ofc_id']
959 port_data
['switch_dpid'] = port_mapping_data
[0]['switch_dpid']
960 port_data
['switch_port'] = port_mapping_data
[0]['switch_port']
961 port_data
['switch_mac'] = port_mapping_data
[0]['switch_mac']
963 # remove from compute_node, region and pci of_port_data to adapt to 'ports' structure
964 if 'region' in port_data
:
965 del port_data
['region']
966 if 'pci' in port_data
:
968 if 'compute_node' in port_data
:
969 del port_data
['compute_node']
971 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
974 self
.net_update_ofc_thread(port_data
['net_id'], port_data
['ofc_id'])
975 except ovimException
as e
:
976 raise ovimException("Cannot insert a task for updating network '{}' {}".
977 format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
978 except Exception as e
:
979 raise ovimException("Cannot insert a task for updating network '{}' {}"
980 .format(port_data
['net_id'], e
), HTTP_Internal_Server_Error
)
983 raise ovimException(str(uuid
), -result
)
985 def net_update_ofc_thread(self
, net_id
, ofc_id
=None, switch_dpid
=None):
987 Insert a update net task by net id or ofc_id for each ofc thread
988 :param net_id: network id
989 :param ofc_id: openflow controller id
990 :param switch_dpid: switch dpid
994 raise ovimException("No net_id received", HTTP_Internal_Server_Error
)
997 c
= 'No valid ofc_id or switch_dpid received'
1000 ports
= self
.get_ports(filter={"net_id": net_id
})
1002 port_ofc_id
= port
.get('ofc_id', None)
1004 ofc_id
= port
['ofc_id']
1005 switch_dpid
= port
['switch_dpid']
1007 #TODO if not ofc_id: look at database table ofcs
1010 # If no ofc_id found it, default ofc_id is used.
1011 if not ofc_id
and not switch_dpid
:
1014 if ofc_id
and ofc_id
in self
.config
['ofcs_thread']:
1015 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("update-net", net_id
)
1018 ofcs_dpid_list
= self
.config
['ofcs_thread_dpid']
1019 for ofc_t
in ofcs_dpid_list
:
1020 if switch_dpid
in ofc_t
:
1021 r
, c
= ofc_t
[switch_dpid
].insert_task("update-net", net_id
)
1024 message
= "Cannot insert a task for updating network '{}', {}".format(net_id
, c
)
1025 self
.logger
.error(message
)
1026 raise ovimException(message
, HTTP_Internal_Server_Error
)
1028 def delete_port(self
, port_id
):
1029 # Look for the previous port data
1030 result
, ports
= self
.db
.get_table(WHERE
={'uuid': port_id
, "type": "external"}, FROM
='ports')
1032 raise ovimException("Cannot get port info from database: {}".format(ports
), http_code
=-result
)
1033 # delete from the data base
1034 result
, content
= self
.db
.delete_row('ports', port_id
)
1036 raise ovimException("External port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
1038 raise ovimException("Cannot delete port from database: {}".format(content
), http_code
=-result
)
1040 network
= ports
[0].get('net_id', None)
1045 self
.net_update_ofc_thread(network
, ofc_id
=ports
[0]["ofc_id"], switch_dpid
=ports
[0]["switch_dpid"])
1046 except ovimException
as e
:
1047 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1048 HTTP_Internal_Server_Error
)
1049 except Exception as e
:
1050 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1051 HTTP_Internal_Server_Error
)
1055 def edit_port(self
, port_id
, port_data
, admin
=True):
1056 # Look for the previous port data
1057 result
, content
= self
.db
.get_table(FROM
="ports", WHERE
={'uuid': port_id
})
1059 raise ovimException("Cannot get port info from database: {}".format(content
), http_code
=-result
)
1061 raise ovimException("Port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
1066 if 'net_id' in port_data
:
1068 old_net
= port
.get('net_id', None)
1069 new_net
= port_data
['net_id']
1070 if old_net
!= new_net
:
1073 nets
.append(new_net
) # put first the new net, so that new openflow rules are created before removing the old ones
1075 nets
.append(old_net
)
1076 if port
['type'] == 'instance:bridge' or port
['type'] == 'instance:ovs':
1077 raise ovimException("bridge interfaces cannot be attached to a different net", http_code
=HTTP_Forbidden
)
1078 elif port
['type'] == 'external' and not admin
:
1079 raise ovimException("Needed admin privileges",http_code
=HTTP_Unauthorized
)
1081 # check that new net has the correct type
1082 result
, new_net_dict
= self
.db
.check_target_net(new_net
, None, port
['type'])
1084 raise ovimException("Error {}".format(new_net_dict
), http_code
=HTTP_Conflict
)
1085 # change VLAN for SR-IOV ports
1086 if result
>= 0 and port
["type"] == "instance:data" and port
["model"] == "VF": # TODO consider also VFnotShared
1088 port_data
["vlan"] = None
1090 port_data
["vlan"] = new_net_dict
["vlan"]
1091 # get host where this VM is allocated
1092 result
, content
= self
.db
.get_table(FROM
="instances", WHERE
={"uuid": port
["instance_id"]})
1094 host_id
= content
[0]["host_id"]
1096 # insert in data base
1098 result
, content
= self
.db
.update_rows('ports', port_data
, WHERE
={'uuid': port_id
}, log
=False)
1099 port
.update(port_data
)
1101 # Insert task to complete actions
1105 self
.net_update_ofc_thread(net_id
, port
["ofc_id"], switch_dpid
=port
["switch_dpid"])
1106 except ovimException
as e
:
1107 raise ovimException("Error updating network'{}' {}".format(net_id
, str(e
)),
1108 HTTP_Internal_Server_Error
)
1109 except Exception as e
:
1110 raise ovimException("Error updating network '{}' {}".format(net_id
, str(e
)),
1111 HTTP_Internal_Server_Error
)
1114 r
, v
= self
.config
['host_threads'][host_id
].insert_task("edit-iface", port_id
, old_net
, new_net
)
1116 self
.logger
.error("Error updating network '{}' {}".format(r
,v
))
1117 # TODO Do something if fails
1121 raise ovimException("Error {}".format(content
), http_code
=-result
)
1123 def new_of_controller(self
, ofc_data
):
1125 Create a new openflow controller into DB
1126 :param ofc_data: Dict openflow controller data
1127 :return: openflow controller dpid
1130 result
, ofc_uuid
= self
.db
.new_row('ofcs', ofc_data
, True, True)
1132 raise ovimException("New ofc Error %s" % ofc_uuid
, HTTP_Internal_Server_Error
)
1134 ofc_data
['uuid'] = ofc_uuid
1135 of_conn
= self
._load
_of
_module
(ofc_data
)
1136 self
._create
_ofc
_task
(ofc_uuid
, ofc_data
['dpid'], of_conn
)
1140 def edit_of_controller(self
, of_id
, ofc_data
):
1142 Edit an openflow controller entry from DB
1146 raise ovimException("No data received during uptade OF contorller", http_code
=HTTP_Internal_Server_Error
)
1148 old_of_controller
= self
.show_of_controller(of_id
)
1150 if old_of_controller
:
1151 result
, content
= self
.db
.update_rows('ofcs', ofc_data
, WHERE
={'uuid': of_id
}, log
=False)
1155 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1158 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1159 http_code
=HTTP_Internal_Server_Error
)
1161 def delete_of_controller(self
, of_id
):
1163 Delete an openflow controller from DB.
1164 :param of_id: openflow controller dpid
1168 ofc
= self
.show_of_controller(of_id
)
1170 result
, content
= self
.db
.delete_row("ofcs", of_id
)
1172 raise ovimException("Cannot delete ofc from database: {}".format(content
), http_code
=-result
)
1174 raise ovimException("ofc {} not found ".format(content
), http_code
=HTTP_Not_Found
)
1176 ofc_thread
= self
.config
['ofcs_thread'][of_id
]
1177 del self
.config
['ofcs_thread'][of_id
]
1178 for ofc_th
in self
.config
['ofcs_thread_dpid']:
1179 if ofc
['dpid'] in ofc_th
:
1180 self
.config
['ofcs_thread_dpid'].remove(ofc_th
)
1182 ofc_thread
.insert_task("exit")
1187 def show_of_controller(self
, uuid
):
1189 Show an openflow controller by dpid from DB.
1190 :param db_filter: List with where query parameters
1194 result
, content
= self
.db
.get_table(FROM
='ofcs', WHERE
={"uuid": uuid
}, LIMIT
=100)
1197 raise ovimException("Openflow controller with uuid '{}' not found".format(uuid
),
1198 http_code
=HTTP_Not_Found
)
1200 raise ovimException("Openflow controller with uuid '{}' error".format(uuid
),
1201 http_code
=HTTP_Internal_Server_Error
)
1204 def get_of_controllers(self
, columns
=None, db_filter
={}, limit
=None):
1206 Show an openflow controllers from DB.
1207 :param columns: List with SELECT query parameters
1208 :param db_filter: List with where query parameters
1209 :param limit: result Limit
1212 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='ofcs', WHERE
=db_filter
, LIMIT
=limit
)
1215 raise ovimException(str(content
), -result
)
1219 def get_tenants(self
, columns
=None, db_filter
={}, limit
=None):
1221 Retrieve tenant list from DB
1222 :param columns: List with SELECT query parameters
1223 :param db_filter: List with where query parameters
1224 :param limit: result limit
1227 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=columns
, WHERE
=db_filter
, LIMIT
=limit
)
1229 raise ovimException('get_tenatns Error {}'.format(str(content
)), -result
)
1231 convert_boolean(content
, ('enabled',))
1234 def show_tenant_id(self
, tenant_id
):
1236 Get tenant from DB by id
1237 :param tenant_id: tenant id
1240 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid', 'name', 'description', 'enabled'),
1241 WHERE
={"uuid": tenant_id
})
1243 raise ovimException(str(content
), -result
)
1245 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1247 convert_boolean(content
, ('enabled',))
1250 def new_tentant(self
, tenant
):
1252 Create a tenant and store in DB
1253 :param tenant: Dictionary with tenant data
1254 :return: the uuid of created tenant. Raise exception upon error
1257 # insert in data base
1258 result
, tenant_uuid
= self
.db
.new_tenant(tenant
)
1263 raise ovimException(str(tenant_uuid
), -result
)
1265 def delete_tentant(self
, tenant_id
):
1267 Delete a tenant from the database.
1268 :param tenant_id: Tenant id
1269 :return: delete tenant id
1273 r
, tenants_flavors
= self
.db
.get_table(FROM
='tenants_flavors', SELECT
=('flavor_id', 'tenant_id'),
1274 WHERE
={'tenant_id': tenant_id
})
1276 tenants_flavors
= ()
1277 r
, tenants_images
= self
.db
.get_table(FROM
='tenants_images', SELECT
=('image_id', 'tenant_id'),
1278 WHERE
={'tenant_id': tenant_id
})
1282 result
, content
= self
.db
.delete_row('tenants', tenant_id
)
1284 raise ovimException("tenant '%s' not found" % tenant_id
, HTTP_Not_Found
)
1286 for flavor
in tenants_flavors
:
1287 self
.db
.delete_row_by_key("flavors", "uuid", flavor
['flavor_id'])
1288 for image
in tenants_images
:
1289 self
.db
.delete_row_by_key("images", "uuid", image
['image_id'])
1292 raise ovimException("Error deleting tenant '%s' " % tenant_id
, HTTP_Internal_Server_Error
)
1294 def edit_tenant(self
, tenant_id
, tenant_data
):
1296 Update a tenant data identified by tenant id
1297 :param tenant_id: tenant id
1298 :param tenant_data: Dictionary with tenant data
1302 # Look for the previous data
1303 result
, tenant_data_old
= self
.db
.get_table(FROM
='tenants', WHERE
={'uuid': tenant_id
})
1305 raise ovimException("Error updating tenant with uuid='{}': {}".format(tenant_id
, tenant_data_old
),
1306 HTTP_Internal_Server_Error
)
1308 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1310 # insert in data base
1311 result
, content
= self
.db
.update_rows('tenants', tenant_data
, WHERE
={'uuid': tenant_id
}, log
=True)
1315 raise ovimException(str(content
), -result
)
1317 def set_of_port_mapping(self
, of_maps
, ofc_id
=None, switch_dpid
=None, region
=None):
1319 Create new port mapping entry
1320 :param of_maps: List with port mapping information
1321 # maps =[{"ofc_id": <ofc_id>,"region": datacenter region,"compute_node": compute uuid,"pci": pci adress,
1322 "switch_dpid": swith dpid,"switch_port": port name,"switch_mac": mac}]
1323 :param ofc_id: ofc id
1324 :param switch_dpid: switch dpid
1325 :param region: datacenter region id
1331 map['ofc_id'] = ofc_id
1333 map['switch_dpid'] = switch_dpid
1335 map['region'] = region
1337 for of_map
in of_maps
:
1338 result
, uuid
= self
.db
.new_row('of_port_mappings', of_map
, True)
1340 of_map
["uuid"] = uuid
1342 raise ovimException(str(uuid
), -result
)
1345 def clear_of_port_mapping(self
, db_filter
={}):
1347 Clear port mapping filtering using db_filter dict
1348 :param db_filter: Parameter to filter during remove process
1351 result
, content
= self
.db
.delete_row_by_dict(FROM
='of_port_mappings', WHERE
=db_filter
)
1356 raise ovimException("Error deleting of_port_mappings with filter='{}'".format(str(db_filter
)),
1357 HTTP_Internal_Server_Error
)
1359 def get_of_port_mappings(self
, column
=None, db_filter
=None, db_limit
=None):
1361 Retrive port mapping from DB
1366 result
, content
= self
.db
.get_table(SELECT
=column
, WHERE
=db_filter
, FROM
='of_port_mappings', LIMIT
=db_limit
)
1369 self
.logger
.error("get_of_port_mappings Error %d %s", result
, content
)
1370 raise ovimException(str(content
), -result
)
1374 def get_dhcp_controller(self
):
1376 Create an host_thread object for manage openvim controller and not create a thread for itself
1377 :return: dhcp_host openvim controller object
1380 if 'openvim_controller' in self
.config
['host_threads']:
1381 return self
.config
['host_threads']['openvim_controller']
1384 controller_ip
= self
.config
['ovs_controller_ip']
1385 ovs_controller_user
= self
.config
.get('ovs_controller_user')
1387 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
1388 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
1390 dhcp_host
= ht
.host_thread(name
='openvim_controller', user
=ovs_controller_user
, host
=controller_ip
,
1391 password
=self
.config
.get('ovs_controller_password'),
1392 keyfile
=self
.config
.get('ovs_controller_keyfile'),
1393 db
=self
.config
["db"], db_lock
=self
.config
["db_lock"], test
=host_test_mode
,
1394 image_path
=self
.config
['host_image_path'], version
=self
.config
['version'],
1395 host_id
='openvim_controller', develop_mode
=host_develop_mode
,
1396 develop_bridge_iface
=bridge_ifaces
,
1397 logger_name
=self
.logger_name
+ ".host.controller",
1398 debug
=self
.config
.get('log_level_host'))
1400 self
.config
['host_threads']['openvim_controller'] = dhcp_host
1402 dhcp_host
.check_connectivity()
1403 except Exception as e
:
1408 def launch_dhcp_server(self
, vlan
, first_ip
, last_ip
, cidr
, gateway
, dns
, routes
):
1410 Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
1411 :param vlan: vlan identifier
1412 :param first_ip: First dhcp range ip
1413 :param last_ip: Last dhcp range ip
1414 :param cidr: net cidr
1415 :param gateway: net gateway
1418 ip_tools
= IPNetwork(cidr
)
1419 dhcp_netmask
= str(ip_tools
.netmask
)
1420 ip_range
= [first_ip
, last_ip
]
1422 dhcp_path
= self
.config
['ovs_controller_file_path']
1424 controller_host
= self
.get_dhcp_controller()
1425 # TODO leo check if is need ti to create an ovim-vlan bridge, looks like not
1426 # controller_host.create_linux_bridge(vlan)
1427 controller_host
.create_dhcp_interfaces(vlan
, first_ip
, dhcp_netmask
)
1428 dhcp_path
= self
.config
['ovs_controller_file_path']
1429 controller_host
.launch_dhcp_server(vlan
, ip_range
, dhcp_netmask
, dhcp_path
, gateway
, dns
, routes
)
1431 def launch_link_bridge_to_ovs(self
, vlan
, gateway
, dhcp_cidr
, links
=None, routes
=None):
1433 Launch creating of connections (veth) between user bridge (link) and OVS
1441 controller_host
= self
.get_dhcp_controller()
1443 if 'iface' in link
and 'nat' not in link
:
1444 controller_host
.create_link_bridge_to_ovs(vlan
, link
['iface'])
1446 controller_host
.create_qrouter_ovs_connection(vlan
, gateway
, dhcp_cidr
)
1447 controller_host
.create_qrouter_br_connection(vlan
, dhcp_cidr
, link
)
1450 controller_host
.add_ns_routes(vlan
, routes
)
1452 def delete_link_bridge_to_ovs(self
, vlan
, links
=None):
1454 Delete connections (veth) between user bridge (link) and OVS
1460 controller_host
= self
.get_dhcp_controller()
1463 if 'iface' in link
and 'nat' not in link
:
1464 controller_host
.remove_link_bridge_to_ovs(vlan
, link
['iface'])
1466 controller_host
.delete_qrouter_connection(vlan
, link
['iface'])
1469 if __name__
== "__main__":
1471 parser
= argparse
.ArgumentParser()
1472 parser
.add_argument("-v","--version", help="show ovim library version", action
="store_true")
1473 parser
.add_argument("--database-version", help="show required database version", action
="store_true")
1474 args
= parser
.parse_args()
1476 print ('openvimd version {} {}'.format(ovim
.get_version(), ovim
.get_version_date()))
1477 print ('(c) Copyright Telefonica')
1478 elif args
.database_version
:
1479 print ('required database version: {}'.format(ovim
.get_database_version()))