# -*- 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.
#
class host_thread(threading.Thread):
lvirt_module = None
- def __init__(self, name, host, user, db, db_lock, test, image_path, host_id, version, develop_mode,
- develop_bridge_iface, password=None, keyfile = None, logger_name=None, debug=None):
+ def __init__(self, name, host, user, db, test, image_path, host_id, version, develop_mode,
+ develop_bridge_iface, password=None, keyfile = None, logger_name=None, debug=None, hypervisors=None):
"""Init a thread to communicate with compute node or ovs_controller.
:param host_id: host identity
:param name: name of the thread
:param host: host ip or name to manage and user
:param user, password, keyfile: user and credentials to connect to host
- :param db, db_lock': database class and lock to use it in exclusion
+ :param db: database class, threading safe
"""
threading.Thread.__init__(self)
self.name = name
self.host = host
self.user = user
self.db = db
- self.db_lock = db_lock
self.test = test
self.password = password
self.keyfile = keyfile
self.pending_terminate_server =[] #list with pairs (time,server_uuid) time to send a terminate for a server being destroyed
self.next_update_server_status = 0 #time when must be check servers status
+####### self.hypervisor = "kvm" #hypervisor flag (default: kvm)
+ if hypervisors:
+ self.hypervisors = hypervisors
+ else:
+ self.hypervisors = "kvm"
+
+ self.xen_hyp = True if "xen" in self.hypervisors else False
+
self.hostinfo = None
self.queueLock = threading.Lock()
self.run_command_session = None
self.error = None
self.localhost = True if host == 'localhost' else False
- self.lvirt_conn_uri = "qemu+ssh://{user}@{host}/system?no_tty=1&no_verify=1".format(
- user=self.user, host=self.host)
+
+ if self.xen_hyp:
+ self.lvirt_conn_uri = "xen+ssh://{user}@{host}/?no_tty=1&no_verify=1".format(
+ user=self.user, host=self.host)
+ else:
+ self.lvirt_conn_uri = "qemu+ssh://{user}@{host}/system?no_tty=1&no_verify=1".format(
+ user=self.user, host=self.host)
if keyfile:
self.lvirt_conn_uri += "&keyfile=" + keyfile
+
self.remote_ip = None
self.local_ip = None
self.logger.error("save_localinfo Exception: " + text)
def load_servers_from_db(self):
- self.db_lock.acquire()
r,c = self.db.get_table(SELECT=('uuid','status', 'image_id'), FROM='instances', WHERE={'host_id': self.host_id})
- self.db_lock.release()
self.server_status = {}
if r<0:
bus_ide = True if bus=='ide' else False
self.xml_level = 0
+ hypervisor = server.get('hypervisor', 'kvm')
+ os_type_img = server.get('os_image_type', 'other')
- text = "<domain type='kvm'>"
+ if hypervisor[:3] == 'xen':
+ text = "<domain type='xen'>"
+ else:
+ text = "<domain type='kvm'>"
#get topology
topo = server_metadata.get('topology', None)
if topo == None and 'metadata' in dev_list[0]:
if dev['type']=='cdrom' :
boot_cdrom = True
break
- text += self.tab()+ '<os>' + \
- self.inc_tab() + "<type arch='x86_64' machine='pc'>hvm</type>"
- if boot_cdrom:
- text += self.tab() + "<boot dev='cdrom'/>"
- text += self.tab() + "<boot dev='hd'/>" + \
- self.dec_tab()+'</os>'
+ if hypervisor == 'xenhvm':
+ text += self.tab()+ '<os>' + \
+ self.inc_tab() + "<type arch='x86_64' machine='xenfv'>hvm</type>"
+ text += self.tab() + "<loader type='rom'>/usr/lib/xen/boot/hvmloader</loader>"
+ if boot_cdrom:
+ text += self.tab() + "<boot dev='cdrom'/>"
+ text += self.tab() + "<boot dev='hd'/>" + \
+ self.dec_tab()+'</os>'
+ elif hypervisor == 'xen-unik':
+ text += self.tab()+ '<os>' + \
+ self.inc_tab() + "<type arch='x86_64' machine='xenpv'>xen</type>"
+ text += self.tab() + "<kernel>" + str(dev_list[0]['source file']) + "</kernel>" + \
+ self.dec_tab()+'</os>'
+ else:
+ text += self.tab()+ '<os>' + \
+ self.inc_tab() + "<type arch='x86_64' machine='pc'>hvm</type>"
+ if boot_cdrom:
+ text += self.tab() + "<boot dev='cdrom'/>"
+ text += self.tab() + "<boot dev='hd'/>" + \
+ self.dec_tab()+'</os>'
#features
text += self.tab()+'<features>'+\
self.inc_tab()+'<acpi/>' +\
self.tab() + "<on_poweroff>preserve</on_poweroff>" + \
self.tab() + "<on_reboot>restart</on_reboot>" + \
self.tab() + "<on_crash>restart</on_crash>"
- text += self.tab() + "<devices>" + \
- self.inc_tab() + "<emulator>/usr/libexec/qemu-kvm</emulator>" + \
- self.tab() + "<serial type='pty'>" +\
- self.inc_tab() + "<target port='0'/>" + \
- self.dec_tab() + "</serial>" +\
- self.tab() + "<console type='pty'>" + \
- self.inc_tab()+ "<target type='serial' port='0'/>" + \
- self.dec_tab()+'</console>'
+ if hypervisor == 'xenhvm':
+ text += self.tab() + "<devices>" + \
+ self.inc_tab() + "<emulator>/usr/bin/qemu-system-i386</emulator>" + \
+ self.tab() + "<serial type='pty'>" +\
+ self.inc_tab() + "<target port='0'/>" + \
+ self.dec_tab() + "</serial>" +\
+ self.tab() + "<console type='pty'>" + \
+ self.inc_tab()+ "<target type='serial' port='0'/>" + \
+ self.dec_tab()+'</console>' #In some libvirt version may be: <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> (depends on distro)
+ elif hypervisor == 'xen-unik':
+ text += self.tab() + "<devices>" + \
+ self.tab() + "<console type='pty'>" + \
+ self.inc_tab()+ "<target type='xen' port='0'/>" + \
+ self.dec_tab()+'</console>'
+ else:
+ text += self.tab() + "<devices>" + \
+ self.inc_tab() + "<emulator>/usr/libexec/qemu-kvm</emulator>" + \
+ self.tab() + "<serial type='pty'>" +\
+ self.inc_tab() + "<target port='0'/>" + \
+ self.dec_tab() + "</serial>" +\
+ self.tab() + "<console type='pty'>" + \
+ self.inc_tab()+ "<target type='serial' port='0'/>" + \
+ self.dec_tab()+'</console>'
if windows_os:
text += self.tab() + "<controller type='usb' index='0'/>" + \
self.tab() + "<controller type='ide' index='0'/>" + \
self.dec_tab() + "</video>" + \
self.tab() + "<memballoon model='virtio'/>" + \
self.tab() + "<input type='tablet' bus='usb'/>" #TODO revisar
+ elif hypervisor == 'xen-unik':
+ pass
+ else:
+ text += self.tab() + "<controller type='ide' index='0'/>" + \
+ self.tab() + "<input type='mouse' bus='ps2'/>" + \
+ self.tab() + "<input type='keyboard' bus='ps2'/>" + \
+ self.tab() + "<video>" + \
+ self.inc_tab() + "<model type='cirrus' vram='9216' heads='1'/>" + \
+ self.dec_tab() + "</video>"
#> self.tab()+'<alias name=\'hostdev0\'/>\n' +\
#> self.dec_tab()+'</hostdev>\n' +\
vd_index = 'a'
for dev in dev_list:
bus_ide_dev = bus_ide
- if dev['type']=='cdrom' or dev['type']=='disk':
+ if (dev['type']=='cdrom' or dev['type']=='disk') and hypervisor != 'xen-unik':
if dev['type']=='cdrom':
bus_ide_dev = True
text += self.tab() + "<disk type='file' device='"+dev['type']+"'>"
dev_text = dev_text.replace('__dev__', vd_index)
vd_index = chr(ord(vd_index)+1)
text += dev_text
+ elif hypervisor == 'xen-unik':
+ pass
else:
return -1, 'Unknown device type ' + dev['type']
bridge_interfaces = server.get('networks', [])
for v in bridge_interfaces:
#Get the brifge name
- self.db_lock.acquire()
result, content = self.db.get_table(FROM='nets', SELECT=('provider',),WHERE={'uuid':v['net_id']} )
- self.db_lock.release()
if result <= 0:
self.logger.error("create_xml_server ERROR %d getting nets %s", result, content)
return -1, content
vlan = content[0]['provider'].replace('OVS:', '')
text += self.tab() + "<interface type='bridge'>" + \
self.inc_tab() + "<source bridge='ovim-" + str(vlan) + "'/>"
+ if hypervisor == 'xenhvm' or hypervisor == 'xen-unik':
+ text += self.tab() + "<script path='vif-openvswitch'/>"
else:
return -1, 'Unknown Bridge net provider ' + content[0]['provider']
if model!=None:
command = 'sudo ip netns exec {} cat {}'.format(dhcp_namespace, pid_file)
content = self.run_command(command, ignore_exit_status=True)
dns_pid = content.replace('\n', '')
- command = 'sudo ip netns exec {} kill -9 '.format(dhcp_namespace, dns_pid)
+ command = 'sudo ip netns exec {} kill -9 {}'.format(dhcp_namespace, dns_pid)
self.run_command(command, ignore_exit_status=True)
except RunCommandException as e:
:param net_uuid: network id
:return: True if is not free
"""
- self.db_lock.acquire()
result, content = self.db.get_table(
FROM='ports',
WHERE={'type': 'instance:ovs', 'net_id': net_uuid}
)
- self.db_lock.release()
if len(content) > 0:
return False
: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
command = 'sudo ip link set dev ovim-{} down'.format(str(vlan))
self.run_command(command)
- command = 'sudo ifconfig {} down && sudo brctl delbr {}'.format(port_name, port_name)
+ command = 'sudo ip link delete {} && sudo brctl delbr {}'.format(port_name, port_name)
self.run_command(command)
return True
except RunCommandException as e:
# Delete ovs veth pair
command = 'sudo ip link set dev {} down'.format(br_ovs_name)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
command = 'sudo ovs-vsctl del-port br-int {}'.format(br_ovs_name)
self.run_command(command)
# Delete br veth pair
command = 'sudo ip link set dev {} down'.format(br_tap_name)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
# Delete br veth interface form bridge
command = 'sudo brctl delif {} {}'.format(link, br_tap_name)
# Delete br veth pair
command = 'sudo ip link set dev {} down'.format(link)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
return True
except RunCommandException as e:
command = 'sudo ip link set dev {} down'.format(ovs_veth_name)
self.run_command(command, ignore_exit_status=True) # to end session
+ command = 'sudo ip link delete {} '.format(ovs_veth_name)
+ self.run_command(command, ignore_exit_status=True)
+
command = 'sudo ip netns exec {} ip link set dev {} down'.format(dhcp_namespace, br_veth_name)
self.run_command(command, ignore_exit_status=True)
qrouter_ns_router_veth = '{}-vethQB'.format(str(vlan))
command = 'sudo ovs-vsctl del-port br-int {}'.format(qrouter_ovs_veth)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
# down ns veth
command = 'sudo ip netns exec {} ip link set dev {} down'.format(ns_qouter, qrouter_ns_veth)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
+
+ command = 'sudo ip netns exec {} ip link delete {} '.format(ns_qouter, qrouter_ns_veth)
+ self.run_command(command, ignore_exit_status=True)
command = 'sudo ip netns del ' + ns_qouter
self.run_command(command)
# down ovs veth interface
command = 'sudo ip link set dev {} down'.format(qrouter_br_veth)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
# down br veth interface
command = 'sudo ip link set dev {} down'.format(qrouter_ovs_veth)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
+
+ # delete veth interface
+ command = 'sudo ip link delete {} '.format(link, qrouter_ovs_veth)
+ self.run_command(command, ignore_exit_status=True)
# down br veth interface
command = 'sudo ip link set dev {} down'.format(qrouter_ns_router_veth)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
+
+ # delete veth interface
+ command = 'sudo ip link delete {} '.format(link, qrouter_ns_router_veth)
+ self.run_command(command, ignore_exit_status=True)
# down br veth interface
command = 'sudo brctl delif {} {}'.format(link, qrouter_br_veth)
# Create pait veth
command = 'sudo ip link add {} type veth peer name {}'.format(qrouter_ns_veth, qrouter_ovs_veth)
- self.run_command(command)
+ self.run_command(command, ignore_exit_status=True)
# up ovs veth interface
command = 'sudo ip link set dev {} up'.format(qrouter_ovs_veth)
#self.server_status[server_id] = 'ACTIVE'
return 0, 'Success'
- self.db_lock.acquire()
result, server_data = self.db.get_instance(server_id)
- self.db_lock.release()
if result <= 0:
self.logger.error("launch_server ERROR getting server from DB %d %s", result, server_data)
return result, server_data
+ self.hypervisor = str(server_data['hypervisor'])
+
#0: get image metadata
server_metadata = server.get('metadata', {})
use_incremental = None
if "use_incremental" in server_metadata:
use_incremental = False if server_metadata["use_incremental"] == "no" else True
+ if self.xen_hyp == True:
+ use_incremental = False
server_host_files = self.localinfo['server_files'].get( server['uuid'], {})
if rebuild:
continue
else:
- self.db_lock.acquire()
result, content = self.db.get_table(FROM='images', SELECT=('path', 'metadata'),
WHERE={'uuid': image_id})
- self.db_lock.release()
if result <= 0:
error_text = "ERROR", result, content, "when getting image", dev['image_id']
self.logger.error("launch_server " + error_text)
STATUS={'progress':100, 'status':new_status}
if new_status == 'ERROR':
STATUS['last_error'] = 'machine has crashed'
- self.db_lock.acquire()
r,_ = self.db.update_rows('instances', STATUS, {'uuid':server_id}, log=False)
- self.db_lock.release()
if r>=0:
self.server_status[server_id] = new_status
elif 'terminate' in req['action']:
#PUT a log in the database
self.logger.error("PANIC deleting server id='%s' %s", server_id, last_error)
- self.db_lock.acquire()
- self.db.new_row('logs',
+ self.db.new_row('logs',
{'uuid':server_id, 'tenant_id':req['tenant_id'], 'related':'instances','level':'panic',
'description':'PANIC deleting server from host '+self.name+': '+last_error}
)
- self.db_lock.release()
if server_id in self.server_status:
del self.server_status[server_id]
return -1
else:
UPDATE['last_error'] = last_error
if new_status != 'deleted' and (new_status != old_status or new_status == 'ERROR') :
- self.db_lock.acquire()
self.db.update_rows('instances', UPDATE, {'uuid':server_id}, log=True)
self.server_status[server_id] = new_status
- self.db_lock.release()
if new_status == 'ERROR':
return -1
return 1
self.logger.error("create_image id='%s' Exception: %s", server_id, error_text)
#TODO insert a last_error at database
- self.db_lock.acquire()
- self.db.update_rows('images', {'status':image_status, 'progress': 100, 'path':file_dst},
+ self.db.update_rows('images', {'status':image_status, 'progress': 100, 'path':file_dst},
{'uuid':req['new_image']['uuid']}, log=True)
- self.db_lock.release()
-
+
def edit_iface(self, port_id, old_net, new_net):
#This action imply remove and insert interface to put proper parameters
if self.test:
time.sleep(1)
else:
#get iface details
- self.db_lock.acquire()
r,c = self.db.get_table(FROM='ports as p join resources_port as rp on p.uuid=rp.port_id',
WHERE={'port_id': port_id})
- self.db_lock.release()
if r<0:
self.logger.error("edit_iface %s DDBB error: %s", port_id, c)
return
if conn is not None: conn.close()
-def create_server(server, db, db_lock, only_of_ports):
+def create_server(server, db, only_of_ports):
extended = server.get('extended', None)
requirements={}
requirements['numa']={'memory':0, 'proc_req_type': 'threads', 'proc_req_nb':0, 'port_list':[], 'sriov_list':[]}
elif requirements['vcpus']==0:
return (-1, "Processor information not set neither at extended field not at vcpus")
+ if 'hypervisor' in server: requirements['hypervisor'] = server['hypervisor'] #Unikernels extension
- db_lock.acquire()
result, content = db.get_numas(requirements, server.get('host_id', None), only_of_ports)
- db_lock.release()
-
+
if result == -1:
return (-1, content)
cpu_pinning = []
reserved_threads=[]
if requirements['numa']['proc_req_nb']>0:
- db_lock.acquire()
- result, content = db.get_table(FROM='resources_core',
+ result, content = db.get_table(FROM='resources_core',
SELECT=('id','core_id','thread_id'),
WHERE={'numa_id':numa_id,'instance_id': None, 'status':'ok'} )
- db_lock.release()
if result <= 0:
#print content
return -1, content
#Get the source pci addresses for the selected numa
used_sriov_ports = []
for port in requirements['numa']['sriov_list']:
- db_lock.acquire()
result, content = db.get_table(FROM='resources_port', SELECT=('id', 'pci', 'mac'),WHERE={'numa_id':numa_id,'root_id': port['port_id'], 'port_id': None, 'Mbps_used': 0} )
- db_lock.release()
if result <= 0:
#print content
return -1, content
port['mac_address'] = port['mac']
del port['mac']
continue
- db_lock.acquire()
result, content = db.get_table(FROM='resources_port', SELECT=('id', 'pci', 'mac', 'Mbps'),WHERE={'numa_id':numa_id,'root_id': port['port_id'], 'port_id': None, 'Mbps_used': 0} )
- db_lock.release()
if result <= 0:
#print content
return -1, content
for control_iface in server.get('networks', []):
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', 'provider', 'enable_dhcp','dhcp_first_ip',
'dhcp_last_ip', 'cidr', 'gateway_ip', 'dns', 'links', 'routes'),
WHERE={'uuid': control_iface['net_id']})
- db_lock.release()
- if result < 0:
+ if result < 0:
pass
elif result==0:
return -1, "Error at field netwoks: Not found any network wit uuid %s" % control_iface['net_id']
if 'description' in server: resources['description'] = server['description']
if 'name' in server: resources['name'] = server['name']
+ if 'hypervisor' in server: resources['hypervisor'] = server['hypervisor']
+ if 'os_image_type' in server: resources['os_image_type'] = server['os_image_type']
resources['extended'] = {} #optional
resources['extended']['numas'] = []