X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_openvim%2Fovim.py;h=612e4dfa703d3def8365fef2c073da034bc9fe92;hb=9cead2a0262deabadc900d580ef312fbc468efc0;hp=2fca38fe83a193f475418afa1cb27991226f8373;hpb=6878e3f50618cf9a6dfe8d365951cb8bc9a98a6a;p=osm%2Fopenvim.git diff --git a/osm_openvim/ovim.py b/osm_openvim/ovim.py index 2fca38f..612e4df 100755 --- a/osm_openvim/ovim.py +++ b/osm_openvim/ovim.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- ## -# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. +# Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U. # This file is part of openvim # All Rights Reserved. # @@ -43,9 +43,9 @@ import openflow_conn __author__ = "Alfonso Tierno, Leonardo Mirabal" __date__ = "$06-Feb-2017 12:07:15$" -__version__ = "0.5.18-r534" -version_date = "Jun 2017" -database_version = 21 #needed database schema version +__version__ = "0.5.29-r549" +version_date = "Sep 2018" +database_version = 23 #needed database schema version HTTP_Bad_Request = 400 HTTP_Unauthorized = 401 @@ -189,7 +189,6 @@ class ovim(): self.get_version(), self.get_version_date(), self.get_database_version())) # create database connection for openflow threads self.config["db"] = self._create_database_connection() - self.config["db_lock"] = threading.Lock() self.of_test_mode = False if self.config['mode'] == 'normal' or self.config['mode'] == "OF only" else True @@ -199,8 +198,8 @@ class ovim(): host_develop_bridge_iface = self.config.get('development_bridge', None) # get host list from data base before starting threads - r, hosts = self.db.get_table(SELECT=('name', 'ip_name', 'user', 'uuid', 'password', 'keyfile'), - FROM='hosts', WHERE={'status': 'ok'}) + r, hosts = self.db.get_table(SELECT=('name', 'ip_name', 'user', 'uuid', 'hypervisors', 'password', 'keyfile'), + FROM='hosts', WHERE={'status': 'ok'}) #Unikernels extension if r < 0: raise ovimException("Cannot get hosts from database {}".format(hosts)) @@ -210,11 +209,12 @@ class ovim(): thread = ht.host_thread(name=host['name'], user=host['user'], host=host['ip_name'], db=self.config["db"], password=host['password'], keyfile=host.get('keyfile', self.config["host_ssh_keyfile"]), - db_lock=self.config["db_lock"], test=host_test_mode, + test=host_test_mode, image_path=self.config['host_image_path'], version=self.config['version'], host_id=host['uuid'], develop_mode=host_develop_mode, develop_bridge_iface=host_develop_bridge_iface, + hypervisors=host['hypervisors'], #Unikernels extension logger_name=self.logger_name + ".host." + host['name'], debug=self.config.get('log_level_host')) @@ -267,7 +267,7 @@ class ovim(): dhcp_params = self.config.get("dhcp_server") if dhcp_params: thread = dt.dhcp_thread(dhcp_params=dhcp_params, test=host_test_mode, dhcp_nets=self.config["dhcp_nets"], - db=self.config["db"], db_lock=self.config["db_lock"], + db=self.config["db"], logger_name=self.logger_name + ".dhcp", debug=self.config.get('log_level_of')) thread.start() @@ -283,31 +283,47 @@ class ovim(): for net in content: net_type = net['type'] - if (net_type == 'bridge_data' or net_type == 'bridge_man') and \ + if net['status'] != "INACTIVE" and (net_type == 'bridge_data' or net_type == 'bridge_man') and \ net["provider"][:4] == 'OVS:' and net["enable_dhcp"] == "true": try: - routes = yaml.safe_load(net.get('routes')) - dns = yaml.safe_load(net.get('dns')) - self.launch_dhcp_server(net.get('vlan'), - net.get('dhcp_first_ip'), - net.get('dhcp_last_ip'), - net.get('cidr'), - net.get('gateway_ip'), - dns, - routes) - self.launch_link_bridge_to_ovs(net['vlan'], net.get('links'), net.get('routes')) + config_routes = net.get('routes') + if config_routes: + routes = yaml.safe_load(config_routes) + else: + routes = None + + config_dns = net.get('dns') + if config_dns: + dns = yaml.safe_load(config_dns) + else: + dns = None + + links = net.get('links') + if links: + links = yaml.safe_load(net.get('links')) + if net.get('enable_dhcp'): + self.launch_dhcp_server(net.get('vlan'), + net.get('dhcp_first_ip'), + net.get('dhcp_last_ip'), + net.get('cidr'), + net.get('gateway_ip'), + dns, + routes) + self.launch_link_bridge_to_ovs(net['vlan'], net.get('gateway_ip'), net.get('cidr'), links, routes) + if net["status"] == "ERROR": + self.db.update_rows("nets", UPDATE={"status": "ACTIVE", "last_error": None}, + WHERE={"uuid": net["uuid"]}) except Exception as e: self.logger.error("Fail at launching dhcp server for net_id='%s' net_name='%s': %s", net["uuid"], net["name"], str(e)) - self.db.update_rows("nets", {"status": "ERROR", + self.db.update_rows("nets", UPDATE={"status": "ERROR", "last_error": "Fail at launching dhcp server: " + str(e)}, - {"uuid": net["uuid"]}) + WHERE={"uuid": net["uuid"]}) def _start_of_db_tasks(self): """ Start ofc task for existing ofcs in database :param db_of: - :param db_lock: :return: """ ofcs = self.get_of_controllers() @@ -435,7 +451,6 @@ class ovim(): ofc_net_same_vlan = False thread = oft.openflow_thread(ofc_uuid, of_conn, of_test=self.of_test_mode, db=self.config["db"], - db_lock=self.config["db_lock"], pmp_with_same_vlan=ofc_net_same_vlan, logger_name=self.logger_name + ".ofc." + ofc_uuid, debug=self.config.get('log_level_of')) @@ -483,7 +498,7 @@ class ovim(): return content - def show_network(self, network_id, db_filter={}): + def show_network(self, network_id, db_filter={}, skip_on_not_found=False): """ Get network from DB by id :param network_id: net Id @@ -500,7 +515,9 @@ class ovim(): if result < 0: raise ovimException(str(content), -result) elif result == 0: - raise ovimException("show_network network '%s' not found" % network_id, -result) + if skip_on_not_found: + return + raise ovimException("show_network network '%s' not found" % network_id, HTTP_Not_Found) else: convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp')) # get ports from DB @@ -508,8 +525,12 @@ class ovim(): WHERE={'net_id': network_id}, LIMIT=100) if len(ports) > 0: content[0]['ports'] = ports - convert_boolean(content, ('shared', 'admin_state_up', 'enable_dhcp')) + + result, flows = self.db.get_table(FROM='of_flows', SELECT=('priority', 'vlan_id', 'ingress_port', 'src_mac', 'dst_mac', 'actions'), + WHERE={'net_id': network_id}, LIMIT=100) + if len(flows) > 0: + content[0]['flows'] = flows return content[0] def new_network(self, network): @@ -644,7 +665,7 @@ class ovim(): network['vlan'] = net_vlan network['region'] = net_region dhcp_integrity = True - if 'enable_dhcp' in network and network['enable_dhcp']: + if network.get('enable_dhcp'): dhcp_integrity = self._check_dhcp_data_integrity(network) if network.get('links'): @@ -655,8 +676,7 @@ class ovim(): network['routes'] = yaml.safe_dump(network['routes'], default_flow_style=True, width=256) result, content = self.db.new_row('nets', network, True, True) - - if result >= 0 and dhcp_integrity: + if result >= 0: # and dhcp_integrity: if bridge_net: bridge_net[3] = content if self.config.get("dhcp_server") and self.config['network_type'] == 'bridge': @@ -668,7 +688,8 @@ class ovim(): self.logger.debug("dhcp_server: add new net", content, content) return content else: - raise ovimException("Error posting network", HTTP_Internal_Server_Error) + raise ovimException("Error creating network: {}".format(content), -result) + # TODO kei change update->edit def edit_network(self, network_id, network): @@ -762,12 +783,15 @@ class ovim(): else: raise ovimException(content, -result) - def delete_network(self, network_id): + def delete_network(self, network_id, idempotent=True): """ Delete network by network id :param network_id: network id :return: """ + net_data = self.show_network(network_id, skip_on_not_found=idempotent) + if not net_data: # network does not exist + return # delete from the data base result, content = self.db.delete_row('nets', network_id) @@ -781,7 +805,18 @@ class ovim(): break if self.config.get("dhcp_server") and network_id in self.config["dhcp_nets"]: self.config["dhcp_nets"].remove(network_id) - return content + + if net_data.get('enable_dhcp'): + dhcp_path = self.config['ovs_controller_file_path'] + dhcp_controller = self.get_dhcp_controller() + dhcp_controller.delete_dhcp_server(net_data['vlan'], network_id, dhcp_path) + dhcp_controller.delete_dhcp_port(net_data['vlan'], network_id, dhcp_path) + links = yaml.load(net_data.get('links')) + if links: + links = yaml.load(net_data.get('links')) + self.delete_link_bridge_to_ovs(net_data['vlan'], links) + + return content else: raise ovimException("Error deleting network '{}': {}".format(network_id, content), -result) @@ -969,6 +1004,8 @@ class ovim(): del port_data['compute_node'] result, uuid = self.db.new_row('ports', port_data, True, True) + # set net status to BUILD + self.db.update_rows('nets', {"status": "BUILD"}, WHERE={'uuid': port_data['net_id']}) if result > 0: try: self.net_update_ofc_thread(port_data['net_id'], port_data['ofc_id']) @@ -1025,7 +1062,7 @@ class ovim(): self.logger.error(message) raise ovimException(message, HTTP_Internal_Server_Error) - def delete_port(self, port_id): + def delete_port(self, port_id, idempotent=False): # Look for the previous port data result, ports = self.db.get_table(WHERE={'uuid': port_id, "type": "external"}, FROM='ports') if result < 0: @@ -1033,21 +1070,25 @@ class ovim(): # delete from the data base result, content = self.db.delete_row('ports', port_id) if result == 0: + if idempotent: + return raise ovimException("External port '{}' not found".format(port_id), http_code=HTTP_Not_Found) elif result < 0: raise ovimException("Cannot delete port from database: {}".format(content), http_code=-result) # update network - network = ports[0].get('net_id', None) - if network: + net_id = ports[0].get('net_id', None) + if net_id: # change of net. + # set net status to BUILD + self.db.update_rows('nets', {"status": "BUILD"}, WHERE={'uuid': net_id}) try: - self.net_update_ofc_thread(network, ofc_id=ports[0]["ofc_id"], switch_dpid=ports[0]["switch_dpid"]) + self.net_update_ofc_thread(net_id, ofc_id=ports[0]["ofc_id"], switch_dpid=ports[0]["switch_dpid"]) except ovimException as e: - raise ovimException("Cannot insert a task for delete network '{}' {}".format(network, str(e)), + raise ovimException("Cannot insert a task for delete network '{}' {}".format(net_id, str(e)), HTTP_Internal_Server_Error) except Exception as e: - raise ovimException("Cannot insert a task for delete network '{}' {}".format(network, str(e)), + raise ovimException("Cannot insert a task for delete network '{}' {}".format(net_id, str(e)), HTTP_Internal_Server_Error) return content @@ -1333,6 +1374,8 @@ class ovim(): map['switch_dpid'] = switch_dpid if region: map['region'] = region + if map.get("pci"): + map["pci"] = map["pci"].lower() for of_map in of_maps: result, uuid = self.db.new_row('of_port_mappings', of_map, True) @@ -1390,7 +1433,7 @@ class ovim(): dhcp_host = ht.host_thread(name='openvim_controller', user=ovs_controller_user, host=controller_ip, password=self.config.get('ovs_controller_password'), keyfile=self.config.get('ovs_controller_keyfile'), - db=self.config["db"], db_lock=self.config["db_lock"], test=host_test_mode, + db=self.config["db"], test=host_test_mode, image_path=self.config['host_image_path'], version=self.config['version'], host_id='openvim_controller', develop_mode=host_develop_mode, develop_bridge_iface=bridge_ifaces, @@ -1422,7 +1465,7 @@ class ovim(): dhcp_path = self.config['ovs_controller_file_path'] controller_host = self.get_dhcp_controller() - # TODO leo check if is need ti to create an ovim-vlan bridge, looks like not + # controller_host.create_linux_bridge(vlan) controller_host.create_dhcp_interfaces(vlan, first_ip, dhcp_netmask) dhcp_path = self.config['ovs_controller_file_path']