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.
35 from netaddr
import IPNetwork
36 from jsonschema
import validate
as js_v
, exceptions
as js_e
37 import host_thread
as ht
38 import dhcp_thread
as dt
39 import openflow_thread
as oft
42 __author__
= "Alfonso Tierno, Leonardo Mirabal"
43 __date__
= "$06-Feb-2017 12:07:15$"
44 __version__
= "0.5.11-r527"
45 version_date
= "Apr 2017"
46 database_version
= "0.17" #expected database schema version
48 HTTP_Bad_Request
= 400
49 HTTP_Unauthorized
= 401
52 HTTP_Method_Not_Allowed
= 405
53 HTTP_Not_Acceptable
= 406
54 HTTP_Request_Timeout
= 408
56 HTTP_Service_Unavailable
= 503
57 HTTP_Internal_Server_Error
= 500
60 def convert_boolean(data
, items
):
61 '''Check recursively the content of data, and if there is an key contained in items, convert value from string to boolean
62 It assumes that bandwidth is well formed
64 'data': dictionary bottle.FormsDict variable to be checked. None or empty is consideted valid
65 'items': tuple of keys to convert
69 if type(data
) is dict:
71 if type(data
[k
]) is dict or type(data
[k
]) is tuple or type(data
[k
]) is list:
72 convert_boolean(data
[k
], items
)
74 if type(data
[k
]) is str:
75 if data
[k
] == "false":
77 elif data
[k
] == "true":
79 if type(data
) is tuple or type(data
) is list:
81 if type(k
) is dict or type(k
) is tuple or type(k
) is list:
82 convert_boolean(k
, items
)
86 class ovimException(Exception):
87 def __init__(self
, message
, http_code
=HTTP_Bad_Request
):
88 self
.http_code
= http_code
89 Exception.__init
__(self
, message
)
93 running_info
= {} #TODO OVIM move the info of running threads from config_dic to this static variable
96 def __init__(self
, configuration
):
97 self
.config
= configuration
98 self
.logger_name
= configuration
.get("logger_name", "openvim")
99 self
.logger
= logging
.getLogger(self
.logger_name
)
101 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
[2])
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 raise ovimException("DATABASE is not a VIM one or it is a '0.0' version. Try to upgrade to version '{}' with "\
176 "'./database_utils/migrate_vim_db.sh'".format(database_version
) )
177 elif r
[1] != database_version
:
178 raise ovimException("DATABASE wrong version '{}'. Try to upgrade/downgrade to version '{}' with "\
179 "'./database_utils/migrate_vim_db.sh'".format(r
[1], database_version
) )
180 self
.logger
.critical("Starting ovim server version: '{} {}' database version '{}'".format(
181 self
.get_version(), self
.get_version_date(), self
.get_database_version()))
182 # create database connection for openflow threads
183 self
.db_of
= self
._create
_database
_connection
()
184 self
.config
["db"] = self
.db_of
185 self
.db_lock
= threading
.Lock()
186 self
.config
["db_lock"] = self
.db_lock
188 self
.of_test_mode
= False if self
.config
['mode'] == 'normal' or self
.config
['mode'] == "OF only" else True
189 # precreate interfaces; [bridge:<host_bridge_name>, VLAN used at Host, uuid of network camping in this bridge,
192 self
.config
['dhcp_nets'] = []
193 self
.config
['bridge_nets'] = []
194 for bridge
, vlan_speed
in self
.config
["bridge_ifaces"].items():
195 # skip 'development_bridge'
196 if self
.config
['mode'] == 'development' and self
.config
['development_bridge'] == bridge
:
198 self
.config
['bridge_nets'].append([bridge
, vlan_speed
[0], vlan_speed
[1], None])
200 # check if this bridge is already used (present at database) for a network)
201 used_bridge_nets
= []
202 for brnet
in self
.config
['bridge_nets']:
203 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'provider': "bridge:" + brnet
[0]})
205 brnet
[3] = nets
[0]['uuid']
206 used_bridge_nets
.append(brnet
[0])
207 if self
.config
.get("dhcp_server"):
208 if brnet
[0] in self
.config
["dhcp_server"]["bridge_ifaces"]:
209 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
210 if len(used_bridge_nets
) > 0:
211 self
.logger
.info("found used bridge nets: " + ",".join(used_bridge_nets
))
212 # get nets used by dhcp
213 if self
.config
.get("dhcp_server"):
214 for net
in self
.config
["dhcp_server"].get("nets", ()):
215 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'name': net
})
217 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
220 self
._start
_ofc
_default
_task
()
222 # OFC per tenant in DB
223 self
._start
_of
_db
_tasks
()
225 # create dhcp_server thread
226 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
227 dhcp_params
= self
.config
.get("dhcp_server")
229 thread
= dt
.dhcp_thread(dhcp_params
=dhcp_params
, test
=host_test_mode
, dhcp_nets
=self
.config
["dhcp_nets"],
230 db
=self
.db_of
, db_lock
=self
.db_lock
, logger_name
=self
.logger_name
+ ".dhcp",
231 debug
=self
.config
.get('log_level_of'))
233 self
.config
['dhcp_thread'] = thread
235 # Create one thread for each host
236 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
237 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
238 host_develop_bridge_iface
= self
.config
.get('development_bridge', None)
240 # get host list from data base before starting threads
241 r
, hosts
= self
.db
.get_table(SELECT
=('name', 'ip_name', 'user', 'uuid'), FROM
='hosts', WHERE
={'status': 'ok'})
243 raise ovimException("Cannot get hosts from database {}".format(hosts
))
245 self
.config
['host_threads'] = {}
247 host
['image_path'] = '/opt/VNF/images/openvim'
248 thread
= ht
.host_thread(name
=host
['name'], user
=host
['user'], host
=host
['ip_name'], db
=self
.db_of
,
249 db_lock
=self
.db_lock
, test
=host_test_mode
, image_path
=self
.config
['image_path'],
250 version
=self
.config
['version'], host_id
=host
['uuid'], develop_mode
=host_develop_mode
,
251 develop_bridge_iface
=host_develop_bridge_iface
,
252 logger_name
=self
.logger_name
+ ".host." + host
['name'],
253 debug
=self
.config
.get('log_level_host'))
255 self
.config
['host_threads'][host
['uuid']] = thread
257 # create ovs dhcp thread
258 result
, content
= self
.db
.get_table(FROM
='nets')
260 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
261 raise ovimException(str(content
), -result
)
264 net_type
= net
['type']
265 if (net_type
== 'bridge_data' or net_type
== 'bridge_man') \
266 and net
["provider"][:4] == 'OVS:' and net
["enable_dhcp"] == "true":
267 self
.launch_dhcp_server(net
['vlan'],
268 net
['dhcp_first_ip'],
273 def _start_of_db_tasks(self
):
275 Start ofc task for existing ofcs in database
280 ofcs
= self
.get_of_controllers()
283 of_conn
= self
._load
_of
_module
(ofc
)
284 # create ofc thread per of controller
285 self
._create
_ofc
_task
(ofc
['uuid'], ofc
['dpid'], of_conn
)
287 def _create_ofc_task(self
, ofc_uuid
, dpid
, of_conn
):
289 Create an ofc thread for handle each sdn controllers
290 :param ofc_uuid: sdn controller uuid
291 :param dpid: sdn controller dpid
292 :param of_conn: OF_conn module
295 if 'ofcs_thread' not in self
.config
and 'ofcs_thread_dpid' not in self
.config
:
297 ofcs_thread_dpid
= []
299 ofcs_threads
= self
.config
['ofcs_thread']
300 ofcs_thread_dpid
= self
.config
['ofcs_thread_dpid']
302 if ofc_uuid
not in ofcs_threads
:
303 ofc_thread
= self
._create
_ofc
_thread
(of_conn
, ofc_uuid
)
304 if ofc_uuid
== "Default":
305 self
.config
['of_thread'] = ofc_thread
307 ofcs_threads
[ofc_uuid
] = ofc_thread
308 self
.config
['ofcs_thread'] = ofcs_threads
310 ofcs_thread_dpid
.append({dpid
: ofc_thread
})
311 self
.config
['ofcs_thread_dpid'] = ofcs_thread_dpid
313 def _start_ofc_default_task(self
):
315 Create default ofc thread
317 if 'of_controller' not in self
.config \
318 and 'of_controller_ip' not in self
.config \
319 and 'of_controller_port' not in self
.config \
320 and 'of_controller_dpid' not in self
.config
:
325 db_config
['ip'] = self
.config
.get('of_controller_ip')
326 db_config
['port'] = self
.config
.get('of_controller_port')
327 db_config
['dpid'] = self
.config
.get('of_controller_dpid')
328 db_config
['type'] = self
.config
.get('of_controller')
329 db_config
['user'] = self
.config
.get('of_user')
330 db_config
['password'] = self
.config
.get('of_password')
332 # create connector to the openflow controller
333 # load other parameters starting by of_ from config dict in a temporal dict
335 of_conn
= self
._load
_of
_module
(db_config
)
336 # create openflow thread
337 self
._create
_ofc
_task
("Default", db_config
['dpid'], of_conn
)
339 def _load_of_module(self
, db_config
):
341 import python module for each SDN controller supported
342 :param db_config: SDN dn information
346 raise ovimException("No module found it", HTTP_Internal_Server_Error
)
351 if self
.of_test_mode
:
352 return openflow_conn
.OfTestConnector({"name": db_config
['type'],
353 "dpid": db_config
['dpid'],
354 "of_debug": self
.config
['log_level_of']})
358 temp_dict
['of_ip'] = db_config
['ip']
359 temp_dict
['of_port'] = db_config
['port']
360 temp_dict
['of_dpid'] = db_config
['dpid']
361 temp_dict
['of_controller'] = db_config
['type']
362 temp_dict
['of_user'] = db_config
.get('user')
363 temp_dict
['of_password'] = db_config
.get('password')
365 temp_dict
['of_debug'] = self
.config
['log_level_of']
367 if temp_dict
['of_controller'] == 'opendaylight':
370 module
= temp_dict
['of_controller']
372 if module
not in ovim
.of_module
:
373 for base
in ("", "osm_openvim.", "lib_osm_openvim."):
375 pkg
= __import__(base
+ module
)
377 of_conn_module
= getattr(pkg
, module
)
380 ovim
.of_module
[module
] = of_conn_module
381 self
.logger
.debug("Module load from {}".format(base
+ module
))
383 except Exception as e
:
384 self
.logger
.warning("Module {} not found {}".format(base
+ module
, e
))
386 self
.logger
.error("Cannot open openflow controller module of type '%s'", module
)
387 raise ovimException("Cannot open openflow controller of type module '{}'"
388 "Revise it is installed".format(module
),
389 HTTP_Internal_Server_Error
)
391 of_conn_module
= ovim
.of_module
[module
]
392 return of_conn_module
.OF_conn(temp_dict
)
393 except Exception as e
:
394 self
.logger
.error("Cannot open the Openflow controller '%s': %s", type(e
).__name
__, str(e
))
395 raise ovimException("Cannot open the Openflow controller '{}': '{}'".format(type(e
).__name
__, str(e
)),
396 HTTP_Internal_Server_Error
)
398 def _create_ofc_thread(self
, of_conn
, ofc_uuid
="Default"):
400 Create and launch a of thread
403 # create openflow thread
405 #if 'of_controller_nets_with_same_vlan' in self.config:
406 # ofc_net_same_vlan = self.config['of_controller_nets_with_same_vlan']
408 # ofc_net_same_vlan = False
409 ofc_net_same_vlan
= False
411 thread
= oft
.openflow_thread(ofc_uuid
, of_conn
, of_test
=self
.of_test_mode
, db
=self
.db_of
, db_lock
=self
.db_lock
,
412 pmp_with_same_vlan
=ofc_net_same_vlan
, debug
=self
.config
['log_level_of'])
413 #r, c = thread.OF_connector.obtain_port_correspondence()
415 # raise ovimException("Cannot get openflow information %s", c)
419 def stop_service(self
):
420 threads
= self
.config
.get('host_threads', {})
421 if 'of_thread' in self
.config
:
422 threads
['of'] = (self
.config
['of_thread'])
423 if 'ofcs_thread' in self
.config
:
424 ofcs_thread
= self
.config
['ofcs_thread']
425 for ofc
in ofcs_thread
:
426 threads
[ofc
] = ofcs_thread
[ofc
]
428 if 'dhcp_thread' in self
.config
:
429 threads
['dhcp'] = (self
.config
['dhcp_thread'])
431 for thread
in threads
.values():
432 thread
.insert_task("exit")
433 for thread
in threads
.values():
436 def get_networks(self
, columns
=None, db_filter
={}, limit
=None):
438 Retreive networks available
439 :param columns: List with select query parameters
440 :param db_filter: List with where query parameters
441 :param limit: Query limit result
444 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='nets', WHERE
=db_filter
, LIMIT
=limit
)
447 raise ovimException(str(content
), -result
)
449 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
453 def show_network(self
, network_id
, db_filter
={}):
455 Get network from DB by id
456 :param network_id: net Id
457 :param db_filter: List with where query parameters
462 raise ovimException("Not network id was not found")
463 db_filter
['uuid'] = network_id
465 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
=db_filter
, LIMIT
=100)
468 raise ovimException(str(content
), -result
)
470 raise ovimException("show_network network '%s' not found" % network_id
, -result
)
472 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
474 result
, ports
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
475 WHERE
={'net_id': network_id
}, LIMIT
=100)
477 content
[0]['ports'] = ports
479 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
482 def new_network(self
, network
):
487 tenant_id
= network
.get('tenant_id')
490 result
, _
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
, "enabled": True})
492 raise ovimException("set_network error, no tenant founded", -result
)
496 net_provider
= network
.get('provider')
497 net_type
= network
.get('type')
498 net_vlan
= network
.get("vlan")
499 net_bind_net
= network
.get("bind_net")
500 net_bind_type
= network
.get("bind_type")
501 name
= network
["name"]
503 # check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
504 vlan_index
= name
.rfind(":")
505 if not net_bind_net
and not net_bind_type
and vlan_index
> 1:
507 vlan_tag
= int(name
[vlan_index
+ 1:])
508 if not vlan_tag
and vlan_tag
< 4096:
509 net_bind_net
= name
[:vlan_index
]
510 net_bind_type
= "vlan:" + name
[vlan_index
+ 1:]
515 # look for a valid net
516 if self
._check
_valid
_uuid
(net_bind_net
):
517 net_bind_key
= "uuid"
519 net_bind_key
= "name"
520 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
522 raise ovimException(' getting nets from db ' + content
, HTTP_Internal_Server_Error
)
524 raise ovimException(" bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
526 raise ovimException(" more than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
527 network
["bind_net"] = content
[0]["uuid"]
530 if net_bind_type
[0:5] != "vlan:":
531 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
532 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
533 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
535 network
["bind_type"] = net_bind_type
538 if net_provider
[:9] == "openflow:":
540 if net_type
!= "ptp" and net_type
!= "data":
541 raise ovimException(" only 'ptp' or 'data' net types can be bound to 'openflow'",
547 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
548 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound "
549 "to 'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
551 net_type
= 'bridge_man'
554 net_type
= 'bridge_man'
557 if net_provider
[:7] == 'bridge:':
558 # check it is one of the pre-provisioned bridges
559 bridge_net_name
= net_provider
[7:]
560 for brnet
in self
.config
['bridge_nets']:
561 if brnet
[0] == bridge_net_name
: # free
563 raise ovimException("invalid 'provider:physical', "
564 "bridge '%s' is already used" % bridge_net_name
, HTTP_Conflict
)
568 # if bridge_net==None:
569 # bottle.abort(HTTP_Bad_Request, "invalid 'provider:physical', bridge '%s' is not one of the
570 # provisioned 'bridge_ifaces' in the configuration file" % bridge_net_name)
573 elif self
.config
['network_type'] == 'bridge' and (net_type
== 'bridge_data' or net_type
== 'bridge_man'):
574 # look for a free precreated nets
575 for brnet
in self
.config
['bridge_nets']:
576 if not brnet
[3]: # free
578 if net_type
== 'bridge_man': # look for the smaller speed
579 if brnet
[2] < bridge_net
[2]:
581 else: # look for the larger speed
582 if brnet
[2] > bridge_net
[2]:
588 raise ovimException("Max limits of bridge networks reached. Future versions of VIM "
589 "will overcome this limit", HTTP_Bad_Request
)
591 self
.logger
.debug("using net " + bridge_net
)
592 net_provider
= "bridge:" + bridge_net
[0]
593 net_vlan
= bridge_net
[1]
594 elif net_type
== 'bridge_data' or net_type
== 'bridge_man' and self
.config
['network_type'] == 'ovs':
596 if not net_vlan
and (net_type
== "data" or net_type
== "ptp" or net_provider
== "OVS"):
597 net_vlan
= self
.db
.get_free_net_vlan()
599 raise ovimException("Error getting an available vlan", HTTP_Internal_Server_Error
)
600 if net_provider
== 'OVS':
601 net_provider
= 'OVS' + ":" + str(net_vlan
)
603 network
['provider'] = net_provider
604 network
['type'] = net_type
605 network
['vlan'] = net_vlan
606 dhcp_integrity
= True
607 if 'enable_dhcp' in network
and network
['enable_dhcp']:
608 dhcp_integrity
= self
._check
_dhcp
_data
_integrity
(network
)
610 result
, content
= self
.db
.new_row('nets', network
, True, True)
612 if result
>= 0 and dhcp_integrity
:
614 bridge_net
[3] = content
615 if self
.config
.get("dhcp_server") and self
.config
['network_type'] == 'bridge':
616 if network
["name"] in self
.config
["dhcp_server"].get("nets", ()):
617 self
.config
["dhcp_nets"].append(content
)
618 self
.logger
.debug("dhcp_server: add new net", content
)
619 elif not bridge_net
and bridge_net
[0] in self
.config
["dhcp_server"].get("bridge_ifaces", ()):
620 self
.config
["dhcp_nets"].append(content
)
621 self
.logger
.debug("dhcp_server: add new net", content
, content
)
624 raise ovimException("Error posting network", HTTP_Internal_Server_Error
)
625 # TODO kei change update->edit
627 def edit_network(self
, network_id
, network
):
629 Update entwork data byt id
632 # Look for the previous data
633 where_
= {'uuid': network_id
}
634 result
, network_old
= self
.db
.get_table(FROM
='nets', WHERE
=where_
)
636 raise ovimException("Error updating network %s" % network_old
, HTTP_Internal_Server_Error
)
638 raise ovimException('network %s not found' % network_id
, HTTP_Not_Found
)
640 nbports
, content
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
641 WHERE
={'net_id': network_id
}, LIMIT
=100)
643 raise ovimException("http_put_network_id error %d %s" % (result
, network_old
), HTTP_Internal_Server_Error
)
645 if 'type' in network
and network
['type'] != network_old
[0]['type']:
646 raise ovimException("Can not change type of network while having ports attached",
647 HTTP_Method_Not_Allowed
)
648 if 'vlan' in network
and network
['vlan'] != network_old
[0]['vlan']:
649 raise ovimException("Can not change vlan of network while having ports attached",
650 HTTP_Method_Not_Allowed
)
653 net_provider
= network
.get('provider', network_old
[0]['provider'])
654 net_type
= network
.get('type', network_old
[0]['type'])
655 net_bind_net
= network
.get("bind_net")
656 net_bind_type
= network
.get("bind_type")
658 # look for a valid net
659 if self
._check
_valid
_uuid
(net_bind_net
):
660 net_bind_key
= "uuid"
662 net_bind_key
= "name"
663 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
665 raise ovimException('Getting nets from db ' + content
, HTTP_Internal_Server_Error
)
667 raise ovimException("bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
669 raise ovimException("More than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
),
671 network
["bind_net"] = content
[0]["uuid"]
673 if net_bind_type
[0:5] != "vlan:":
674 raise ovimException("Bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
675 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
676 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
679 if net_provider
[:9] == "openflow:":
680 if net_type
!= "ptp" and net_type
!= "data":
681 raise ovimException("Only 'ptp' or 'data' net types can be bound to 'openflow'", HTTP_Bad_Request
)
683 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
684 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound to "
685 "'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
687 # insert in data base
688 result
, content
= self
.db
.update_rows('nets', network
, WHERE
={'uuid': network_id
}, log
=True)
690 # if result > 0 and nbports>0 and 'admin_state_up' in network
691 # and network['admin_state_up'] != network_old[0]['admin_state_up']:
696 self
.net_update_ofc_thread(network_id
)
697 except ovimException
as e
:
698 raise ovimException("Error while launching openflow rules in network '{}' {}"
699 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
700 except Exception as e
:
701 raise ovimException("Error while launching openflow rules in network '{}' {}"
702 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
704 if self
.config
.get("dhcp_server"):
705 if network_id
in self
.config
["dhcp_nets"]:
706 self
.config
["dhcp_nets"].remove(network_id
)
707 if network
.get("name", network_old
[0]["name"]) in self
.config
["dhcp_server"].get("nets", ()):
708 self
.config
["dhcp_nets"].append(network_id
)
710 net_bind
= network
.get("bind_type", network_old
[0]["bind_type"])
711 if net_bind
and net_bind
and net_bind
[:7] == "bridge:" and net_bind
[7:] in self
.config
["dhcp_server"].get(
712 "bridge_ifaces", ()):
713 self
.config
["dhcp_nets"].append(network_id
)
716 raise ovimException(content
, -result
)
718 def delete_network(self
, network_id
):
720 Delete network by network id
721 :param network_id: network id
725 # delete from the data base
726 result
, content
= self
.db
.delete_row('nets', network_id
)
729 raise ovimException("Network %s not found " % network_id
, HTTP_Not_Found
)
731 for brnet
in self
.config
['bridge_nets']:
732 if brnet
[3] == network_id
:
735 if self
.config
.get("dhcp_server") and network_id
in self
.config
["dhcp_nets"]:
736 self
.config
["dhcp_nets"].remove(network_id
)
739 raise ovimException("Error deleting network %s" % network_id
, HTTP_Internal_Server_Error
)
741 def get_openflow_rules(self
, network_id
=None):
743 Get openflow id from DB
744 :param network_id: Network id, if none all networks will be retrieved
745 :return: Return a list with Openflow rules per net
751 where_
= {"net_id": network_id
}
752 result
, content
= self
.db
.get_table(
753 SELECT
=("name", "net_id", "ofc_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
754 WHERE
=where_
, FROM
='of_flows')
757 raise ovimException(str(content
), -result
)
760 def edit_openflow_rules(self
, network_id
=None):
763 To make actions over the net. The action is to reinstall the openflow rules
764 network_id can be 'all'
765 :param network_id: Network id, if none all networks will be retrieved
766 :return : Number of nets updated
773 where_
= {"uuid": network_id
}
774 result
, content
= self
.db
.get_table(SELECT
=("uuid", "type"), WHERE
=where_
, FROM
='nets')
777 raise ovimException(str(content
), -result
)
780 if net
["type"] != "ptp" and net
["type"] != "data":
785 self
.net_update_ofc_thread(net
['uuid'])
786 except ovimException
as e
:
787 raise ovimException("Error updating network'{}' {}".format(net
['uuid'], str(e
)),
788 HTTP_Internal_Server_Error
)
789 except Exception as e
:
790 raise ovimException("Error updating network '{}' {}".format(net
['uuid'], str(e
)),
791 HTTP_Internal_Server_Error
)
795 def delete_openflow_rules(self
, ofc_id
=None):
797 To make actions over the net. The action is to delete ALL openflow rules
798 :return: return operation result
802 if 'Default' in self
.config
['ofcs_thread']:
803 r
, c
= self
.config
['ofcs_thread']['Default'].insert_task("clear-all")
805 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
807 elif ofc_id
in self
.config
['ofcs_thread']:
808 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("clear-all")
812 raise ovimException(str(c
), -r
)
814 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
817 def get_openflow_ports(self
, ofc_id
=None):
819 Obtain switch ports names of openflow controller
820 :return: Return flow ports in DB
823 if 'Default' in self
.config
['ofcs_thread']:
824 conn
= self
.config
['ofcs_thread']['Default'].OF_connector
826 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
828 if ofc_id
in self
.config
['ofcs_thread']:
829 conn
= self
.config
['ofcs_thread'][ofc_id
].OF_connector
831 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
834 def get_ports(self
, columns
=None, filter={}, limit
=None):
835 # result, content = my.db.get_ports(where_)
836 result
, content
= self
.db
.get_table(SELECT
=columns
, WHERE
=filter, FROM
='ports', LIMIT
=limit
)
838 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
839 raise ovimException(str(content
), -result
)
841 convert_boolean(content
, ('admin_state_up',))
844 def new_port(self
, port_data
):
845 port_data
['type'] = 'external'
846 if port_data
.get('net_id'):
847 # check that new net has the correct type
848 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
850 raise ovimException(str(new_net
), -result
)
851 # insert in data base
852 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
854 if 'net_id' in port_data
:
856 self
.net_update_ofc_thread(port_data
['net_id'])
857 except ovimException
as e
:
858 raise ovimException("Cannot insert a task for updating network '{}' {}"
859 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
860 except Exception as e
:
861 raise ovimException("Cannot insert a task for updating network '{}' {}"
862 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
866 raise ovimException(str(uuid
), -result
)
868 def new_external_port(self
, port_data
):
870 Create new external port and check port mapping correspondence
871 :param port_data: port_data = {
872 'region': 'datacenter region',
873 'compute_node': 'compute node id',
874 'pci': 'pci port address',
877 'tenant_id': 'tenant id',
880 'ip_address': 'ip address - optional'}
884 port_data
['type'] = 'external'
886 if port_data
.get('net_id'):
887 # check that new net has the correct type
888 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
890 raise ovimException(str(new_net
), -result
)
891 # insert in data base
894 if port_data
.get('region'):
895 db_filter
['region'] = port_data
['region']
896 if port_data
.get('pci'):
897 db_filter
['pci'] = port_data
['pci']
898 if port_data
.get('compute_node'):
899 db_filter
['compute_node'] = port_data
['compute_node']
901 columns
= ['ofc_id', 'switch_dpid', 'switch_port', 'switch_mac', 'pci']
902 port_mapping_data
= self
.get_of_port_mappings(columns
, db_filter
)
904 if not len(port_mapping_data
):
905 raise ovimException("No port mapping founded for '{}'".format(str(db_filter
)),
907 elif len(port_mapping_data
) > 1:
908 raise ovimException("Wrong port data was given, please check pci, region & compute id data",
911 port_data
['ofc_id'] = port_mapping_data
[0]['ofc_id']
912 port_data
['switch_dpid'] = port_mapping_data
[0]['switch_dpid']
913 port_data
['switch_port'] = port_mapping_data
[0]['switch_port']
914 port_data
['switch_mac'] = port_mapping_data
[0]['switch_mac']
916 # remove from compute_node, region and pci of_port_data to adapt to 'ports' structure
917 if 'region' in port_data
:
918 del port_data
['region']
919 if 'pci' in port_data
:
921 if 'compute_node' in port_data
:
922 del port_data
['compute_node']
924 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
927 self
.net_update_ofc_thread(port_data
['net_id'], port_data
['ofc_id'])
928 except ovimException
as e
:
929 raise ovimException("Cannot insert a task for updating network '{}' {}".
930 format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
931 except Exception as e
:
932 raise ovimException("Cannot insert a task for updating network '{}' {}"
933 .format(port_data
['net_id'], e
), HTTP_Internal_Server_Error
)
936 raise ovimException(str(uuid
), -result
)
938 def net_update_ofc_thread(self
, net_id
, ofc_id
=None, switch_dpid
=None):
940 Insert a update net task by net id or ofc_id for each ofc thread
941 :param net_id: network id
942 :param ofc_id: openflow controller id
943 :param switch_dpid: switch dpid
947 raise ovimException("No net_id received", HTTP_Internal_Server_Error
)
950 c
= 'No valid ofc_id or switch_dpid received'
953 ports
= self
.get_ports(filter={"net_id": net_id
})
955 port_ofc_id
= port
.get('ofc_id', None)
957 ofc_id
= port
['ofc_id']
958 switch_dpid
= port
['switch_dpid']
960 #TODO if not ofc_id: look at database table ofcs
963 # If no ofc_id found it, default ofc_id is used.
964 if not ofc_id
and not switch_dpid
:
967 if ofc_id
and ofc_id
in self
.config
['ofcs_thread']:
968 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("update-net", net_id
)
971 ofcs_dpid_list
= self
.config
['ofcs_thread_dpid']
972 for ofc_t
in ofcs_dpid_list
:
973 if switch_dpid
in ofc_t
:
974 r
, c
= ofc_t
[switch_dpid
].insert_task("update-net", net_id
)
977 message
= "Cannot insert a task for updating network '{}', {}".format(net_id
, c
)
978 self
.logger
.error(message
)
979 raise ovimException(message
, HTTP_Internal_Server_Error
)
981 def delete_port(self
, port_id
):
982 # Look for the previous port data
983 result
, ports
= self
.db
.get_table(WHERE
={'uuid': port_id
, "type": "external"}, FROM
='ports')
985 raise ovimException("Cannot get port info from database: {}".format(ports
), http_code
=-result
)
986 # delete from the data base
987 result
, content
= self
.db
.delete_row('ports', port_id
)
989 raise ovimException("External port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
991 raise ovimException("Cannot delete port from database: {}".format(content
), http_code
=-result
)
993 network
= ports
[0].get('net_id', None)
998 self
.net_update_ofc_thread(network
, ofc_id
=ports
[0]["ofc_id"], switch_dpid
=ports
[0]["switch_dpid"])
999 except ovimException
as e
:
1000 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1001 HTTP_Internal_Server_Error
)
1002 except Exception as e
:
1003 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1004 HTTP_Internal_Server_Error
)
1008 def edit_port(self
, port_id
, port_data
, admin
=True):
1009 # Look for the previous port data
1010 result
, content
= self
.db
.get_table(FROM
="ports", WHERE
={'uuid': port_id
})
1012 raise ovimException("Cannot get port info from database: {}".format(content
), http_code
=-result
)
1014 raise ovimException("Port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
1019 if 'net_id' in port_data
:
1021 old_net
= port
.get('net_id', None)
1022 new_net
= port_data
['net_id']
1023 if old_net
!= new_net
:
1026 nets
.append(new_net
) # put first the new net, so that new openflow rules are created before removing the old ones
1028 nets
.append(old_net
)
1029 if port
['type'] == 'instance:bridge' or port
['type'] == 'instance:ovs':
1030 raise ovimException("bridge interfaces cannot be attached to a different net", http_code
=HTTP_Forbidden
)
1031 elif port
['type'] == 'external' and not admin
:
1032 raise ovimException("Needed admin privileges",http_code
=HTTP_Unauthorized
)
1034 # check that new net has the correct type
1035 result
, new_net_dict
= self
.db
.check_target_net(new_net
, None, port
['type'])
1037 raise ovimException("Error {}".format(new_net_dict
), http_code
=HTTP_Conflict
)
1038 # change VLAN for SR-IOV ports
1039 if result
>= 0 and port
["type"] == "instance:data" and port
["model"] == "VF": # TODO consider also VFnotShared
1041 port_data
["vlan"] = None
1043 port_data
["vlan"] = new_net_dict
["vlan"]
1044 # get host where this VM is allocated
1045 result
, content
= self
.db
.get_table(FROM
="instances", WHERE
={"uuid": port
["instance_id"]})
1047 host_id
= content
[0]["host_id"]
1049 # insert in data base
1051 result
, content
= self
.db
.update_rows('ports', port_data
, WHERE
={'uuid': port_id
}, log
=False)
1052 port
.update(port_data
)
1054 # Insert task to complete actions
1058 self
.net_update_ofc_thread(net_id
, port
["ofc_id"], switch_dpid
=port
["switch_dpid"])
1059 except ovimException
as e
:
1060 raise ovimException("Error updating network'{}' {}".format(net_id
, str(e
)),
1061 HTTP_Internal_Server_Error
)
1062 except Exception as e
:
1063 raise ovimException("Error updating network '{}' {}".format(net_id
, str(e
)),
1064 HTTP_Internal_Server_Error
)
1067 r
, v
= self
.config
['host_threads'][host_id
].insert_task("edit-iface", port_id
, old_net
, new_net
)
1069 self
.logger
.error("Error updating network '{}' {}".format(r
,v
))
1070 # TODO Do something if fails
1074 raise ovimException("Error {}".format(content
), http_code
=-result
)
1076 def new_of_controller(self
, ofc_data
):
1078 Create a new openflow controller into DB
1079 :param ofc_data: Dict openflow controller data
1080 :return: openflow controller dpid
1083 result
, ofc_uuid
= self
.db
.new_row('ofcs', ofc_data
, True, True)
1085 raise ovimException("New ofc Error %s" % ofc_uuid
, HTTP_Internal_Server_Error
)
1087 ofc_data
['uuid'] = ofc_uuid
1088 of_conn
= self
._load
_of
_module
(ofc_data
)
1089 self
._create
_ofc
_task
(ofc_uuid
, ofc_data
['dpid'], of_conn
)
1093 def edit_of_controller(self
, of_id
, ofc_data
):
1095 Edit an openflow controller entry from DB
1099 raise ovimException("No data received during uptade OF contorller", http_code
=HTTP_Internal_Server_Error
)
1101 old_of_controller
= self
.show_of_controller(of_id
)
1103 if old_of_controller
:
1104 result
, content
= self
.db
.update_rows('ofcs', ofc_data
, WHERE
={'uuid': of_id
}, log
=False)
1108 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1111 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1112 http_code
=HTTP_Internal_Server_Error
)
1114 def delete_of_controller(self
, of_id
):
1116 Delete an openflow controller from DB.
1117 :param of_id: openflow controller dpid
1121 ofc
= self
.show_of_controller(of_id
)
1123 result
, content
= self
.db
.delete_row("ofcs", of_id
)
1125 raise ovimException("Cannot delete ofc from database: {}".format(content
), http_code
=-result
)
1127 raise ovimException("ofc {} not found ".format(content
), http_code
=HTTP_Not_Found
)
1129 ofc_thread
= self
.config
['ofcs_thread'][of_id
]
1130 del self
.config
['ofcs_thread'][of_id
]
1131 for ofc_th
in self
.config
['ofcs_thread_dpid']:
1132 if ofc
['dpid'] in ofc_th
:
1133 self
.config
['ofcs_thread_dpid'].remove(ofc_th
)
1135 ofc_thread
.insert_task("exit")
1140 def show_of_controller(self
, uuid
):
1142 Show an openflow controller by dpid from DB.
1143 :param db_filter: List with where query parameters
1147 result
, content
= self
.db
.get_table(FROM
='ofcs', WHERE
={"uuid": uuid
}, LIMIT
=100)
1150 raise ovimException("Openflow controller with uuid '{}' not found".format(uuid
),
1151 http_code
=HTTP_Not_Found
)
1153 raise ovimException("Openflow controller with uuid '{}' error".format(uuid
),
1154 http_code
=HTTP_Internal_Server_Error
)
1157 def get_of_controllers(self
, columns
=None, db_filter
={}, limit
=None):
1159 Show an openflow controllers from DB.
1160 :param columns: List with SELECT query parameters
1161 :param db_filter: List with where query parameters
1162 :param limit: result Limit
1165 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='ofcs', WHERE
=db_filter
, LIMIT
=limit
)
1168 raise ovimException(str(content
), -result
)
1172 def get_tenants(self
, columns
=None, db_filter
={}, limit
=None):
1174 Retrieve tenant list from DB
1175 :param columns: List with SELECT query parameters
1176 :param db_filter: List with where query parameters
1177 :param limit: result limit
1180 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=columns
, WHERE
=db_filter
, LIMIT
=limit
)
1182 raise ovimException('get_tenatns Error {}'.format(str(content
)), -result
)
1184 convert_boolean(content
, ('enabled',))
1187 def show_tenant_id(self
, tenant_id
):
1189 Get tenant from DB by id
1190 :param tenant_id: tenant id
1193 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid', 'name', 'description', 'enabled'),
1194 WHERE
={"uuid": tenant_id
})
1196 raise ovimException(str(content
), -result
)
1198 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1200 convert_boolean(content
, ('enabled',))
1203 def new_tentant(self
, tenant
):
1205 Create a tenant and store in DB
1206 :param tenant: Dictionary with tenant data
1207 :return: the uuid of created tenant. Raise exception upon error
1210 # insert in data base
1211 result
, tenant_uuid
= self
.db
.new_tenant(tenant
)
1216 raise ovimException(str(tenant_uuid
), -result
)
1218 def delete_tentant(self
, tenant_id
):
1220 Delete a tenant from the database.
1221 :param tenant_id: Tenant id
1222 :return: delete tenant id
1226 r
, tenants_flavors
= self
.db
.get_table(FROM
='tenants_flavors', SELECT
=('flavor_id', 'tenant_id'),
1227 WHERE
={'tenant_id': tenant_id
})
1229 tenants_flavors
= ()
1230 r
, tenants_images
= self
.db
.get_table(FROM
='tenants_images', SELECT
=('image_id', 'tenant_id'),
1231 WHERE
={'tenant_id': tenant_id
})
1235 result
, content
= self
.db
.delete_row('tenants', tenant_id
)
1237 raise ovimException("tenant '%s' not found" % tenant_id
, HTTP_Not_Found
)
1239 for flavor
in tenants_flavors
:
1240 self
.db
.delete_row_by_key("flavors", "uuid", flavor
['flavor_id'])
1241 for image
in tenants_images
:
1242 self
.db
.delete_row_by_key("images", "uuid", image
['image_id'])
1245 raise ovimException("Error deleting tenant '%s' " % tenant_id
, HTTP_Internal_Server_Error
)
1247 def edit_tenant(self
, tenant_id
, tenant_data
):
1249 Update a tenant data identified by tenant id
1250 :param tenant_id: tenant id
1251 :param tenant_data: Dictionary with tenant data
1255 # Look for the previous data
1256 result
, tenant_data_old
= self
.db
.get_table(FROM
='tenants', WHERE
={'uuid': tenant_id
})
1258 raise ovimException("Error updating tenant with uuid='{}': {}".format(tenant_id
, tenant_data_old
),
1259 HTTP_Internal_Server_Error
)
1261 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1263 # insert in data base
1264 result
, content
= self
.db
.update_rows('tenants', tenant_data
, WHERE
={'uuid': tenant_id
}, log
=True)
1268 raise ovimException(str(content
), -result
)
1270 def set_of_port_mapping(self
, of_maps
, ofc_id
=None, switch_dpid
=None, region
=None):
1272 Create new port mapping entry
1273 :param of_maps: List with port mapping information
1274 # maps =[{"ofc_id": <ofc_id>,"region": datacenter region,"compute_node": compute uuid,"pci": pci adress,
1275 "switch_dpid": swith dpid,"switch_port": port name,"switch_mac": mac}]
1276 :param ofc_id: ofc id
1277 :param switch_dpid: switch dpid
1278 :param region: datacenter region id
1284 map['ofc_id'] = ofc_id
1286 map['switch_dpid'] = switch_dpid
1288 map['region'] = region
1290 for of_map
in of_maps
:
1291 result
, uuid
= self
.db
.new_row('of_port_mappings', of_map
, True)
1293 of_map
["uuid"] = uuid
1295 raise ovimException(str(uuid
), -result
)
1298 def clear_of_port_mapping(self
, db_filter
={}):
1300 Clear port mapping filtering using db_filter dict
1301 :param db_filter: Parameter to filter during remove process
1304 result
, content
= self
.db
.delete_row_by_dict(FROM
='of_port_mappings', WHERE
=db_filter
)
1309 raise ovimException("Error deleting of_port_mappings with filter='{}'".format(str(db_filter
)),
1310 HTTP_Internal_Server_Error
)
1312 def get_of_port_mappings(self
, column
=None, db_filter
=None, db_limit
=None):
1314 Retrive port mapping from DB
1319 result
, content
= self
.db
.get_table(SELECT
=column
, WHERE
=db_filter
, FROM
='of_port_mappings', LIMIT
=db_limit
)
1322 self
.logger
.error("get_of_port_mappings Error %d %s", result
, content
)
1323 raise ovimException(str(content
), -result
)
1327 def get_dhcp_controller(self
):
1329 Create an host_thread object for manage openvim controller and not create a thread for itself
1330 :return: dhcp_host openvim controller object
1333 if 'openvim_controller' in self
.config
['host_threads']:
1334 return self
.config
['host_threads']['openvim_controller']
1337 controller_ip
= self
.config
['ovs_controller_ip']
1338 ovs_controller_user
= self
.config
['ovs_controller_user']
1340 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
1341 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
1343 dhcp_host
= ht
.host_thread(name
='openvim_controller', user
=ovs_controller_user
, host
=controller_ip
,
1345 db_lock
=self
.db_lock
, test
=host_test_mode
,
1346 image_path
=self
.config
['image_path'], version
=self
.config
['version'],
1347 host_id
='openvim_controller', develop_mode
=host_develop_mode
,
1348 develop_bridge_iface
=bridge_ifaces
, logger_name
=self
.logger_name
+ ".host.controller",
1349 debug
=self
.config
.get('log_level_host'))
1351 self
.config
['host_threads']['openvim_controller'] = dhcp_host
1352 if not host_test_mode
:
1353 dhcp_host
.ssh_connect()
1356 def launch_dhcp_server(self
, vlan
, first_ip
, last_ip
, cidr
, gateway
):
1358 Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
1359 :param vlan: vlan identifier
1360 :param first_ip: First dhcp range ip
1361 :param last_ip: Last dhcp range ip
1362 :param cidr: net cidr
1363 :param gateway: net gateway
1366 ip_tools
= IPNetwork(cidr
)
1367 dhcp_netmask
= str(ip_tools
.netmask
)
1368 ip_range
= [first_ip
, last_ip
]
1370 dhcp_path
= self
.config
['ovs_controller_file_path']
1372 controller_host
= self
.get_dhcp_controller()
1373 controller_host
.create_linux_bridge(vlan
)
1374 controller_host
.create_dhcp_interfaces(vlan
, first_ip
, dhcp_netmask
)
1375 controller_host
.launch_dhcp_server(vlan
, ip_range
, dhcp_netmask
, dhcp_path
, gateway
)
1377 if __name__
== "__main__":
1379 parser
= argparse
.ArgumentParser()
1380 parser
.add_argument("-v","--version", help="show ovim library version", action
="store_true")
1381 parser
.add_argument("--database-version", help="show required database version", action
="store_true")
1382 args
= parser
.parse_args()
1384 print ('openvimd version {} {}'.format(ovim
.get_version(), ovim
.get_version_date()))
1385 print ('(c) Copyright Telefonica')
1386 elif args
.database_version
:
1387 print ('required database version: {}'.format(ovim
.get_database_version()))