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.
30 __author__
= "Alfonso Tierno, Leonardo Mirabal"
31 __date__
= "$06-Feb-2017 12:07:15$"
32 __version__
= "0.5.10-r526"
33 version_date
= "Apr 2017"
34 database_version
= "0.17" #expected database schema version
37 import osm_openvim
.vim_db
as vim_db
41 from netaddr
import IPNetwork
42 from jsonschema
import validate
as js_v
, exceptions
as js_e
43 import osm_openvim
.host_thread
as ht
44 import osm_openvim
.dhcp_thread
as dt
45 import osm_openvim
.openflow_thread
as oft
46 import osm_openvim
.openflow_conn
as openflow_conn
49 HTTP_Bad_Request
= 400
50 HTTP_Unauthorized
= 401
53 HTTP_Method_Not_Allowed
= 405
54 HTTP_Not_Acceptable
= 406
55 HTTP_Request_Timeout
= 408
57 HTTP_Service_Unavailable
= 503
58 HTTP_Internal_Server_Error
= 500
61 def convert_boolean(data
, items
):
62 '''Check recursively the content of data, and if there is an key contained in items, convert value from string to boolean
63 It assumes that bandwidth is well formed
65 'data': dictionary bottle.FormsDict variable to be checked. None or empty is consideted valid
66 'items': tuple of keys to convert
70 if type(data
) is dict:
72 if type(data
[k
]) is dict or type(data
[k
]) is tuple or type(data
[k
]) is list:
73 convert_boolean(data
[k
], items
)
75 if type(data
[k
]) is str:
76 if data
[k
] == "false":
78 elif data
[k
] == "true":
80 if type(data
) is tuple or type(data
) is list:
82 if type(k
) is dict or type(k
) is tuple or type(k
) is list:
83 convert_boolean(k
, items
)
87 class ovimException(Exception):
88 def __init__(self
, message
, http_code
=HTTP_Bad_Request
):
89 self
.http_code
= http_code
90 Exception.__init
__(self
, message
)
94 running_info
= {} #TODO OVIM move the info of running threads from config_dic to this static variable
97 def __init__(self
, configuration
):
98 self
.config
= configuration
99 self
.logger_name
= configuration
.get("logger_name", "openvim")
100 self
.logger
= logging
.getLogger(self
.logger_name
)
102 self
.db
= self
._create
_database
_connection
()
105 self
.of_test_mode
= False
107 def _create_database_connection(self
):
108 db
= vim_db
.vim_db((self
.config
["network_vlan_range_start"], self
.config
["network_vlan_range_end"]),
109 self
.logger_name
+ ".db", self
.config
.get('log_level_db'))
110 if db
.connect(self
.config
['db_host'], self
.config
['db_user'], self
.config
['db_passwd'],
111 self
.config
['db_name']) == -1:
112 # self.logger.error("Cannot connect to database %s at %s@%s", self.config['db_name'], self.config['db_user'],
113 # self.config['db_host'])
114 raise ovimException("Cannot connect to database {} at {}@{}".format(self
.config
['db_name'],
115 self
.config
['db_user'],
116 self
.config
['db_host']) )
124 def get_version_date():
128 def get_database_version():
129 return database_version
132 def _check_dhcp_data_integrity(network
):
134 Check if all dhcp parameter for anet are valid, if not will be calculated from cidr value
135 :param network: list with user nets paramters
138 if "cidr" in network
:
139 cidr
= network
["cidr"]
140 ip_tools
= IPNetwork(cidr
)
141 cidr_len
= ip_tools
.prefixlen
145 ips
= IPNetwork(cidr
)
146 if "dhcp_first_ip" not in network
:
147 network
["dhcp_first_ip"] = str(ips
[2])
148 if "dhcp_last_ip" not in network
:
149 network
["dhcp_last_ip"] = str(ips
[-2])
150 if "gateway_ip" not in network
:
151 network
["gateway_ip"] = str(ips
[1])
158 def _check_valid_uuid(uuid
):
159 id_schema
= {"type": "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
161 js_v(uuid
, id_schema
)
163 except js_e
.ValidationError
:
166 def start_service(self
):
171 global database_version
172 # if self.running_info:
173 # return #TODO service can be checked and rebuild broken threads
174 r
= self
.db
.get_db_version()
176 raise ovimException("DATABASE is not a VIM one or it is a '0.0' version. Try to upgrade to version '{}' with "\
177 "'./database_utils/migrate_vim_db.sh'".format(database_version
) )
178 elif r
[1] != database_version
:
179 raise ovimException("DATABASE wrong version '{}'. Try to upgrade/downgrade to version '{}' with "\
180 "'./database_utils/migrate_vim_db.sh'".format(r
[1], database_version
) )
181 self
.logger
.critical("Starting ovim server version: '{} {}' database version '{}'".format(
182 self
.get_version(), self
.get_version_date(), self
.get_database_version()))
183 # create database connection for openflow threads
184 self
.db_of
= self
._create
_database
_connection
()
185 self
.config
["db"] = self
.db_of
186 self
.db_lock
= threading
.Lock()
187 self
.config
["db_lock"] = self
.db_lock
189 self
.of_test_mode
= False if self
.config
['mode'] == 'normal' or self
.config
['mode'] == "OF only" else True
190 # precreate interfaces; [bridge:<host_bridge_name>, VLAN used at Host, uuid of network camping in this bridge,
193 self
.config
['dhcp_nets'] = []
194 self
.config
['bridge_nets'] = []
195 for bridge
, vlan_speed
in self
.config
["bridge_ifaces"].items():
196 # skip 'development_bridge'
197 if self
.config
['mode'] == 'development' and self
.config
['development_bridge'] == bridge
:
199 self
.config
['bridge_nets'].append([bridge
, vlan_speed
[0], vlan_speed
[1], None])
201 # check if this bridge is already used (present at database) for a network)
202 used_bridge_nets
= []
203 for brnet
in self
.config
['bridge_nets']:
204 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'provider': "bridge:" + brnet
[0]})
206 brnet
[3] = nets
[0]['uuid']
207 used_bridge_nets
.append(brnet
[0])
208 if self
.config
.get("dhcp_server"):
209 if brnet
[0] in self
.config
["dhcp_server"]["bridge_ifaces"]:
210 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
211 if len(used_bridge_nets
) > 0:
212 self
.logger
.info("found used bridge nets: " + ",".join(used_bridge_nets
))
213 # get nets used by dhcp
214 if self
.config
.get("dhcp_server"):
215 for net
in self
.config
["dhcp_server"].get("nets", ()):
216 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'name': net
})
218 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
221 self
._start
_ofc
_default
_task
()
223 # OFC per tenant in DB
224 self
._start
_of
_db
_tasks
()
226 # create dhcp_server thread
227 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
228 dhcp_params
= self
.config
.get("dhcp_server")
230 thread
= dt
.dhcp_thread(dhcp_params
=dhcp_params
, test
=host_test_mode
, dhcp_nets
=self
.config
["dhcp_nets"],
231 db
=self
.db_of
, db_lock
=self
.db_lock
, logger_name
=self
.logger_name
+ ".dhcp",
232 debug
=self
.config
.get('log_level_of'))
234 self
.config
['dhcp_thread'] = thread
236 # Create one thread for each host
237 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
238 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
239 host_develop_bridge_iface
= self
.config
.get('development_bridge', None)
241 # get host list from data base before starting threads
242 r
, hosts
= self
.db
.get_table(SELECT
=('name', 'ip_name', 'user', 'uuid'), FROM
='hosts', WHERE
={'status': 'ok'})
244 raise ovimException("Cannot get hosts from database {}".format(hosts
))
246 self
.config
['host_threads'] = {}
248 host
['image_path'] = '/opt/VNF/images/openvim'
249 thread
= ht
.host_thread(name
=host
['name'], user
=host
['user'], host
=host
['ip_name'], db
=self
.db_of
,
250 db_lock
=self
.db_lock
, test
=host_test_mode
, image_path
=self
.config
['image_path'],
251 version
=self
.config
['version'], host_id
=host
['uuid'], develop_mode
=host_develop_mode
,
252 develop_bridge_iface
=host_develop_bridge_iface
)
254 self
.config
['host_threads'][host
['uuid']] = thread
256 # create ovs dhcp thread
257 result
, content
= self
.db
.get_table(FROM
='nets')
259 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
260 raise ovimException(str(content
), -result
)
263 net_type
= net
['type']
264 if (net_type
== 'bridge_data' or net_type
== 'bridge_man') \
265 and net
["provider"][:4] == 'OVS:' and net
["enable_dhcp"] == "true":
266 self
.launch_dhcp_server(net
['vlan'],
267 net
['dhcp_first_ip'],
272 def _start_of_db_tasks(self
):
274 Start ofc task for existing ofcs in database
279 ofcs
= self
.get_of_controllers()
282 of_conn
= self
._load
_of
_module
(ofc
)
283 # create ofc thread per of controller
284 self
._create
_ofc
_task
(ofc
['uuid'], ofc
['dpid'], of_conn
)
286 def _create_ofc_task(self
, ofc_uuid
, dpid
, of_conn
):
288 Create an ofc thread for handle each sdn controllers
289 :param ofc_uuid: sdn controller uuid
290 :param dpid: sdn controller dpid
291 :param of_conn: OF_conn module
294 if 'ofcs_thread' not in self
.config
and 'ofcs_thread_dpid' not in self
.config
:
296 ofcs_thread_dpid
= []
298 ofcs_threads
= self
.config
['ofcs_thread']
299 ofcs_thread_dpid
= self
.config
['ofcs_thread_dpid']
301 if ofc_uuid
not in ofcs_threads
:
302 ofc_thread
= self
._create
_ofc
_thread
(of_conn
, ofc_uuid
)
303 if ofc_uuid
== "Default":
304 self
.config
['of_thread'] = ofc_thread
306 ofcs_threads
[ofc_uuid
] = ofc_thread
307 self
.config
['ofcs_thread'] = ofcs_threads
309 ofcs_thread_dpid
.append({dpid
: ofc_thread
})
310 self
.config
['ofcs_thread_dpid'] = ofcs_thread_dpid
312 def _start_ofc_default_task(self
):
314 Create default ofc thread
316 if 'of_controller' not in self
.config \
317 and 'of_controller_ip' not in self
.config \
318 and 'of_controller_port' not in self
.config \
319 and 'of_controller_dpid' not in self
.config
:
324 db_config
['ip'] = self
.config
.get('of_controller_ip')
325 db_config
['port'] = self
.config
.get('of_controller_port')
326 db_config
['dpid'] = self
.config
.get('of_controller_dpid')
327 db_config
['type'] = self
.config
.get('of_controller')
328 db_config
['user'] = self
.config
.get('of_user')
329 db_config
['password'] = self
.config
.get('of_password')
331 # create connector to the openflow controller
332 # load other parameters starting by of_ from config dict in a temporal dict
334 of_conn
= self
._load
_of
_module
(db_config
)
335 # create openflow thread
336 self
._create
_ofc
_task
("Default", db_config
['dpid'], of_conn
)
338 def _load_of_module(self
, db_config
):
340 import python module for each SDN controller supported
341 :param db_config: SDN dn information
345 raise ovimException("No module found it", HTTP_Internal_Server_Error
)
350 if self
.of_test_mode
:
351 return openflow_conn
.OfTestConnector({"name": db_config
['type'],
352 "dpid": db_config
['dpid'],
353 "of_debug": self
.config
['log_level_of']})
357 temp_dict
['of_ip'] = db_config
['ip']
358 temp_dict
['of_port'] = db_config
['port']
359 temp_dict
['of_dpid'] = db_config
['dpid']
360 temp_dict
['of_controller'] = db_config
['type']
361 temp_dict
['of_user'] = db_config
.get('user')
362 temp_dict
['of_password'] = db_config
.get('password')
364 temp_dict
['of_debug'] = self
.config
['log_level_of']
366 if temp_dict
['of_controller'] == 'opendaylight':
369 module
= temp_dict
['of_controller']
371 if module
not in ovim
.of_module
:
372 module_info
= imp
.find_module(module
)
373 of_conn_module
= imp
.load_module("OF_conn", *module_info
)
374 ovim
.of_module
[module
] = of_conn_module
376 of_conn_module
= ovim
.of_module
[module
]
379 return of_conn_module
.OF_conn(temp_dict
)
380 except Exception as e
:
381 self
.logger
.error("Cannot open the Openflow controller '%s': %s", type(e
).__name
__, str(e
))
382 if module_info
and module_info
[0]:
383 file.close(module_info
[0])
384 raise ovimException("Cannot open the Openflow controller '{}': '{}'".format(type(e
).__name
__, str(e
)),
385 HTTP_Internal_Server_Error
)
386 except (IOError, ImportError) as e
:
387 if module_info
and module_info
[0]:
388 file.close(module_info
[0])
389 self
.logger
.error("Cannot open openflow controller module '%s'; %s: %s; revise 'of_controller' "
390 "field of configuration file.", module
, type(e
).__name
__, str(e
))
391 raise ovimException("Cannot open openflow controller module '{}'; {}: {}; revise 'of_controller' "
392 "field of configuration file.".format(module
, type(e
).__name
__, str(e
)),
393 HTTP_Internal_Server_Error
)
395 def _create_ofc_thread(self
, of_conn
, ofc_uuid
="Default"):
397 Create and launch a of thread
400 # create openflow thread
402 #if 'of_controller_nets_with_same_vlan' in self.config:
403 # ofc_net_same_vlan = self.config['of_controller_nets_with_same_vlan']
405 # ofc_net_same_vlan = False
406 ofc_net_same_vlan
= False
408 thread
= oft
.openflow_thread(ofc_uuid
, of_conn
, of_test
=self
.of_test_mode
, db
=self
.db_of
, db_lock
=self
.db_lock
,
409 pmp_with_same_vlan
=ofc_net_same_vlan
, debug
=self
.config
['log_level_of'])
410 #r, c = thread.OF_connector.obtain_port_correspondence()
412 # raise ovimException("Cannot get openflow information %s", c)
416 def stop_service(self
):
417 threads
= self
.config
.get('host_threads', {})
418 if 'of_thread' in self
.config
:
419 threads
['of'] = (self
.config
['of_thread'])
420 if 'ofcs_thread' in self
.config
:
421 ofcs_thread
= self
.config
['ofcs_thread']
422 for ofc
in ofcs_thread
:
423 threads
[ofc
] = ofcs_thread
[ofc
]
425 if 'dhcp_thread' in self
.config
:
426 threads
['dhcp'] = (self
.config
['dhcp_thread'])
428 for thread
in threads
.values():
429 thread
.insert_task("exit")
430 for thread
in threads
.values():
433 def get_networks(self
, columns
=None, db_filter
={}, limit
=None):
435 Retreive networks available
436 :param columns: List with select query parameters
437 :param db_filter: List with where query parameters
438 :param limit: Query limit result
441 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='nets', WHERE
=db_filter
, LIMIT
=limit
)
444 raise ovimException(str(content
), -result
)
446 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
450 def show_network(self
, network_id
, db_filter
={}):
452 Get network from DB by id
453 :param network_id: net Id
454 :param db_filter: List with where query parameters
459 raise ovimException("Not network id was not found")
460 db_filter
['uuid'] = network_id
462 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
=db_filter
, LIMIT
=100)
465 raise ovimException(str(content
), -result
)
467 raise ovimException("show_network network '%s' not found" % network_id
, -result
)
469 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
471 result
, ports
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
472 WHERE
={'net_id': network_id
}, LIMIT
=100)
474 content
[0]['ports'] = ports
476 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
479 def new_network(self
, network
):
484 tenant_id
= network
.get('tenant_id')
487 result
, _
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
, "enabled": True})
489 raise ovimException("set_network error, no tenant founded", -result
)
493 net_provider
= network
.get('provider')
494 net_type
= network
.get('type')
495 net_vlan
= network
.get("vlan")
496 net_bind_net
= network
.get("bind_net")
497 net_bind_type
= network
.get("bind_type")
498 name
= network
["name"]
500 # check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
501 vlan_index
= name
.rfind(":")
502 if not net_bind_net
and not net_bind_type
and vlan_index
> 1:
504 vlan_tag
= int(name
[vlan_index
+ 1:])
505 if not vlan_tag
and vlan_tag
< 4096:
506 net_bind_net
= name
[:vlan_index
]
507 net_bind_type
= "vlan:" + name
[vlan_index
+ 1:]
512 # look for a valid net
513 if self
._check
_valid
_uuid
(net_bind_net
):
514 net_bind_key
= "uuid"
516 net_bind_key
= "name"
517 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
519 raise ovimException(' getting nets from db ' + content
, HTTP_Internal_Server_Error
)
521 raise ovimException(" bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
523 raise ovimException(" more than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
524 network
["bind_net"] = content
[0]["uuid"]
527 if net_bind_type
[0:5] != "vlan:":
528 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
529 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
530 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
532 network
["bind_type"] = net_bind_type
535 if net_provider
[:9] == "openflow:":
537 if net_type
!= "ptp" and net_type
!= "data":
538 raise ovimException(" only 'ptp' or 'data' net types can be bound to 'openflow'",
544 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
545 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound "
546 "to 'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
548 net_type
= 'bridge_man'
551 net_type
= 'bridge_man'
554 if net_provider
[:7] == 'bridge:':
555 # check it is one of the pre-provisioned bridges
556 bridge_net_name
= net_provider
[7:]
557 for brnet
in self
.config
['bridge_nets']:
558 if brnet
[0] == bridge_net_name
: # free
560 raise ovimException("invalid 'provider:physical', "
561 "bridge '%s' is already used" % bridge_net_name
, HTTP_Conflict
)
565 # if bridge_net==None:
566 # bottle.abort(HTTP_Bad_Request, "invalid 'provider:physical', bridge '%s' is not one of the
567 # provisioned 'bridge_ifaces' in the configuration file" % bridge_net_name)
570 elif self
.config
['network_type'] == 'bridge' and (net_type
== 'bridge_data' or net_type
== 'bridge_man'):
571 # look for a free precreated nets
572 for brnet
in self
.config
['bridge_nets']:
573 if not brnet
[3]: # free
575 if net_type
== 'bridge_man': # look for the smaller speed
576 if brnet
[2] < bridge_net
[2]:
578 else: # look for the larger speed
579 if brnet
[2] > bridge_net
[2]:
585 raise ovimException("Max limits of bridge networks reached. Future versions of VIM "
586 "will overcome this limit", HTTP_Bad_Request
)
588 self
.logger
.debug("using net " + bridge_net
)
589 net_provider
= "bridge:" + bridge_net
[0]
590 net_vlan
= bridge_net
[1]
591 elif net_type
== 'bridge_data' or net_type
== 'bridge_man' and self
.config
['network_type'] == 'ovs':
593 if not net_vlan
and (net_type
== "data" or net_type
== "ptp" or net_provider
== "OVS"):
594 net_vlan
= self
.db
.get_free_net_vlan()
596 raise ovimException("Error getting an available vlan", HTTP_Internal_Server_Error
)
597 if net_provider
== 'OVS':
598 net_provider
= 'OVS' + ":" + str(net_vlan
)
600 network
['provider'] = net_provider
601 network
['type'] = net_type
602 network
['vlan'] = net_vlan
603 dhcp_integrity
= True
604 if 'enable_dhcp' in network
and network
['enable_dhcp']:
605 dhcp_integrity
= self
._check
_dhcp
_data
_integrity
(network
)
607 result
, content
= self
.db
.new_row('nets', network
, True, True)
609 if result
>= 0 and dhcp_integrity
:
611 bridge_net
[3] = content
612 if self
.config
.get("dhcp_server") and self
.config
['network_type'] == 'bridge':
613 if network
["name"] in self
.config
["dhcp_server"].get("nets", ()):
614 self
.config
["dhcp_nets"].append(content
)
615 self
.logger
.debug("dhcp_server: add new net", content
)
616 elif not bridge_net
and bridge_net
[0] in self
.config
["dhcp_server"].get("bridge_ifaces", ()):
617 self
.config
["dhcp_nets"].append(content
)
618 self
.logger
.debug("dhcp_server: add new net", content
, content
)
621 raise ovimException("Error posting network", HTTP_Internal_Server_Error
)
622 # TODO kei change update->edit
624 def edit_network(self
, network_id
, network
):
626 Update entwork data byt id
629 # Look for the previous data
630 where_
= {'uuid': network_id
}
631 result
, network_old
= self
.db
.get_table(FROM
='nets', WHERE
=where_
)
633 raise ovimException("Error updating network %s" % network_old
, HTTP_Internal_Server_Error
)
635 raise ovimException('network %s not found' % network_id
, HTTP_Not_Found
)
637 nbports
, content
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
638 WHERE
={'net_id': network_id
}, LIMIT
=100)
640 raise ovimException("http_put_network_id error %d %s" % (result
, network_old
), HTTP_Internal_Server_Error
)
642 if 'type' in network
and network
['type'] != network_old
[0]['type']:
643 raise ovimException("Can not change type of network while having ports attached",
644 HTTP_Method_Not_Allowed
)
645 if 'vlan' in network
and network
['vlan'] != network_old
[0]['vlan']:
646 raise ovimException("Can not change vlan of network while having ports attached",
647 HTTP_Method_Not_Allowed
)
650 net_provider
= network
.get('provider', network_old
[0]['provider'])
651 net_type
= network
.get('type', network_old
[0]['type'])
652 net_bind_net
= network
.get("bind_net")
653 net_bind_type
= network
.get("bind_type")
655 # look for a valid net
656 if self
._check
_valid
_uuid
(net_bind_net
):
657 net_bind_key
= "uuid"
659 net_bind_key
= "name"
660 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
662 raise ovimException('Getting nets from db ' + content
, HTTP_Internal_Server_Error
)
664 raise ovimException("bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
666 raise ovimException("More than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
),
668 network
["bind_net"] = content
[0]["uuid"]
670 if net_bind_type
[0:5] != "vlan:":
671 raise ovimException("Bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
672 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
673 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
676 if net_provider
[:9] == "openflow:":
677 if net_type
!= "ptp" and net_type
!= "data":
678 raise ovimException("Only 'ptp' or 'data' net types can be bound to 'openflow'", HTTP_Bad_Request
)
680 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
681 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound to "
682 "'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
684 # insert in data base
685 result
, content
= self
.db
.update_rows('nets', network
, WHERE
={'uuid': network_id
}, log
=True)
687 # if result > 0 and nbports>0 and 'admin_state_up' in network
688 # and network['admin_state_up'] != network_old[0]['admin_state_up']:
693 self
.net_update_ofc_thread(network_id
)
694 except ovimException
as e
:
695 raise ovimException("Error while launching openflow rules in network '{}' {}"
696 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
697 except Exception as e
:
698 raise ovimException("Error while launching openflow rules in network '{}' {}"
699 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
701 if self
.config
.get("dhcp_server"):
702 if network_id
in self
.config
["dhcp_nets"]:
703 self
.config
["dhcp_nets"].remove(network_id
)
704 if network
.get("name", network_old
[0]["name"]) in self
.config
["dhcp_server"].get("nets", ()):
705 self
.config
["dhcp_nets"].append(network_id
)
707 net_bind
= network
.get("bind_type", network_old
[0]["bind_type"])
708 if net_bind
and net_bind
and net_bind
[:7] == "bridge:" and net_bind
[7:] in self
.config
["dhcp_server"].get(
709 "bridge_ifaces", ()):
710 self
.config
["dhcp_nets"].append(network_id
)
713 raise ovimException(content
, -result
)
715 def delete_network(self
, network_id
):
717 Delete network by network id
718 :param network_id: network id
722 # delete from the data base
723 result
, content
= self
.db
.delete_row('nets', network_id
)
726 raise ovimException("Network %s not found " % network_id
, HTTP_Not_Found
)
728 for brnet
in self
.config
['bridge_nets']:
729 if brnet
[3] == network_id
:
732 if self
.config
.get("dhcp_server") and network_id
in self
.config
["dhcp_nets"]:
733 self
.config
["dhcp_nets"].remove(network_id
)
736 raise ovimException("Error deleting network %s" % network_id
, HTTP_Internal_Server_Error
)
738 def get_openflow_rules(self
, network_id
=None):
740 Get openflow id from DB
741 :param network_id: Network id, if none all networks will be retrieved
742 :return: Return a list with Openflow rules per net
748 where_
= {"net_id": network_id
}
749 result
, content
= self
.db
.get_table(
750 SELECT
=("name", "net_id", "ofc_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
751 WHERE
=where_
, FROM
='of_flows')
754 raise ovimException(str(content
), -result
)
757 def edit_openflow_rules(self
, network_id
=None):
760 To make actions over the net. The action is to reinstall the openflow rules
761 network_id can be 'all'
762 :param network_id: Network id, if none all networks will be retrieved
763 :return : Number of nets updated
770 where_
= {"uuid": network_id
}
771 result
, content
= self
.db
.get_table(SELECT
=("uuid", "type"), WHERE
=where_
, FROM
='nets')
774 raise ovimException(str(content
), -result
)
777 if net
["type"] != "ptp" and net
["type"] != "data":
782 self
.net_update_ofc_thread(net
['uuid'])
783 except ovimException
as e
:
784 raise ovimException("Error updating network'{}' {}".format(net
['uuid'], str(e
)),
785 HTTP_Internal_Server_Error
)
786 except Exception as e
:
787 raise ovimException("Error updating network '{}' {}".format(net
['uuid'], str(e
)),
788 HTTP_Internal_Server_Error
)
792 def delete_openflow_rules(self
, ofc_id
=None):
794 To make actions over the net. The action is to delete ALL openflow rules
795 :return: return operation result
799 if 'Default' in self
.config
['ofcs_thread']:
800 r
, c
= self
.config
['ofcs_thread']['Default'].insert_task("clear-all")
802 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
804 elif ofc_id
in self
.config
['ofcs_thread']:
805 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("clear-all")
809 raise ovimException(str(c
), -r
)
811 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
814 def get_openflow_ports(self
, ofc_id
=None):
816 Obtain switch ports names of openflow controller
817 :return: Return flow ports in DB
820 if 'Default' in self
.config
['ofcs_thread']:
821 conn
= self
.config
['ofcs_thread']['Default'].OF_connector
823 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
825 if ofc_id
in self
.config
['ofcs_thread']:
826 conn
= self
.config
['ofcs_thread'][ofc_id
].OF_connector
828 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
831 def get_ports(self
, columns
=None, filter={}, limit
=None):
832 # result, content = my.db.get_ports(where_)
833 result
, content
= self
.db
.get_table(SELECT
=columns
, WHERE
=filter, FROM
='ports', LIMIT
=limit
)
835 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
836 raise ovimException(str(content
), -result
)
838 convert_boolean(content
, ('admin_state_up',))
841 def new_port(self
, port_data
):
842 port_data
['type'] = 'external'
843 if port_data
.get('net_id'):
844 # check that new net has the correct type
845 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
847 raise ovimException(str(new_net
), -result
)
848 # insert in data base
849 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
851 if 'net_id' in port_data
:
853 self
.net_update_ofc_thread(port_data
['net_id'])
854 except ovimException
as e
:
855 raise ovimException("Cannot insert a task for updating network '{}' {}"
856 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
857 except Exception as e
:
858 raise ovimException("Cannot insert a task for updating network '{}' {}"
859 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
863 raise ovimException(str(uuid
), -result
)
865 def new_external_port(self
, port_data
):
867 Create new external port and check port mapping correspondence
868 :param port_data: port_data = {
869 'region': 'datacenter region',
870 'compute_node': 'compute node id',
871 'pci': 'pci port address',
874 'tenant_id': 'tenant id',
877 'ip_address': 'ip address - optional'}
881 port_data
['type'] = 'external'
883 if port_data
.get('net_id'):
884 # check that new net has the correct type
885 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
887 raise ovimException(str(new_net
), -result
)
888 # insert in data base
891 if port_data
.get('region'):
892 db_filter
['region'] = port_data
['region']
893 if port_data
.get('pci'):
894 db_filter
['pci'] = port_data
['pci']
895 if port_data
.get('compute_node'):
896 db_filter
['compute_node'] = port_data
['compute_node']
898 columns
= ['ofc_id', 'switch_dpid', 'switch_port', 'switch_mac', 'pci']
899 port_mapping_data
= self
.get_of_port_mappings(columns
, db_filter
)
901 if not len(port_mapping_data
):
902 raise ovimException("No port mapping founded for '{}'".format(str(db_filter
)),
904 elif len(port_mapping_data
) > 1:
905 raise ovimException("Wrong port data was given, please check pci, region & compute id data",
908 port_data
['ofc_id'] = port_mapping_data
[0]['ofc_id']
909 port_data
['switch_dpid'] = port_mapping_data
[0]['switch_dpid']
910 port_data
['switch_port'] = port_mapping_data
[0]['switch_port']
911 port_data
['switch_mac'] = port_mapping_data
[0]['switch_mac']
913 # remove from compute_node, region and pci of_port_data to adapt to 'ports' structure
914 if 'region' in port_data
:
915 del port_data
['region']
916 if 'pci' in port_data
:
918 if 'compute_node' in port_data
:
919 del port_data
['compute_node']
921 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
924 self
.net_update_ofc_thread(port_data
['net_id'], port_data
['ofc_id'])
925 except ovimException
as e
:
926 raise ovimException("Cannot insert a task for updating network '{}' {}".
927 format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
928 except Exception as e
:
929 raise ovimException("Cannot insert a task for updating network '{}' {}"
930 .format(port_data
['net_id'], e
), HTTP_Internal_Server_Error
)
933 raise ovimException(str(uuid
), -result
)
935 def net_update_ofc_thread(self
, net_id
, ofc_id
=None, switch_dpid
=None):
937 Insert a update net task by net id or ofc_id for each ofc thread
938 :param net_id: network id
939 :param ofc_id: openflow controller id
940 :param switch_dpid: switch dpid
944 raise ovimException("No net_id received", HTTP_Internal_Server_Error
)
947 c
= 'No valid ofc_id or switch_dpid received'
950 ports
= self
.get_ports(filter={"net_id": net_id
})
952 port_ofc_id
= port
.get('ofc_id', None)
954 ofc_id
= port
['ofc_id']
955 switch_dpid
= port
['switch_dpid']
957 #TODO if not ofc_id: look at database table ofcs
960 # If no ofc_id found it, default ofc_id is used.
961 if not ofc_id
and not switch_dpid
:
964 if ofc_id
and ofc_id
in self
.config
['ofcs_thread']:
965 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("update-net", net_id
)
968 ofcs_dpid_list
= self
.config
['ofcs_thread_dpid']
969 for ofc_t
in ofcs_dpid_list
:
970 if switch_dpid
in ofc_t
:
971 r
, c
= ofc_t
[switch_dpid
].insert_task("update-net", net_id
)
974 message
= "Cannot insert a task for updating network '{}', {}".format(net_id
, c
)
975 self
.logger
.error(message
)
976 raise ovimException(message
, HTTP_Internal_Server_Error
)
978 def delete_port(self
, port_id
):
979 # Look for the previous port data
980 result
, ports
= self
.db
.get_table(WHERE
={'uuid': port_id
, "type": "external"}, FROM
='ports')
982 raise ovimException("Cannot get port info from database: {}".format(ports
), http_code
=-result
)
983 # delete from the data base
984 result
, content
= self
.db
.delete_row('ports', port_id
)
986 raise ovimException("External port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
988 raise ovimException("Cannot delete port from database: {}".format(content
), http_code
=-result
)
990 network
= ports
[0].get('net_id', None)
995 self
.net_update_ofc_thread(network
, ofc_id
=ports
[0]["ofc_id"], switch_dpid
=ports
[0]["switch_dpid"])
996 except ovimException
as e
:
997 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
998 HTTP_Internal_Server_Error
)
999 except Exception as e
:
1000 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1001 HTTP_Internal_Server_Error
)
1005 def edit_port(self
, port_id
, port_data
, admin
=True):
1006 # Look for the previous port data
1007 result
, content
= self
.db
.get_table(FROM
="ports", WHERE
={'uuid': port_id
})
1009 raise ovimException("Cannot get port info from database: {}".format(content
), http_code
=-result
)
1011 raise ovimException("Port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
1016 if 'net_id' in port_data
:
1018 old_net
= port
.get('net_id', None)
1019 new_net
= port_data
['net_id']
1020 if old_net
!= new_net
:
1023 nets
.append(new_net
) # put first the new net, so that new openflow rules are created before removing the old ones
1025 nets
.append(old_net
)
1026 if port
['type'] == 'instance:bridge' or port
['type'] == 'instance:ovs':
1027 raise ovimException("bridge interfaces cannot be attached to a different net", http_code
=HTTP_Forbidden
)
1028 elif port
['type'] == 'external' and not admin
:
1029 raise ovimException("Needed admin privileges",http_code
=HTTP_Unauthorized
)
1031 # check that new net has the correct type
1032 result
, new_net_dict
= self
.db
.check_target_net(new_net
, None, port
['type'])
1034 raise ovimException("Error {}".format(new_net_dict
), http_code
=HTTP_Conflict
)
1035 # change VLAN for SR-IOV ports
1036 if result
>= 0 and port
["type"] == "instance:data" and port
["model"] == "VF": # TODO consider also VFnotShared
1038 port_data
["vlan"] = None
1040 port_data
["vlan"] = new_net_dict
["vlan"]
1041 # get host where this VM is allocated
1042 result
, content
= self
.db
.get_table(FROM
="instances", WHERE
={"uuid": port
["instance_id"]})
1044 host_id
= content
[0]["host_id"]
1046 # insert in data base
1048 result
, content
= self
.db
.update_rows('ports', port_data
, WHERE
={'uuid': port_id
}, log
=False)
1049 port
.update(port_data
)
1051 # Insert task to complete actions
1055 self
.net_update_ofc_thread(net_id
, port
["ofc_id"], switch_dpid
=port
["switch_dpid"])
1056 except ovimException
as e
:
1057 raise ovimException("Error updating network'{}' {}".format(net_id
, str(e
)),
1058 HTTP_Internal_Server_Error
)
1059 except Exception as e
:
1060 raise ovimException("Error updating network '{}' {}".format(net_id
, str(e
)),
1061 HTTP_Internal_Server_Error
)
1064 r
, v
= self
.config
['host_threads'][host_id
].insert_task("edit-iface", port_id
, old_net
, new_net
)
1066 self
.logger
.error("Error updating network '{}' {}".format(r
,v
))
1067 # TODO Do something if fails
1071 raise ovimException("Error {}".format(content
), http_code
=-result
)
1073 def new_of_controller(self
, ofc_data
):
1075 Create a new openflow controller into DB
1076 :param ofc_data: Dict openflow controller data
1077 :return: openflow controller dpid
1080 result
, ofc_uuid
= self
.db
.new_row('ofcs', ofc_data
, True, True)
1082 raise ovimException("New ofc Error %s" % ofc_uuid
, HTTP_Internal_Server_Error
)
1084 ofc_data
['uuid'] = ofc_uuid
1085 of_conn
= self
._load
_of
_module
(ofc_data
)
1086 self
._create
_ofc
_task
(ofc_uuid
, ofc_data
['dpid'], of_conn
)
1090 def edit_of_controller(self
, of_id
, ofc_data
):
1092 Edit an openflow controller entry from DB
1096 raise ovimException("No data received during uptade OF contorller", http_code
=HTTP_Internal_Server_Error
)
1098 old_of_controller
= self
.show_of_controller(of_id
)
1100 if old_of_controller
:
1101 result
, content
= self
.db
.update_rows('ofcs', ofc_data
, WHERE
={'uuid': of_id
}, log
=False)
1105 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1108 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1109 http_code
=HTTP_Internal_Server_Error
)
1111 def delete_of_controller(self
, of_id
):
1113 Delete an openflow controller from DB.
1114 :param of_id: openflow controller dpid
1118 ofc
= self
.show_of_controller(of_id
)
1120 result
, content
= self
.db
.delete_row("ofcs", of_id
)
1122 raise ovimException("Cannot delete ofc from database: {}".format(content
), http_code
=-result
)
1124 raise ovimException("ofc {} not found ".format(content
), http_code
=HTTP_Not_Found
)
1126 ofc_thread
= self
.config
['ofcs_thread'][of_id
]
1127 del self
.config
['ofcs_thread'][of_id
]
1128 for ofc_th
in self
.config
['ofcs_thread_dpid']:
1129 if ofc
['dpid'] in ofc_th
:
1130 self
.config
['ofcs_thread_dpid'].remove(ofc_th
)
1132 ofc_thread
.insert_task("exit")
1137 def show_of_controller(self
, uuid
):
1139 Show an openflow controller by dpid from DB.
1140 :param db_filter: List with where query parameters
1144 result
, content
= self
.db
.get_table(FROM
='ofcs', WHERE
={"uuid": uuid
}, LIMIT
=100)
1147 raise ovimException("Openflow controller with uuid '{}' not found".format(uuid
),
1148 http_code
=HTTP_Not_Found
)
1150 raise ovimException("Openflow controller with uuid '{}' error".format(uuid
),
1151 http_code
=HTTP_Internal_Server_Error
)
1154 def get_of_controllers(self
, columns
=None, db_filter
={}, limit
=None):
1156 Show an openflow controllers from DB.
1157 :param columns: List with SELECT query parameters
1158 :param db_filter: List with where query parameters
1159 :param limit: result Limit
1162 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='ofcs', WHERE
=db_filter
, LIMIT
=limit
)
1165 raise ovimException(str(content
), -result
)
1169 def get_tenants(self
, columns
=None, db_filter
={}, limit
=None):
1171 Retrieve tenant list from DB
1172 :param columns: List with SELECT query parameters
1173 :param db_filter: List with where query parameters
1174 :param limit: result limit
1177 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=columns
, WHERE
=db_filter
, LIMIT
=limit
)
1179 raise ovimException('get_tenatns Error {}'.format(str(content
)), -result
)
1181 convert_boolean(content
, ('enabled',))
1184 def show_tenant_id(self
, tenant_id
):
1186 Get tenant from DB by id
1187 :param tenant_id: tenant id
1190 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid', 'name', 'description', 'enabled'),
1191 WHERE
={"uuid": tenant_id
})
1193 raise ovimException(str(content
), -result
)
1195 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1197 convert_boolean(content
, ('enabled',))
1200 def new_tentant(self
, tenant
):
1202 Create a tenant and store in DB
1203 :param tenant: Dictionary with tenant data
1204 :return: the uuid of created tenant. Raise exception upon error
1207 # insert in data base
1208 result
, tenant_uuid
= self
.db
.new_tenant(tenant
)
1213 raise ovimException(str(tenant_uuid
), -result
)
1215 def delete_tentant(self
, tenant_id
):
1217 Delete a tenant from the database.
1218 :param tenant_id: Tenant id
1219 :return: delete tenant id
1223 r
, tenants_flavors
= self
.db
.get_table(FROM
='tenants_flavors', SELECT
=('flavor_id', 'tenant_id'),
1224 WHERE
={'tenant_id': tenant_id
})
1226 tenants_flavors
= ()
1227 r
, tenants_images
= self
.db
.get_table(FROM
='tenants_images', SELECT
=('image_id', 'tenant_id'),
1228 WHERE
={'tenant_id': tenant_id
})
1232 result
, content
= self
.db
.delete_row('tenants', tenant_id
)
1234 raise ovimException("tenant '%s' not found" % tenant_id
, HTTP_Not_Found
)
1236 for flavor
in tenants_flavors
:
1237 self
.db
.delete_row_by_key("flavors", "uuid", flavor
['flavor_id'])
1238 for image
in tenants_images
:
1239 self
.db
.delete_row_by_key("images", "uuid", image
['image_id'])
1242 raise ovimException("Error deleting tenant '%s' " % tenant_id
, HTTP_Internal_Server_Error
)
1244 def edit_tenant(self
, tenant_id
, tenant_data
):
1246 Update a tenant data identified by tenant id
1247 :param tenant_id: tenant id
1248 :param tenant_data: Dictionary with tenant data
1252 # Look for the previous data
1253 result
, tenant_data_old
= self
.db
.get_table(FROM
='tenants', WHERE
={'uuid': tenant_id
})
1255 raise ovimException("Error updating tenant with uuid='{}': {}".format(tenant_id
, tenant_data_old
),
1256 HTTP_Internal_Server_Error
)
1258 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1260 # insert in data base
1261 result
, content
= self
.db
.update_rows('tenants', tenant_data
, WHERE
={'uuid': tenant_id
}, log
=True)
1265 raise ovimException(str(content
), -result
)
1267 def set_of_port_mapping(self
, of_maps
, ofc_id
=None, switch_dpid
=None, region
=None):
1269 Create new port mapping entry
1270 :param of_maps: List with port mapping information
1271 # maps =[{"ofc_id": <ofc_id>,"region": datacenter region,"compute_node": compute uuid,"pci": pci adress,
1272 "switch_dpid": swith dpid,"switch_port": port name,"switch_mac": mac}]
1273 :param ofc_id: ofc id
1274 :param switch_dpid: switch dpid
1275 :param region: datacenter region id
1281 map['ofc_id'] = ofc_id
1283 map['switch_dpid'] = switch_dpid
1285 map['region'] = region
1287 for of_map
in of_maps
:
1288 result
, uuid
= self
.db
.new_row('of_port_mappings', of_map
, True)
1290 of_map
["uuid"] = uuid
1292 raise ovimException(str(uuid
), -result
)
1295 def clear_of_port_mapping(self
, db_filter
={}):
1297 Clear port mapping filtering using db_filter dict
1298 :param db_filter: Parameter to filter during remove process
1301 result
, content
= self
.db
.delete_row_by_dict(FROM
='of_port_mappings', WHERE
=db_filter
)
1306 raise ovimException("Error deleting of_port_mappings with filter='{}'".format(str(db_filter
)),
1307 HTTP_Internal_Server_Error
)
1309 def get_of_port_mappings(self
, column
=None, db_filter
=None, db_limit
=None):
1311 Retrive port mapping from DB
1316 result
, content
= self
.db
.get_table(SELECT
=column
, WHERE
=db_filter
, FROM
='of_port_mappings', LIMIT
=db_limit
)
1319 self
.logger
.error("get_of_port_mappings Error %d %s", result
, content
)
1320 raise ovimException(str(content
), -result
)
1324 def get_dhcp_controller(self
):
1326 Create an host_thread object for manage openvim controller and not create a thread for itself
1327 :return: dhcp_host openvim controller object
1330 if 'openvim_controller' in self
.config
['host_threads']:
1331 return self
.config
['host_threads']['openvim_controller']
1334 controller_ip
= self
.config
['ovs_controller_ip']
1335 ovs_controller_user
= self
.config
['ovs_controller_user']
1337 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
1338 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
1340 dhcp_host
= ht
.host_thread(name
='openvim_controller', user
=ovs_controller_user
, host
=controller_ip
,
1342 db_lock
=self
.db_lock
, test
=host_test_mode
,
1343 image_path
=self
.config
['image_path'], version
=self
.config
['version'],
1344 host_id
='openvim_controller', develop_mode
=host_develop_mode
,
1345 develop_bridge_iface
=bridge_ifaces
)
1347 self
.config
['host_threads']['openvim_controller'] = dhcp_host
1348 if not host_test_mode
:
1349 dhcp_host
.ssh_connect()
1352 def launch_dhcp_server(self
, vlan
, first_ip
, last_ip
, cidr
, gateway
):
1354 Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
1355 :param vlan: vlan identifier
1356 :param first_ip: First dhcp range ip
1357 :param last_ip: Last dhcp range ip
1358 :param cidr: net cidr
1359 :param gateway: net gateway
1362 ip_tools
= IPNetwork(cidr
)
1363 dhcp_netmask
= str(ip_tools
.netmask
)
1364 ip_range
= [first_ip
, last_ip
]
1366 dhcp_path
= self
.config
['ovs_controller_file_path']
1368 controller_host
= self
.get_dhcp_controller()
1369 controller_host
.create_linux_bridge(vlan
)
1370 controller_host
.create_dhcp_interfaces(vlan
, first_ip
, dhcp_netmask
)
1371 controller_host
.launch_dhcp_server(vlan
, ip_range
, dhcp_netmask
, dhcp_path
, gateway
)
1373 if __name__
== "__main__":
1375 parser
= argparse
.ArgumentParser()
1376 parser
.add_argument("-v","--version", help="show ovim library version", action
="store_true")
1377 parser
.add_argument("--database-version", help="show required database version", action
="store_true")
1378 args
= parser
.parse_args()
1380 print ('openvimd version {} {}'.format(ovim
.get_version(), ovim
.get_version_date()))
1381 print ('(c) Copyright Telefonica')
1382 elif args
.database_version
:
1383 print ('required database version: {}'.format(ovim
.get_database_version()))