X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=host_thread.py;h=d8bca2e2e1ca13d091a34566d29610672f520cb8;hb=refs%2Fchanges%2F17%2F1317%2F3;hp=1049e404b4d4ae2873127be9565b55c5f545e570;hpb=f053737a7b5dbf4b2ccee3c483da8371367dbeb7;p=osm%2Fopenvim.git diff --git a/host_thread.py b/host_thread.py index 1049e40..d8bca2e 100644 --- a/host_thread.py +++ b/host_thread.py @@ -2,7 +2,7 @@ ## # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. -# This file is part of openmano +# This file is part of openvim # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -25,9 +25,8 @@ This is thread that interact with the host and the libvirt to manage VM One thread will be launched per host ''' -__author__="Pablo Montes, Alfonso Tierno" -__date__ ="$10-jul-2014 12:07:15$" - +__author__ = "Pablo Montes, Alfonso Tierno, Leonardo Mirabal" +__date__ = "$10-jul-2014 12:07:15$" import json import yaml @@ -36,18 +35,27 @@ import time import Queue import paramiko from jsonschema import validate as js_v, exceptions as js_e -import libvirt +#import libvirt +import imp from vim_schema import localinfo_schema, hostinfo_schema import random -#from logging import Logger -#import auxiliary_functions as af +import os #TODO: insert a logging system +# from logging import Logger +# import auxiliary_functions as af + +# TODO: insert a logging system + + class host_thread(threading.Thread): - def __init__(self, name, host, user, db, db_lock, test, image_path, host_id, version, develop_mode, develop_bridge_iface): + lvirt_module = None + + def __init__(self, name, host, user, db, db_lock, test, image_path, host_id, version, develop_mode, + develop_bridge_iface): '''Init a thread. - Arguments: + Arguments: 'id' number of thead 'name' name of thread 'host','user': host ip or name to manage and user @@ -60,6 +68,15 @@ class host_thread(threading.Thread): self.db = db self.db_lock = db_lock self.test = test + + if not test and not host_thread.lvirt_module: + try: + module_info = imp.find_module("libvirt") + host_thread.lvirt_module = imp.load_module("libvirt", *module_info) + except (IOError, ImportError) as e: + raise ImportError("Cannot import python-libvirt. Openvim not properly installed" +str(e)) + + self.develop_mode = develop_mode self.develop_bridge_iface = develop_bridge_iface self.image_path = image_path @@ -77,7 +94,8 @@ class host_thread(threading.Thread): self.queueLock = threading.Lock() self.taskQueue = Queue.Queue(2000) - + self.ssh_conn = None + def ssh_connect(self): try: #Connect SSH @@ -120,7 +138,7 @@ class host_thread(threading.Thread): except paramiko.ssh_exception.SSHException as e: text = e.args[0] print self.name, ": load_localinfo ssh Exception:", text - except libvirt.libvirtError as e: + except host_thread.lvirt_module.libvirtError as e: text = e.get_error_message() print self.name, ": load_localinfo libvirt Exception:", text except yaml.YAMLError as exc: @@ -165,7 +183,7 @@ class host_thread(threading.Thread): except paramiko.ssh_exception.SSHException as e: text = e.args[0] print self.name, ": load_hostinfo ssh Exception:", text - except libvirt.libvirtError as e: + except host_thread.lvirt_module.libvirtError as e: text = e.get_error_message() print self.name, ": load_hostinfo libvirt Exception:", text except yaml.YAMLError as exc: @@ -206,7 +224,7 @@ class host_thread(threading.Thread): print self.name, ": save_localinfo ssh Exception:", text if "SSH session not active" in text: self.ssh_connect() - except libvirt.libvirtError as e: + except host_thread.lvirt_module.libvirtError as e: text = e.get_error_message() print self.name, ": save_localinfo libvirt Exception:", text except yaml.YAMLError as exc: @@ -320,6 +338,24 @@ class host_thread(threading.Thread): elif task[0] == 'restore-iface': print self.name, ": processing task restore-iface %s mac=%s" % (task[1], task[2]) self.restore_iface(task[1], task[2]) + elif task[0] == 'new-ovsbridge': + print self.name, ": Creating compute OVS bridge" + self.create_ovs_bridge() + elif task[0] == 'new-vxlan': + print self.name, ": Creating vxlan tunnel=" + task[1] + ", remote ip=" + task[2] + self.create_ovs_vxlan_tunnel(task[1], task[2]) + elif task[0] == 'del-ovsbridge': + print self.name, ": Deleting OVS bridge" + self.delete_ovs_bridge() + elif task[0] == 'del-vxlan': + print self.name, ": Deleting vxlan " + task[1] + " tunnel" + self.delete_ovs_vxlan_tunnel(task[1]) + elif task[0] == 'create-ovs-bridge-port': + print self.name, ": Adding port ovim-" + task[1] + " to OVS bridge" + self.create_ovs_bridge_port(task[1]) + elif task[0] == 'del-ovs-port': + print self.name, ": Delete bridge attached to ovs port vlan {} net {}".format(task[1], task[2]) + self.delete_bridge_port_attached_to_ovs(task[1], task[2]) else: print self.name, ": unknown task", task @@ -465,8 +501,12 @@ class host_thread(threading.Thread): self.tab()+'' +\ self.tab()+''+ \ self.dec_tab() +'' - if windows_os or topo=="oneSocket": - text += self.tab() + " "% vcpus + if topo == "oneSocket:hyperthreading": + if vcpus % 2 != 0: + return -1, 'Cannot expose hyperthreading with an odd number of vcpus' + text += self.tab() + " " % vcpus/2 + elif windows_os or topo == "oneSocket": + text += self.tab() + " " % vcpus else: text += self.tab() + "" text += self.tab() + "" +\ @@ -578,6 +618,10 @@ class host_thread(threading.Thread): self.tab() + "" elif model==None: model = "virtio" + elif content[0]['provider'][0:3] == "OVS": + vlan = content[0]['provider'].replace('OVS:', '') + text += self.tab() + "" + \ + self.inc_tab() + "" else: return -1, 'Unknown Bridge net provider ' + content[0]['provider'] if model!=None: @@ -666,7 +710,519 @@ class host_thread(threading.Thread): """Decrement and return indentation according to xml_level""" self.xml_level -= 1 return self.tab() - + + def create_ovs_bridge(self): + """ + Create a bridge in compute OVS to allocate VMs + :return: True if success + """ + if self.test: + return + command = 'sudo ovs-vsctl --may-exist add-br br-int -- set Bridge br-int stp_enable=true' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + if len(content) == 0: + return True + else: + return False + + def delete_port_to_ovs_bridge(self, vlan, net_uuid): + """ + Delete linux bridge port attched to a OVS bridge, if port is not free the port is not removed + :param vlan: vlan port id + :param net_uuid: network id + :return: + """ + + if self.test: + return + + port_name = 'ovim-' + vlan + command = 'sudo ovs-vsctl del-port br-int ' + port_name + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + if len(content) == 0: + return True + else: + return False + + def delete_dhcp_server(self, vlan, net_uuid, dhcp_path): + """ + Delete dhcp server process lining in namespace + :param vlan: segmentation id + :param net_uuid: network uuid + :param dhcp_path: conf fiel path that live in namespace side + :return: + """ + if self.test: + return + if not self.is_dhcp_port_free(vlan, net_uuid): + return True + + net_namespace = 'ovim-' + vlan + dhcp_path = os.path.join(dhcp_path, net_namespace) + pid_file = os.path.join(dhcp_path, 'dnsmasq.pid') + + command = 'sudo ip netns exec ' + net_namespace + ' cat ' + pid_file + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip netns exec ' + net_namespace + ' kill -9 ' + content + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + # if len(content) == 0: + # return True + # else: + # return False + + def is_dhcp_port_free(self, host_id, net_uuid): + """ + Check if any port attached to the a net in a vxlan mesh across computes nodes + :param host_id: host id + :param net_uuid: network id + :return: True if is not free + """ + self.db_lock.acquire() + result, content = self.db.get_table( + FROM='ports', + WHERE={'p.type': 'instance:ovs', 'p.net_id': net_uuid} + ) + self.db_lock.release() + + if len(content) > 0: + return False + else: + return True + + def is_port_free(self, host_id, net_uuid): + """ + Check if there not ovs ports of a network in a compute host. + :param host_id: host id + :param net_uuid: network id + :return: True if is not free + """ + + self.db_lock.acquire() + result, content = self.db.get_table( + FROM='ports as p join instances as i on p.instance_id=i.uuid', + WHERE={"i.host_id": self.host_id, 'p.type': 'instance:ovs', 'p.net_id': net_uuid} + ) + self.db_lock.release() + + if len(content) > 0: + return False + else: + return True + + def add_port_to_ovs_bridge(self, vlan): + """ + Add a bridge linux as a port to a OVS bridge and set a vlan for an specific linux bridge + :param vlan: vlan port id + :return: True if success + """ + + if self.test: + return + + port_name = 'ovim-' + vlan + command = 'sudo ovs-vsctl add-port br-int ' + port_name + ' tag=' + vlan + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + if len(content) == 0: + return True + else: + return False + + def delete_dhcp_port(self, vlan, net_uuid): + """ + Delete from an existing OVS bridge a linux bridge port attached and the linux bridge itself. + :param vlan: segmentation id + :param net_uuid: network id + :return: True if success + """ + + if self.test: + return + + if not self.is_dhcp_port_free(vlan, net_uuid): + return True + self.delete_dhcp_interfaces(vlan) + return True + + def delete_bridge_port_attached_to_ovs(self, vlan, net_uuid): + """ + Delete from an existing OVS bridge a linux bridge port attached and the linux bridge itself. + :param vlan: + :param net_uuid: + :return: True if success + """ + if self.test: + return + + if not self.is_port_free(vlan, net_uuid): + return True + self.delete_port_to_ovs_bridge(vlan, net_uuid) + self.delete_linux_bridge(vlan) + return True + + def delete_linux_bridge(self, vlan): + """ + Delete a linux bridge in a scpecific compute. + :param vlan: vlan port id + :return: True if success + """ + + if self.test: + return + + port_name = 'ovim-' + vlan + command = 'sudo ip link set dev veth0-' + vlan + ' down' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + # + # if len(content) != 0: + # return False + + command = 'sudo ifconfig ' + port_name + ' down && sudo brctl delbr ' + port_name + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + if len(content) == 0: + return True + else: + return False + + def create_ovs_bridge_port(self, vlan): + """ + Generate a linux bridge and attache the port to a OVS bridge + :param vlan: vlan port id + :return: + """ + if self.test: + return + self.create_linux_bridge(vlan) + self.add_port_to_ovs_bridge(vlan) + + def create_linux_bridge(self, vlan): + """ + Create a linux bridge with STP active + :param vlan: netowrk vlan id + :return: + """ + + if self.test: + return + + port_name = 'ovim-' + vlan + command = 'sudo brctl show | grep ' + port_name + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + # if exist nothing to create + # if len(content) == 0: + # return False + + command = 'sudo brctl addbr ' + port_name + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + # if len(content) == 0: + # return True + # else: + # return False + + command = 'sudo brctl stp ' + port_name + ' on' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + # if len(content) == 0: + # return True + # else: + # return False + command = 'sudo ip link set dev ' + port_name + ' up' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + if len(content) == 0: + return True + else: + return False + + def set_mac_dhcp_server(self, ip, mac, vlan, netmask, dhcp_path): + """ + Write into dhcp conf file a rule to assigned a fixed ip given to an specific MAC address + :param ip: IP address asigned to a VM + :param mac: VM vnic mac to be macthed with the IP received + :param vlan: Segmentation id + :param netmask: netmask value + :param path: dhcp conf file path that live in namespace side + :return: True if success + """ + + if self.test: + return + + net_namespace = 'ovim-' + vlan + dhcp_path = os.path.join(dhcp_path, net_namespace) + dhcp_hostsdir = os.path.join(dhcp_path, net_namespace) + + if not ip: + return False + + ip_data = mac.upper() + ',' + ip + + command = 'sudo ip netns exec ' + net_namespace + ' touch ' + dhcp_hostsdir + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip netns exec ' + net_namespace + ' sudo bash -ec "echo ' + ip_data + ' >> ' + dhcp_hostsdir + '"' + + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + if len(content) == 0: + return True + else: + return False + + def delete_mac_dhcp_server(self, ip, mac, vlan, dhcp_path): + """ + Delete into dhcp conf file the ip assigned to a specific MAC address + + :param ip: IP address asigned to a VM + :param mac: VM vnic mac to be macthed with the IP received + :param vlan: Segmentation id + :param dhcp_path: dhcp conf file path that live in namespace side + :return: + """ + + if self.test: + return + + net_namespace = 'ovim-' + vlan + dhcp_path = os.path.join(dhcp_path, net_namespace) + dhcp_hostsdir = os.path.join(dhcp_path, net_namespace) + + if not ip: + return False + + ip_data = mac.upper() + ',' + ip + + command = 'sudo ip netns exec ' + net_namespace + ' sudo sed -i \'/' + ip_data + '/d\' ' + dhcp_hostsdir + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + if len(content) == 0: + return True + else: + return False + + def launch_dhcp_server(self, vlan, ip_range, netmask, dhcp_path, gateway): + """ + Generate a linux bridge and attache the port to a OVS bridge + :param self: + :param vlan: Segmentation id + :param ip_range: IP dhcp range + :param netmask: network netmask + :param dhcp_path: dhcp conf file path that live in namespace side + :param gateway: Gateway address for dhcp net + :return: True if success + """ + + if self.test: + return + + interface = 'tap-' + vlan + net_namespace = 'ovim-' + vlan + dhcp_path = os.path.join(dhcp_path, net_namespace) + leases_path = os.path.join(dhcp_path, "dnsmasq.leases") + pid_file = os.path.join(dhcp_path, 'dnsmasq.pid') + + dhcp_range = ip_range[0] + ',' + ip_range[1] + ',' + netmask + + command = 'sudo ip netns exec ' + net_namespace + ' mkdir -p ' + dhcp_path + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + pid_path = os.path.join(dhcp_path, 'dnsmasq.pid') + command = 'sudo ip netns exec ' + net_namespace + ' cat ' + pid_path + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + # check if pid is runing + pid_status_path = content + if content: + command = "ps aux | awk '{print $2 }' | grep " + pid_status_path + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + if not content: + command = 'sudo ip netns exec ' + net_namespace + ' /usr/sbin/dnsmasq --strict-order --except-interface=lo ' \ + '--interface=' + interface + ' --bind-interfaces --dhcp-hostsdir=' + dhcp_path + \ + ' --dhcp-range ' + dhcp_range + ' --pid-file=' + pid_file + ' --dhcp-leasefile=' + leases_path + \ + ' --listen-address ' + gateway + + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.readline() + + if len(content) == 0: + return True + else: + return False + + def delete_dhcp_interfaces(self, vlan): + """ + Create a linux bridge with STP active + :param vlan: netowrk vlan id + :return: + """ + + if self.test: + return + + net_namespace = 'ovim-' + vlan + command = 'sudo ovs-vsctl del-port br-int ovs-tap-' + vlan + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip netns exec ' + net_namespace + ' ip link set dev tap-' + vlan + ' down' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip link set dev ovs-tap-' + vlan + ' down' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + def create_dhcp_interfaces(self, vlan, ip, netmask): + """ + Create a linux bridge with STP active + :param vlan: segmentation id + :param ip: Ip included in the dhcp range for the tap interface living in namesapce side + :param netmask: dhcp net CIDR + :return: True if success + """ + + if self.test: + return + + net_namespace = 'ovim-' + vlan + namespace_interface = 'tap-' + vlan + + command = 'sudo ip netns add ' + net_namespace + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip link add tap-' + vlan + ' type veth peer name ovs-tap-' + vlan + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ovs-vsctl add-port br-int ovs-tap-' + vlan + ' tag=' + vlan + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip link set tap-' + vlan + ' netns ' + net_namespace + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip netns exec ' + net_namespace + ' ip link set dev tap-' + vlan + ' up' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip link set dev ovs-tap-' + vlan + ' up' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + command = 'sudo ip netns exec ' + net_namespace + ' ' + ' ifconfig ' + namespace_interface \ + + ' ' + ip + ' netmask ' + netmask + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + + if len(content) == 0: + return True + else: + return False + + def create_ovs_vxlan_tunnel(self, vxlan_interface, remote_ip): + """ + Create a vlxn tunnel between to computes with an OVS installed. STP is also active at port level + :param vxlan_interface: vlxan inteface name. + :param remote_ip: tunnel endpoint remote compute ip. + :return: + """ + if self.test: + return + command = 'sudo ovs-vsctl add-port br-int ' + vxlan_interface + \ + ' -- set Interface ' + vxlan_interface + ' type=vxlan options:remote_ip=' + remote_ip + \ + ' -- set Port ' + vxlan_interface + ' other_config:stp-path-cost=10' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + print content + if len(content) == 0: + return True + else: + return False + + def delete_ovs_vxlan_tunnel(self, vxlan_interface): + """ + Delete a vlxan tunnel port from a OVS brdige. + :param vxlan_interface: vlxan name to be delete it. + :return: True if success. + """ + if self.test: + return + command = 'sudo ovs-vsctl del-port br-int ' + vxlan_interface + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + print content + if len(content) == 0: + return True + else: + return False + + def delete_ovs_bridge(self): + """ + Delete a OVS bridge from a compute. + :return: True if success + """ + if self.test: + return + command = 'sudo ovs-vsctl del-br br-int' + print self.name, ': command:', command + (_, stdout, _) = self.ssh_conn.exec_command(command) + content = stdout.read() + if len(content) == 0: + return True + else: + return False + def get_file_info(self, path): command = 'ls -lL --time-style=+%Y-%m-%dT%H:%M:%S ' + path print self.name, ': command:', command @@ -757,9 +1313,14 @@ class host_thread(threading.Thread): raise paramiko.ssh_exception.SSHException("Error deleting file: " + error_msg) def copy_file(self, source, destination, perserve_time=True): - command = 'cp --no-preserve=mode ' - if perserve_time: command += '--preserve=timestamps ' - command += source + ' ' + destination + if source[0:4]=="http": + command = "wget --no-verbose -O '{dst}' '{src}' 2>'{dst_result}' || cat '{dst_result}' >&2 && rm '{dst_result}'".format( + dst=destination, src=source, dst_result=destination + ".result" ) + else: + command = 'cp --no-preserve=mode' + if perserve_time: + command += ' --preserve=timestamps' + command += " '{}' '{}'".format(source, destination) print self.name, ': command:', command (_, _, stderr) = self.ssh_conn.exec_command(command) error_msg = stderr.read() @@ -783,24 +1344,29 @@ class host_thread(threading.Thread): use_incremental_out = use_incremental new_backing_file = None local_file = None + file_from_local = True #in case incremental use is not decided, take the decision depending on the image #avoid the use of incremental if this image is already incremental - qemu_remote_info = self.qemu_get_info(remote_file) + if remote_file[0:4] == "http": + file_from_local = False + if file_from_local: + qemu_remote_info = self.qemu_get_info(remote_file) if use_incremental_out==None: - use_incremental_out = not 'backing file' in qemu_remote_info + use_incremental_out = not ( file_from_local and 'backing file' in qemu_remote_info) #copy recursivelly the backing files - if 'backing file' in qemu_remote_info: + if file_from_local and 'backing file' in qemu_remote_info: new_backing_file, _, _ = self.copy_remote_file(qemu_remote_info['backing file'], True) #check if remote file is present locally if use_incremental_out and remote_file in self.localinfo['files']: local_file = self.localinfo['files'][remote_file] local_file_info = self.get_file_info(local_file) - remote_file_info = self.get_file_info(remote_file) + if file_from_local: + remote_file_info = self.get_file_info(remote_file) if local_file_info == None: local_file = None - elif local_file_info[4]!=remote_file_info[4] or local_file_info[5]!=remote_file_info[5]: + elif file_from_local and (local_file_info[4]!=remote_file_info[4] or local_file_info[5]!=remote_file_info[5]): #local copy of file not valid because date or size are different. #TODO DELETE local file if this file is not used by any active virtual machine try: @@ -874,7 +1440,8 @@ class host_thread(threading.Thread): continue self.db_lock.acquire() - result, content = self.db.get_table(FROM='images', SELECT=('path','metadata'),WHERE={'uuid':dev['image_id']} ) + result, content = self.db.get_table(FROM='images', SELECT=('path', 'metadata'), + WHERE={'uuid': dev['image_id']}) self.db_lock.release() if result <= 0: error_text = "ERROR", result, content, "when getting image", dev['image_id'] @@ -923,7 +1490,7 @@ class host_thread(threading.Thread): print self.name, ": create xml server error:", xml return -2, xml print self.name, ": create xml:", xml - atribute = libvirt.VIR_DOMAIN_START_PAUSED if paused == "yes" else 0 + atribute = host_thread.lvirt_module.VIR_DOMAIN_START_PAUSED if paused == "yes" else 0 #4 Start the domain if not rebuild: #ensures that any pending destroying server is done self.server_forceoff(True) @@ -938,7 +1505,7 @@ class host_thread(threading.Thread): print self.name, ": launch_server(%s) ssh Exception: %s" %(server_id, text) if "SSH session not active" in text: self.ssh_connect() - except libvirt.libvirtError as e: + except host_thread.lvirt_module.libvirtError as e: text = e.get_error_message() print self.name, ": launch_server(%s) libvirt Exception: %s" %(server_id, text) except Exception as e: @@ -961,26 +1528,26 @@ class host_thread(threading.Thread): return try: - conn = libvirt.open("qemu+ssh://"+self.user+"@"+self.host+"/system") + conn = host_thread.lvirt_module.open("qemu+ssh://"+self.user+"@"+self.host+"/system") domains= conn.listAllDomains() domain_dict={} for domain in domains: uuid = domain.UUIDString() ; libvirt_status = domain.state() #print libvirt_status - if libvirt_status[0] == libvirt.VIR_DOMAIN_RUNNING or libvirt_status[0] == libvirt.VIR_DOMAIN_SHUTDOWN: + if libvirt_status[0] == host_thread.lvirt_module.VIR_DOMAIN_RUNNING or libvirt_status[0] == host_thread.lvirt_module.VIR_DOMAIN_SHUTDOWN: new_status = "ACTIVE" - elif libvirt_status[0] == libvirt.VIR_DOMAIN_PAUSED: + elif libvirt_status[0] == host_thread.lvirt_module.VIR_DOMAIN_PAUSED: new_status = "PAUSED" - elif libvirt_status[0] == libvirt.VIR_DOMAIN_SHUTOFF: + elif libvirt_status[0] == host_thread.lvirt_module.VIR_DOMAIN_SHUTOFF: new_status = "INACTIVE" - elif libvirt_status[0] == libvirt.VIR_DOMAIN_CRASHED: + elif libvirt_status[0] == host_thread.lvirt_module.VIR_DOMAIN_CRASHED: new_status = "ERROR" else: new_status = None domain_dict[uuid] = new_status - conn.close - except libvirt.libvirtError as e: + conn.close() + except host_thread.lvirt_module.libvirtError as e: print self.name, ": get_state() Exception '", e.get_error_message() return @@ -1046,15 +1613,15 @@ class host_thread(threading.Thread): self.create_image(None, req) else: try: - conn = libvirt.open("qemu+ssh://"+self.user+"@"+self.host+"/system") + conn = host_thread.lvirt_module.open("qemu+ssh://"+self.user+"@"+self.host+"/system") try: dom = conn.lookupByUUIDString(server_id) - except libvirt.libvirtError as e: + except host_thread.lvirt_module.libvirtError as e: text = e.get_error_message() if 'LookupByUUIDString' in text or 'Domain not found' in text or 'No existe un dominio coincidente' in text: dom = None else: - print self.name, ": action_on_server(",server_id,") libvirt exception:", text + print self.name, ": action_on_server(",server_id,") libvirt exception:", text raise e if 'forceOff' in req['action']: @@ -1131,8 +1698,8 @@ class host_thread(threading.Thread): else: new_status = 'ACTIVE' elif 'start' in req['action']: - #La instancia está sólo en la base de datos pero no en la libvirt. es necesario crearla - rebuild = True if req['action']['start']=='rebuild' else False + # The instance is only create in DB but not yet at libvirt domain, needs to be create + rebuild = True if req['action']['start'] == 'rebuild' else False r = self.launch_server(conn, req, rebuild, dom) if r[0] <0: new_status = 'ERROR' @@ -1175,8 +1742,8 @@ class host_thread(threading.Thread): conn.close() - except libvirt.libvirtError as e: - if conn is not None: conn.close + except host_thread.lvirt_module.libvirtError as e: + if conn is not None: conn.close() text = e.get_error_message() new_status = "ERROR" last_error = text @@ -1232,7 +1799,7 @@ class host_thread(threading.Thread): return 0, None try: if not lib_conn: - conn = libvirt.open("qemu+ssh://"+self.user+"@"+self.host+"/system") + conn = host_thread.lvirt_module.open("qemu+ssh://"+self.user+"@"+self.host+"/system") else: conn = lib_conn @@ -1243,13 +1810,13 @@ class host_thread(threading.Thread): iface.destroy() iface.create() print self.name, ": restore_iface '%s' %s" % (name, mac) - except libvirt.libvirtError as e: + except host_thread.lvirt_module.libvirtError as e: error_text = e.get_error_message() print self.name, ": restore_iface '%s' '%s' libvirt exception: %s" %(name, mac, error_text) ret=-1 finally: if lib_conn is None and conn is not None: - conn.close + conn.close() return ret, error_text @@ -1333,12 +1900,12 @@ class host_thread(threading.Thread): try: conn=None - conn = libvirt.open("qemu+ssh://"+self.user+"@"+self.host+"/system") + conn = host_thread.lvirt_module.open("qemu+ssh://"+self.user+"@"+self.host+"/system") dom = conn.lookupByUUIDString(port["instance_id"]) if old_net: text="\n".join(xml) print self.name, ": edit_iface detaching SRIOV interface", text - dom.detachDeviceFlags(text, flags=libvirt.VIR_DOMAIN_AFFECT_LIVE) + dom.detachDeviceFlags(text, flags=host_thread.lvirt_module.VIR_DOMAIN_AFFECT_LIVE) if new_net: xml[-1] =" " self.xml_level = 1 @@ -1346,16 +1913,16 @@ class host_thread(threading.Thread): xml.append('') text="\n".join(xml) print self.name, ": edit_iface attaching SRIOV interface", text - dom.attachDeviceFlags(text, flags=libvirt.VIR_DOMAIN_AFFECT_LIVE) + dom.attachDeviceFlags(text, flags=host_thread.lvirt_module.VIR_DOMAIN_AFFECT_LIVE) - except libvirt.libvirtError as e: + except host_thread.lvirt_module.libvirtError as e: text = e.get_error_message() print self.name, ": edit_iface(",port["instance_id"],") libvirt exception:", text finally: - if conn is not None: conn.close - - + if conn is not None: conn.close() + + def create_server(server, db, db_lock, only_of_ports): #print "server" #print "server" @@ -1622,7 +2189,10 @@ def create_server(server, db, db_lock, only_of_ports): control_iface['net_id']=control_iface.pop('uuid') #Get the brifge name db_lock.acquire() - result, content = db.get_table(FROM='nets', SELECT=('name','type', 'vlan'),WHERE={'uuid':control_iface['net_id']} ) + result, content = db.get_table(FROM='nets', + SELECT=('name', 'type', 'vlan', 'provider', 'enable_dhcp', + 'dhcp_first_ip', 'dhcp_last_ip', 'cidr'), + WHERE={'uuid': control_iface['net_id']}) db_lock.release() if result < 0: pass @@ -1634,6 +2204,18 @@ def create_server(server, db, db_lock, only_of_ports): if network['type']!='bridge_data' and network['type']!='bridge_man': return -1, "Error at field netwoks: network uuid %s for control interface is not of type bridge_man or bridge_data" % control_iface['net_id'] resources['bridged-ifaces'].append(control_iface) + if network.get("provider") and network["provider"][0:3] == "OVS": + control_iface["type"] = "instance:ovs" + else: + control_iface["type"] = "instance:bridge" + if network.get("vlan"): + control_iface["vlan"] = network["vlan"] + + if network.get("enable_dhcp") == 'true': + control_iface["enable_dhcp"] = network.get("enable_dhcp") + control_iface["dhcp_first_ip"] = network["dhcp_first_ip"] + control_iface["dhcp_last_ip"] = network["dhcp_last_ip"] + control_iface["cidr"] = network["cidr"] else: if network['type']!='data' and network['type']!='ptp': return -1, "Error at field netwoks: network uuid %s for dataplane interface is not of type data or ptp" % control_iface['net_id']