1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2025-07-31 12:41:08 +00:00

Instances overhaul

This commit is contained in:
Real-Gecko 2020-07-13 15:33:09 +06:00
parent f23e6b000f
commit 47009d47ca
69 changed files with 5011 additions and 4127 deletions

View file

@ -7,7 +7,6 @@ from vrtManager.rwlock import ReadWriteLock
from django.conf import settings
from libvirt import libvirtError
CONN_SOCKET = 4
CONN_TLS = 3
CONN_SSH = 2
@ -19,7 +18,6 @@ TCP_PORT = 16509
class wvmEventLoop(threading.Thread):
""" Event Loop Class"""
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
# register the default event implementation
# of libvirt, as we do not have an existing
@ -48,7 +46,6 @@ class wvmConnection(object):
class representing a single connection stored in the Connection Manager
# to-do: may also need some locking to ensure to not connect simultaniously in 2 threads
"""
def __init__(self, host, login, passwd, conn):
"""
Sets all class attributes and tries to open the connection
@ -208,7 +205,7 @@ class wvmConnection(object):
except:
pass
def __unicode__(self):
def __str__(self):
if self.type == CONN_TCP:
type_str = 'tcp'
elif self.type == CONN_SSH:
@ -323,7 +320,7 @@ class wvmConnectionManager(object):
socket_host.connect((hostname, TLS_PORT))
if conn_type == CONN_SOCKET:
socket_host = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
socket_host.connect('/var/run/libvirt/libvirt-sock')
socket_host.connect('/var/run/libvirt/libvirt-sock')
socket_host.close()
return True
except Exception as err:
@ -332,7 +329,7 @@ class wvmConnectionManager(object):
connection_manager = wvmConnectionManager(
settings.LIBVIRT_KEEPALIVE_INTERVAL if hasattr(settings, 'LIBVIRT_KEEPALIVE_INTERVAL') else 5,
settings.LIBVIRT_KEEPALIVE_COUNT if hasattr(settings, 'LIBVIRT_KEEPALIVE_COUNT') else 5
settings.LIBVIRT_KEEPALIVE_COUNT if hasattr(settings, 'LIBVIRT_KEEPALIVE_COUNT') else 5,
)
@ -374,9 +371,11 @@ class wvmConnect(object):
result["machines"] = []
for m in arch_el.xpath("machine"):
result["machines"].append({"machine": m.text,
"max_cpu": m.get("maxCpus"),
"canonical": m.get("canonical")})
result["machines"].append({
"machine": m.text,
"max_cpu": m.get("maxCpus"),
"canonical": m.get("canonical")
})
guest_el = arch_el.getparent()
for f in guest_el.xpath("features"):
@ -385,6 +384,7 @@ class wvmConnect(object):
result["os_type"] = guest_el.find("os_type").text
return result
return util.get_xml_path(self.get_cap_xml(), func=guests)
def get_dom_capabilities(self, arch, machine):
@ -560,6 +560,7 @@ class wvmConnect(object):
arch_name = arch.xpath('@name')[0]
result[arch_name] = domain_types
return result
return util.get_xml_path(self.get_cap_xml(), func=hypervisors)
def get_hypervisors_machines(self):
@ -573,6 +574,7 @@ class wvmConnect(object):
result[arch] = self.get_machine_types(arch)
return result
return util.get_xml_path(self.get_cap_xml(), func=machines)
def get_emulator(self, arch):
@ -607,6 +609,7 @@ class wvmConnect(object):
arch_name = arch.xpath('@name')[0]
result[arch_name] = emulator
return result
return util.get_xml_path(self.get_cap_xml(), func=emulators)
def get_os_loaders(self, arch='x86_64', machine='pc'):
@ -617,6 +620,7 @@ class wvmConnect(object):
"""
def get_os_loaders(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/os/loader[@supported='yes']/value")]
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_os_loaders)
def get_os_loader_enums(self, arch, machine):
@ -632,6 +636,7 @@ class wvmConnect(object):
path = "/domainCapabilities/os/loader[@supported='yes']/enum[@name='{}']/value".format(enum)
result[enum] = [v.text for v in ctx.xpath(path)]
return result
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_os_loader_enums)
def get_disk_bus_types(self, arch, machine):
@ -642,6 +647,7 @@ class wvmConnect(object):
"""
def get_bus_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/disk/enum[@name='bus']/value")]
# return [ 'ide', 'scsi', 'usb', 'virtio' ]
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_bus_list)
@ -653,6 +659,7 @@ class wvmConnect(object):
"""
def get_device_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/disk/enum[@name='diskDevice']/value")]
# return [ 'disk', 'cdrom', 'floppy', 'lun' ]
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_device_list)
@ -664,6 +671,7 @@ class wvmConnect(object):
"""
def get_graphics_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/graphics/enum[@name='type']/value")]
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_graphics_list)
def get_cpu_modes(self, arch, machine):
@ -674,6 +682,7 @@ class wvmConnect(object):
"""
def get_cpu_modes(ctx):
return [v for v in ctx.xpath("/domainCapabilities/cpu/mode[@supported='yes']/@name")]
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_cpu_modes)
def get_cpu_custom_types(self, arch, machine):
@ -688,6 +697,7 @@ class wvmConnect(object):
result = [v.text for v in ctx.xpath(usable_yes)]
result += [v.text for v in ctx.xpath(usable_unknown)]
return result
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_custom_list)
def get_hostdev_modes(self, arch, machine):
@ -698,6 +708,7 @@ class wvmConnect(object):
"""
def get_hostdev_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/hostdev/enum[@name='mode']/value")]
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_hostdev_list)
def get_hostdev_startup_policies(self, arch, machine):
@ -708,6 +719,7 @@ class wvmConnect(object):
"""
def get_hostdev_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/hostdev/enum[@name='startupPolicy']/value")]
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_hostdev_list)
def get_hostdev_subsys_types(self, arch, machine):
@ -718,6 +730,7 @@ class wvmConnect(object):
"""
def get_hostdev_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/hostdev/enum[@name='subsysType']/value")]
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_hostdev_list)
def get_network_models(self):
@ -748,9 +761,10 @@ class wvmConnect(object):
result = []
for video_enum in ctx.xpath('/domainCapabilities/devices/video/enum'):
if video_enum.xpath("@name")[0] == "modelType":
for values in video_enum:
for values in video_enum:
result.append(values.text)
return result
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_video_list)
def get_iface(self, name):
@ -829,7 +843,7 @@ class wvmConnect(object):
mem = util.get_xpath(doc, "/domain/currentMemory")
mem = int(mem) / 1024
if raw_mem_size:
mem = int(mem) * (1024*1024)
mem = int(mem) * (1024 * 1024)
cur_vcpu = util.get_xpath(doc, "/domain/vcpu/@current")
if cur_vcpu:
vcpu = cur_vcpu
@ -840,6 +854,7 @@ class wvmConnect(object):
description = util.get_xpath(doc, "/domain/description")
description = description if description else ''
return mem, vcpu, title, description
for name in self.get_instances():
dom = self.get_instance(name)
xml = dom.XMLDesc(0)
@ -871,6 +886,7 @@ class wvmConnect(object):
description = util.get_xpath(ctx, "/domain/description")
description = description if description else ''
return mem, vcpu, title, description
(mem, vcpu, title, description) = util.get_xml_path(xml, func=get_info)
return {
'name': dom.name(),
@ -929,8 +945,7 @@ class wvmConnect(object):
"""
Return True if libvirt advertises support for proper UEFI setup
"""
return ("readonly" in loader_enums and
"yes" in loader_enums.get("readonly"))
return ("readonly" in loader_enums and "yes" in loader_enums.get("readonly"))
def is_supports_virtio(self, arch, machine):
if not self.is_qemu():

View file

@ -206,6 +206,8 @@ class wvmInstance(wvmConnect):
cur_vcpu = util.get_xml_path(self._XMLDesc(0), "/domain/vcpu/@current")
if cur_vcpu:
return int(cur_vcpu)
else:
return self.get_vcpu()
def get_arch(self):
return util.get_xml_path(self._XMLDesc(0), "/domain/os/type/@arch")
@ -251,7 +253,6 @@ class wvmInstance(wvmConnect):
return title if title else ''
def get_filterrefs(self):
def filterrefs(ctx):
result = []
for net in ctx.xpath('/domain/devices/interface'):
@ -295,8 +296,7 @@ class wvmInstance(wvmConnect):
for addr in addrs["addrs"]:
if addr["type"] == 0:
ipv4.append(addr["addr"])
elif (addr["type"] == 1 and
not str(addr["addr"]).startswith("fe80")):
elif (addr["type"] == 1 and not str(addr["addr"]).startswith("fe80")):
ipv6.append(addr["addr"] + "/" + str(addr["prefix"]))
return ipv4, ipv6
@ -335,14 +335,12 @@ class wvmInstance(wvmConnect):
return
if self.is_agent_ready():
self._ip_cache["qemuga"] = self._get_interface_addresses(
VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT)
self._ip_cache["qemuga"] = self._get_interface_addresses(VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT)
arp_flag = 3 # libvirt."VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP"
self._ip_cache["arp"] = self._get_interface_addresses(arp_flag)
def get_net_devices(self):
def networks(ctx):
result = []
inbound = outbound = []
@ -370,17 +368,18 @@ class wvmInstance(wvmConnect):
ipv4, ipv6 = self.get_interface_addresses(mac_inst)
except libvirtError:
ipv4, ipv6 = None, None
result.append({'mac': mac_inst,
'nic': nic_inst,
'target': target_inst,
'state': link_state,
'model': model_type,
'ipv4': ipv4,
'ipv6': ipv6,
'filterref': filterref_inst,
'inbound': inbound,
'outbound': outbound,
})
result.append({
'mac': mac_inst,
'nic': nic_inst,
'target': target_inst,
'state': link_state,
'model': model_type,
'ipv4': ipv4,
'ipv6': ipv6,
'filterref': filterref_inst,
'inbound': inbound,
'outbound': outbound,
})
return result
return util.get_xml_path(self._XMLDesc(0), func=networks)
@ -388,7 +387,7 @@ class wvmInstance(wvmConnect):
def get_disk_devices(self):
def disks(doc):
result = []
for disk in doc.xpath('/domain/devices/disk'):
dev = volume = storage = src_file = bus = None
disk_format = used_size = disk_size = None
@ -400,7 +399,13 @@ class wvmInstance(wvmConnect):
try:
dev = disk.xpath('target/@dev')[0]
bus = disk.xpath('target/@bus')[0]
src_file = disk.xpath('source/@file|source/@dev|source/@name|source/@volume')[0]
try:
src_file = disk.xpath('source/@file|source/@dev|source/@name')[0]
except Exception as e:
v = disk.xpath('source/@volume')[0]
s_name = disk.xpath('source/@pool')[0]
s = self.wvm.storagePoolLookupByName(s_name)
src_file = s.storageVolLookupByName(v).path()
try:
disk_format = disk.xpath('driver/@type')[0]
except:
@ -436,14 +441,26 @@ class wvmInstance(wvmConnect):
storage = stg.name()
except libvirtError:
volume = src_file
except:
pass
except Exception as e:
print(f'Exception: {e}')
finally:
result.append(
{'dev': dev, 'bus': bus, 'image': volume, 'storage': storage, 'path': src_file,
'format': disk_format, 'size': disk_size, 'used': used_size,
'cache': disk_cache, 'io': disk_io, 'discard': disk_discard, 'detect_zeroes': disk_zeroes,
'readonly': readonly, 'shareable': shareable, 'serial': serial})
result.append({
'dev': dev,
'bus': bus,
'image': volume,
'storage': storage,
'path': src_file,
'format': disk_format,
'size': disk_size,
'used': used_size,
'cache': disk_cache,
'io': disk_io,
'discard': disk_discard,
'detect_zeroes': disk_zeroes,
'readonly': readonly,
'shareable': shareable,
'serial': serial
})
return result
return util.get_xml_path(self._XMLDesc(0), func=disks)
@ -544,7 +561,7 @@ class wvmInstance(wvmConnect):
elif dev_type == 'usb':
pass
boot_order[int(idx)-1] = {"type": dev_type, "dev": dev_device, "target": dev_target}
boot_order[int(idx) - 1] = {"type": dev_type, "dev": dev_device, "target": dev_target}
return boot_order
@ -642,14 +659,25 @@ class wvmInstance(wvmConnect):
xmldom = ElementTree.tostring(tree).decode()
self._defineXML(xmldom)
def attach_disk(self, target_dev, source, target_bus='ide', disk_type='file',
disk_device='disk', driver_name='qemu', driver_type='raw',
readonly=False, shareable=False, serial=None,
cache_mode=None, io_mode=None, discard_mode=None, detect_zeroes_mode=None):
def attach_disk(self,
target_dev,
source,
target_bus='ide',
disk_type='file',
disk_device='disk',
driver_name='qemu',
driver_type='raw',
readonly=False,
shareable=False,
serial=None,
cache_mode=None,
io_mode=None,
discard_mode=None,
detect_zeroes_mode=None):
additionals = ''
if cache_mode is not None and cache_mode != 'default' and disk_device != 'cdrom':
additionals += f"cache='{cache_mode}' "
additionals += f"cache='{cache_mode}' "
if io_mode is not None and io_mode != 'default':
additionals += f"io='{io_mode}' "
if discard_mode is not None and discard_mode != 'default':
@ -691,7 +719,8 @@ class wvmInstance(wvmConnect):
if self.get_status() == 5:
self.instance.detachDeviceFlags(xml_disk, VIR_DOMAIN_AFFECT_CONFIG)
def edit_disk(self, target_dev, source, readonly, shareable, target_bus, serial, format, cache_mode, io_mode, discard_mode, detect_zeroes_mode):
def edit_disk(self, target_dev, source, readonly, shareable, target_bus, serial, format, cache_mode, io_mode, discard_mode,
detect_zeroes_mode):
tree = etree.fromstring(self._XMLDesc(0))
disk_el = tree.xpath("./devices/disk/target[@dev='{}']".format(target_dev))[0].getparent()
old_disk_type = disk_el.get('type')
@ -735,7 +764,7 @@ class wvmInstance(wvmConnect):
time.sleep(1)
cpu_use_now = self.instance.info()[4]
diff_usage = cpu_use_now - cpu_use_ago
cpu_usage['cpu'] = 100 * diff_usage / (1 * nbcore * 10 ** 9)
cpu_usage['cpu'] = 100 * diff_usage / (1 * nbcore * 10**9)
else:
cpu_usage['cpu'] = 0
return cpu_usage
@ -928,8 +957,7 @@ class wvmInstance(wvmConnect):
def get_console_websocket_port(self):
console_type = self.get_console_type()
websocket_port = util.get_xml_path(self._XMLDesc(0),
"/domain/devices/graphics[@type='%s']/@websocket" % console_type)
websocket_port = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics[@type='%s']/@websocket" % console_type)
return websocket_port
def get_console_passwd(self):
@ -1124,7 +1152,7 @@ class wvmInstance(wvmConnect):
return mac
# if mac does not contain ":", try to split into tuples and join with ":"
n = 2
mac_tuples = [mac[i:i+n] for i in range(0, len(mac), n)]
mac_tuples = [mac[i:i + n] for i in range(0, len(mac), n)]
return ':'.join(mac_tuples)
def clone_instance(self, clone_data):
@ -1215,7 +1243,7 @@ class wvmInstance(wvmConnect):
stg = vol.storagePoolLookupByVolume()
stg.createXMLFrom(vol_clone_xml, vol, meta_prealloc)
source_protocol = elm.get('protocol')
if source_protocol == 'rbd':
source_name = elm.get('name')
@ -1241,13 +1269,13 @@ class wvmInstance(wvmConnect):
if source_dev:
clone_path = os.path.join(os.path.dirname(source_dev), target_file)
elm.set('dev', clone_path)
vol = self.get_volume_by_path(source_dev)
stg = vol.storagePoolLookupByVolume()
vol_name = util.get_xml_path(vol.XMLDesc(0), "/volume/name")
pool_name = util.get_xml_path(stg.XMLDesc(0), "/pool/name")
storage = self.get_wvmStorage(pool_name)
storage.clone_volume(vol_name, target_file)
@ -1388,7 +1416,7 @@ class wvmInstance(wvmConnect):
tree.remove(option)
else:
if option is None:
option = etree.SubElement(tree , o)
option = etree.SubElement(tree, o)
option.text = option_value
def set_options(self, options):
@ -1421,7 +1449,13 @@ class wvmInstance(wvmConnect):
in_peak = in_qos.get('peak')
in_burst = in_qos.get('burst')
in_floor = in_qos.get('floor')
bound_list.append({'direction': 'inbound', 'average': in_av, 'peak': in_peak, 'floor': in_floor, 'burst': in_burst})
bound_list.append({
'direction': 'inbound',
'average': in_av,
'peak': in_peak,
'floor': in_floor,
'burst': in_burst
})
out_qos = band.find('outbound')
if out_qos is not None: