mirror of
https://github.com/retspen/webvirtcloud
synced 2025-07-31 12:41:08 +00:00
Instances overhaul
This commit is contained in:
parent
f23e6b000f
commit
47009d47ca
69 changed files with 5011 additions and 4127 deletions
|
@ -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():
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue