diff --git a/accounts/apps.py b/accounts/apps.py index 446ec40..2a6f631 100644 --- a/accounts/apps.py +++ b/accounts/apps.py @@ -30,9 +30,10 @@ def create_admin(sender, **kwargs): """ Create initial admin user """ - from accounts.models import UserAttributes from django.contrib.auth.models import User + from accounts.models import UserAttributes + plan = kwargs.get("plan", []) for migration, rolled_back in plan: if ( diff --git a/accounts/views.py b/accounts/views.py index c4979bf..f973676 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -173,8 +173,7 @@ 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") @@ -195,12 +194,8 @@ 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 bdb2294..fd4ead4 100644 --- a/admin/views.py +++ b/admin/views.py @@ -1,3 +1,5 @@ +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 @@ -6,9 +8,6 @@ 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 @@ -149,8 +148,7 @@ 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 e79ab05..d816934 100644 --- a/computes/api/serializers.py +++ b/computes/api/serializers.py @@ -1,11 +1,6 @@ -from rest_framework import serializers from computes.models import Compute -from vrtManager.connection import ( - CONN_SOCKET, - CONN_SSH, - CONN_TCP, - CONN_TLS, -) +from rest_framework import serializers +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 df960cb..4d0b1f9 100644 --- a/computes/api/viewsets.py +++ b/computes/api/viewsets.py @@ -1,10 +1,9 @@ from computes.models import Compute -from rest_framework import viewsets -from rest_framework import permissions - -from vrtManager.create import wvmCreate -from .serializers import ComputeSerializer +from rest_framework import permissions, viewsets from rest_framework.response import Response +from vrtManager.create import wvmCreate + +from .serializers import ComputeSerializer class ComputeViewSet(viewsets.ModelViewSet): diff --git a/computes/utils.py b/computes/utils.py index 881f5eb..80fec5a 100644 --- a/computes/utils.py +++ b/computes/utils.py @@ -12,4 +12,6 @@ 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 0883b54..e31cc1a 100644 --- a/computes/views.py +++ b/computes/views.py @@ -1,20 +1,12 @@ 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 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 libvirt import libvirtError from vrtManager.connection import ( CONN_SOCKET, CONN_SSH, @@ -25,6 +17,14 @@ 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,7 +45,8 @@ 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( @@ -82,9 +83,7 @@ def instances(request, compute_id): ) return render( - request, - "computes/instances.html", - {"compute": compute, "instances": instances} + request, "computes/instances.html", {"compute": compute, "instances": instances} ) diff --git a/datasource/views.py b/datasource/views.py index ce74650..bbdd27a 100644 --- a/datasource/views.py +++ b/datasource/views.py @@ -1,15 +1,13 @@ 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" @@ -100,11 +98,7 @@ 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 dab19aa..39d0c0d 100644 --- a/instances/api/serializers.py +++ b/instances/api/serializers.py @@ -1,7 +1,6 @@ +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 9a42619..587c0b0 100644 --- a/instances/api/viewsets.py +++ b/instances/api/viewsets.py @@ -1,33 +1,31 @@ -from django.shortcuts import get_object_or_404 from appsettings.settings import app_settings -from computes.models import Compute from computes import utils +from computes.models import Compute +from django.shortcuts import get_object_or_404 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 ( - poweron, + force_off, + get_instance, powercycle, poweroff, - force_off, - suspend, + poweron, resume, - destroy as instance_destroy, + suspend, ) - -from rest_framework import status, viewsets, permissions +from rest_framework import permissions, status, viewsets from rest_framework.decorators import action from rest_framework.response import Response - from vrtManager import util - from vrtManager.create import wvmCreate + from .serializers import ( - FlavorSerializer, - InstanceSerializer, - InstanceDetailsSerializer, - MigrateSerializer, CreateInstanceSerializer, + FlavorSerializer, + InstanceDetailsSerializer, + InstanceSerializer, + MigrateSerializer, ) @@ -40,14 +38,16 @@ 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,7 +190,9 @@ 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) @@ -227,7 +229,9 @@ 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 d9f09b3..a3ef884 100644 --- a/instances/forms.py +++ b/instances/forms.py @@ -1,9 +1,8 @@ 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 1488b7e..2946715 100644 --- a/instances/models.py +++ b/instances/models.py @@ -1,12 +1,10 @@ +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 webvirtcloud.settings import QEMU_CONSOLE_LISTENER_ADDRESSES - -from computes.models import Compute from vrtManager.instance import wvmInstance +from webvirtcloud.settings import QEMU_CONSOLE_LISTENER_ADDRESSES class Flavor(models.Model): @@ -210,14 +208,10 @@ 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")) @@ -234,9 +228,7 @@ 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 ef979b0..3b018bb 100644 --- a/instances/views.py +++ b/instances/views.py @@ -3,8 +3,8 @@ import json import os import re import socket -import time import subprocess +import time from bisect import insort from accounts.models import UserInstance, UserSSHKey @@ -20,12 +20,8 @@ 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 instances.models import Instance -from libvirt import ( - VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, - VIR_DOMAIN_UNDEFINE_NVRAM, - libvirtError, -) +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 @@ -34,6 +30,8 @@ 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 90c4ee0..7ef2b2d 100644 --- a/interfaces/forms.py +++ b/interfaces/forms.py @@ -6,89 +6,103 @@ 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 36e9b3e..ec82ea5 100644 --- a/interfaces/views.py +++ b/interfaces/views.py @@ -1,3 +1,4 @@ +import contextlib from django.contrib import messages from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect @@ -28,10 +29,10 @@ def interfaces(request, compute_id): compute.type ) ifaces = conn.get_ifaces() - try: + + netdevs = ["eth0", "eth1"] + with contextlib.suppress(Exception): 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 61f5a8d..eb2588b 100644 --- a/networks/api/serializers.py +++ b/networks/api/serializers.py @@ -1,5 +1,5 @@ -from rest_framework import serializers from networks.models import Networks +from rest_framework import serializers class NetworksSerializer(serializers.ModelSerializer): diff --git a/networks/api/viewsets.py b/networks/api/viewsets.py index 892511d..fc7321a 100644 --- a/networks/api/viewsets.py +++ b/networks/api/viewsets.py @@ -1,26 +1,28 @@ -from django.shortcuts import get_object_or_404 from computes.models import Compute -from rest_framework import status, viewsets - +from django.shortcuts import get_object_or_404 +from rest_framework import viewsets +from rest_framework.response import Response 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 5c014cf..1776dd8 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 bb95741..0ca9d0e 100644 --- a/networks/views.py +++ b/networks/views.py @@ -1,15 +1,15 @@ +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 admin.decorators import superuser_only -from computes.models import Compute -from networks.forms import AddNetPool from vrtManager.network import network_size, wvmNetwork, wvmNetworks +from networks.forms import AddNetPool + @superuser_only def networks(request, compute_id): diff --git a/storages/api/viewsets.py b/storages/api/viewsets.py index 023aaf9..b37e478 100644 --- a/storages/api/viewsets.py +++ b/storages/api/viewsets.py @@ -1,36 +1,40 @@ -from django.shortcuts import get_object_or_404 +from appsettings.settings import app_settings from computes.models import Compute +from django.shortcuts import get_object_or_404 from rest_framework import status, viewsets from rest_framework.decorators import action -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 vrtManager.storage import wvmStorage, wvmStorages +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(), @@ -40,48 +44,57 @@ 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): @@ -89,14 +102,17 @@ 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: @@ -105,29 +121,37 @@ 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(): @@ -135,28 +159,30 @@ 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 bb65887..5518337 100644 --- a/storages/models.py +++ b/storages/models.py @@ -1,6 +1,7 @@ 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 58fb7df..a1690ec 100644 --- a/storages/views.py +++ b/storages/views.py @@ -1,19 +1,19 @@ 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 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 +from storages.forms import AddStgPool, CloneImage, CreateVolumeForm + @superuser_only def storages(request, compute_id): @@ -28,10 +28,7 @@ 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() @@ -125,10 +122,7 @@ 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() @@ -234,11 +228,7 @@ 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() @@ -281,11 +271,7 @@ 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 adf577f..f8f96e7 100644 --- a/virtsecrets/views.py +++ b/virtsecrets/views.py @@ -1,5 +1,3 @@ -from virtsecrets.forms import AddSecret - from admin.decorators import superuser_only from computes.models import Compute from django.contrib import messages @@ -15,6 +13,8 @@ from libvirt import ( ) from vrtManager.virtsecrets import wvmSecrets +from virtsecrets.forms import AddSecret + @superuser_only def secrets(request, compute_id): @@ -36,10 +36,7 @@ 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 63a8f7a..014a70b 100644 --- a/vrtManager/create.py +++ b/vrtManager/create.py @@ -1,5 +1,5 @@ -import string import contextlib +import string from vrtManager import util from vrtManager.connection import wvmConnect diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 0ae7435..2f98cf7 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -1,27 +1,26 @@ +import contextlib import json import os.path import time try: from libvirt import ( - libvirtError, - VIR_DOMAIN_XML_SECURE, - VIR_DOMAIN_RUNNING, - VIR_DOMAIN_AFFECT_LIVE, VIR_DOMAIN_AFFECT_CONFIG, - ) - from libvirt import ( - VIR_MIGRATE_LIVE, - VIR_MIGRATE_UNSAFE, - VIR_MIGRATE_PERSIST_DEST, - VIR_MIGRATE_UNDEFINE_SOURCE, - VIR_MIGRATE_OFFLINE, - VIR_MIGRATE_COMPRESSED, + 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, ) - from libvirt import VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT - from libvirt_qemu import qemuAgentCommand, VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT + from libvirt_qemu import VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, qemuAgentCommand except: from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE @@ -496,26 +495,21 @@ class wvmInstance(wvmConnect): s_name = disk.xpath("source/@pool")[0] s = self.wvm.storagePoolLookupByName(s_name) src_file = s.storageVolLookupByName(v).path() - try: + + with contextlib.suppress(Exception): disk_format = disk.xpath("driver/@type")[0] - except: - pass - try: + + with contextlib.suppress(Exception): disk_cache = disk.xpath("driver/@cache")[0] - except: - pass - try: + + with contextlib.suppress(Exception): disk_io = disk.xpath("driver/@io")[0] - except: - pass - try: + + with contextlib.suppress(Exception): disk_discard = disk.xpath("driver/@discard")[0] - except: - pass - try: + + with contextlib.suppress(Exception): 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 @@ -572,15 +566,14 @@ class wvmInstance(wvmConnect): try: dev = media.xpath("target/@dev")[0] bus = media.xpath("target/@bus")[0] - try: + src_file = None + volume = src_file + with contextlib.suppress(Exception): 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: @@ -1083,11 +1076,10 @@ class wvmInstance(wvmConnect): graphic.set("listen", listener_addr) listen.set("address", listener_addr) else: - try: + with contextlib.suppress(Exception): graphic.attrib.pop("listen") listen.attrib.pop("address") - except: - pass + newxml = ElementTree.tostring(root).decode() return self._defineXML(newxml) @@ -1158,10 +1150,9 @@ class wvmInstance(wvmConnect): if passwd: graphic.set("passwd", passwd) else: - try: + with contextlib.suppress(Exception): graphic.attrib.pop("passwd") - except: - pass + newxml = ElementTree.tostring(root).decode() return self._defineXML(newxml) @@ -1177,10 +1168,9 @@ class wvmInstance(wvmConnect): if keymap != "auto": graphic.set("keymap", keymap) else: - try: + with contextlib.suppress(Exception): graphic.attrib.pop("keymap") - except: - pass + newxml = ElementTree.tostring(root).decode() self._defineXML(newxml) @@ -1279,10 +1269,9 @@ class wvmInstance(wvmConnect): for storage in storages: stg = self.get_storage(storage) if stg.info()[0] != 0: - try: + with contextlib.suppress(Exception): stg.refresh(0) - except: - pass + for img in stg.listVolumes(): if img.lower().endswith(".iso"): iso.append(img) @@ -1424,10 +1413,10 @@ class wvmInstance(wvmConnect): device_name = elm.get("dev") if device_name: target_file = clone_data["disk-" + device_name] - try: + meta_prealloc = False + with contextlib.suppress(Exception): meta_prealloc = clone_data["meta-" + device_name] - except: - meta_prealloc = False + elm.set("dev", device_name) elm = disk.find("source") @@ -1522,12 +1511,7 @@ 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": @@ -1588,11 +1572,7 @@ 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 a2eb777..9dbecf6 100644 --- a/vrtManager/interface.py +++ b/vrtManager/interface.py @@ -1,17 +1,29 @@ 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""" """ @@ -74,15 +86,21 @@ 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: @@ -91,15 +109,21 @@ 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: @@ -133,7 +157,15 @@ 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 b55aa5f..7aff7b5 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_volume_details(self, volname): + def get_volumes_details(self): with contextlib.suppress(Exception): self.refresh()