From d283e0e1b3ec8dde9b869eb27a2593a672609998 Mon Sep 17 00:00:00 2001 From: catborise Date: Fri, 24 Apr 2020 16:30:39 +0300 Subject: [PATCH 01/11] remove unused resize request from instance --- Dockerfile | 1 - instances/views.py | 34 ---------------------------------- 2 files changed, 35 deletions(-) diff --git a/Dockerfile b/Dockerfile index c3b122f..b04b9d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,4 @@ FROM phusion/baseimage:0.11 -MAINTAINER Jethro Yu RUN echo 'APT::Get::Clean=always;' >> /etc/apt/apt.conf.d/99AutomaticClean diff --git a/instances/views.py b/instances/views.py index 28e78e4..aa84f7d 100644 --- a/instances/views.py +++ b/instances/views.py @@ -460,40 +460,6 @@ def instance(request, compute_id, vname): msg = _("Please shutdown down your instance and then try again") error_messages.append(msg) - if 'resize' in request.POST and ( - request.user.is_superuser or request.user.is_staff or userinstance.is_change): - new_vcpu = request.POST.get('vcpu', '') - new_cur_vcpu = request.POST.get('cur_vcpu', '') - new_memory = request.POST.get('memory', '') - new_memory_custom = request.POST.get('memory_custom', '') - if new_memory_custom: - new_memory = new_memory_custom - new_cur_memory = request.POST.get('cur_memory', '') - new_cur_memory_custom = request.POST.get('cur_memory_custom', '') - if new_cur_memory_custom: - new_cur_memory = new_cur_memory_custom - disks_new = [] - for disk in disks: - input_disk_size = filesizefstr(request.POST.get('disk_size_' + disk['dev'], '')) - if input_disk_size > disk['size'] + (64 << 20): - disk['size_new'] = input_disk_size - disks_new.append(disk) - disk_sum = sum([disk['size'] >> 30 for disk in disks_new]) - disk_new_sum = sum([disk['size_new'] >> 30 for disk in disks_new]) - quota_msg = check_user_quota(0, int(new_vcpu) - vcpu, int(new_memory) - memory, disk_new_sum - disk_sum) - if not request.user.is_superuser and quota_msg: - msg = _("User %s quota reached, cannot resize '%s'!" % (quota_msg, instance.name)) - error_messages.append(msg) - else: - cur_memory = new_cur_memory - memory = new_memory - cur_vcpu = new_cur_vcpu - vcpu = new_vcpu - conn.resize(cur_memory, memory, cur_vcpu, vcpu, disks_new) - msg = _("Resize") - addlogmsg(request.user.username, instance.name, msg) - return HttpResponseRedirect(request.get_full_path() + '#resize') - if 'resizevm_cpu' in request.POST and ( request.user.is_superuser or request.user.is_staff or userinstance.is_change): new_vcpu = request.POST.get('vcpu', '') From 22cb8f702ad9bc7bf73584b1ec4d522211f1154e Mon Sep 17 00:00:00 2001 From: catborise Date: Fri, 24 Apr 2020 19:34:29 +0300 Subject: [PATCH 02/11] fix code conventions for pylint --- accounts/models.py | 4 +- computes/views.py | 28 +++++++ console/views.py | 2 +- create/views.py | 16 ++-- datasource/views.py | 26 +++++-- instances/views.py | 19 +++-- nwfilters/views.py | 10 ++- storages/views.py | 8 +- vrtManager/connection.py | 157 +++++++++++++++++++++++++++++--------- vrtManager/create.py | 2 +- vrtManager/hostdetails.py | 8 +- vrtManager/instance.py | 23 +++--- vrtManager/interface.py | 9 ++- vrtManager/network.py | 25 +++--- vrtManager/nwfilters.py | 2 +- vrtManager/util.py | 16 ++-- 16 files changed, 245 insertions(+), 110 deletions(-) diff --git a/accounts/models.py b/accounts/models.py index 33b6251..02192fe 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -30,13 +30,13 @@ class UserSSHKey(models.Model): class UserAttributes(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) can_clone_instances = models.BooleanField(default=True) - max_instances = models.IntegerField(default=1, + max_instances = models.IntegerField(default=2, help_text="-1 for unlimited. Any integer value", validators=[ MinValueValidator(-1), ]) max_cpus = models.IntegerField( - default=1, + default=2, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1)], ) diff --git a/computes/views.py b/computes/views.py index 6d7a4bd..7ed3bea 100644 --- a/computes/views.py +++ b/computes/views.py @@ -141,6 +141,14 @@ def compute_graph(request, compute_id): def get_compute_disk_buses(request, compute_id, arch, machine, disk): + """ + :param request: + :param compute_id: + :param arch: + :param machine: + :param disk: + :return: + """ data = dict() compute = get_object_or_404(Compute, pk=compute_id) try: @@ -169,6 +177,12 @@ def get_compute_disk_buses(request, compute_id, arch, machine, disk): def get_compute_machine_types(request, compute_id, arch): + """ + :param request: + :param compute_id: + :param arch: + :return: + """ data = dict() try: compute = get_object_or_404(Compute, pk=compute_id) @@ -186,6 +200,13 @@ def get_compute_machine_types(request, compute_id, arch): def get_compute_video_models(request, compute_id, arch, machine): + """ + :param request: + :param compute_id: + :param arch: + :param machine: + :return: + """ data = dict() try: compute = get_object_or_404(Compute, pk=compute_id) @@ -203,6 +224,13 @@ def get_compute_video_models(request, compute_id, arch, machine): def get_dom_capabilities(request, compute_id, arch, machine): + """ + :param request: + :param compute_id: + :param arch: + :param machine: + :return: + """ data = dict() try: compute = get_object_or_404(Compute, pk=compute_id) diff --git a/console/views.py b/console/views.py index cc4358a..bdfddd5 100644 --- a/console/views.py +++ b/console/views.py @@ -1,10 +1,10 @@ import re from django.shortcuts import render +from libvirt import libvirtError from instances.models import Instance from vrtManager.instance import wvmInstance from webvirtcloud.settings import WS_PUBLIC_PORT from webvirtcloud.settings import WS_PUBLIC_HOST -from libvirt import libvirtError def console(request): diff --git a/create/views.py b/create/views.py index 0c84bea..30e2475 100644 --- a/create/views.py +++ b/create/views.py @@ -1,14 +1,18 @@ +from django.contrib import messages from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect from django.utils.translation import ugettext_lazy as _ from django.urls import reverse +from libvirt import libvirtError +from admin.decorators import superuser_only from computes.models import Compute from create.models import Flavor from create.forms import FlavorAddForm, NewVMForm from instances.models import Instance from vrtManager.create import wvmCreate from vrtManager import util -from libvirt import libvirtError +from logs.views import addlogmsg + from webvirtcloud.settings import QEMU_CONSOLE_LISTEN_ADDRESSES from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_CACHE from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_BUS @@ -21,14 +25,14 @@ from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_DISCARD from webvirtcloud.settings import INSTANCE_ARCH_DEFAULT_TYPE from webvirtcloud.settings import INSTANCE_FIRMWARE_DEFAULT_TYPE -from django.contrib import messages -from logs.views import addlogmsg -from admin.decorators import superuser_only - @superuser_only def create_instance_select_type(request, compute_id): - + """ + :param request: + :param compute_id: + :return: + """ conn = None error_messages = list() storages = list() diff --git a/datasource/views.py b/datasource/views.py index a3d3521..6f6078c 100644 --- a/datasource/views.py +++ b/datasource/views.py @@ -1,17 +1,22 @@ +import json +import socket from django.shortcuts import render from django.http import HttpResponse, Http404 +from libvirt import libvirtError from accounts.models import UserInstance, UserSSHKey from instances.models import Instance from vrtManager.instance import wvmInstance -from libvirt import libvirtError -import json -import socket + OS_VERSIONS = ['latest', ''] OS_UUID = "iid-dswebvirtcloud" def os_index(request): + """ + :param request: + :return: + """ response = '\n'.join(OS_VERSIONS) return HttpResponse(response) @@ -59,6 +64,10 @@ def os_userdata(request, version): def get_client_ip(request): + """ + :param request: + :return: + """ x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: ip = x_forwarded_for.split(',')[-1].strip() @@ -68,6 +77,10 @@ def get_client_ip(request): def get_hostname_by_ip(ip): + """ + :param ip: + :return: + """ try: addrs = socket.gethostbyaddr(ip) except: @@ -76,6 +89,11 @@ def get_hostname_by_ip(ip): def get_vdi_url(request, vname): + """ + :param request: + :param vname: + :return: + """ instance = Instance.objects.get(name=vname) compute = instance.compute data = {} @@ -90,8 +108,6 @@ def get_vdi_url(request, vname): url = "{}://{}:{}".format(conn.get_console_type(), fqdn, conn.get_console_port()) response = url return HttpResponse(response) - except libvirtError as lib_err: err = "Error getting vdi url for {}".format(vname) raise Http404(err) - diff --git a/instances/views.py b/instances/views.py index aa84f7d..0a7cf75 100644 --- a/instances/views.py +++ b/instances/views.py @@ -128,15 +128,15 @@ def instance(request, compute_id, vname): if size_str == '': return 0 size_str = size_str.upper().replace("B", "") - if 'K' == size_str[-1]: + if size_str[-1] == 'K': return int(float(size_str[:-1])) << 10 - elif 'M' == size_str[-1]: + elif size_str[-1] == 'M': return int(float(size_str[:-1])) << 20 - elif 'G' == size_str[-1]: + elif size_str[-1] == 'G': return int(float(size_str[:-1])) << 30 - elif 'T' == size_str[-1]: + elif size_str[-1] == 'T': return int(float(size_str[:-1])) << 40 - elif 'P' == size_str[-1]: + elif size_str[-1] == 'P': return int(float(size_str[:-1])) << 50 else: return int(float(size_str)) @@ -585,9 +585,9 @@ def instance(request, compute_id, vname): if new_bus != bus: conn.detach_disk(target_dev) conn.attach_disk(new_target_dev, new_path, target_bus=new_bus, - driver_type=format, cache_mode=cache, - readonly=readonly, shareable=shareable, serial=serial, - io_mode=io, discard_mode=discard, detect_zeroes_mode=zeroes) + driver_type=format, cache_mode=cache, + readonly=readonly, shareable=shareable, serial=serial, + io_mode=io, discard_mode=discard, detect_zeroes_mode=zeroes) else: conn.edit_disk(target_dev, new_path, readonly, shareable, new_bus, serial, format, cache, io, discard, zeroes) @@ -635,7 +635,7 @@ def instance(request, compute_id, vname): if 'add_cdrom' in request.POST and allow_admin_or_not_template: bus = request.POST.get('bus', 'ide' if machine == 'pc' else 'sata') target = get_new_disk_dev(media, disks, bus) - conn.attach_disk(target, "", disk_device='cdrom', cache_mode='none', target_bus=bus, readonly=True) + conn.attach_disk(target, "", disk_device='cdrom', cache_mode='none', target_bus=bus, readonly=True) msg = _('Add CD-ROM: ' + target) addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#disks') @@ -1433,4 +1433,3 @@ def delete_instance(instance, delete_disk=False): except libvirtError as lib_err: print("Error removing instance {} on compute {}".format(instance_name, compute.hostname)) raise lib_err - diff --git a/nwfilters/views.py b/nwfilters/views.py index 00b7e4f..2d5dd40 100644 --- a/nwfilters/views.py +++ b/nwfilters/views.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse @@ -110,7 +107,12 @@ def nwfilters(request, compute_id): def nwfilter(request, compute_id, nwfltr): - + """ + :param request: + :param compute_id: + :param nwfltr: + :return: + """ error_messages = [] nwfilters_all = [] compute = get_object_or_404(Compute, pk=compute_id) diff --git a/storages/views.py b/storages/views.py index 9f2215c..cf6e6c4 100644 --- a/storages/views.py +++ b/storages/views.py @@ -1,3 +1,4 @@ +import json from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect, HttpResponse from django.utils.translation import ugettext_lazy as _ @@ -7,7 +8,6 @@ from storages.forms import AddStgPool, AddImage, CloneImage from vrtManager.storage import wvmStorage, wvmStorages from libvirt import libvirtError from django.contrib import messages -import json from admin.decorators import superuser_only @@ -200,6 +200,12 @@ def storage(request, compute_id, pool): def get_volumes(request, compute_id, pool): + """ + :param request: + :param compute_id: compute id + :param pool: pool name + :return: volumes list of pool + """ data = {} compute = get_object_or_404(Compute, pk=compute_id) try: diff --git a/vrtManager/connection.py b/vrtManager/connection.py index 9639909..3acd715 100644 --- a/vrtManager/connection.py +++ b/vrtManager/connection.py @@ -18,6 +18,8 @@ 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 @@ -309,12 +311,12 @@ class wvmConnectionManager(object): socket_host.settimeout(1) if conn_type == CONN_SSH: if ':' in hostname: - LIBVIRT_HOST, PORT = hostname.split(":") + libvirt_host, PORT = hostname.split(":") PORT = int(PORT) else: PORT = SSH_PORT - LIBVIRT_HOST = hostname - socket_host.connect((LIBVIRT_HOST, PORT)) + libvirt_host = hostname + socket_host.connect((libvirt_host, PORT)) if conn_type == CONN_TCP: socket_host.connect((hostname, TCP_PORT)) if conn_type == CONN_TLS: @@ -387,7 +389,7 @@ class wvmConnect(object): result = dict() xml = self.get_dom_cap_xml(arch, machine) - result["path"] = util.get_xml_path(xml,"/domainCapabilities/path") + result["path"] = util.get_xml_path(xml, "/domainCapabilities/path") result["domain"] = util.get_xml_path(xml, "/domainCapabilities/domain") result["machine"] = util.get_xml_path(xml, "/domainCapabilities/machine") result["vcpu_max"] = util.get_xml_path(xml, "/domainCapabilities/vcpu/@max") @@ -431,6 +433,9 @@ class wvmConnect(object): return result def get_version(self): + """ + :return: libvirt version + """ ver = self.wvm.getVersion() major = ver // 1000000 ver = ver % 1000000 @@ -449,10 +454,15 @@ class wvmConnect(object): return f"{major}.{minor}.{release}" def is_kvm_supported(self): - """Return KVM capabilities.""" + """ + :return: kvm support or not + """ return util.is_kvm_available(self.get_cap_xml()) def get_storages(self, only_actives=False): + """ + :return: list of active or all storages + """ storages = [] for pool in self.wvm.listStoragePools(): storages.append(pool) @@ -462,6 +472,9 @@ class wvmConnect(object): return storages def get_networks(self): + """ + :return: list of networks + """ virtnet = [] for net in self.wvm.listNetworks(): virtnet.append(net) @@ -470,6 +483,9 @@ class wvmConnect(object): return virtnet def get_ifaces(self): + """ + :return: list of network interfaces + """ interface = [] for inface in self.wvm.listInterfaces(): interface.append(inface) @@ -478,13 +494,18 @@ class wvmConnect(object): return interface def get_nwfilters(self): + """ + :return: list of network filters + """ nwfilters = [] for nwfilter in self.wvm.listNWFilters(): nwfilters.append(nwfilter) return nwfilters def get_cache_modes(self): - """Get cache available modes""" + """ + :return: Get cache available modes + """ return { 'default': 'Default', 'none': 'Disabled', @@ -495,7 +516,9 @@ class wvmConnect(object): } def get_io_modes(self): - """Get io threads available modes""" + """ + :return: available io modes + """ return { 'default': 'Default', 'native': 'Native', @@ -503,7 +526,9 @@ class wvmConnect(object): } def get_discard_modes(self): - """Get discard available modes""" + """ + :return: available discard modes + """ return { 'default': 'Default', 'ignore': 'Ignore', @@ -511,7 +536,9 @@ class wvmConnect(object): } def get_detect_zeroes_modes(self): - """Get detect zeroes available modes""" + """ + :return: available detect zeroes modes + """ return { 'default': 'Default', 'on': 'On', @@ -520,7 +547,9 @@ class wvmConnect(object): } def get_hypervisors_domain_types(self): - """Return hypervisor type""" + """ + :return: hypervisor domain types + """ def hypervisors(ctx): result = {} for arch in ctx.xpath('/capabilities/guest/arch'): @@ -531,7 +560,9 @@ class wvmConnect(object): return util.get_xml_path(self.get_cap_xml(), func=hypervisors) def get_hypervisors_machines(self): - """Return hypervisor and its machine types""" + """ + :return: hypervisor and its machine types + """ def machines(ctx): result = dict() for arche in ctx.xpath('/capabilities/guest/arch'): @@ -542,11 +573,15 @@ class wvmConnect(object): return util.get_xml_path(self.get_cap_xml(), func=machines) def get_emulator(self, arch): - """Return emulator """ + """ + :return: emulator list + """ return util.get_xml_path(self.get_cap_xml(), "/capabilities/guest/arch[@name='{}']/emulator".format(arch)) def get_machine_types(self, arch): - """Return canonical(if exist) name of machine types """ + """ + :return: canonical(if exist) name of machine types + """ def machines(ctx): result = list() canonical_name = ctx.xpath("/capabilities/guest/arch[@name='{}']/machine[@canonical]".format(arch)) @@ -559,6 +594,9 @@ class wvmConnect(object): return util.get_xml_path(self.get_cap_xml(), func=machines) def get_emulators(self): + """ + :return: host emulators list + """ def emulators(ctx): result = {} for arch in ctx.xpath('/capabilities/guest/arch'): @@ -569,13 +607,21 @@ class wvmConnect(object): return util.get_xml_path(self.get_cap_xml(), func=emulators) def get_os_loaders(self, arch='x86_64', machine='pc'): - """Get available os loaders list""" + """ + :param arch: architecture + :param machine: + :return: available os loaders list + """ 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): - """Get available os loaders list""" + """ + :param arch: architecture + :param machine: + :return: available os loaders list + """ def get_os_loader_enums(ctx): result = dict() enums = [v for v in ctx.xpath("/domainCapabilities/os/loader[@supported='yes']/enum/@name")] @@ -586,33 +632,53 @@ class wvmConnect(object): 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): - """Get available disk bus types list""" + """ + :param machine: + :param arch: + :return: available disk bus types list + """ 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) def get_disk_device_types(self, arch, machine): - """Get available disk device type list""" + """ + :param arch: architecture + :param machine: + :return: available disk device type list + """ 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) def get_graphics_types(self, arch, machine): - """Get available graphics types """ + """ + :param arch: architecture + :param machine: + :return: available graphics types + """ def get_graphics_list(ctx): - return [ v.text for v in ctx.xpath("/domainCapabilities/devices/graphics/enum[@name='type']/value")] + 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): - """Get available cpu modes """ + """ + :param arch: architecture + :param machine: + :return: available cpu modes + """ 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): - """Get available graphics types """ + """ + :param arch: architecture + :param machine: + :return: available graphics types + """ def get_custom_list(ctx): usable_yes = "/domainCapabilities/cpu/mode[@name='custom'][@supported='yes']/model[@usable='yes']" usable_unknown = "/domainCapabilities/cpu/mode[@name='custom'][@supported='yes']/model[@usable='unknown']" @@ -622,42 +688,65 @@ class wvmConnect(object): return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_custom_list) def get_hostdev_modes(self, arch, machine): - """Get available nodedev modes """ + """ + :param arch: architecture + :param machine: + :return. available nodedev modes + """ 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): - """Get available hostdev modes """ + """ + :param arch: architecture + :param machine: + :return: available hostdev modes + """ 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): - """Get available nodedev sub system types """ + """ + :param arch: architecture + :param machine: + :return: available nodedev sub system types + """ 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): - """Get available image filename extensions""" + """ + :return: network card models + """ return ['default', 'e1000', 'virtio'] def get_image_formats(self): - """Get available image formats""" + """ + :return: available image formats + """ return ['raw', 'qcow', 'qcow2'] def get_file_extensions(self): - """Get available image filename extensions""" + """ + :return: available image filename extensions + """ return ['img', 'qcow', 'qcow2'] def get_video_models(self, arch, machine): - """ Get available graphics video types """ + """ + :param arch: architecture + :param machine: + :return: available graphics video types + """ def get_video_list(ctx): result = [] for video_enum in ctx.xpath('/domainCapabilities/devices/video/enum'): if video_enum.xpath("@name")[0] == "modelType": - for values in video_enum: result.append(values.text) + 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) @@ -804,7 +893,7 @@ class wvmConnect(object): return loaders = self.get_os_loaders(arch, machine) - patterns = util.uefi_arch_patterns.get(arch) + patterns = util.UEFI_ARCH_PATTERNS.get(arch) for pattern in patterns: for path in loaders: if re.match(pattern, path): @@ -820,11 +909,10 @@ class wvmConnect(object): return "BIOS" return - for arch, patterns in util.uefi_arch_patterns.items(): + for arch, patterns in util.UEFI_ARCH_PATTERNS.items(): for pattern in patterns: if re.match(pattern, path): - return ("UEFI %(arch)s: %(path)s" % - {"arch": arch, "path": path}) + return ("UEFI %(arch)s: %(path)s" % {"arch": arch, "path": path}) return "Custom: %(path)s" % {"path": path} @@ -832,7 +920,7 @@ class wvmConnect(object): """ Return True if we know how to setup UEFI for the passed arch """ - return arch in list(util.uefi_arch_patterns.keys()) + return arch in list(util.UEFI_ARCH_PATTERNS.keys()) def supports_uefi_xml(self, loader_enums): """ @@ -854,4 +942,3 @@ class wvmConnect(object): return True return False - diff --git a/vrtManager/create.py b/vrtManager/create.py index f4e0faf..8c6d2cf 100644 --- a/vrtManager/create.py +++ b/vrtManager/create.py @@ -210,7 +210,7 @@ class wvmCreate(wvmConnect): xml += """""" if 'pae' in caps["features"]: xml += """""" - if 'yes' == firmware.get("secure", 'no'): + if firmware.get("secure", 'no') == 'yes': xml += """""" xml += """""" diff --git a/vrtManager/hostdetails.py b/vrtManager/hostdetails.py index 9a88853..09c894f 100644 --- a/vrtManager/hostdetails.py +++ b/vrtManager/hostdetails.py @@ -18,7 +18,7 @@ class wvmHostDetails(wvmConnect): """ all_mem = self.wvm.getInfo()[1] * 1048576 freemem = self.wvm.getMemoryStats(-1, 0) - if type(freemem) == dict: + if isinstance(dict, freemem): free = (freemem['buffers'] + freemem['free'] + freemem['cached']) * 1024 @@ -36,7 +36,7 @@ class wvmHostDetails(wvmConnect): prev_idle = 0 prev_total = 0 cpu = self.wvm.getCPUStats(-1, 0) - if type(cpu) == dict: + if isinstance(dict, cpu): for num in range(2): idle = self.wvm.getCPUStats(-1, 0)['idle'] total = sum(self.wvm.getCPUStats(-1, 0).values()) @@ -66,7 +66,3 @@ class wvmHostDetails(wvmConnect): info.append(get_xml_path(self.wvm.getSysinfo(0), func=cpu_version)) # cpu version info.append(self.wvm.getURI()) # uri return info - - - - diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 869d577..fe46d58 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -15,11 +15,11 @@ try: except: from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE -from vrtManager import util from xml.etree import ElementTree from lxml import etree from datetime import datetime from collections import OrderedDict +from vrtManager import util from vrtManager.connection import wvmConnect from vrtManager.storage import wvmStorage, wvmStorages from webvirtcloud.settings import QEMU_CONSOLE_TYPES @@ -224,19 +224,19 @@ class wvmInstance(wvmConnect): def get_loader(self): xml = self._XMLDesc(0) loader = util.get_xml_path(xml, "/domain/os/loader") - type = util.get_xml_path(xml, "/domain/os/loader/@type") + loader_type = util.get_xml_path(xml, "/domain/os/loader/@type") readonly = util.get_xml_path(xml, "/domain/os/loader/@readonly") - return {"loader": loader, "type": type, "readonly": readonly} + return {"loader": loader, "type": loader_type, "readonly": readonly} def get_vcpus(self): vcpus = OrderedDict() tree = etree.fromstring(self._XMLDesc(0)) for vcpu in tree.xpath("/domain/vcpus/vcpu"): - id = vcpu.get("id") + vcpu_id = vcpu.get("id") enabled = vcpu.get("enabled") hotplug = vcpu.get("hotpluggable") order = vcpu.get("order") - vcpus[id] = {"enabled": enabled, "hotpluggable": hotplug, "order": order} + vcpus[vcpu_id] = {"enabled": enabled, "hotpluggable": hotplug, "order": order} return vcpus @@ -325,7 +325,7 @@ class wvmInstance(wvmConnect): # ("Calling interfaceAddresses source=%s", source) try: return self.instance.interfaceAddresses(source) - except Exception as e: + except libvirtError as e: # log.debug("interfaceAddresses failed: %s", str(e)) pass return {} @@ -370,7 +370,7 @@ class wvmInstance(wvmConnect): try: ipv4, ipv6 = self.get_interface_addresses(mac_inst) - except: + except libvirtError: ipv4, ipv6 = None, None result.append({'mac': mac_inst, 'nic': nic_inst, @@ -644,7 +644,7 @@ class wvmInstance(wvmConnect): xmldom = ElementTree.tostring(tree).decode() self._defineXML(xmldom) - def attach_disk(self, target_dev, source, target_bus='ide', disk_type='file', + 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): @@ -896,7 +896,7 @@ class wvmInstance(wvmConnect): pass newxml = ElementTree.tostring(root).decode() return self._defineXML(newxml) - + def get_console_socket(self): socket = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics/@socket") return socket @@ -1264,7 +1264,7 @@ class wvmInstance(wvmConnect): net = self.get_network(source) bridge_name = net.bridgeName() return bridge_name - + def add_network(self, mac_address, source, source_type='net', model='virtio', nwfilter=None): bridge_name = self.get_bridge_name(source, source_type) @@ -1527,6 +1527,3 @@ class wvmInstance(wvmConnect): if state == "connected": return True return False - - - diff --git a/vrtManager/interface.py b/vrtManager/interface.py index ceaea18..f769b6c 100644 --- a/vrtManager/interface.py +++ b/vrtManager/interface.py @@ -1,7 +1,8 @@ -from vrtManager.connection import wvmConnect -from vrtManager import util from xml.etree import ElementTree from libvirt import VIR_INTERFACE_XML_INACTIVE +from vrtManager.connection import wvmConnect +from vrtManager import util + class wvmInterfaces(wvmConnect): @@ -138,7 +139,7 @@ class wvmInterface(wvmConnect): for iface in tree.findall("./bridge/"): address = state = speed = None name = iface.get('name') - type = iface.get('type') + if_type = iface.get('type') link = iface.find('link') if link is not None: state = link.get('state') @@ -146,7 +147,7 @@ class wvmInterface(wvmConnect): mac = iface.find('mac') if mac is not None: address = mac.get('address') - ifaces.append({'name': name, 'type': type, 'state': state, 'speed': speed, 'mac': address}) + ifaces.append({'name': name, 'type': if_type, 'state': state, 'speed': speed, 'mac': address}) return ifaces else: return None diff --git a/vrtManager/network.py b/vrtManager/network.py index dafc1e4..f5b04b0 100644 --- a/vrtManager/network.py +++ b/vrtManager/network.py @@ -1,11 +1,10 @@ -from vrtManager import util -from vrtManager.IPy import IP -from vrtManager.connection import wvmConnect from lxml import etree from libvirt import VIR_NETWORK_SECTION_IP_DHCP_HOST from libvirt import VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, VIR_NETWORK_UPDATE_COMMAND_DELETE, VIR_NETWORK_UPDATE_COMMAND_MODIFY from libvirt import VIR_NETWORK_UPDATE_AFFECT_LIVE, VIR_NETWORK_UPDATE_AFFECT_CONFIG - +from vrtManager import util +from vrtManager.IPy import IP +from vrtManager.connection import wvmConnect def network_size(subnet, dhcp=None): """ @@ -211,31 +210,31 @@ class wvmNetwork(wvmConnect): if ipdhcp.get('family') is None: hosts = ipdhcp.findall('./dhcp/host') for host in hosts: - ip = host.get('ip') + host_ip = host.get('ip') mac = host.get('mac') name = host.get('name', '') - result.append({'ip': ip, 'mac': mac, 'name': name}) + result.append({'ip': host_ip, 'mac': mac, 'name': name}) return result else: continue if family == 'ipv6': hosts = tree.xpath("./ip[@family='ipv6']/dhcp/host") for host in hosts: - ip = host.get('ip') - id = host.get('id') + host_ip = host.get('ip') + host_id = host.get('id') name = host.get('name', '') - result.append({'ip': ip, 'id': id, 'name': name}) + result.append({'ip': host_ip, 'id': host_id, 'name': name}) return result def modify_dhcp_range(self, range_start, range_end, family='ipv4'): if not self.is_active(): tree = etree.fromstring(self._XMLDesc(0)) if family == 'ipv4': - range = tree.xpath("./ip[not(@family='ipv6')]/dhcp/range") + dhcp_range = tree.xpath("./ip[not(@family='ipv6')]/dhcp/range") if family == 'ipv6': - range = tree.xpath("./ip[@family='ipv6']/dhcp/range") - range[0].set('start', range_start) - range[0].set('end', range_end) + dhcp_range = tree.xpath("./ip[@family='ipv6']/dhcp/range") + dhcp_range[0].set('start', range_start) + dhcp_range[0].set('end', range_end) self.wvm.networkDefineXML(etree.tostring(tree).decode()) def delete_fixed_address(self, ip, family='ipv4'): diff --git a/vrtManager/nwfilters.py b/vrtManager/nwfilters.py index 901aa6f..f0a89a5 100644 --- a/vrtManager/nwfilters.py +++ b/vrtManager/nwfilters.py @@ -1,5 +1,5 @@ -from vrtManager.connection import wvmConnect from xml.etree import ElementTree +from vrtManager.connection import wvmConnect class wvmNWFilters(wvmConnect): diff --git a/vrtManager/util.py b/vrtManager/util.py index ea59881..9299e21 100644 --- a/vrtManager/util.py +++ b/vrtManager/util.py @@ -1,8 +1,8 @@ import random -import lxml.etree as etree -import libvirt import string import re +import lxml.etree as etree +import libvirt def is_kvm_available(xml): @@ -108,7 +108,7 @@ def get_xpath(doc, path): ret = doc.xpath(path) if ret is not None: - if type(ret) == list: + if isinstance(list, ret): if len(ret) >= 1: if hasattr(ret[0], 'text'): result = ret[0].text @@ -137,7 +137,7 @@ def pretty_bytes(val): def validate_uuid(val): - if type(val) is not str: + if not isinstance(str, val): raise ValueError("UUID must be a string.") form = re.match("[a-fA-F0-9]{8}[-]([a-fA-F0-9]{4}[-]){3}[a-fA-F0-9]{12}$", @@ -146,9 +146,9 @@ def validate_uuid(val): form = re.match("[a-fA-F0-9]{32}$", val) if form is None: raise ValueError( - "UUID must be a 32-digit hexadecimal number. It may take " - "the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx or may " - "omit hyphens altogether.") + "UUID must be a 32-digit hexadecimal number. It may take " + "the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx or may " + "omit hyphens altogether.") else: # UUID had no dashes, so add them in val = (val[0:8] + "-" + val[8:12] + "-" + val[12:16] + @@ -171,7 +171,7 @@ def validate_macaddr(val): # Mapping of UEFI binary names to their associated architectures. We # only use this info to do things automagically for the user, it shouldn't # validate anything the user explicitly enters. -uefi_arch_patterns = { +UEFI_ARCH_PATTERNS = { "i686": [ r".*ovmf-ia32.*", # fedora, gerd's firmware repo ], From e911db81247f9234e39ab0baef8f457e4959f877 Mon Sep 17 00:00:00 2001 From: catborise Date: Sun, 26 Apr 2020 16:14:34 +0300 Subject: [PATCH 03/11] fix isinstance method call --- vrtManager/hostdetails.py | 4 ++-- vrtManager/util.py | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/vrtManager/hostdetails.py b/vrtManager/hostdetails.py index 09c894f..f2defa3 100644 --- a/vrtManager/hostdetails.py +++ b/vrtManager/hostdetails.py @@ -18,7 +18,7 @@ class wvmHostDetails(wvmConnect): """ all_mem = self.wvm.getInfo()[1] * 1048576 freemem = self.wvm.getMemoryStats(-1, 0) - if isinstance(dict, freemem): + if isinstance(freemem, dict): free = (freemem['buffers'] + freemem['free'] + freemem['cached']) * 1024 @@ -36,7 +36,7 @@ class wvmHostDetails(wvmConnect): prev_idle = 0 prev_total = 0 cpu = self.wvm.getCPUStats(-1, 0) - if isinstance(dict, cpu): + if isinstance(cpu, dict): for num in range(2): idle = self.wvm.getCPUStats(-1, 0)['idle'] total = sum(self.wvm.getCPUStats(-1, 0).values()) diff --git a/vrtManager/util.py b/vrtManager/util.py index 9299e21..7c9a08e 100644 --- a/vrtManager/util.py +++ b/vrtManager/util.py @@ -26,7 +26,6 @@ def randomMAC(): def randomUUID(): """Generate a random UUID.""" - u = [random.randint(0, 255) for ignore in range(0, 16)] u[6] = (u[6] & 0x0F) | (4 << 4) u[8] = (u[8] & 0x3F) | (2 << 6) @@ -108,7 +107,7 @@ def get_xpath(doc, path): ret = doc.xpath(path) if ret is not None: - if isinstance(list, ret): + if isinstance(ret, list): if len(ret) >= 1: if hasattr(ret[0], 'text'): result = ret[0].text @@ -137,11 +136,10 @@ def pretty_bytes(val): def validate_uuid(val): - if not isinstance(str, val): + if not isinstance(val, str): raise ValueError("UUID must be a string.") - form = re.match("[a-fA-F0-9]{8}[-]([a-fA-F0-9]{4}[-]){3}[a-fA-F0-9]{12}$", - val) + form = re.match("[a-fA-F0-9]{8}[-]([a-fA-F0-9]{4}[-]){3}[a-fA-F0-9]{12}$", val) if form is None: form = re.match("[a-fA-F0-9]{32}$", val) if form is None: From e72073fa79b85c39bb1a225b1ef232b1f6e43655 Mon Sep 17 00:00:00 2001 From: catborise Date: Thu, 14 May 2020 14:13:04 +0300 Subject: [PATCH 04/11] fix setting title/description function (xml -> lxml) --- vrtManager/instance.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/vrtManager/instance.py b/vrtManager/instance.py index fe46d58..14f265d 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -1139,6 +1139,12 @@ class wvmInstance(wvmConnect): uuid = tree.find('uuid') tree.remove(uuid) + options = { + 'title': clone_data.get('clone-title', ''), + 'description': clone_data.get('clone-description', ''), + } + self._set_options(tree, options) + src_nvram_path = self.get_nvram() if src_nvram_path: # Change XML for nvram @@ -1247,11 +1253,6 @@ class wvmInstance(wvmConnect): storage = self.get_wvmStorage(pool_name) storage.clone_volume(vol_name, target_file) - options = { - 'title': clone_data.get('clone-title', ''), - 'description': clone_data.get('clone-description', ''), - } - self._set_options(tree, options) self._defineXML(ElementTree.tostring(tree).decode()) return self.get_instance(clone_data['name']).UUIDString() @@ -1391,7 +1392,7 @@ class wvmInstance(wvmConnect): tree.remove(option) else: if option is None: - option = ElementTree.SubElement(tree, o) + option = etree.SubElement(tree , o) option.text = option_value def set_options(self, options): @@ -1399,10 +1400,10 @@ class wvmInstance(wvmConnect): Function change description, title """ xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) - tree = ElementTree.fromstring(xml) + tree = etree.fromstring(xml) self._set_options(tree, options) - new_xml = ElementTree.tostring(tree).decode() + new_xml = etree.tostring(tree).decode() self._defineXML(new_xml) def set_memory(self, size, flags=0): From 966da065b4633d878418226c164133a2e1eb8f45 Mon Sep 17 00:00:00 2001 From: catborise Date: Thu, 14 May 2020 16:45:37 +0300 Subject: [PATCH 05/11] get host info from compute not instance --- datasource/urls.py | 3 +-- datasource/views.py | 15 +++++++-------- instances/templates/instance.html | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/datasource/urls.py b/datasource/urls.py index ec02ad3..2979a4e 100644 --- a/datasource/urls.py +++ b/datasource/urls.py @@ -8,6 +8,5 @@ urlpatterns = [ views.os_metadata_json, name='ds_openstack_metadata'), url(r'^openstack/(?P[\w\-\.]+)/user_data$', views.os_userdata, name='ds_openstack_userdata'), - url(r'^vdi/(?P[\w\-\.]+)/$', - views.get_vdi_url, name='vdi_url'), + url(r'^vdi/(?P[0-9]+)/(?P[\w\-\.]+)/$', views.get_vdi_url, name='vdi_url'), ] diff --git a/datasource/views.py b/datasource/views.py index 6f6078c..3688d65 100644 --- a/datasource/views.py +++ b/datasource/views.py @@ -1,10 +1,10 @@ import json import socket -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404 from django.http import HttpResponse, Http404 from libvirt import libvirtError from accounts.models import UserInstance, UserSSHKey -from instances.models import Instance +from computes.models import Compute from vrtManager.instance import wvmInstance @@ -88,26 +88,25 @@ def get_hostname_by_ip(ip): return addrs[0] -def get_vdi_url(request, vname): +def get_vdi_url(request, compute_id, vname): """ :param request: :param vname: :return: """ - instance = Instance.objects.get(name=vname) - compute = instance.compute + compute = get_object_or_404(Compute, pk=compute_id) data = {} try: conn = wvmInstance(compute.hostname, compute.login, compute.password, compute.type, - instance.name) + vname) fqdn = get_hostname_by_ip(compute.hostname) - url = "{}://{}:{}".format(conn.get_console_type(), fqdn, conn.get_console_port()) + url = f"{conn.get_console_type()}://{fqdn}:{conn.get_console_port()}" response = url return HttpResponse(response) except libvirtError as lib_err: - err = "Error getting vdi url for {}".format(vname) + err = f"Error getting vdi url for {vname}" raise Http404(err) diff --git a/instances/templates/instance.html b/instances/templates/instance.html index a93dbf8..3c3a4b8 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -1817,7 +1817,7 @@ }); $(document).ready(function () { // set vdi url - $.get("{% url 'vdi_url' vname %}", function(data) { + $.get("{% url 'vdi_url' compute_id vname %}", function(data) { $("#vdi_url_input").attr("value", data); $("#vdi_url").attr("href", data); }); From d384c914a40ef90abccb9b0c84c07dc9c1d7ae1a Mon Sep 17 00:00:00 2001 From: catborise Date: Thu, 14 May 2020 19:34:28 +0300 Subject: [PATCH 06/11] stop getting status info before instance delete to prevent domain not found error --- instances/templates/instance.html | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/instances/templates/instance.html b/instances/templates/instance.html index 3c3a4b8..dae1ee1 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -1629,7 +1629,7 @@ {% ifequal status 3 %} {% else %} -
{% csrf_token %} + {% csrf_token %}