diff --git a/accounts/apps.py b/accounts/apps.py index 2a6f631..446ec40 100644 --- a/accounts/apps.py +++ b/accounts/apps.py @@ -30,9 +30,8 @@ def create_admin(sender, **kwargs): """ Create initial admin user """ - from django.contrib.auth.models import User - from accounts.models import UserAttributes + from django.contrib.auth.models import User plan = kwargs.get("plan", []) for migration, rolled_back in plan: diff --git a/accounts/views.py b/accounts/views.py index f973676..c4979bf 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -173,7 +173,8 @@ def email_otp(request): send_email_with_otp(user, device) messages.success( - request, _("OTP Sent to %(email)s") % {"email": form.cleaned_data["email"]} + request, + _("OTP Sent to %(email)s") % {"email": form.cleaned_data["email"]} ) return redirect("accounts:login") @@ -194,8 +195,12 @@ def admin_email_otp(request, user_id): if user.email != "": send_email_with_otp(user, device) messages.success( - request, _("OTP QR code was emailed to user %(user)s") % {"user": user} + request, + _("OTP QR code was emailed to user %(user)s") % {"user": user} ) else: - messages.error(request, _("User email not set, failed to send QR code")) + messages.error( + request, + _("User email not set, failed to send QR code") + ) return redirect("accounts:account", user.id) diff --git a/admin/views.py b/admin/views.py index fd4ead4..bdb2294 100644 --- a/admin/views.py +++ b/admin/views.py @@ -1,5 +1,3 @@ -from accounts.models import Instance, UserAttributes, UserInstance -from appsettings.settings import app_settings from django.conf import settings from django.contrib import messages from django.contrib.auth import update_session_auth_hash @@ -8,6 +6,9 @@ from django.contrib.auth.models import Group, User from django.core.paginator import Paginator from django.shortcuts import get_object_or_404, redirect, render from django.utils.translation import gettext_lazy as _ + +from accounts.models import UserAttributes, UserInstance, Instance +from appsettings.settings import app_settings from logs.models import Logs from . import forms @@ -148,7 +149,8 @@ def user_update_password(request, pk): user = form.save() update_session_auth_hash(request, user) # Important! messages.success( - request, _("Password changed for %(user)s") % {"user": user.username} + request, + _("Password changed for %(user)s") % {"user": user.username} ) return redirect("admin:user_list") else: diff --git a/computes/api/serializers.py b/computes/api/serializers.py index d816934..e79ab05 100644 --- a/computes/api/serializers.py +++ b/computes/api/serializers.py @@ -1,6 +1,11 @@ -from computes.models import Compute from rest_framework import serializers -from vrtManager.connection import CONN_SOCKET, CONN_SSH, CONN_TCP, CONN_TLS +from computes.models import Compute +from vrtManager.connection import ( + CONN_SOCKET, + CONN_SSH, + CONN_TCP, + CONN_TLS, +) class ComputeSerializer(serializers.ModelSerializer): diff --git a/computes/api/viewsets.py b/computes/api/viewsets.py index 4d0b1f9..df960cb 100644 --- a/computes/api/viewsets.py +++ b/computes/api/viewsets.py @@ -1,9 +1,10 @@ from computes.models import Compute -from rest_framework import permissions, viewsets -from rest_framework.response import Response -from vrtManager.create import wvmCreate +from rest_framework import viewsets +from rest_framework import permissions +from vrtManager.create import wvmCreate from .serializers import ComputeSerializer +from rest_framework.response import Response class ComputeViewSet(viewsets.ModelViewSet): diff --git a/computes/utils.py b/computes/utils.py index 80fec5a..881f5eb 100644 --- a/computes/utils.py +++ b/computes/utils.py @@ -12,6 +12,4 @@ def refresh_instance_database(compute): names = Instance.objects.filter(compute=compute).values_list("name", flat=True) for domain in domains: if domain.name() not in names: - Instance( - compute=compute, name=domain.name(), uuid=domain.UUIDString() - ).save() + Instance( compute=compute, name=domain.name(), uuid=domain.UUIDString()).save() diff --git a/computes/views.py b/computes/views.py index 22b7c3e..0883b54 100644 --- a/computes/views.py +++ b/computes/views.py @@ -1,12 +1,20 @@ import json -from admin.decorators import superuser_only from django.http import HttpResponse from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils import timezone -from instances.models import Instance from libvirt import libvirtError + +from admin.decorators import superuser_only +from computes.forms import ( + SocketComputeForm, + SshComputeForm, + TcpComputeForm, + TlsComputeForm, +) +from computes.models import Compute +from instances.models import Instance from vrtManager.connection import ( CONN_SOCKET, CONN_SSH, @@ -17,14 +25,6 @@ from vrtManager.connection import ( ) from vrtManager.hostdetails import wvmHostDetails -from computes.forms import ( - SocketComputeForm, - SshComputeForm, - TcpComputeForm, - TlsComputeForm, -) -from computes.models import Compute - from . import utils @@ -45,8 +45,7 @@ def overview(request, compute_id): compute = get_object_or_404(Compute, pk=compute_id) status = ( "true" - if connection_manager.host_is_up(compute.type, compute.hostname) is True - else "false" + if connection_manager.host_is_up(compute.type, compute.hostname) is True else "false" ) conn = wvmHostDetails( @@ -83,7 +82,9 @@ def instances(request, compute_id): ) return render( - request, "computes/instances.html", {"compute": compute, "instances": instances} + request, + "computes/instances.html", + {"compute": compute, "instances": instances} ) @@ -138,9 +139,30 @@ def compute_graph(request, compute_id): :param compute_id: :return: """ - comp_mgr = ComputeManager(compute_id) - data = comp_mgr.compute_graph() + compute = get_object_or_404(Compute, pk=compute_id) + try: + conn = wvmHostDetails( + compute.hostname, + compute.login, + compute.password, + compute.type, + ) + current_time = timezone.now().strftime("%H:%M:%S") + cpu_usage = conn.get_cpu_usage() + mem_usage = conn.get_memory_usage() + conn.close() + except libvirtError: + cpu_usage = {"usage": 0} + mem_usage = {"usage": 0} + current_time = 0 + data = json.dumps( + { + "cpudata": cpu_usage["usage"], + "memdata": mem_usage, + "timeline": current_time, + } + ) response = HttpResponse() response["Content-Type"] = "text/javascript" response.write(data) @@ -156,8 +178,31 @@ def get_compute_disk_buses(request, compute_id, arch, machine, disk): :param disk: :return: """ - comp_mgr = ComputeManager(compute_id) - return HttpResponse(comp_mgr.get_disk_buses(arch, machine, disk)) + data = dict() + compute = get_object_or_404(Compute, pk=compute_id) + try: + conn = wvmConnect( + compute.hostname, + compute.login, + compute.password, + compute.type, + ) + + disk_device_types = conn.get_disk_device_types(arch, machine) + + if disk in disk_device_types: + if disk == "disk": + data["bus"] = sorted(disk_device_types) + elif disk == "cdrom": + data["bus"] = ["ide", "sata", "scsi"] + elif disk == "floppy": + data["bus"] = ["fdc"] + elif disk == "lun": + data["bus"] = ["scsi"] + except libvirtError: + pass + + return HttpResponse(json.dumps(data)) def get_compute_machine_types(request, compute_id, arch): @@ -167,8 +212,20 @@ def get_compute_machine_types(request, compute_id, arch): :param arch: :return: """ - comp_mgr = ComputeManager(compute_id) - return HttpResponse(comp_mgr.get_machine_types(arch)) + data = dict() + try: + compute = get_object_or_404(Compute, pk=compute_id) + conn = wvmConnect( + compute.hostname, + compute.login, + compute.password, + compute.type, + ) + data["machines"] = conn.get_machine_types(arch) + except libvirtError: + pass + + return HttpResponse(json.dumps(data)) def get_compute_video_models(request, compute_id, arch, machine): @@ -179,8 +236,20 @@ def get_compute_video_models(request, compute_id, arch, machine): :param machine: :return: """ - comp_mgr = ComputeManager(compute_id) - return HttpResponse(comp_mgr.get_video_models(arch, machine)) + data = dict() + try: + compute = get_object_or_404(Compute, pk=compute_id) + conn = wvmConnect( + compute.hostname, + compute.login, + compute.password, + compute.type, + ) + data["videos"] = conn.get_video_models(arch, machine) + except libvirtError: + pass + + return HttpResponse(json.dumps(data)) def get_dom_capabilities(request, compute_id, arch, machine): @@ -191,88 +260,18 @@ def get_dom_capabilities(request, compute_id, arch, machine): :param machine: :return: """ - comp_mgr = ComputeManager(compute_id) - return HttpResponse(comp_mgr.get_dom_capabilities(arch, machine)) - - -class ComputeManager: - def __init__(self, compute_id): - self.compute = get_object_or_404(Compute, pk=compute_id) - self.conn = wvmConnect( - self.compute.hostname, - self.compute.login, - self.compute.password, - self.compute.type, + data = dict() + try: + compute = get_object_or_404(Compute, pk=compute_id) + conn = wvmConnect( + compute.hostname, + compute.login, + compute.password, + compute.type, ) + data["videos"] = conn.get_disk_device_types(arch, machine) + data["bus"] = conn.get_disk_device_types(arch, machine) + except libvirtError: + pass - def get_video_models(self, arch, machine): - data = dict() - try: - data["videos"] = self.conn.get_video_models(arch, machine) - except libvirtError: - pass - - return json.dumps(data) - - def get_dom_capabilities(self, arch, machine): - data = dict() - try: - data["videos"] = self.conn.get_disk_device_types(arch, machine) - data["bus"] = self.conn.get_disk_device_types(arch, machine) - except libvirtError: - pass - - return json.dumps(data) - - def get_machine_types(self, arch): - data = dict() - try: - data["machines"] = self.conn.get_machine_types(arch) - except libvirtError: - pass - - return json.dumps(data) - - def get_disk_buses(self, arch, machine, disk): - data = dict() - try: - disk_device_types = self.conn.get_disk_device_types(arch, machine) - - if disk in disk_device_types: - if disk == "disk": - data["bus"] = sorted(disk_device_types) - elif disk == "cdrom": - data["bus"] = ["ide", "sata", "scsi"] - elif disk == "floppy": - data["bus"] = ["fdc"] - elif disk == "lun": - data["bus"] = ["scsi"] - except libvirtError: - pass - - return json.dumps(data) - - def compute_graph(self): - try: - conn = wvmHostDetails( - self.compute.hostname, - self.compute.login, - self.compute.password, - self.compute.type, - ) - current_time = timezone.now().strftime("%H:%M:%S") - cpu_usage = conn.get_cpu_usage() - mem_usage = conn.get_memory_usage() - conn.close() - except libvirtError: - cpu_usage = {"usage": 0} - mem_usage = {"usage": 0} - current_time = 0 - - return json.dumps( - { - "cpudata": cpu_usage["usage"], - "memdata": mem_usage, - "timeline": current_time, - } - ) + return HttpResponse(json.dumps(data)) diff --git a/datasource/views.py b/datasource/views.py index bbdd27a..ce74650 100644 --- a/datasource/views.py +++ b/datasource/views.py @@ -1,13 +1,15 @@ import json import socket +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 computes.models import Compute -from django.http import Http404, HttpResponse -from django.shortcuts import get_object_or_404, render -from libvirt import libvirtError from vrtManager.instance import wvmInstance + OS_VERSIONS = ["latest", ""] OS_UUID = "iid-dswebvirtcloud" @@ -98,7 +100,11 @@ def get_vdi_url(request, compute_id, vname): try: conn = wvmInstance( - compute.hostname, compute.login, compute.password, compute.type, vname + compute.hostname, + compute.login, + compute.password, + compute.type, + vname ) fqdn = get_hostname_by_ip(compute.hostname) diff --git a/instances/api/serializers.py b/instances/api/serializers.py index 39d0c0d..dab19aa 100644 --- a/instances/api/serializers.py +++ b/instances/api/serializers.py @@ -1,6 +1,7 @@ -from instances.models import CreateInstance, Flavor, Instance, MigrateInstance from rest_framework import serializers +from instances.models import Flavor, Instance, MigrateInstance, CreateInstance + class InstanceSerializer(serializers.ModelSerializer): class Meta: diff --git a/instances/api/viewsets.py b/instances/api/viewsets.py index 587c0b0..9a42619 100644 --- a/instances/api/viewsets.py +++ b/instances/api/viewsets.py @@ -1,31 +1,33 @@ -from appsettings.settings import app_settings -from computes import utils -from computes.models import Compute from django.shortcuts import get_object_or_404 +from appsettings.settings import app_settings +from computes.models import Compute +from computes import utils from instances.models import Flavor, Instance +from instances.views import get_instance from instances.utils import migrate_instance -from instances.views import destroy as instance_destroy from instances.views import ( - force_off, - get_instance, + poweron, powercycle, poweroff, - poweron, - resume, + force_off, suspend, + resume, + destroy as instance_destroy, ) -from rest_framework import permissions, status, viewsets + +from rest_framework import status, viewsets, permissions from rest_framework.decorators import action from rest_framework.response import Response -from vrtManager import util -from vrtManager.create import wvmCreate +from vrtManager import util + +from vrtManager.create import wvmCreate from .serializers import ( - CreateInstanceSerializer, FlavorSerializer, - InstanceDetailsSerializer, InstanceSerializer, + InstanceDetailsSerializer, MigrateSerializer, + CreateInstanceSerializer, ) @@ -38,16 +40,14 @@ class InstancesViewSet(viewsets.ViewSet): def list(self, request): - if request.user.is_superuser or request.user.has_perm( - "instances.view_instances" - ): + if request.user.is_superuser or request.user.has_perm("instances.view_instances"): queryset = Instance.objects.all().prefetch_related("userinstance_set") else: - queryset = Instance.objects.filter( - userinstance__user=request.user - ).prefetch_related("userinstance_set") + queryset = Instance.objects.filter(userinstance__user=request.user).prefetch_related("userinstance_set") serializer = InstanceSerializer( - queryset, many=True, context={"request": request} + queryset, + many=True, + context={"request": request} ) return Response(serializer.data) @@ -72,11 +72,11 @@ class InstanceViewSet(viewsets.ViewSet): utils.refresh_instance_database(compute) - queryset = Instance.objects.filter(compute=compute).prefetch_related( - "userinstance_set" - ) + queryset = Instance.objects.filter(compute=compute).prefetch_related("userinstance_set") serializer = InstanceSerializer( - queryset, many=True, context={"request": request} + queryset, + many=True, + context={"request": request} ) return Response(serializer.data) @@ -190,9 +190,7 @@ class CreateInstanceViewSet(viewsets.ViewSet): default_io = app_settings.INSTANCE_VOLUME_DEFAULT_IO default_discard = app_settings.INSTANCE_VOLUME_DEFAULT_DISCARD default_zeroes = app_settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES - default_scsi_disk_model = ( - app_settings.INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER - ) + default_scsi_disk_model = app_settings.INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER default_disk_format = app_settings.INSTANCE_VOLUME_DEFAULT_FORMAT default_disk_owner_uid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID) default_disk_owner_gid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_GID) @@ -229,9 +227,7 @@ class CreateInstanceViewSet(viewsets.ViewSet): volume_list.append(volume) if "UEFI" in serializer.validated_data["firmware"]: - firmware["loader"] = ( - serializer.validated_data["firmware"].split(":")[1].strip() - ) + firmware["loader"] = (serializer.validated_data["firmware"].split(":")[1].strip()) firmware["secure"] = "no" firmware["readonly"] = "yes" firmware["type"] = "pflash" diff --git a/instances/forms.py b/instances/forms.py index a3ef884..d9f09b3 100644 --- a/instances/forms.py +++ b/instances/forms.py @@ -1,8 +1,9 @@ import re -from appsettings.models import AppSettings from django import forms from django.utils.translation import gettext_lazy as _ + +from appsettings.models import AppSettings from webvirtcloud.settings import QEMU_CONSOLE_LISTENER_ADDRESSES, QEMU_KEYMAPS from .models import CreateInstance, Flavor diff --git a/instances/models.py b/instances/models.py index 2946715..1488b7e 100644 --- a/instances/models.py +++ b/instances/models.py @@ -1,11 +1,13 @@ -from computes.models import Compute from django.db import models from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ + from libvirt import VIR_DOMAIN_XML_SECURE -from vrtManager.instance import wvmInstance from webvirtcloud.settings import QEMU_CONSOLE_LISTENER_ADDRESSES +from computes.models import Compute +from vrtManager.instance import wvmInstance + class Flavor(models.Model): label = models.CharField(_("label"), max_length=12, unique=True) @@ -208,10 +210,14 @@ class Instance(models.Model): class MigrateInstance(models.Model): instance = models.ForeignKey( - Instance, related_name="source_host", on_delete=models.DO_NOTHING + Instance, + related_name="source_host", + on_delete=models.DO_NOTHING ) target_compute = models.ForeignKey( - Compute, related_name="target_host", on_delete=models.DO_NOTHING + Compute, + related_name="target_host", + on_delete=models.DO_NOTHING ) live = models.BooleanField(_("Live")) @@ -228,7 +234,9 @@ class MigrateInstance(models.Model): class CreateInstance(models.Model): compute = models.ForeignKey( - Compute, related_name="host", on_delete=models.DO_NOTHING + Compute, + related_name="host", + on_delete=models.DO_NOTHING ) name = models.CharField( max_length=64, diff --git a/instances/views.py b/instances/views.py index 3b018bb..ef979b0 100644 --- a/instances/views.py +++ b/instances/views.py @@ -3,8 +3,8 @@ import json import os import re import socket -import subprocess import time +import subprocess from bisect import insort from accounts.models import UserInstance, UserSSHKey @@ -20,8 +20,12 @@ from django.http import Http404, HttpResponse, JsonResponse from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from libvirt import (VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, VIR_DOMAIN_UNDEFINE_NVRAM, - libvirtError) +from instances.models import Instance +from libvirt import ( + VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, + VIR_DOMAIN_UNDEFINE_NVRAM, + libvirtError, +) from logs.views import addlogmsg from vrtManager import util from vrtManager.create import wvmCreate @@ -30,8 +34,6 @@ from vrtManager.interface import wvmInterface from vrtManager.storage import wvmStorage from vrtManager.util import randomPasswd -from instances.models import Instance - from . import utils from .forms import ConsoleForm, FlavorForm, NewVMForm from .models import Flavor diff --git a/interfaces/forms.py b/interfaces/forms.py index 7ef2b2d..90c4ee0 100644 --- a/interfaces/forms.py +++ b/interfaces/forms.py @@ -6,103 +6,89 @@ from django.utils.translation import gettext_lazy as _ class AddInterface(forms.Form): name = forms.CharField(max_length=10, required=True) - itype = forms.ChoiceField( - required=True, choices=(("bridge", "bridge"), ("ethernet", "ethernet")) - ) + itype = forms.ChoiceField(required=True, choices=(('bridge', 'bridge'), ('ethernet', 'ethernet'))) start_mode = forms.ChoiceField( required=True, - choices=(("none", "none"), ("onboot", "onboot"), ("hotplug", "hotplug")), + choices=( + ('none', 'none'), + ('onboot', 'onboot'), + ('hotplug', 'hotplug') + ) ) netdev = forms.CharField(max_length=15, required=True) ipv4_type = forms.ChoiceField( required=True, - choices=(("dhcp", "dhcp"), ("static", "static"), ("none", "none")), + choices=( + ('dhcp', 'dhcp'), + ('static', 'static'), + ('none', 'none') + ) ) ipv4_addr = forms.CharField(max_length=18, required=False) ipv4_gw = forms.CharField(max_length=15, required=False) ipv6_type = forms.ChoiceField( required=True, - choices=(("dhcp", "dhcp"), ("static", "static"), ("none", "none")), + choices=( + ('dhcp', 'dhcp'), + ('static', 'static'), + ('none', 'none') + ) ) ipv6_addr = forms.CharField(max_length=100, required=False) ipv6_gw = forms.CharField(max_length=100, required=False) - stp = forms.ChoiceField(required=False, choices=(("on", "on"), ("off", "off"))) + stp = forms.ChoiceField(required=False, choices=(('on', 'on'), ('off', 'off'))) delay = forms.IntegerField(required=False) def clean_ipv4_addr(self): - ipv4_addr = self.cleaned_data["ipv4_addr"] - have_symbol = re.match("^[0-9./]+$", ipv4_addr) + ipv4_addr = self.cleaned_data['ipv4_addr'] + have_symbol = re.match('^[0-9./]+$', ipv4_addr) if not have_symbol: - raise forms.ValidationError( - _("The IPv4 address must not contain any special characters") - ) + raise forms.ValidationError(_('The IPv4 address must not contain any special characters')) elif len(ipv4_addr) > 20: - raise forms.ValidationError( - _("The IPv4 address must not exceed 20 characters") - ) + raise forms.ValidationError(_('The IPv4 address must not exceed 20 characters')) return ipv4_addr def clean_ipv4_gw(self): - ipv4_gw = self.cleaned_data["ipv4_gw"] - have_symbol = re.match("^[0-9.]+$", ipv4_gw) + ipv4_gw = self.cleaned_data['ipv4_gw'] + have_symbol = re.match('^[0-9.]+$', ipv4_gw) if not have_symbol: - raise forms.ValidationError( - _("The IPv4 gateway must not contain any special characters") - ) + raise forms.ValidationError(_('The IPv4 gateway must not contain any special characters')) elif len(ipv4_gw) > 20: - raise forms.ValidationError( - _("The IPv4 gateway must not exceed 20 characters") - ) + raise forms.ValidationError(_('The IPv4 gateway must not exceed 20 characters')) return ipv4_gw def clean_ipv6_addr(self): - ipv6_addr = self.cleaned_data["ipv6_addr"] - have_symbol = re.match("^[0-9a-f./:]+|^$", ipv6_addr) + ipv6_addr = self.cleaned_data['ipv6_addr'] + have_symbol = re.match('^[0-9a-f./:]+|^$', ipv6_addr) if not have_symbol: - raise forms.ValidationError( - _("The IPv6 address must not contain any special characters") - ) + raise forms.ValidationError(_('The IPv6 address must not contain any special characters')) elif len(ipv6_addr) > 100: - raise forms.ValidationError( - _("The IPv6 address must not exceed 100 characters") - ) + raise forms.ValidationError(_('The IPv6 address must not exceed 100 characters')) return ipv6_addr def clean_ipv6_gw(self): - ipv6_gw = self.cleaned_data["ipv6_gw"] - have_symbol = re.match("^[0-9a-f./:]+|^$", ipv6_gw) + ipv6_gw = self.cleaned_data['ipv6_gw'] + have_symbol = re.match('^[0-9a-f./:]+|^$', ipv6_gw) if not have_symbol: - raise forms.ValidationError( - _("The IPv6 gateway must not contain any special characters") - ) + raise forms.ValidationError(_('The IPv6 gateway must not contain any special characters')) elif len(ipv6_gw) > 100: - raise forms.ValidationError( - _("The IPv6 gateway must not exceed 100 characters") - ) + raise forms.ValidationError(_('The IPv6 gateway must not exceed 100 characters')) return ipv6_gw def clean_name(self): - name = self.cleaned_data["name"] - have_symbol = re.match("^[a-z0-9.]+$", name) + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-z0-9.]+$', name) if not have_symbol: - raise forms.ValidationError( - _("The interface must not contain any special characters") - ) + raise forms.ValidationError(_('The interface must not contain any special characters')) elif len(name) > 10: - raise forms.ValidationError( - _("The interface must not exceed 10 characters") - ) + raise forms.ValidationError(_('The interface must not exceed 10 characters')) return name def clean_netdev(self): - netdev = self.cleaned_data["netdev"] - have_symbol = re.match("^[a-z0-9.:]+$", netdev) + netdev = self.cleaned_data['netdev'] + have_symbol = re.match('^[a-z0-9.:]+$', netdev) if not have_symbol: - raise forms.ValidationError( - _("The interface must not contain any special characters") - ) + raise forms.ValidationError(_('The interface must not contain any special characters')) elif len(netdev) > 10: - raise forms.ValidationError( - _("The interface must not exceed 10 characters") - ) + raise forms.ValidationError(_('The interface must not exceed 10 characters')) return netdev diff --git a/interfaces/views.py b/interfaces/views.py index ec82ea5..36e9b3e 100644 --- a/interfaces/views.py +++ b/interfaces/views.py @@ -1,4 +1,3 @@ -import contextlib from django.contrib import messages from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect @@ -29,10 +28,10 @@ def interfaces(request, compute_id): compute.type ) ifaces = conn.get_ifaces() - - netdevs = ["eth0", "eth1"] - with contextlib.suppress(Exception): + try: netdevs = conn.get_net_devices() + except: + netdevs = ["eth0", "eth1"] for iface in ifaces: interf = wvmInterface( diff --git a/networks/api/serializers.py b/networks/api/serializers.py index eb2588b..61f5a8d 100644 --- a/networks/api/serializers.py +++ b/networks/api/serializers.py @@ -1,5 +1,5 @@ -from networks.models import Networks from rest_framework import serializers +from networks.models import Networks class NetworksSerializer(serializers.ModelSerializer): diff --git a/networks/api/viewsets.py b/networks/api/viewsets.py index fc7321a..892511d 100644 --- a/networks/api/viewsets.py +++ b/networks/api/viewsets.py @@ -1,28 +1,26 @@ -from computes.models import Compute from django.shortcuts import get_object_or_404 -from rest_framework import viewsets -from rest_framework.response import Response +from computes.models import Compute +from rest_framework import status, viewsets + from vrtManager.network import wvmNetworks from .serializers import NetworksSerializer +from rest_framework.response import Response class NetworkViewSet(viewsets.ViewSet): """ A viewset for listing retrieving networks. """ - + def list(self, request, compute_pk=None): - + compute = get_object_or_404(Compute, pk=compute_pk) - - conn = wvmNetworks( - compute.hostname, compute.login, compute.password, compute.type - ) + + conn = wvmNetworks(compute.hostname, compute.login, compute.password, compute.type) queryset = conn.get_networks_info() - serializer = NetworksSerializer( - queryset, many=True, context={"request": request} - ) + serializer = NetworksSerializer(queryset, many=True, context={'request': request}) return Response(serializer.data) + diff --git a/networks/forms.py b/networks/forms.py index 1776dd8..5c014cf 100644 --- a/networks/forms.py +++ b/networks/forms.py @@ -6,7 +6,7 @@ from django.utils.translation import gettext_lazy as _ class AddNetPool(forms.Form): name = forms.CharField( - error_messages={"required": _("No pool name has been entered")}, + error_messages={"required": _("No pool name has been entered")}, max_length=20 ) subnet = forms.CharField( diff --git a/networks/views.py b/networks/views.py index 0ca9d0e..bb95741 100644 --- a/networks/views.py +++ b/networks/views.py @@ -1,14 +1,14 @@ -from admin.decorators import superuser_only -from computes.models import Compute from django.contrib import messages from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.utils.translation import gettext_lazy as _ from libvirt import libvirtError -from vrtManager.network import network_size, wvmNetwork, wvmNetworks +from admin.decorators import superuser_only +from computes.models import Compute from networks.forms import AddNetPool +from vrtManager.network import network_size, wvmNetwork, wvmNetworks @superuser_only diff --git a/storages/api/viewsets.py b/storages/api/viewsets.py index b37e478..023aaf9 100644 --- a/storages/api/viewsets.py +++ b/storages/api/viewsets.py @@ -1,40 +1,36 @@ -from appsettings.settings import app_settings -from computes.models import Compute from django.shortcuts import get_object_or_404 +from computes.models import Compute from rest_framework import status, viewsets from rest_framework.decorators import action -from rest_framework.response import Response -from vrtManager.storage import wvmStorage, wvmStorages +from appsettings.settings import app_settings + +from vrtManager.storage import wvmStorages, wvmStorage + +from .serializers import StoragesSerializer, StorageSerializer, VolumeSerializer +from rest_framework.response import Response -from .serializers import StorageSerializer, StoragesSerializer, VolumeSerializer class StorageViewSet(viewsets.ViewSet): """ A viewset for listing retrieving storages. """ - + def list(self, request, compute_pk=None): - + compute = get_object_or_404(Compute, pk=compute_pk) - - conn = wvmStorages( - compute.hostname, compute.login, compute.password, compute.type - ) + + conn = wvmStorages(compute.hostname, compute.login, compute.password, compute.type) queryset = conn.get_storages_info() - serializer = StoragesSerializer( - queryset, many=True, context={"request": request} - ) + serializer = StoragesSerializer(queryset, many=True, context={'request': request}) return Response(serializer.data) - + def retrieve(self, request, pk=None, compute_pk=None): compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pk) infoset = { "state": conn.is_active(), @@ -44,57 +40,48 @@ class StorageViewSet(viewsets.ViewSet): "path": conn.get_target_path(), "type": conn.get_type(), "autostart": conn.get_autostart(), - "volumes": conn.update_volumes(), + "volumes": conn.update_volumes() } - serializer = StorageSerializer( - infoset, many=False, context={"request": request} - ) + serializer = StorageSerializer(infoset, many=False, context={'request': request}) return Response(serializer.data) - @action(detail=True, methods=["post"]) + + @action(detail=True, methods=['post']) def start(self, request, pk=None, compute_pk=None): compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pk) ret = conn.start() conn.close() - return Response({"status": "Pool start command send: " + str(ret)}) + return Response({'status': 'Pool start command send: ' + str(ret)}) - @action(detail=True, methods=["post"]) + @action(detail=True, methods=['post']) def stop(self, request, pk=None, compute_pk=None): compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pk) ret = conn.stop() conn.close() - return Response({"status": "Pool stop command send: " + str(ret)}) + return Response({'status': 'Pool stop command send: ' + str(ret)}) - @action(detail=True, methods=["post"]) + @action(detail=True, methods=['post']) def refresh(self, request, pk=None, compute_pk=None): compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pk) ret = conn.refresh() conn.close() - return Response({"status": "Pool refresh command send: " + str(ret)}) + return Response({'status': 'Pool refresh command send: ' + str(ret)}) - @action(detail=True, methods=["post"]) + @action(detail=True, methods=['post']) def XML_description(self, request, pk=None, compute_pk=None): compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pk) ret = conn._XMLDesc(0) conn.close() - return Response({"return": str(ret)}) + return Response({'return': str(ret)}) class VolumeViewSet(viewsets.ViewSet): @@ -102,17 +89,14 @@ class VolumeViewSet(viewsets.ViewSet): """ A simple ViewSet for listing or retrieving Storage Volumes. """ - serializer_class = VolumeSerializer lookup_value_regex = "[^/]+" def list(self, request, storage_pk=None, compute_pk=None): - + compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, storage_pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, storage_pk) state = conn.is_active() if state: @@ -121,37 +105,29 @@ class VolumeViewSet(viewsets.ViewSet): else: volume_queryset = None conn.close() - serializer = VolumeSerializer( - volume_queryset, many=True, context={"request": request} - ) + serializer = VolumeSerializer(volume_queryset, many=True, context={'request': request}) return Response(serializer.data) def retrieve(self, request, storage_pk=None, compute_pk=None, pk=None): compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, storage_pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, storage_pk) state = conn.is_active() - + if state: volume_queryset = conn.get_volume_details(pk) else: volume_queryset = None conn.close() - serializer = VolumeSerializer( - volume_queryset, many=False, context={"request": request} - ) + serializer = VolumeSerializer(volume_queryset, many=False, context={'request': request}) return Response(serializer.data) def create(self, request, storage_pk=None, compute_pk=None): compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, storage_pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, storage_pk) serializer = VolumeSerializer(data=request.data) if serializer.is_valid(): @@ -159,30 +135,28 @@ class VolumeViewSet(viewsets.ViewSet): if state: conn.refresh() ret = conn.create_volume( - serializer.validated_data["name"], - serializer.validated_data["size"], - serializer.validated_data["type"], - serializer.validated_data["meta_prealloc"], + serializer.validated_data['name'], + serializer.validated_data['size'], + serializer.validated_data['type'], + serializer.validated_data['meta_prealloc'], int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID), int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_GID), ) conn.close() - return Response({"status": "Volume: " + ret + " is created"}) + return Response({'status': 'Volume: ' + ret + ' is created'}) else: - return Response({"status": "Pool is not active"}) + return Response({'status': 'Pool is not active'}) else: - return Response({"status": "Data is not right for create volume"}) + return Response({'status': 'Data is not right for create volume'}) def destroy(self, request, storage_pk=None, compute_pk=None, pk=None): compute = get_object_or_404(Compute, pk=compute_pk) - conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, storage_pk - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, storage_pk) if conn.is_active(): conn.del_volume(pk) conn.close() - return Response({"status": "Volume: " + pk + " is deleted"}) + return Response({'status': 'Volume: ' + pk + ' is deleted'}) else: - return Response({"status": "Pool is not active"}) + return Response({'status': 'Pool is not active'}) diff --git a/storages/models.py b/storages/models.py index 5518337..bb65887 100644 --- a/storages/models.py +++ b/storages/models.py @@ -1,7 +1,6 @@ from django.db import models from django.utils.translation import gettext_lazy as _ - # Create your models here. class Storages(models.Model): name = models.CharField( diff --git a/storages/views.py b/storages/views.py index a1690ec..58fb7df 100644 --- a/storages/views.py +++ b/storages/views.py @@ -1,18 +1,18 @@ import json import os -from admin.decorators import superuser_only -from appsettings.settings import app_settings -from computes.models import Compute from django.contrib import messages from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.translation import gettext_lazy as _ from libvirt import libvirtError -from vrtManager.storage import wvmStorage, wvmStorages +from admin.decorators import superuser_only +from appsettings.settings import app_settings +from computes.models import Compute from storages.forms import AddStgPool, CloneImage, CreateVolumeForm +from vrtManager.storage import wvmStorage, wvmStorages @superuser_only @@ -28,7 +28,10 @@ def storages(request, compute_id): try: conn = wvmStorages( - compute.hostname, compute.login, compute.password, compute.type + compute.hostname, + compute.login, + compute.password, + compute.type ) storages = conn.get_storages_info() secrets = conn.get_secrets() @@ -122,7 +125,10 @@ def storage(request, compute_id, pool): form = CreateVolumeForm() conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, pool + compute.hostname, + compute.login, + compute.password, + compute.type, pool ) storages = conn.get_storages() @@ -228,7 +234,11 @@ def create_volume(request, compute_id, pool): meta_prealloc = False conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, pool + compute.hostname, + compute.login, + compute.password, + compute.type, + pool ) storages = conn.get_storages() @@ -271,7 +281,11 @@ def get_volumes(request, compute_id, pool): compute = get_object_or_404(Compute, pk=compute_id) try: conn = wvmStorage( - compute.hostname, compute.login, compute.password, compute.type, pool + compute.hostname, + compute.login, + compute.password, + compute.type, + pool ) conn.refresh() data["vols"] = sorted(conn.get_volumes()) diff --git a/virtsecrets/views.py b/virtsecrets/views.py index f8f96e7..adf577f 100644 --- a/virtsecrets/views.py +++ b/virtsecrets/views.py @@ -1,3 +1,5 @@ +from virtsecrets.forms import AddSecret + from admin.decorators import superuser_only from computes.models import Compute from django.contrib import messages @@ -13,8 +15,6 @@ from libvirt import ( ) from vrtManager.virtsecrets import wvmSecrets -from virtsecrets.forms import AddSecret - @superuser_only def secrets(request, compute_id): @@ -36,7 +36,10 @@ def secrets(request, compute_id): try: conn = wvmSecrets( - compute.hostname, compute.login, compute.password, compute.type + compute.hostname, + compute.login, + compute.password, + compute.type ) secrets = conn.get_secrets() diff --git a/vrtManager/create.py b/vrtManager/create.py index 014a70b..63a8f7a 100644 --- a/vrtManager/create.py +++ b/vrtManager/create.py @@ -1,5 +1,5 @@ -import contextlib import string +import contextlib from vrtManager import util from vrtManager.connection import wvmConnect diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 2f98cf7..0ae7435 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -1,26 +1,27 @@ -import contextlib import json import os.path import time try: from libvirt import ( - VIR_DOMAIN_AFFECT_CONFIG, - VIR_DOMAIN_AFFECT_LIVE, - VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT, - VIR_DOMAIN_RUNNING, - VIR_DOMAIN_XML_SECURE, - VIR_MIGRATE_AUTO_CONVERGE, - VIR_MIGRATE_COMPRESSED, - VIR_MIGRATE_LIVE, - VIR_MIGRATE_OFFLINE, - VIR_MIGRATE_PERSIST_DEST, - VIR_MIGRATE_POSTCOPY, - VIR_MIGRATE_UNDEFINE_SOURCE, - VIR_MIGRATE_UNSAFE, libvirtError, + VIR_DOMAIN_XML_SECURE, + VIR_DOMAIN_RUNNING, + VIR_DOMAIN_AFFECT_LIVE, + VIR_DOMAIN_AFFECT_CONFIG, ) - from libvirt_qemu import VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, qemuAgentCommand + from libvirt import ( + VIR_MIGRATE_LIVE, + VIR_MIGRATE_UNSAFE, + VIR_MIGRATE_PERSIST_DEST, + VIR_MIGRATE_UNDEFINE_SOURCE, + VIR_MIGRATE_OFFLINE, + VIR_MIGRATE_COMPRESSED, + VIR_MIGRATE_AUTO_CONVERGE, + VIR_MIGRATE_POSTCOPY, + ) + from libvirt import VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT + from libvirt_qemu import qemuAgentCommand, VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT except: from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE @@ -495,21 +496,26 @@ class wvmInstance(wvmConnect): s_name = disk.xpath("source/@pool")[0] s = self.wvm.storagePoolLookupByName(s_name) src_file = s.storageVolLookupByName(v).path() - - with contextlib.suppress(Exception): + try: disk_format = disk.xpath("driver/@type")[0] - - with contextlib.suppress(Exception): + except: + pass + try: disk_cache = disk.xpath("driver/@cache")[0] - - with contextlib.suppress(Exception): + except: + pass + try: disk_io = disk.xpath("driver/@io")[0] - - with contextlib.suppress(Exception): + except: + pass + try: disk_discard = disk.xpath("driver/@discard")[0] - - with contextlib.suppress(Exception): + except: + pass + try: disk_zeroes = disk.xpath("driver/@detect_zeroes")[0] + except: + pass readonly = True if disk.xpath("readonly") else False shareable = True if disk.xpath("shareable") else False @@ -566,14 +572,15 @@ class wvmInstance(wvmConnect): try: dev = media.xpath("target/@dev")[0] bus = media.xpath("target/@bus")[0] - src_file = None - volume = src_file - with contextlib.suppress(Exception): + try: src_file = media.xpath("source/@file")[0] vol = self.get_volume_by_path(src_file) volume = vol.name() stg = vol.storagePoolLookupByVolume() storage = stg.name() + except: + src_file = None + volume = src_file except: pass finally: @@ -1076,10 +1083,11 @@ class wvmInstance(wvmConnect): graphic.set("listen", listener_addr) listen.set("address", listener_addr) else: - with contextlib.suppress(Exception): + try: graphic.attrib.pop("listen") listen.attrib.pop("address") - + except: + pass newxml = ElementTree.tostring(root).decode() return self._defineXML(newxml) @@ -1150,9 +1158,10 @@ class wvmInstance(wvmConnect): if passwd: graphic.set("passwd", passwd) else: - with contextlib.suppress(Exception): + try: graphic.attrib.pop("passwd") - + except: + pass newxml = ElementTree.tostring(root).decode() return self._defineXML(newxml) @@ -1168,9 +1177,10 @@ class wvmInstance(wvmConnect): if keymap != "auto": graphic.set("keymap", keymap) else: - with contextlib.suppress(Exception): + try: graphic.attrib.pop("keymap") - + except: + pass newxml = ElementTree.tostring(root).decode() self._defineXML(newxml) @@ -1269,9 +1279,10 @@ class wvmInstance(wvmConnect): for storage in storages: stg = self.get_storage(storage) if stg.info()[0] != 0: - with contextlib.suppress(Exception): + try: stg.refresh(0) - + except: + pass for img in stg.listVolumes(): if img.lower().endswith(".iso"): iso.append(img) @@ -1413,10 +1424,10 @@ class wvmInstance(wvmConnect): device_name = elm.get("dev") if device_name: target_file = clone_data["disk-" + device_name] - meta_prealloc = False - with contextlib.suppress(Exception): + try: meta_prealloc = clone_data["meta-" + device_name] - + except: + meta_prealloc = False elm.set("dev", device_name) elm = disk.find("source") @@ -1511,7 +1522,12 @@ class wvmInstance(wvmConnect): return bridge_name def add_network( - self, mac_address, source, source_type="net", model="virtio", nwfilter=None + self, + mac_address, + source, + source_type="net", + model="virtio", + nwfilter=None ): if source_type == "net": @@ -1572,7 +1588,11 @@ class wvmInstance(wvmConnect): status = self.delete_network(net_mac) try: self.add_network( - net_mac, net_source, net_source_type, net_model, net_filter + net_mac, + net_source, + net_source_type, + net_model, + net_filter ) except libvirtError: if status is not None: diff --git a/vrtManager/interface.py b/vrtManager/interface.py index 9dbecf6..a2eb777 100644 --- a/vrtManager/interface.py +++ b/vrtManager/interface.py @@ -1,29 +1,17 @@ from xml.etree import ElementTree from libvirt import VIR_INTERFACE_XML_INACTIVE - from vrtManager import util from vrtManager.connection import wvmConnect class wvmInterfaces(wvmConnect): + def define_iface(self, xml, flag=0): self.wvm.interfaceDefineXML(xml, flag) def create_iface( - self, - name, - itype, - mode, - netdev, - ipv4_type, - ipv4_addr, - ipv4_gw, - ipv6_type, - ipv6_addr, - ipv6_gw, - stp, - delay, + self, name, itype, mode, netdev, ipv4_type, ipv4_addr, ipv4_gw, ipv6_type, ipv6_addr, ipv6_gw, stp, delay ): xml = f""" """ @@ -86,21 +74,15 @@ class wvmInterface(wvmConnect): def get_ipv4_type(self): try: xml = self._XMLDesc(VIR_INTERFACE_XML_INACTIVE) - ipaddr = util.get_xml_path( - xml, "/interface/protocol[@family='ipv4']/ip/@address" - ) + ipaddr = util.get_xml_path(xml, "/interface/protocol[@family='ipv4']/ip/@address") return "static" if ipaddr else "dhcp" except Exception: return None def get_ipv4(self): xml = self._XMLDesc() - int_ipv4_ip = util.get_xml_path( - xml, "/interface/protocol[@family='ipv4']/ip/@address" - ) - int_ipv4_mask = util.get_xml_path( - xml, "/interface/protocol[@family='ipv4']/ip/@prefix" - ) + int_ipv4_ip = util.get_xml_path(xml, "/interface/protocol[@family='ipv4']/ip/@address") + int_ipv4_mask = util.get_xml_path(xml, "/interface/protocol[@family='ipv4']/ip/@prefix") if not int_ipv4_ip or not int_ipv4_mask: return None else: @@ -109,21 +91,15 @@ class wvmInterface(wvmConnect): def get_ipv6_type(self): try: xml = self._XMLDesc(VIR_INTERFACE_XML_INACTIVE) - ipaddr = util.get_xml_path( - xml, "/interface/protocol[@family='ipv6']/ip/@address" - ) + ipaddr = util.get_xml_path(xml, "/interface/protocol[@family='ipv6']/ip/@address") return "static" if ipaddr else "dhcp" except Exception: return None def get_ipv6(self): xml = self._XMLDesc() - int_ipv6_ip = util.get_xml_path( - xml, "/interface/protocol[@family='ipv6']/ip/@address" - ) - int_ipv6_mask = util.get_xml_path( - xml, "/interface/protocol[@family='ipv6']/ip/@prefix" - ) + int_ipv6_ip = util.get_xml_path(xml, "/interface/protocol[@family='ipv6']/ip/@address") + int_ipv6_mask = util.get_xml_path(xml, "/interface/protocol[@family='ipv6']/ip/@prefix") if not int_ipv6_ip or not int_ipv6_mask: return None else: @@ -157,15 +133,7 @@ class wvmInterface(wvmConnect): mac = iface.find("mac") if mac is not None: address = mac.get("address") - ifaces.append( - { - "name": name, - "type": if_type, - "state": state, - "speed": speed, - "mac": address, - } - ) + ifaces.append({"name": name, "type": if_type, "state": state, "speed": speed, "mac": address}) return ifaces def get_details(self): diff --git a/vrtManager/storage.py b/vrtManager/storage.py index 7aff7b5..b55aa5f 100644 --- a/vrtManager/storage.py +++ b/vrtManager/storage.py @@ -242,7 +242,7 @@ class wvmStorage(wvmConnect): def refresh(self): return self.pool.refresh(0) - def get_volumes_details(self): + def get_volume_details(self, volname): with contextlib.suppress(Exception): self.refresh()