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.
36 from netaddr
import IPNetwork
37 from jsonschema
import validate
as js_v
, exceptions
as js_e
38 import host_thread
as ht
39 import dhcp_thread
as dt
40 import openflow_thread
as oft
43 __author__
= "Alfonso Tierno, Leonardo Mirabal"
44 __date__
= "$06-Feb-2017 12:07:15$"
45 __version__
= "0.5.13-r529"
46 version_date
= "May 2017"
47 database_version
= 18 #needed database schema version
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 db_path
= db_path
[:db_path
.rfind("/")]
177 if os
.path
.exists(db_path
+ "/database_utils/migrate_vim_db.sh"):
178 db_path
+= "/database_utils"
180 db_path
+= "/../database_utils"
183 raise ovimException("DATABASE is not valid. If you think it is corrupted, you can init it with"
184 " '{db_path}/init_vim_db.sh' script".format(db_path
=db_path
))
185 elif r
[0] != database_version
:
186 raise ovimException("DATABASE wrong version '{current}'. Try to upgrade/downgrade to version '{target}'"
187 " with '{db_path}/migrate_vim_db.sh {target}'".format(
188 current
=r
[0], target
=database_version
, db_path
=db_path
))
189 self
.logger
.critical("Starting ovim server version: '{} {}' database version '{}'".format(
190 self
.get_version(), self
.get_version_date(), self
.get_database_version()))
191 # create database connection for openflow threads
192 self
.db_of
= self
._create
_database
_connection
()
193 self
.config
["db"] = self
.db_of
194 self
.db_lock
= threading
.Lock()
195 self
.config
["db_lock"] = self
.db_lock
197 self
.of_test_mode
= False if self
.config
['mode'] == 'normal' or self
.config
['mode'] == "OF only" else True
198 # precreate interfaces; [bridge:<host_bridge_name>, VLAN used at Host, uuid of network camping in this bridge,
201 self
.config
['dhcp_nets'] = []
202 self
.config
['bridge_nets'] = []
203 for bridge
, vlan_speed
in self
.config
["bridge_ifaces"].items():
204 # skip 'development_bridge'
205 if self
.config
['mode'] == 'development' and self
.config
['development_bridge'] == bridge
:
207 self
.config
['bridge_nets'].append([bridge
, vlan_speed
[0], vlan_speed
[1], None])
209 # check if this bridge is already used (present at database) for a network)
210 used_bridge_nets
= []
211 for brnet
in self
.config
['bridge_nets']:
212 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'provider': "bridge:" + brnet
[0]})
214 brnet
[3] = nets
[0]['uuid']
215 used_bridge_nets
.append(brnet
[0])
216 if self
.config
.get("dhcp_server"):
217 if brnet
[0] in self
.config
["dhcp_server"]["bridge_ifaces"]:
218 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
219 if len(used_bridge_nets
) > 0:
220 self
.logger
.info("found used bridge nets: " + ",".join(used_bridge_nets
))
221 # get nets used by dhcp
222 if self
.config
.get("dhcp_server"):
223 for net
in self
.config
["dhcp_server"].get("nets", ()):
224 r
, nets
= self
.db
.get_table(SELECT
=('uuid',), FROM
='nets', WHERE
={'name': net
})
226 self
.config
['dhcp_nets'].append(nets
[0]['uuid'])
229 self
._start
_ofc
_default
_task
()
231 # OFC per tenant in DB
232 self
._start
_of
_db
_tasks
()
234 # create dhcp_server thread
235 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
236 dhcp_params
= self
.config
.get("dhcp_server")
238 thread
= dt
.dhcp_thread(dhcp_params
=dhcp_params
, test
=host_test_mode
, dhcp_nets
=self
.config
["dhcp_nets"],
239 db
=self
.db_of
, db_lock
=self
.db_lock
, logger_name
=self
.logger_name
+ ".dhcp",
240 debug
=self
.config
.get('log_level_of'))
242 self
.config
['dhcp_thread'] = thread
244 # Create one thread for each host
245 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
246 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
247 host_develop_bridge_iface
= self
.config
.get('development_bridge', None)
249 # get host list from data base before starting threads
250 r
, hosts
= self
.db
.get_table(SELECT
=('name', 'ip_name', 'user', 'uuid'), FROM
='hosts', WHERE
={'status': 'ok'})
252 raise ovimException("Cannot get hosts from database {}".format(hosts
))
254 self
.config
['host_threads'] = {}
256 host
['image_path'] = '/opt/VNF/images/openvim'
257 thread
= ht
.host_thread(name
=host
['name'], user
=host
['user'], host
=host
['ip_name'], db
=self
.db_of
,
258 db_lock
=self
.db_lock
, test
=host_test_mode
, image_path
=self
.config
['image_path'],
259 version
=self
.config
['version'], host_id
=host
['uuid'], develop_mode
=host_develop_mode
,
260 develop_bridge_iface
=host_develop_bridge_iface
,
261 logger_name
=self
.logger_name
+ ".host." + host
['name'],
262 debug
=self
.config
.get('log_level_host'))
264 self
.config
['host_threads'][host
['uuid']] = thread
266 # create ovs dhcp thread
267 result
, content
= self
.db
.get_table(FROM
='nets')
269 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
270 raise ovimException(str(content
), -result
)
273 net_type
= net
['type']
274 if (net_type
== 'bridge_data' or net_type
== 'bridge_man') \
275 and net
["provider"][:4] == 'OVS:' and net
["enable_dhcp"] == "true":
276 self
.launch_dhcp_server(net
['vlan'],
277 net
['dhcp_first_ip'],
282 def _start_of_db_tasks(self
):
284 Start ofc task for existing ofcs in database
289 ofcs
= self
.get_of_controllers()
292 of_conn
= self
._load
_of
_module
(ofc
)
293 # create ofc thread per of controller
294 self
._create
_ofc
_task
(ofc
['uuid'], ofc
['dpid'], of_conn
)
296 def _create_ofc_task(self
, ofc_uuid
, dpid
, of_conn
):
298 Create an ofc thread for handle each sdn controllers
299 :param ofc_uuid: sdn controller uuid
300 :param dpid: sdn controller dpid
301 :param of_conn: OF_conn module
304 if 'ofcs_thread' not in self
.config
and 'ofcs_thread_dpid' not in self
.config
:
306 ofcs_thread_dpid
= []
308 ofcs_threads
= self
.config
['ofcs_thread']
309 ofcs_thread_dpid
= self
.config
['ofcs_thread_dpid']
311 if ofc_uuid
not in ofcs_threads
:
312 ofc_thread
= self
._create
_ofc
_thread
(of_conn
, ofc_uuid
)
313 if ofc_uuid
== "Default":
314 self
.config
['of_thread'] = ofc_thread
316 ofcs_threads
[ofc_uuid
] = ofc_thread
317 self
.config
['ofcs_thread'] = ofcs_threads
319 ofcs_thread_dpid
.append({dpid
: ofc_thread
})
320 self
.config
['ofcs_thread_dpid'] = ofcs_thread_dpid
322 def _start_ofc_default_task(self
):
324 Create default ofc thread
326 if 'of_controller' not in self
.config \
327 and 'of_controller_ip' not in self
.config \
328 and 'of_controller_port' not in self
.config \
329 and 'of_controller_dpid' not in self
.config
:
334 db_config
['ip'] = self
.config
.get('of_controller_ip')
335 db_config
['port'] = self
.config
.get('of_controller_port')
336 db_config
['dpid'] = self
.config
.get('of_controller_dpid')
337 db_config
['type'] = self
.config
.get('of_controller')
338 db_config
['user'] = self
.config
.get('of_user')
339 db_config
['password'] = self
.config
.get('of_password')
341 # create connector to the openflow controller
342 # load other parameters starting by of_ from config dict in a temporal dict
344 of_conn
= self
._load
_of
_module
(db_config
)
345 # create openflow thread
346 self
._create
_ofc
_task
("Default", db_config
['dpid'], of_conn
)
348 def _load_of_module(self
, db_config
):
350 import python module for each SDN controller supported
351 :param db_config: SDN dn information
355 raise ovimException("No module found it", HTTP_Internal_Server_Error
)
360 if self
.of_test_mode
:
361 return openflow_conn
.OfTestConnector({"name": db_config
['type'],
362 "dpid": db_config
['dpid'],
363 "of_debug": self
.config
['log_level_of']})
367 temp_dict
['of_ip'] = db_config
['ip']
368 temp_dict
['of_port'] = db_config
['port']
369 temp_dict
['of_dpid'] = db_config
['dpid']
370 temp_dict
['of_controller'] = db_config
['type']
371 temp_dict
['of_user'] = db_config
.get('user')
372 temp_dict
['of_password'] = db_config
.get('password')
374 temp_dict
['of_debug'] = self
.config
['log_level_of']
376 if temp_dict
['of_controller'] == 'opendaylight':
379 module
= temp_dict
['of_controller']
381 if module
not in ovim
.of_module
:
382 for base
in ("", "osm_openvim.", "lib_osm_openvim."):
384 pkg
= __import__(base
+ module
)
386 of_conn_module
= getattr(pkg
, module
)
389 ovim
.of_module
[module
] = of_conn_module
390 self
.logger
.debug("Module load from {}".format(base
+ module
))
392 except Exception as e
:
393 self
.logger
.warning("Module {} not found {}".format(base
+ module
, e
))
395 self
.logger
.error("Cannot open openflow controller module of type '%s'", module
)
396 raise ovimException("Cannot open openflow controller of type module '{}'"
397 "Revise it is installed".format(module
),
398 HTTP_Internal_Server_Error
)
400 of_conn_module
= ovim
.of_module
[module
]
401 return of_conn_module
.OF_conn(temp_dict
)
402 except Exception as e
:
403 self
.logger
.error("Cannot open the Openflow controller '%s': %s", type(e
).__name
__, str(e
))
404 raise ovimException("Cannot open the Openflow controller '{}': '{}'".format(type(e
).__name
__, str(e
)),
405 HTTP_Internal_Server_Error
)
407 def _create_ofc_thread(self
, of_conn
, ofc_uuid
="Default"):
409 Create and launch a of thread
412 # create openflow thread
414 #if 'of_controller_nets_with_same_vlan' in self.config:
415 # ofc_net_same_vlan = self.config['of_controller_nets_with_same_vlan']
417 # ofc_net_same_vlan = False
418 ofc_net_same_vlan
= False
420 thread
= oft
.openflow_thread(ofc_uuid
, of_conn
, of_test
=self
.of_test_mode
, db
=self
.db_of
, db_lock
=self
.db_lock
,
421 pmp_with_same_vlan
=ofc_net_same_vlan
, debug
=self
.config
['log_level_of'])
422 #r, c = thread.OF_connector.obtain_port_correspondence()
424 # raise ovimException("Cannot get openflow information %s", c)
428 def stop_service(self
):
429 threads
= self
.config
.get('host_threads', {})
430 if 'of_thread' in self
.config
:
431 threads
['of'] = (self
.config
['of_thread'])
432 if 'ofcs_thread' in self
.config
:
433 ofcs_thread
= self
.config
['ofcs_thread']
434 for ofc
in ofcs_thread
:
435 threads
[ofc
] = ofcs_thread
[ofc
]
437 if 'dhcp_thread' in self
.config
:
438 threads
['dhcp'] = (self
.config
['dhcp_thread'])
440 for thread
in threads
.values():
441 thread
.insert_task("exit")
442 for thread
in threads
.values():
445 def get_networks(self
, columns
=None, db_filter
={}, limit
=None):
447 Retreive networks available
448 :param columns: List with select query parameters
449 :param db_filter: List with where query parameters
450 :param limit: Query limit result
453 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='nets', WHERE
=db_filter
, LIMIT
=limit
)
456 raise ovimException(str(content
), -result
)
458 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
462 def show_network(self
, network_id
, db_filter
={}):
464 Get network from DB by id
465 :param network_id: net Id
466 :param db_filter: List with where query parameters
471 raise ovimException("Not network id was not found")
472 db_filter
['uuid'] = network_id
474 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
=db_filter
, LIMIT
=100)
477 raise ovimException(str(content
), -result
)
479 raise ovimException("show_network network '%s' not found" % network_id
, -result
)
481 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
483 result
, ports
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
484 WHERE
={'net_id': network_id
}, LIMIT
=100)
486 content
[0]['ports'] = ports
488 convert_boolean(content
, ('shared', 'admin_state_up', 'enable_dhcp'))
491 def new_network(self
, network
):
496 tenant_id
= network
.get('tenant_id')
499 result
, _
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
, "enabled": True})
501 raise ovimException("set_network error, no tenant founded", -result
)
505 net_provider
= network
.get('provider')
506 net_type
= network
.get('type')
507 net_vlan
= network
.get("vlan")
508 net_bind_net
= network
.get("bind_net")
509 net_bind_type
= network
.get("bind_type")
510 net_region
= network
.get("region")
511 name
= network
["name"]
513 # check if network name ends with :<vlan_tag> and network exist in order to make and automated bindning
514 vlan_index
= name
.rfind(":")
515 if not net_bind_net
and not net_bind_type
and vlan_index
> 1:
517 vlan_tag
= int(name
[vlan_index
+ 1:])
518 if not vlan_tag
and vlan_tag
< 4096:
519 net_bind_net
= name
[:vlan_index
]
520 net_bind_type
= "vlan:" + name
[vlan_index
+ 1:]
525 # look for a valid net
526 if self
._check
_valid
_uuid
(net_bind_net
):
527 net_bind_key
= "uuid"
529 net_bind_key
= "name"
530 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
532 raise ovimException(' getting nets from db ' + content
, HTTP_Internal_Server_Error
)
534 raise ovimException(" bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
536 raise ovimException(" more than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
537 network
["bind_net"] = content
[0]["uuid"]
540 if net_bind_type
[0:5] != "vlan:":
541 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
542 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
543 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
545 network
["bind_type"] = net_bind_type
548 if net_provider
[:9] == "openflow:":
550 if net_type
!= "ptp" and net_type
!= "data":
551 raise ovimException(" only 'ptp' or 'data' net types can be bound to 'openflow'",
557 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
558 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound "
559 "to 'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
561 net_type
= 'bridge_man'
564 net_type
= 'bridge_man'
567 if net_provider
[:7] == 'bridge:':
568 # check it is one of the pre-provisioned bridges
569 bridge_net_name
= net_provider
[7:]
570 for brnet
in self
.config
['bridge_nets']:
571 if brnet
[0] == bridge_net_name
: # free
573 raise ovimException("invalid 'provider:physical', "
574 "bridge '%s' is already used" % bridge_net_name
, HTTP_Conflict
)
578 # if bridge_net==None:
579 # bottle.abort(HTTP_Bad_Request, "invalid 'provider:physical', bridge '%s' is not one of the
580 # provisioned 'bridge_ifaces' in the configuration file" % bridge_net_name)
583 elif self
.config
['network_type'] == 'bridge' and (net_type
== 'bridge_data' or net_type
== 'bridge_man'):
584 # look for a free precreated nets
585 for brnet
in self
.config
['bridge_nets']:
586 if not brnet
[3]: # free
588 if net_type
== 'bridge_man': # look for the smaller speed
589 if brnet
[2] < bridge_net
[2]:
591 else: # look for the larger speed
592 if brnet
[2] > bridge_net
[2]:
598 raise ovimException("Max limits of bridge networks reached. Future versions of VIM "
599 "will overcome this limit", HTTP_Bad_Request
)
601 self
.logger
.debug("using net " + bridge_net
)
602 net_provider
= "bridge:" + bridge_net
[0]
603 net_vlan
= bridge_net
[1]
604 elif net_type
== 'bridge_data' or net_type
== 'bridge_man' and self
.config
['network_type'] == 'ovs':
607 if net_type
== "data" or net_type
== "ptp":
608 net_region
= "__DATA__"
609 elif net_provider
== "OVS":
610 net_region
= "__OVS__"
611 if not net_vlan
and (net_type
== "data" or net_type
== "ptp" or net_provider
== "OVS"):
612 net_vlan
= self
.db
.get_free_net_vlan(net_region
)
614 raise ovimException("Error getting an available vlan", HTTP_Internal_Server_Error
)
615 if net_provider
== 'OVS':
616 net_provider
= 'OVS' + ":" + str(net_vlan
)
618 network
['provider'] = net_provider
619 network
['type'] = net_type
620 network
['vlan'] = net_vlan
621 network
['region'] = net_region
622 dhcp_integrity
= True
623 if 'enable_dhcp' in network
and network
['enable_dhcp']:
624 dhcp_integrity
= self
._check
_dhcp
_data
_integrity
(network
)
626 result
, content
= self
.db
.new_row('nets', network
, True, True)
628 if result
>= 0 and dhcp_integrity
:
630 bridge_net
[3] = content
631 if self
.config
.get("dhcp_server") and self
.config
['network_type'] == 'bridge':
632 if network
["name"] in self
.config
["dhcp_server"].get("nets", ()):
633 self
.config
["dhcp_nets"].append(content
)
634 self
.logger
.debug("dhcp_server: add new net", content
)
635 elif not bridge_net
and bridge_net
[0] in self
.config
["dhcp_server"].get("bridge_ifaces", ()):
636 self
.config
["dhcp_nets"].append(content
)
637 self
.logger
.debug("dhcp_server: add new net", content
, content
)
640 raise ovimException("Error posting network", HTTP_Internal_Server_Error
)
641 # TODO kei change update->edit
643 def edit_network(self
, network_id
, network
):
645 Update entwork data byt id
648 # Look for the previous data
649 where_
= {'uuid': network_id
}
650 result
, network_old
= self
.db
.get_table(FROM
='nets', WHERE
=where_
)
652 raise ovimException("Error updating network %s" % network_old
, HTTP_Internal_Server_Error
)
654 raise ovimException('network %s not found' % network_id
, HTTP_Not_Found
)
656 nbports
, content
= self
.db
.get_table(FROM
='ports', SELECT
=('uuid as port_id',),
657 WHERE
={'net_id': network_id
}, LIMIT
=100)
659 raise ovimException("http_put_network_id error %d %s" % (result
, network_old
), HTTP_Internal_Server_Error
)
661 if 'type' in network
and network
['type'] != network_old
[0]['type']:
662 raise ovimException("Can not change type of network while having ports attached",
663 HTTP_Method_Not_Allowed
)
664 if 'vlan' in network
and network
['vlan'] != network_old
[0]['vlan']:
665 raise ovimException("Can not change vlan of network while having ports attached",
666 HTTP_Method_Not_Allowed
)
669 net_provider
= network
.get('provider', network_old
[0]['provider'])
670 net_type
= network
.get('type', network_old
[0]['type'])
671 net_bind_net
= network
.get("bind_net")
672 net_bind_type
= network
.get("bind_type")
674 # look for a valid net
675 if self
._check
_valid
_uuid
(net_bind_net
):
676 net_bind_key
= "uuid"
678 net_bind_key
= "name"
679 result
, content
= self
.db
.get_table(FROM
='nets', WHERE
={net_bind_key
: net_bind_net
})
681 raise ovimException('Getting nets from db ' + content
, HTTP_Internal_Server_Error
)
683 raise ovimException("bind_net %s '%s'not found" % (net_bind_key
, net_bind_net
), HTTP_Bad_Request
)
685 raise ovimException("More than one bind_net %s '%s' found, use uuid" % (net_bind_key
, net_bind_net
),
687 network
["bind_net"] = content
[0]["uuid"]
689 if net_bind_type
[0:5] != "vlan:":
690 raise ovimException("Bad format for 'bind_type', must be 'vlan:<tag>'", HTTP_Bad_Request
)
691 if int(net_bind_type
[5:]) > 4095 or int(net_bind_type
[5:]) <= 0:
692 raise ovimException("bad format for 'bind_type', must be 'vlan:<tag>' with a tag between 1 and 4095",
695 if net_provider
[:9] == "openflow:":
696 if net_type
!= "ptp" and net_type
!= "data":
697 raise ovimException("Only 'ptp' or 'data' net types can be bound to 'openflow'", HTTP_Bad_Request
)
699 if net_type
!= "bridge_man" and net_type
!= "bridge_data":
700 raise ovimException("Only 'bridge_man' or 'bridge_data' net types can be bound to "
701 "'bridge', 'macvtap' or 'default", HTTP_Bad_Request
)
703 # insert in data base
704 result
, content
= self
.db
.update_rows('nets', network
, WHERE
={'uuid': network_id
}, log
=True)
706 # if result > 0 and nbports>0 and 'admin_state_up' in network
707 # and network['admin_state_up'] != network_old[0]['admin_state_up']:
712 self
.net_update_ofc_thread(network_id
)
713 except ovimException
as e
:
714 raise ovimException("Error while launching openflow rules in network '{}' {}"
715 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
716 except Exception as e
:
717 raise ovimException("Error while launching openflow rules in network '{}' {}"
718 .format(network_id
, str(e
)), HTTP_Internal_Server_Error
)
720 if self
.config
.get("dhcp_server"):
721 if network_id
in self
.config
["dhcp_nets"]:
722 self
.config
["dhcp_nets"].remove(network_id
)
723 if network
.get("name", network_old
[0]["name"]) in self
.config
["dhcp_server"].get("nets", ()):
724 self
.config
["dhcp_nets"].append(network_id
)
726 net_bind
= network
.get("bind_type", network_old
[0]["bind_type"])
727 if net_bind
and net_bind
and net_bind
[:7] == "bridge:" and net_bind
[7:] in self
.config
["dhcp_server"].get(
728 "bridge_ifaces", ()):
729 self
.config
["dhcp_nets"].append(network_id
)
732 raise ovimException(content
, -result
)
734 def delete_network(self
, network_id
):
736 Delete network by network id
737 :param network_id: network id
741 # delete from the data base
742 result
, content
= self
.db
.delete_row('nets', network_id
)
745 raise ovimException("Network %s not found " % network_id
, HTTP_Not_Found
)
747 for brnet
in self
.config
['bridge_nets']:
748 if brnet
[3] == network_id
:
751 if self
.config
.get("dhcp_server") and network_id
in self
.config
["dhcp_nets"]:
752 self
.config
["dhcp_nets"].remove(network_id
)
755 raise ovimException("Error deleting network %s" % network_id
, HTTP_Internal_Server_Error
)
757 def get_openflow_rules(self
, network_id
=None):
759 Get openflow id from DB
760 :param network_id: Network id, if none all networks will be retrieved
761 :return: Return a list with Openflow rules per net
767 where_
= {"net_id": network_id
}
768 result
, content
= self
.db
.get_table(
769 SELECT
=("name", "net_id", "ofc_id", "priority", "vlan_id", "ingress_port", "src_mac", "dst_mac", "actions"),
770 WHERE
=where_
, FROM
='of_flows')
773 raise ovimException(str(content
), -result
)
776 def edit_openflow_rules(self
, network_id
=None):
779 To make actions over the net. The action is to reinstall the openflow rules
780 network_id can be 'all'
781 :param network_id: Network id, if none all networks will be retrieved
782 :return : Number of nets updated
789 where_
= {"uuid": network_id
}
790 result
, content
= self
.db
.get_table(SELECT
=("uuid", "type"), WHERE
=where_
, FROM
='nets')
793 raise ovimException(str(content
), -result
)
796 if net
["type"] != "ptp" and net
["type"] != "data":
801 self
.net_update_ofc_thread(net
['uuid'])
802 except ovimException
as e
:
803 raise ovimException("Error updating network'{}' {}".format(net
['uuid'], str(e
)),
804 HTTP_Internal_Server_Error
)
805 except Exception as e
:
806 raise ovimException("Error updating network '{}' {}".format(net
['uuid'], str(e
)),
807 HTTP_Internal_Server_Error
)
811 def delete_openflow_rules(self
, ofc_id
=None):
813 To make actions over the net. The action is to delete ALL openflow rules
814 :return: return operation result
818 if 'Default' in self
.config
['ofcs_thread']:
819 r
, c
= self
.config
['ofcs_thread']['Default'].insert_task("clear-all")
821 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
823 elif ofc_id
in self
.config
['ofcs_thread']:
824 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("clear-all")
828 raise ovimException(str(c
), -r
)
830 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
833 def get_openflow_ports(self
, ofc_id
=None):
835 Obtain switch ports names of openflow controller
836 :return: Return flow ports in DB
839 if 'Default' in self
.config
['ofcs_thread']:
840 conn
= self
.config
['ofcs_thread']['Default'].OF_connector
842 raise ovimException("Default Openflow controller not not running", HTTP_Not_Found
)
844 if ofc_id
in self
.config
['ofcs_thread']:
845 conn
= self
.config
['ofcs_thread'][ofc_id
].OF_connector
847 raise ovimException("Openflow controller not found with ofc_id={}".format(ofc_id
), HTTP_Not_Found
)
850 def get_ports(self
, columns
=None, filter={}, limit
=None):
851 # result, content = my.db.get_ports(where_)
852 result
, content
= self
.db
.get_table(SELECT
=columns
, WHERE
=filter, FROM
='ports', LIMIT
=limit
)
854 self
.logger
.error("http_get_ports Error %d %s", result
, content
)
855 raise ovimException(str(content
), -result
)
857 convert_boolean(content
, ('admin_state_up',))
860 def new_port(self
, port_data
):
861 port_data
['type'] = 'external'
862 if port_data
.get('net_id'):
863 # check that new net has the correct type
864 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
866 raise ovimException(str(new_net
), -result
)
867 # insert in data base
868 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
870 if 'net_id' in port_data
:
872 self
.net_update_ofc_thread(port_data
['net_id'])
873 except ovimException
as e
:
874 raise ovimException("Cannot insert a task for updating network '{}' {}"
875 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
876 except Exception as e
:
877 raise ovimException("Cannot insert a task for updating network '{}' {}"
878 .format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
882 raise ovimException(str(uuid
), -result
)
884 def new_external_port(self
, port_data
):
886 Create new external port and check port mapping correspondence
887 :param port_data: port_data = {
888 'region': 'datacenter region',
889 'compute_node': 'compute node id',
890 'pci': 'pci port address',
893 'tenant_id': 'tenant id',
896 'ip_address': 'ip address - optional'}
900 port_data
['type'] = 'external'
902 if port_data
.get('net_id'):
903 # check that new net has the correct type
904 result
, new_net
= self
.db
.check_target_net(port_data
['net_id'], None, 'external')
906 raise ovimException(str(new_net
), -result
)
907 # insert in data base
910 if port_data
.get('region'):
911 db_filter
['region'] = port_data
['region']
912 if port_data
.get('pci'):
913 db_filter
['pci'] = port_data
['pci']
914 if port_data
.get('compute_node'):
915 db_filter
['compute_node'] = port_data
['compute_node']
917 columns
= ['ofc_id', 'switch_dpid', 'switch_port', 'switch_mac', 'pci']
918 port_mapping_data
= self
.get_of_port_mappings(columns
, db_filter
)
920 if not len(port_mapping_data
):
921 raise ovimException("No port mapping founded for '{}'".format(str(db_filter
)),
923 elif len(port_mapping_data
) > 1:
924 raise ovimException("Wrong port data was given, please check pci, region & compute id data",
927 port_data
['ofc_id'] = port_mapping_data
[0]['ofc_id']
928 port_data
['switch_dpid'] = port_mapping_data
[0]['switch_dpid']
929 port_data
['switch_port'] = port_mapping_data
[0]['switch_port']
930 port_data
['switch_mac'] = port_mapping_data
[0]['switch_mac']
932 # remove from compute_node, region and pci of_port_data to adapt to 'ports' structure
933 if 'region' in port_data
:
934 del port_data
['region']
935 if 'pci' in port_data
:
937 if 'compute_node' in port_data
:
938 del port_data
['compute_node']
940 result
, uuid
= self
.db
.new_row('ports', port_data
, True, True)
943 self
.net_update_ofc_thread(port_data
['net_id'], port_data
['ofc_id'])
944 except ovimException
as e
:
945 raise ovimException("Cannot insert a task for updating network '{}' {}".
946 format(port_data
['net_id'], str(e
)), HTTP_Internal_Server_Error
)
947 except Exception as e
:
948 raise ovimException("Cannot insert a task for updating network '{}' {}"
949 .format(port_data
['net_id'], e
), HTTP_Internal_Server_Error
)
952 raise ovimException(str(uuid
), -result
)
954 def net_update_ofc_thread(self
, net_id
, ofc_id
=None, switch_dpid
=None):
956 Insert a update net task by net id or ofc_id for each ofc thread
957 :param net_id: network id
958 :param ofc_id: openflow controller id
959 :param switch_dpid: switch dpid
963 raise ovimException("No net_id received", HTTP_Internal_Server_Error
)
966 c
= 'No valid ofc_id or switch_dpid received'
969 ports
= self
.get_ports(filter={"net_id": net_id
})
971 port_ofc_id
= port
.get('ofc_id', None)
973 ofc_id
= port
['ofc_id']
974 switch_dpid
= port
['switch_dpid']
976 #TODO if not ofc_id: look at database table ofcs
979 # If no ofc_id found it, default ofc_id is used.
980 if not ofc_id
and not switch_dpid
:
983 if ofc_id
and ofc_id
in self
.config
['ofcs_thread']:
984 r
, c
= self
.config
['ofcs_thread'][ofc_id
].insert_task("update-net", net_id
)
987 ofcs_dpid_list
= self
.config
['ofcs_thread_dpid']
988 for ofc_t
in ofcs_dpid_list
:
989 if switch_dpid
in ofc_t
:
990 r
, c
= ofc_t
[switch_dpid
].insert_task("update-net", net_id
)
993 message
= "Cannot insert a task for updating network '{}', {}".format(net_id
, c
)
994 self
.logger
.error(message
)
995 raise ovimException(message
, HTTP_Internal_Server_Error
)
997 def delete_port(self
, port_id
):
998 # Look for the previous port data
999 result
, ports
= self
.db
.get_table(WHERE
={'uuid': port_id
, "type": "external"}, FROM
='ports')
1001 raise ovimException("Cannot get port info from database: {}".format(ports
), http_code
=-result
)
1002 # delete from the data base
1003 result
, content
= self
.db
.delete_row('ports', port_id
)
1005 raise ovimException("External port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
1007 raise ovimException("Cannot delete port from database: {}".format(content
), http_code
=-result
)
1009 network
= ports
[0].get('net_id', None)
1014 self
.net_update_ofc_thread(network
, ofc_id
=ports
[0]["ofc_id"], switch_dpid
=ports
[0]["switch_dpid"])
1015 except ovimException
as e
:
1016 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1017 HTTP_Internal_Server_Error
)
1018 except Exception as e
:
1019 raise ovimException("Cannot insert a task for delete network '{}' {}".format(network
, str(e
)),
1020 HTTP_Internal_Server_Error
)
1024 def edit_port(self
, port_id
, port_data
, admin
=True):
1025 # Look for the previous port data
1026 result
, content
= self
.db
.get_table(FROM
="ports", WHERE
={'uuid': port_id
})
1028 raise ovimException("Cannot get port info from database: {}".format(content
), http_code
=-result
)
1030 raise ovimException("Port '{}' not found".format(port_id
), http_code
=HTTP_Not_Found
)
1035 if 'net_id' in port_data
:
1037 old_net
= port
.get('net_id', None)
1038 new_net
= port_data
['net_id']
1039 if old_net
!= new_net
:
1042 nets
.append(new_net
) # put first the new net, so that new openflow rules are created before removing the old ones
1044 nets
.append(old_net
)
1045 if port
['type'] == 'instance:bridge' or port
['type'] == 'instance:ovs':
1046 raise ovimException("bridge interfaces cannot be attached to a different net", http_code
=HTTP_Forbidden
)
1047 elif port
['type'] == 'external' and not admin
:
1048 raise ovimException("Needed admin privileges",http_code
=HTTP_Unauthorized
)
1050 # check that new net has the correct type
1051 result
, new_net_dict
= self
.db
.check_target_net(new_net
, None, port
['type'])
1053 raise ovimException("Error {}".format(new_net_dict
), http_code
=HTTP_Conflict
)
1054 # change VLAN for SR-IOV ports
1055 if result
>= 0 and port
["type"] == "instance:data" and port
["model"] == "VF": # TODO consider also VFnotShared
1057 port_data
["vlan"] = None
1059 port_data
["vlan"] = new_net_dict
["vlan"]
1060 # get host where this VM is allocated
1061 result
, content
= self
.db
.get_table(FROM
="instances", WHERE
={"uuid": port
["instance_id"]})
1063 host_id
= content
[0]["host_id"]
1065 # insert in data base
1067 result
, content
= self
.db
.update_rows('ports', port_data
, WHERE
={'uuid': port_id
}, log
=False)
1068 port
.update(port_data
)
1070 # Insert task to complete actions
1074 self
.net_update_ofc_thread(net_id
, port
["ofc_id"], switch_dpid
=port
["switch_dpid"])
1075 except ovimException
as e
:
1076 raise ovimException("Error updating network'{}' {}".format(net_id
, str(e
)),
1077 HTTP_Internal_Server_Error
)
1078 except Exception as e
:
1079 raise ovimException("Error updating network '{}' {}".format(net_id
, str(e
)),
1080 HTTP_Internal_Server_Error
)
1083 r
, v
= self
.config
['host_threads'][host_id
].insert_task("edit-iface", port_id
, old_net
, new_net
)
1085 self
.logger
.error("Error updating network '{}' {}".format(r
,v
))
1086 # TODO Do something if fails
1090 raise ovimException("Error {}".format(content
), http_code
=-result
)
1092 def new_of_controller(self
, ofc_data
):
1094 Create a new openflow controller into DB
1095 :param ofc_data: Dict openflow controller data
1096 :return: openflow controller dpid
1099 result
, ofc_uuid
= self
.db
.new_row('ofcs', ofc_data
, True, True)
1101 raise ovimException("New ofc Error %s" % ofc_uuid
, HTTP_Internal_Server_Error
)
1103 ofc_data
['uuid'] = ofc_uuid
1104 of_conn
= self
._load
_of
_module
(ofc_data
)
1105 self
._create
_ofc
_task
(ofc_uuid
, ofc_data
['dpid'], of_conn
)
1109 def edit_of_controller(self
, of_id
, ofc_data
):
1111 Edit an openflow controller entry from DB
1115 raise ovimException("No data received during uptade OF contorller", http_code
=HTTP_Internal_Server_Error
)
1117 old_of_controller
= self
.show_of_controller(of_id
)
1119 if old_of_controller
:
1120 result
, content
= self
.db
.update_rows('ofcs', ofc_data
, WHERE
={'uuid': of_id
}, log
=False)
1124 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1127 raise ovimException("Error uptating OF contorller with uuid {}".format(of_id
),
1128 http_code
=HTTP_Internal_Server_Error
)
1130 def delete_of_controller(self
, of_id
):
1132 Delete an openflow controller from DB.
1133 :param of_id: openflow controller dpid
1137 ofc
= self
.show_of_controller(of_id
)
1139 result
, content
= self
.db
.delete_row("ofcs", of_id
)
1141 raise ovimException("Cannot delete ofc from database: {}".format(content
), http_code
=-result
)
1143 raise ovimException("ofc {} not found ".format(content
), http_code
=HTTP_Not_Found
)
1145 ofc_thread
= self
.config
['ofcs_thread'][of_id
]
1146 del self
.config
['ofcs_thread'][of_id
]
1147 for ofc_th
in self
.config
['ofcs_thread_dpid']:
1148 if ofc
['dpid'] in ofc_th
:
1149 self
.config
['ofcs_thread_dpid'].remove(ofc_th
)
1151 ofc_thread
.insert_task("exit")
1156 def show_of_controller(self
, uuid
):
1158 Show an openflow controller by dpid from DB.
1159 :param db_filter: List with where query parameters
1163 result
, content
= self
.db
.get_table(FROM
='ofcs', WHERE
={"uuid": uuid
}, LIMIT
=100)
1166 raise ovimException("Openflow controller with uuid '{}' not found".format(uuid
),
1167 http_code
=HTTP_Not_Found
)
1169 raise ovimException("Openflow controller with uuid '{}' error".format(uuid
),
1170 http_code
=HTTP_Internal_Server_Error
)
1173 def get_of_controllers(self
, columns
=None, db_filter
={}, limit
=None):
1175 Show an openflow controllers from DB.
1176 :param columns: List with SELECT query parameters
1177 :param db_filter: List with where query parameters
1178 :param limit: result Limit
1181 result
, content
= self
.db
.get_table(SELECT
=columns
, FROM
='ofcs', WHERE
=db_filter
, LIMIT
=limit
)
1184 raise ovimException(str(content
), -result
)
1188 def get_tenants(self
, columns
=None, db_filter
={}, limit
=None):
1190 Retrieve tenant list from DB
1191 :param columns: List with SELECT query parameters
1192 :param db_filter: List with where query parameters
1193 :param limit: result limit
1196 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=columns
, WHERE
=db_filter
, LIMIT
=limit
)
1198 raise ovimException('get_tenatns Error {}'.format(str(content
)), -result
)
1200 convert_boolean(content
, ('enabled',))
1203 def show_tenant_id(self
, tenant_id
):
1205 Get tenant from DB by id
1206 :param tenant_id: tenant id
1209 result
, content
= self
.db
.get_table(FROM
='tenants', SELECT
=('uuid', 'name', 'description', 'enabled'),
1210 WHERE
={"uuid": tenant_id
})
1212 raise ovimException(str(content
), -result
)
1214 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1216 convert_boolean(content
, ('enabled',))
1219 def new_tentant(self
, tenant
):
1221 Create a tenant and store in DB
1222 :param tenant: Dictionary with tenant data
1223 :return: the uuid of created tenant. Raise exception upon error
1226 # insert in data base
1227 result
, tenant_uuid
= self
.db
.new_tenant(tenant
)
1232 raise ovimException(str(tenant_uuid
), -result
)
1234 def delete_tentant(self
, tenant_id
):
1236 Delete a tenant from the database.
1237 :param tenant_id: Tenant id
1238 :return: delete tenant id
1242 r
, tenants_flavors
= self
.db
.get_table(FROM
='tenants_flavors', SELECT
=('flavor_id', 'tenant_id'),
1243 WHERE
={'tenant_id': tenant_id
})
1245 tenants_flavors
= ()
1246 r
, tenants_images
= self
.db
.get_table(FROM
='tenants_images', SELECT
=('image_id', 'tenant_id'),
1247 WHERE
={'tenant_id': tenant_id
})
1251 result
, content
= self
.db
.delete_row('tenants', tenant_id
)
1253 raise ovimException("tenant '%s' not found" % tenant_id
, HTTP_Not_Found
)
1255 for flavor
in tenants_flavors
:
1256 self
.db
.delete_row_by_key("flavors", "uuid", flavor
['flavor_id'])
1257 for image
in tenants_images
:
1258 self
.db
.delete_row_by_key("images", "uuid", image
['image_id'])
1261 raise ovimException("Error deleting tenant '%s' " % tenant_id
, HTTP_Internal_Server_Error
)
1263 def edit_tenant(self
, tenant_id
, tenant_data
):
1265 Update a tenant data identified by tenant id
1266 :param tenant_id: tenant id
1267 :param tenant_data: Dictionary with tenant data
1271 # Look for the previous data
1272 result
, tenant_data_old
= self
.db
.get_table(FROM
='tenants', WHERE
={'uuid': tenant_id
})
1274 raise ovimException("Error updating tenant with uuid='{}': {}".format(tenant_id
, tenant_data_old
),
1275 HTTP_Internal_Server_Error
)
1277 raise ovimException("tenant with uuid='{}' not found".format(tenant_id
), HTTP_Not_Found
)
1279 # insert in data base
1280 result
, content
= self
.db
.update_rows('tenants', tenant_data
, WHERE
={'uuid': tenant_id
}, log
=True)
1284 raise ovimException(str(content
), -result
)
1286 def set_of_port_mapping(self
, of_maps
, ofc_id
=None, switch_dpid
=None, region
=None):
1288 Create new port mapping entry
1289 :param of_maps: List with port mapping information
1290 # maps =[{"ofc_id": <ofc_id>,"region": datacenter region,"compute_node": compute uuid,"pci": pci adress,
1291 "switch_dpid": swith dpid,"switch_port": port name,"switch_mac": mac}]
1292 :param ofc_id: ofc id
1293 :param switch_dpid: switch dpid
1294 :param region: datacenter region id
1300 map['ofc_id'] = ofc_id
1302 map['switch_dpid'] = switch_dpid
1304 map['region'] = region
1306 for of_map
in of_maps
:
1307 result
, uuid
= self
.db
.new_row('of_port_mappings', of_map
, True)
1309 of_map
["uuid"] = uuid
1311 raise ovimException(str(uuid
), -result
)
1314 def clear_of_port_mapping(self
, db_filter
={}):
1316 Clear port mapping filtering using db_filter dict
1317 :param db_filter: Parameter to filter during remove process
1320 result
, content
= self
.db
.delete_row_by_dict(FROM
='of_port_mappings', WHERE
=db_filter
)
1325 raise ovimException("Error deleting of_port_mappings with filter='{}'".format(str(db_filter
)),
1326 HTTP_Internal_Server_Error
)
1328 def get_of_port_mappings(self
, column
=None, db_filter
=None, db_limit
=None):
1330 Retrive port mapping from DB
1335 result
, content
= self
.db
.get_table(SELECT
=column
, WHERE
=db_filter
, FROM
='of_port_mappings', LIMIT
=db_limit
)
1338 self
.logger
.error("get_of_port_mappings Error %d %s", result
, content
)
1339 raise ovimException(str(content
), -result
)
1343 def get_dhcp_controller(self
):
1345 Create an host_thread object for manage openvim controller and not create a thread for itself
1346 :return: dhcp_host openvim controller object
1349 if 'openvim_controller' in self
.config
['host_threads']:
1350 return self
.config
['host_threads']['openvim_controller']
1353 controller_ip
= self
.config
['ovs_controller_ip']
1354 ovs_controller_user
= self
.config
['ovs_controller_user']
1356 host_test_mode
= True if self
.config
['mode'] == 'test' or self
.config
['mode'] == "OF only" else False
1357 host_develop_mode
= True if self
.config
['mode'] == 'development' else False
1359 dhcp_host
= ht
.host_thread(name
='openvim_controller', user
=ovs_controller_user
, host
=controller_ip
,
1361 db_lock
=self
.db_lock
, test
=host_test_mode
,
1362 image_path
=self
.config
['image_path'], version
=self
.config
['version'],
1363 host_id
='openvim_controller', develop_mode
=host_develop_mode
,
1364 develop_bridge_iface
=bridge_ifaces
, logger_name
=self
.logger_name
+ ".host.controller",
1365 debug
=self
.config
.get('log_level_host'))
1367 self
.config
['host_threads']['openvim_controller'] = dhcp_host
1368 if not host_test_mode
:
1369 dhcp_host
.ssh_connect()
1372 def launch_dhcp_server(self
, vlan
, first_ip
, last_ip
, cidr
, gateway
):
1374 Launch a dhcpserver base on dnsmasq attached to the net base on vlan id across the the openvim computes
1375 :param vlan: vlan identifier
1376 :param first_ip: First dhcp range ip
1377 :param last_ip: Last dhcp range ip
1378 :param cidr: net cidr
1379 :param gateway: net gateway
1382 ip_tools
= IPNetwork(cidr
)
1383 dhcp_netmask
= str(ip_tools
.netmask
)
1384 ip_range
= [first_ip
, last_ip
]
1386 dhcp_path
= self
.config
['ovs_controller_file_path']
1388 controller_host
= self
.get_dhcp_controller()
1389 controller_host
.create_linux_bridge(vlan
)
1390 controller_host
.create_dhcp_interfaces(vlan
, first_ip
, dhcp_netmask
)
1391 controller_host
.launch_dhcp_server(vlan
, ip_range
, dhcp_netmask
, dhcp_path
, gateway
)
1393 if __name__
== "__main__":
1395 parser
= argparse
.ArgumentParser()
1396 parser
.add_argument("-v","--version", help="show ovim library version", action
="store_true")
1397 parser
.add_argument("--database-version", help="show required database version", action
="store_true")
1398 args
= parser
.parse_args()
1400 print ('openvimd version {} {}'.format(ovim
.get_version(), ovim
.get_version_date()))
1401 print ('(c) Copyright Telefonica')
1402 elif args
.database_version
:
1403 print ('required database version: {}'.format(ovim
.get_database_version()))