mirror of
				https://github.com/retspen/webvirtcloud
				synced 2025-07-31 12:41:08 +00:00 
			
		
		
		
	lint with black python. convert f style strings to old one. some small fixes
This commit is contained in:
		
							parent
							
								
									c20c353a40
								
							
						
					
					
						commit
						508e3609be
					
				
					 54 changed files with 2123 additions and 1824 deletions
				
			
		|  | @ -8,7 +8,7 @@ def apply_change_password(sender, **kwargs): | |||
|     Depending on settings SHOW_PROFILE_EDIT_PASSWORD | ||||
|     ''' | ||||
|     from django.conf import settings | ||||
|     from django.contrib.auth.models import User, Permission | ||||
|     from django.contrib.auth.models import Permission, User | ||||
|     if hasattr(settings, 'SHOW_PROFILE_EDIT_PASSWORD'): | ||||
|         print('\033[1m! \033[92mSHOW_PROFILE_EDIT_PASSWORD is found inside settings.py\033[0m') | ||||
|         print('\033[1m* \033[92mApplying permission can_change_password for all users\033[0m') | ||||
|  | @ -29,8 +29,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: | ||||
|  |  | |||
|  | @ -1,9 +1,8 @@ | |||
| # Generated by Django 2.2.10 on 2020-01-28 07:01 | ||||
| 
 | ||||
| from django.conf import settings | ||||
| import django.core.validators | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
| from django.conf import settings | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
|  |  | |||
|  | @ -1,7 +1,8 @@ | |||
| from django import template | ||||
| import base64 | ||||
| import hashlib | ||||
| 
 | ||||
| from django import template | ||||
| 
 | ||||
| register = template.Library() | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -35,11 +35,11 @@ def validate_ssh_key(key): | |||
|         return False | ||||
|     # unpack the contents of data, from data[:4] , property of ssh key . | ||||
|     try: | ||||
|         str_len = struct.unpack('>I', data[:4])[0] | ||||
|         str_len = struct.unpack(">I", data[:4])[0] | ||||
|     except struct.error: | ||||
|         return False | ||||
|     # data[4:str_len] must have string which matches with the typeofkey, another ssh key property. | ||||
|     if data[4:4 + str_len] == typeofkey: | ||||
|     if data[4 : 4 + str_len] == typeofkey: | ||||
|         return True | ||||
|     else:  | ||||
|         return False | ||||
|  | @ -47,15 +47,15 @@ def validate_ssh_key(key): | |||
| 
 | ||||
| def send_email_with_otp(user, device): | ||||
|     send_mail( | ||||
|         _('OTP QR Code'), | ||||
|         _('Please view HTML version of this message.'), | ||||
|         _("OTP QR Code"), | ||||
|         _("Please view HTML version of this message."), | ||||
|         None, | ||||
|         [user.email], | ||||
|         html_message=render_to_string( | ||||
|             'accounts/email/otp.html', | ||||
|             "accounts/email/otp.html", | ||||
|             { | ||||
|                 'totp_url': device.config_url, | ||||
|                 'user': user, | ||||
|                 "totp_url": device.config_url, | ||||
|                 "user": user, | ||||
|             }, | ||||
|         ), | ||||
|         fail_silently=False, | ||||
|  |  | |||
|  | @ -23,40 +23,52 @@ def profile(request): | |||
| 
 | ||||
|     if profile_form.is_valid(): | ||||
|         profile_form.save() | ||||
|         messages.success(request, _('Profile updated')) | ||||
|         return redirect('accounts:profile') | ||||
|         messages.success(request, _("Profile updated")) | ||||
|         return redirect("accounts:profile") | ||||
| 
 | ||||
|     return render(request, "profile.html", { | ||||
|         'publickeys': publickeys, | ||||
|         'profile_form': profile_form, | ||||
|         'ssh_key_form': ssh_key_form, | ||||
|     }) | ||||
|     return render( | ||||
|         request, | ||||
|         "profile.html", | ||||
|         { | ||||
|             "publickeys": publickeys, | ||||
|             "profile_form": profile_form, | ||||
|             "ssh_key_form": ssh_key_form, | ||||
|         }, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def ssh_key_create(request): | ||||
|     key_form = UserSSHKeyForm(request.POST or None, user=request.user) | ||||
|     if key_form.is_valid(): | ||||
|         key_form.save() | ||||
|         messages.success(request, _('SSH key added')) | ||||
|         return redirect('accounts:profile') | ||||
|         messages.success(request, _("SSH key added")) | ||||
|         return redirect("accounts:profile") | ||||
| 
 | ||||
|     return render(request, 'common/form.html', { | ||||
|         'form': key_form, | ||||
|         'title': _('Add SSH key'), | ||||
|     }) | ||||
|     return render( | ||||
|         request, | ||||
|         "common/form.html", | ||||
|         { | ||||
|             "form": key_form, | ||||
|             "title": _("Add SSH key"), | ||||
|         }, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def ssh_key_delete(request, pk): | ||||
|     ssh_key = get_object_or_404(UserSSHKey, pk=pk, user=request.user) | ||||
|     if request.method == 'POST': | ||||
|     if request.method == "POST": | ||||
|         ssh_key.delete() | ||||
|         messages.success(request, _('SSH key deleted')) | ||||
|         return redirect('accounts:profile') | ||||
|         messages.success(request, _("SSH key deleted")) | ||||
|         return redirect("accounts:profile") | ||||
| 
 | ||||
|     return render(request, 'common/confirm_delete.html', { | ||||
|         'object': ssh_key, | ||||
|         'title': _('Delete SSH key'), | ||||
|     }) | ||||
|     return render( | ||||
|         request, | ||||
|         "common/confirm_delete.html", | ||||
|         { | ||||
|             "object": ssh_key, | ||||
|             "title": _("Delete SSH key"), | ||||
|         }, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
|  | @ -67,13 +79,16 @@ def account(request, user_id): | |||
|     publickeys = UserSSHKey.objects.filter(user_id=user_id) | ||||
| 
 | ||||
|     return render( | ||||
|         request, "account.html", { | ||||
|             'user': user, | ||||
|             'user_insts': user_insts, | ||||
|             'instances': instances, | ||||
|             'publickeys': publickeys, | ||||
|             'otp_enabled': settings.OTP_ENABLED, | ||||
|         }) | ||||
|         request, | ||||
|         "account.html", | ||||
|         { | ||||
|             "user": user, | ||||
|             "user_insts": user_insts, | ||||
|             "instances": instances, | ||||
|             "publickeys": publickeys, | ||||
|             "otp_enabled": settings.OTP_ENABLED, | ||||
|         }, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| @permission_required("accounts.change_password", raise_exception=True) | ||||
|  | @ -118,7 +133,7 @@ def user_instance_update(request, pk): | |||
| 
 | ||||
|     return render( | ||||
|         request, | ||||
|         'common/form.html', | ||||
|         "common/form.html", | ||||
|         { | ||||
|             "form": form, | ||||
|             "title": _("Update User Instance"), | ||||
|  | @ -150,29 +165,33 @@ def email_otp(request): | |||
|     if form.is_valid(): | ||||
|         UserModel = get_user_model() | ||||
|         try: | ||||
|             user = UserModel.objects.get(email=form.cleaned_data['email']) | ||||
|             user = UserModel.objects.get(email=form.cleaned_data["email"]) | ||||
|         except UserModel.DoesNotExist: | ||||
|             pass | ||||
|         else: | ||||
|             device = get_user_totp_device(user) | ||||
|             send_email_with_otp(user, device) | ||||
| 
 | ||||
|         messages.success(request, _('OTP Sent to %s') % form.cleaned_data['email']) | ||||
|         return redirect('accounts:login') | ||||
|         messages.success(request, _("OTP Sent to %(email)s") % {"email": form.cleaned_data["email"]}) | ||||
|         return redirect("accounts:login") | ||||
| 
 | ||||
|     return render(request, 'accounts/email_otp_form.html', { | ||||
|         'form': form, | ||||
|         'title': _('Email OTP'), | ||||
|     }) | ||||
|     return render( | ||||
|         request, | ||||
|         "accounts/email_otp_form.html", | ||||
|         { | ||||
|             "form": form, | ||||
|             "title": _("Email OTP"), | ||||
|         }, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
| def admin_email_otp(request, user_id): | ||||
|     user = get_object_or_404(get_user_model(), pk=user_id) | ||||
|     device = get_user_totp_device(user) | ||||
|     if user.email != '': | ||||
|     if user.email != "": | ||||
|         send_email_with_otp(user, device) | ||||
|         messages.success(request, _('OTP QR code was emailed to user %s') % user) | ||||
|         messages.success(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')) | ||||
|     return redirect('accounts:account', user.id) | ||||
|         messages.error(request, _("User email not set, failed to send QR code")) | ||||
|     return redirect("accounts:account", user.id) | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| from django import forms | ||||
| from django.contrib.auth.models import Group, User | ||||
| from django.contrib.auth.forms import ReadOnlyPasswordHashField | ||||
| from django.contrib.auth.models import Group, User | ||||
| from django.urls import reverse_lazy | ||||
| from django.utils.text import format_lazy | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
|  | @ -13,7 +13,7 @@ from .models import Permission | |||
| class GroupForm(forms.ModelForm): | ||||
|     permissions = forms.ModelMultipleChoiceField( | ||||
|         widget=forms.CheckboxSelectMultiple, | ||||
|         queryset=Permission.objects.filter(content_type__model='permissionset'), | ||||
|         queryset=Permission.objects.filter(content_type__model="permissionset"), | ||||
|         required=False, | ||||
|     ) | ||||
| 
 | ||||
|  | @ -25,12 +25,12 @@ class GroupForm(forms.ModelForm): | |||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super(GroupForm, self).__init__(*args, **kwargs) | ||||
|         instance = getattr(self, 'instance', None) | ||||
|         instance = getattr(self, "instance", None) | ||||
|         if instance and instance.id: | ||||
|             self.fields['users'].initial = self.instance.user_set.all() | ||||
|             self.fields["users"].initial = self.instance.user_set.all() | ||||
| 
 | ||||
|     def save_m2m(self): | ||||
|         self.instance.user_set.set(self.cleaned_data['users']) | ||||
|         self.instance.user_set.set(self.cleaned_data["users"]) | ||||
| 
 | ||||
|     def save(self, *args, **kwargs): | ||||
|         instance = super(GroupForm, self).save() | ||||
|  | @ -39,36 +39,36 @@ class GroupForm(forms.ModelForm): | |||
| 
 | ||||
|     class Meta: | ||||
|         model = Group | ||||
|         fields = '__all__' | ||||
|         fields = "__all__" | ||||
| 
 | ||||
| 
 | ||||
| class UserForm(forms.ModelForm): | ||||
|     user_permissions = forms.ModelMultipleChoiceField( | ||||
|         widget=forms.CheckboxSelectMultiple, | ||||
|         queryset=Permission.objects.filter(content_type__model='permissionset'), | ||||
|         label=_('Permissions'), | ||||
|         queryset=Permission.objects.filter(content_type__model="permissionset"), | ||||
|         label=_("Permissions"), | ||||
|         required=False, | ||||
|     ) | ||||
| 
 | ||||
|     groups = forms.ModelMultipleChoiceField( | ||||
|         widget=forms.CheckboxSelectMultiple, | ||||
|         queryset=Group.objects.all(), | ||||
|         label=_('Groups'), | ||||
|         label=_("Groups"), | ||||
|         required=False, | ||||
|     ) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = User | ||||
|         fields = [ | ||||
|             'username', | ||||
|             'groups', | ||||
|             'first_name', | ||||
|             'last_name', | ||||
|             'email', | ||||
|             'user_permissions', | ||||
|             'is_staff', | ||||
|             'is_active', | ||||
|             'is_superuser', | ||||
|             "username", | ||||
|             "groups", | ||||
|             "first_name", | ||||
|             "last_name", | ||||
|             "email", | ||||
|             "user_permissions", | ||||
|             "is_staff", | ||||
|             "is_active", | ||||
|             "is_superuser", | ||||
|         ] | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|  | @ -76,12 +76,20 @@ class UserForm(forms.ModelForm): | |||
|         if self.instance.id: | ||||
|             password = ReadOnlyPasswordHashField( | ||||
|                 label=_("Password"), | ||||
|                 help_text=format_lazy(_("""Raw passwords are not stored, so there is no way to see | ||||
|                 this user's password, but you can change the password using <a href='{}'>this form</a>."""), | ||||
|                 reverse_lazy('admin:user_update_password', | ||||
|                 args=[self.instance.id,])) | ||||
|                 help_text=format_lazy( | ||||
|                     _( | ||||
|                         """Raw passwords are not stored, so there is no way to see this user's password,  | ||||
|                     but you can change the password using <a href='{}'>this form</a>.""" | ||||
|                     ), | ||||
|                     reverse_lazy( | ||||
|                         "admin:user_update_password", | ||||
|                         args=[ | ||||
|                             self.instance.id, | ||||
|                         ], | ||||
|                     ), | ||||
|                 ), | ||||
|             ) | ||||
|             self.fields['Password'] = password | ||||
|             self.fields["Password"] = password | ||||
| 
 | ||||
| 
 | ||||
| class UserCreateForm(UserForm): | ||||
|  | @ -90,20 +98,20 @@ class UserCreateForm(UserForm): | |||
|     class Meta: | ||||
|         model = User | ||||
|         fields = [ | ||||
|             'username', | ||||
|             'password', | ||||
|             'groups', | ||||
|             'first_name', | ||||
|             'last_name', | ||||
|             'email', | ||||
|             'user_permissions', | ||||
|             'is_staff', | ||||
|             'is_active', | ||||
|             'is_superuser', | ||||
|             "username", | ||||
|             "password", | ||||
|             "groups", | ||||
|             "first_name", | ||||
|             "last_name", | ||||
|             "email", | ||||
|             "user_permissions", | ||||
|             "is_staff", | ||||
|             "is_active", | ||||
|             "is_superuser", | ||||
|         ] | ||||
| 
 | ||||
| 
 | ||||
| class UserAttributesForm(forms.ModelForm): | ||||
|     class Meta: | ||||
|         model = UserAttributes | ||||
|         exclude = ['user', 'can_clone_instances'] | ||||
|         exclude = ["user", "can_clone_instances"] | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ def group_update(request, pk): | |||
|     form = forms.GroupForm(request.POST or None, instance=group) | ||||
|     if form.is_valid(): | ||||
|         form.save() | ||||
|         return redirect('admin:group_list') | ||||
|         return redirect("admin:group_list") | ||||
| 
 | ||||
|     return render( | ||||
|         request, | ||||
|  | @ -107,11 +107,7 @@ def user_create(request): | |||
|     return render( | ||||
|         request, | ||||
|         "admin/user_form.html", | ||||
|         { | ||||
|             "user_form": user_form, | ||||
|             "attributes_form": attributes_form, | ||||
|             "title": _("Create User") | ||||
|         }, | ||||
|         {"user_form": user_form, "attributes_form": attributes_form, "title": _("Create User")}, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -124,29 +120,25 @@ def user_update(request, pk): | |||
|     if user_form.is_valid() and attributes_form.is_valid(): | ||||
|         user_form.save() | ||||
|         attributes_form.save() | ||||
|         next = request.GET.get('next') | ||||
|         next = request.GET.get("next") | ||||
|         return redirect(next or "admin:user_list") | ||||
| 
 | ||||
|     return render( | ||||
|         request, | ||||
|         "admin/user_form.html", | ||||
|         { | ||||
|             "user_form": user_form, | ||||
|             "attributes_form": attributes_form, | ||||
|             "title": _("Update User") | ||||
|         }, | ||||
|         {"user_form": user_form, "attributes_form": attributes_form, "title": _("Update User")}, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
| def user_update_password(request, pk): | ||||
|     user = get_object_or_404(User, pk=pk) | ||||
|     if request.method == 'POST': | ||||
|     if request.method == "POST": | ||||
|         form = AdminPasswordChangeForm(user, request.POST) | ||||
|         if form.is_valid(): | ||||
|             user = form.save() | ||||
|             update_session_auth_hash(request, user)  # Important! | ||||
|             messages.success(request, _("User password changed: {}".format(user.username))) | ||||
|             messages.success(request, _("Password changed for %(user)s") % {"user": user.username}) | ||||
|             return redirect("admin:user_list") | ||||
|         else: | ||||
|             messages.error(request, _("Wrong Data Provided")) | ||||
|  |  | |||
|  | @ -29,13 +29,13 @@ def appsettings(request): | |||
|     # Bootstrap settings related with filesystems, because of that they are excluded from other settings | ||||
|     appsettings = AppSettings.objects.exclude(description__startswith="Bootstrap").order_by("name") | ||||
| 
 | ||||
|     if request.method == 'POST': | ||||
|         if 'SASS_DIR' in request.POST: | ||||
|     if request.method == "POST": | ||||
|         if "SASS_DIR" in request.POST: | ||||
|             try: | ||||
|                 sass_dir.value = request.POST.get("SASS_DIR", "") | ||||
|                 sass_dir.save() | ||||
| 
 | ||||
|                 msg = _(f"SASS directory path is changed. Now: {sass_dir.value}") | ||||
|                 msg = _("SASS directory path is changed. Now: %(dir)s") % {"dir": sass_dir.value} | ||||
|                 messages.success(request, msg) | ||||
|             except Exception as err: | ||||
|                 msg = err | ||||
|  | @ -44,7 +44,7 @@ def appsettings(request): | |||
|             addlogmsg(request.user.username, "", msg) | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
| 
 | ||||
|         if 'BOOTSTRAP_THEME' in request.POST: | ||||
|         if "BOOTSTRAP_THEME" in request.POST: | ||||
|             theme = request.POST.get("BOOTSTRAP_THEME", "") | ||||
|             scss_var = f"@import '{sass_dir.value}/wvc-theme/{theme}/variables';" | ||||
|             scss_bootswatch = f"@import '{sass_dir.value}/wvc-theme/{theme}/bootswatch';" | ||||
|  | @ -54,15 +54,17 @@ def appsettings(request): | |||
|                 with open(sass_dir.value + "/wvc-main.scss", "w") as main: | ||||
|                     main.write(scss_var + "\n" + scss_boot + "\n" + scss_bootswatch + "\n") | ||||
| 
 | ||||
|                 css_compressed = sass.compile(string=scss_var + "\n" + scss_boot + "\n" + scss_bootswatch, | ||||
|                                               output_style='compressed') | ||||
|                 css_compressed = sass.compile( | ||||
|                     string=scss_var + "\n" + scss_boot + "\n" + scss_bootswatch, | ||||
|                     output_style="compressed", | ||||
|                 ) | ||||
|                 with open("static/css/" + main_css, "w") as css: | ||||
|                     css.write(css_compressed) | ||||
| 
 | ||||
|                 bootstrap_theme.value = theme | ||||
|                 bootstrap_theme.save() | ||||
| 
 | ||||
|                 msg = _(f"Theme changed. Now: {theme}") | ||||
|                 msg = _("Theme is changed. Now: %(theme)s") % {"theme": theme} | ||||
|                 messages.success(request, msg) | ||||
|             except Exception as err: | ||||
|                 msg = err | ||||
|  | @ -77,7 +79,7 @@ def appsettings(request): | |||
|                     setting.value = request.POST.get(setting.key, "") | ||||
|                     setting.save() | ||||
| 
 | ||||
|                     msg = _(f"{setting.name} is changed. Now: {setting.value}") | ||||
|                     msg = _("%(setting)s is changed. Now: %(value)s") % {"setting": setting.name, "value": setting.value} | ||||
|                     messages.success(request, msg) | ||||
|                 except Exception as err: | ||||
|                     msg = err | ||||
|  | @ -86,4 +88,4 @@ def appsettings(request): | |||
|                 addlogmsg(request.user.username, "", msg) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
| 
 | ||||
|     return render(request, 'appsettings.html', locals()) | ||||
|     return render(request, "appsettings.html", locals()) | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| from secrets.views import secrets | ||||
| 
 | ||||
| from django.urls import include, path | ||||
| 
 | ||||
| # from instances.views import create_instance, create_instance_select_type | ||||
| from interfaces.views import interface, interfaces | ||||
| from networks.views import network, networks | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| from django.core.exceptions import ValidationError | ||||
| 
 | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| import re | ||||
| 
 | ||||
| from django.core.exceptions import ValidationError | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| 
 | ||||
| have_symbol = re.compile('[^a-zA-Z0-9._-]+') | ||||
| wrong_ip = re.compile('^0.|^255.') | ||||
| wrong_name = re.compile('[^a-zA-Z0-9._-]+') | ||||
|  |  | |||
|  | @ -1,18 +1,23 @@ | |||
| import json | ||||
| 
 | ||||
| from django.contrib import messages | ||||
| from django.http import HttpResponse, HttpResponseRedirect | ||||
| from django.shortcuts import get_object_or_404, redirect, render, reverse | ||||
| 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 accounts.models import UserInstance | ||||
| from admin.decorators import superuser_only | ||||
| from computes.forms import (SocketComputeForm, SshComputeForm, TcpComputeForm, TlsComputeForm) | ||||
| 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, CONN_TCP, CONN_TLS, connection_manager, wvmConnect) | ||||
| from vrtManager.connection import ( | ||||
|     CONN_SOCKET, | ||||
|     CONN_SSH, | ||||
|     CONN_TCP, | ||||
|     CONN_TLS, | ||||
|     connection_manager, | ||||
|     wvmConnect, | ||||
| ) | ||||
| from vrtManager.hostdetails import wvmHostDetails | ||||
| 
 | ||||
| from . import utils | ||||
|  | @ -25,15 +30,17 @@ def computes(request): | |||
|     :return: | ||||
|     """ | ||||
| 
 | ||||
|     computes = Compute.objects.filter().order_by('name') | ||||
|     computes = Compute.objects.filter().order_by("name") | ||||
| 
 | ||||
|     return render(request, 'computes/list.html', {'computes': computes}) | ||||
|     return render(request, "computes/list.html", {"computes": computes}) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
| 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' | ||||
|     status = ( | ||||
|         "true" if connection_manager.host_is_up(compute.type, compute.hostname) is True else "false" | ||||
|     ) | ||||
| 
 | ||||
|     conn = wvmHostDetails( | ||||
|         compute.hostname, | ||||
|  | @ -49,7 +56,7 @@ def overview(request, compute_id): | |||
|     lib_version = conn.get_lib_version() | ||||
|     conn.close() | ||||
| 
 | ||||
|     return render(request, 'overview.html', locals()) | ||||
|     return render(request, "overview.html", locals()) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
|  | @ -57,9 +64,9 @@ def instances(request, compute_id): | |||
|     compute = get_object_or_404(Compute, pk=compute_id) | ||||
| 
 | ||||
|     utils.refresh_instance_database(compute) | ||||
|     instances = Instance.objects.filter(compute=compute).prefetch_related('userinstance_set') | ||||
|     instances = Instance.objects.filter(compute=compute).prefetch_related("userinstance_set") | ||||
| 
 | ||||
|     return render(request, 'computes/instances.html', {'compute': compute, 'instances': instances}) | ||||
|     return render(request, "computes/instances.html", {"compute": compute, "instances": instances}) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
|  | @ -67,9 +74,9 @@ def compute_create(request, FormClass): | |||
|     form = FormClass(request.POST or None) | ||||
|     if form.is_valid(): | ||||
|         form.save() | ||||
|         return redirect(reverse('computes')) | ||||
|         return redirect(reverse("computes")) | ||||
| 
 | ||||
|     return render(request, 'computes/form.html', {'form': form}) | ||||
|     return render(request, "computes/form.html", {"form": form}) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
|  | @ -88,22 +95,22 @@ def compute_update(request, compute_id): | |||
|     form = FormClass(request.POST or None, instance=compute) | ||||
|     if form.is_valid(): | ||||
|         form.save() | ||||
|         return redirect(reverse('computes')) | ||||
|         return redirect(reverse("computes")) | ||||
| 
 | ||||
|     return render(request, 'computes/form.html', {'form': form}) | ||||
|     return render(request, "computes/form.html", {"form": form}) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
| def compute_delete(request, compute_id): | ||||
|     compute = get_object_or_404(Compute, pk=compute_id) | ||||
|     if request.method == 'POST': | ||||
|     if request.method == "POST": | ||||
|         compute.delete() | ||||
|         return redirect('computes') | ||||
|         return redirect("computes") | ||||
| 
 | ||||
|     return render( | ||||
|         request, | ||||
|         'common/confirm_delete.html', | ||||
|         {'object': compute}, | ||||
|         "common/confirm_delete.html", | ||||
|         {"object": compute}, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -126,17 +133,19 @@ def compute_graph(request, compute_id): | |||
|         mem_usage = conn.get_memory_usage() | ||||
|         conn.close() | ||||
|     except libvirtError: | ||||
|         cpu_usage = {'usage': 0} | ||||
|         mem_usage = {'usage': 0} | ||||
|         cpu_usage = {"usage": 0} | ||||
|         mem_usage = {"usage": 0} | ||||
|         current_time = 0 | ||||
| 
 | ||||
|     data = json.dumps({ | ||||
|         'cpudata': cpu_usage['usage'], | ||||
|         'memdata': mem_usage, | ||||
|         'timeline': current_time, | ||||
|     }) | ||||
|     data = json.dumps( | ||||
|         { | ||||
|             "cpudata": cpu_usage["usage"], | ||||
|             "memdata": mem_usage, | ||||
|             "timeline": current_time, | ||||
|         } | ||||
|     ) | ||||
|     response = HttpResponse() | ||||
|     response['Content-Type'] = "text/javascript" | ||||
|     response["Content-Type"] = "text/javascript" | ||||
|     response.write(data) | ||||
|     return response | ||||
| 
 | ||||
|  | @ -163,14 +172,14 @@ def get_compute_disk_buses(request, compute_id, arch, machine, disk): | |||
|         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'] | ||||
|             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 | ||||
| 
 | ||||
|  | @ -193,7 +202,7 @@ def get_compute_machine_types(request, compute_id, arch): | |||
|             compute.password, | ||||
|             compute.type, | ||||
|         ) | ||||
|         data['machines'] = conn.get_machine_types(arch) | ||||
|         data["machines"] = conn.get_machine_types(arch) | ||||
|     except libvirtError: | ||||
|         pass | ||||
| 
 | ||||
|  | @ -217,7 +226,7 @@ def get_compute_video_models(request, compute_id, arch, machine): | |||
|             compute.password, | ||||
|             compute.type, | ||||
|         ) | ||||
|         data['videos'] = conn.get_video_models(arch, machine) | ||||
|         data["videos"] = conn.get_video_models(arch, machine) | ||||
|     except libvirtError: | ||||
|         pass | ||||
| 
 | ||||
|  | @ -241,8 +250,8 @@ def get_dom_capabilities(request, compute_id, arch, machine): | |||
|             compute.password, | ||||
|             compute.type, | ||||
|         ) | ||||
|         data['videos'] = conn.get_disk_device_types(arch, machine) | ||||
|         data['bus'] = conn.get_disk_device_types(arch, machine) | ||||
|         data["videos"] = conn.get_disk_device_types(arch, machine) | ||||
|         data["bus"] = conn.get_disk_device_types(arch, machine) | ||||
|     except libvirtError: | ||||
|         pass | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import random, string | ||||
| import random | ||||
| import string | ||||
| 
 | ||||
| haystack = string.ascii_letters + string.digits + string.punctuation | ||||
| print(''.join([random.SystemRandom().choice(haystack.replace('/', '').replace('\'', '').replace('\"', '')) for _ in range(50)])) | ||||
|  |  | |||
|  | @ -4,14 +4,13 @@ | |||
| # See the COPYING file in the top-level directory. | ||||
| 
 | ||||
| import functools | ||||
| import logging as log | ||||
| import os | ||||
| import queue | ||||
| import socket | ||||
| import signal | ||||
| import socket | ||||
| import threading | ||||
| 
 | ||||
| import logging as log | ||||
| 
 | ||||
| 
 | ||||
| class _TunnelScheduler(object): | ||||
|     """ | ||||
|  |  | |||
|  | @ -6,7 +6,11 @@ from libvirt import libvirtError | |||
| from appsettings.settings import app_settings | ||||
| from instances.models import Instance | ||||
| from vrtManager.instance import wvmInstance | ||||
| from webvirtcloud.settings import WS_PUBLIC_HOST, WS_PUBLIC_PATH, WS_PUBLIC_PORT | ||||
| from webvirtcloud.settings import ( | ||||
|     WS_PUBLIC_HOST, | ||||
|     WS_PUBLIC_PATH, | ||||
|     WS_PUBLIC_PORT, | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| def console(request): | ||||
|  | @ -61,7 +65,7 @@ def console(request): | |||
|         if console_type is None: | ||||
|             console_error = "Fail to get console. Please check the console configuration of your VM." | ||||
|         else: | ||||
|             console_error = f"Console type: {console_type} no support" | ||||
|             console_error = "Console type '%(type)s' has not support" % {"type": console_type} | ||||
|         response = render(request, "console-vnc-lite.html", locals()) | ||||
| 
 | ||||
|     response.set_cookie("token", token) | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| from django.urls import path | ||||
| 
 | ||||
| from . import views | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|  |  | |||
|  | @ -1,14 +1,16 @@ | |||
| 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 vrtManager.instance import wvmInstance | ||||
| 
 | ||||
| 
 | ||||
| OS_VERSIONS = ['latest', ''] | ||||
| OS_VERSIONS = ["latest", ""] | ||||
| OS_UUID = "iid-dswebvirtcloud" | ||||
| 
 | ||||
| 
 | ||||
|  | @ -17,7 +19,7 @@ def os_index(request): | |||
|     :param request: | ||||
|     :return: | ||||
|     """ | ||||
|     response = '\n'.join(OS_VERSIONS) | ||||
|     response = "\n".join(OS_VERSIONS) | ||||
|     return HttpResponse(response) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -28,13 +30,13 @@ def os_metadata_json(request, version): | |||
|     :return: | ||||
|     """ | ||||
| 
 | ||||
|     if version == 'latest': | ||||
|     if version == "latest": | ||||
|         ip = get_client_ip(request) | ||||
|         hostname = get_hostname_by_ip(ip) | ||||
|         response = {'uuid': OS_UUID, 'hostname': hostname} | ||||
|         response = {"uuid": OS_UUID, "hostname": hostname} | ||||
|         return HttpResponse(json.dumps(response)) | ||||
|     else: | ||||
|         err = f"Invalid version: {version}" | ||||
|         err = "Invalid version: %(version)s" % {"version": version} | ||||
|         raise Http404(err) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -44,10 +46,10 @@ def os_userdata(request, version): | |||
|     :param version: | ||||
|     :return: | ||||
|     """ | ||||
|     if version == 'latest': | ||||
|     if version == "latest": | ||||
|         ip = get_client_ip(request) | ||||
|         hostname = get_hostname_by_ip(ip) | ||||
|         vname = hostname.split('.')[0] | ||||
|         vname = hostname.split(".")[0] | ||||
| 
 | ||||
|         instance_keys = [] | ||||
|         userinstances = UserInstance.objects.filter(instance__name=vname) | ||||
|  | @ -57,9 +59,9 @@ def os_userdata(request, version): | |||
|             for k in keys: | ||||
|                 instance_keys.append(k.keypublic) | ||||
| 
 | ||||
|         return render(request, 'user_data', locals()) | ||||
|         return render(request, "user_data", locals()) | ||||
|     else: | ||||
|         err = f"Invalid version: {version}" | ||||
|         err = "Invalid version: %(version)s" % {"version": version} | ||||
|         raise Http404(err) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -68,11 +70,11 @@ def get_client_ip(request): | |||
|     :param request: | ||||
|     :return: | ||||
|     """ | ||||
|     x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') | ||||
|     x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR") | ||||
|     if x_forwarded_for: | ||||
|         ip = x_forwarded_for.split(',')[-1].strip() | ||||
|         ip = x_forwarded_for.split(",")[-1].strip() | ||||
|     else: | ||||
|         ip = request.META.get('REMOTE_ADDR') | ||||
|         ip = request.META.get("REMOTE_ADDR") | ||||
|     return ip | ||||
| 
 | ||||
| 
 | ||||
|  | @ -97,16 +99,12 @@ def get_vdi_url(request, compute_id, vname): | |||
|     compute = get_object_or_404(Compute, pk=compute_id) | ||||
| 
 | ||||
|     try: | ||||
|         conn = wvmInstance(compute.hostname, | ||||
|                            compute.login, | ||||
|                            compute.password, | ||||
|                            compute.type, | ||||
|                            vname) | ||||
|         conn = wvmInstance(compute.hostname, compute.login, compute.password, compute.type, vname) | ||||
| 
 | ||||
|         fqdn = get_hostname_by_ip(compute.hostname) | ||||
|         url = f"{conn.get_console_type()}://{fqdn}:{conn.get_console_port()}" | ||||
|         response = url | ||||
|         return HttpResponse(response) | ||||
|     except libvirtError: | ||||
|         err = f"Error getting VDI URL for {vname}" | ||||
|         err = "Error getting VDI URL for %(name)s" % {"name": vname} | ||||
|         raise Http404(err) | ||||
|  |  | |||
|  | @ -25,8 +25,8 @@ def apply_passwordless_console(sender, **kwargs): | |||
|     ''' | ||||
|     Apply new passwordless_console permission for all users | ||||
|     ''' | ||||
|     from django.contrib.auth.models import Permission | ||||
|     from django.contrib.auth import get_user_model | ||||
|     from django.contrib.auth.models import Permission | ||||
|     User = get_user_model() | ||||
|     plan = kwargs.get('plan', []) | ||||
|     for migration, rolled_back in plan: | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| # Generated by Django 2.2.10 on 2020-01-28 07:01 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ | |||
|         <div class="tab-content"> | ||||
|             <div role="tabpanel" class="tab-pane tab-pane-bordered active" id="takesnapshot"> | ||||
|                 {% if instance.status == 5 %} | ||||
|                     <p>{% trans "This may take more than an hour, depending on how much content is on your droplet and how large the disk is." %}</p> | ||||
|                     <p>{% trans "This may take more than an hour, depending on how much content is on your instance and how large the disk is." %}</p> | ||||
|                     <form action="{% url 'instances:snapshot' instance.id %}" class="form-inline" method="post" role="form" aria-label="Create snapshot form"> | ||||
|                         {% csrf_token %} | ||||
|                         <div class="form-group row"> | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| from django import template | ||||
| import re | ||||
| 
 | ||||
| from django import template | ||||
| 
 | ||||
| register = template.Library() | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,12 +8,11 @@ from django.contrib.auth.models import Permission | |||
| from django.http.response import Http404 | ||||
| from django.shortcuts import reverse | ||||
| from django.test import TestCase | ||||
| from instances.views import instance | ||||
| from libvirt import VIR_DOMAIN_UNDEFINE_NVRAM | ||||
| from vrtManager.create import wvmCreate | ||||
| from vrtManager.util import randomUUID | ||||
| 
 | ||||
| from instances.views import instance | ||||
| 
 | ||||
| from .models import Flavor, Instance | ||||
| from .utils import refr | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,4 +1,5 @@ | |||
| import re | ||||
| 
 | ||||
| from django import forms | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,19 +26,30 @@ def interfaces(request, compute_id): | |||
|         try: | ||||
|             netdevs = conn.get_net_devices() | ||||
|         except: | ||||
|             netdevs = ['eth0', 'eth1'] | ||||
|             netdevs = ["eth0", "eth1"] | ||||
| 
 | ||||
|         for iface in ifaces: | ||||
|             ifaces_all.append(conn.get_iface_info(iface)) | ||||
| 
 | ||||
|         if request.method == 'POST': | ||||
|             if 'create' in request.POST: | ||||
|         if request.method == "POST": | ||||
|             if "create" in request.POST: | ||||
|                 form = AddInterface(request.POST) | ||||
|                 if form.is_valid(): | ||||
|                     data = form.cleaned_data | ||||
|                     conn.create_iface(data['name'], data['itype'], data['start_mode'], data['netdev'], data['ipv4_type'], | ||||
|                                       data['ipv4_addr'], data['ipv4_gw'], data['ipv6_type'], data['ipv6_addr'], | ||||
|                                       data['ipv6_gw'], data['stp'], data['delay']) | ||||
|                     conn.create_iface( | ||||
|                         data["name"], | ||||
|                         data["itype"], | ||||
|                         data["start_mode"], | ||||
|                         data["netdev"], | ||||
|                         data["ipv4_type"], | ||||
|                         data["ipv4_addr"], | ||||
|                         data["ipv4_gw"], | ||||
|                         data["ipv6_type"], | ||||
|                         data["ipv6_addr"], | ||||
|                         data["ipv6_gw"], | ||||
|                         data["stp"], | ||||
|                         data["delay"], | ||||
|                     ) | ||||
|                     return HttpResponseRedirect(request.get_full_path()) | ||||
|                 else: | ||||
|                     for msg_err in form.errors.values(): | ||||
|  | @ -47,7 +58,7 @@ def interfaces(request, compute_id): | |||
|     except libvirtError as lib_err: | ||||
|         messages.error(request, lib_err) | ||||
| 
 | ||||
|     return render(request, 'interfaces.html', locals()) | ||||
|     return render(request, "interfaces.html", locals()) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
|  | @ -75,18 +86,18 @@ def interface(request, compute_id, iface): | |||
|         bridge = conn.get_bridge() | ||||
|         slave_ifaces = conn.get_bridge_slave_ifaces() | ||||
| 
 | ||||
|         if request.method == 'POST': | ||||
|             if 'stop' in request.POST: | ||||
|         if request.method == "POST": | ||||
|             if "stop" in request.POST: | ||||
|                 conn.stop_iface() | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             if 'start' in request.POST: | ||||
|             if "start" in request.POST: | ||||
|                 conn.start_iface() | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             if 'delete' in request.POST: | ||||
|             if "delete" in request.POST: | ||||
|                 conn.delete_iface() | ||||
|                 return HttpResponseRedirect(reverse('interfaces', args=[compute_id])) | ||||
|                 return HttpResponseRedirect(reverse("interfaces", args=[compute_id])) | ||||
|         conn.close() | ||||
|     except libvirtError as lib_err: | ||||
|         messages.error(request, lib_err) | ||||
| 
 | ||||
|     return render(request, 'interface.html', locals()) | ||||
|     return render(request, "interface.html", locals()) | ||||
|  |  | |||
|  | @ -1,12 +1,11 @@ | |||
| from django.db.models import Model, CharField, DateTimeField | ||||
| from django.db.models import CharField, DateTimeField, Model | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| 
 | ||||
| 
 | ||||
| class Logs(Model): | ||||
|     user = CharField(_('user'), max_length=50) | ||||
|     instance = CharField(_('instance'), max_length=50) | ||||
|     message = CharField(_('message'), max_length=255) | ||||
|     date = DateTimeField(_('date'), auto_now=True) | ||||
|     user = CharField(_("user"), max_length=50) | ||||
|     instance = CharField(_("instance"), max_length=50) | ||||
|     message = CharField(_("message"), max_length=255) | ||||
|     date = DateTimeField(_("date"), auto_now=True) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return self.instance | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| from django.urls import path | ||||
| 
 | ||||
| from . import views | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|     path('vm_logs/<vname>/', views.vm_logs, name='vm_logs'), | ||||
|     path("vm_logs/<vname>/", views.vm_logs, name="vm_logs"), | ||||
| ] | ||||
|  |  | |||
|  | @ -1,8 +1,6 @@ | |||
| import json | ||||
| 
 | ||||
| from django.http import HttpResponse, HttpResponseRedirect | ||||
| from django.shortcuts import render | ||||
| from django.urls import reverse | ||||
| from django.http import HttpResponse | ||||
| 
 | ||||
| from admin.decorators import superuser_only | ||||
| from instances.models import Instance | ||||
|  | @ -29,14 +27,14 @@ def vm_logs(request, vname): | |||
|     """ | ||||
| 
 | ||||
|     vm = Instance.objects.get(name=vname) | ||||
|     logs_ = Logs.objects.filter(instance=vm.name, date__gte=vm.created).order_by('-date') | ||||
|     logs_ = Logs.objects.filter(instance=vm.name, date__gte=vm.created).order_by("-date") | ||||
|     logs = [] | ||||
|     for l in logs_: | ||||
|         log = dict() | ||||
|         log['user'] = l.user | ||||
|         log['instance'] = l.instance | ||||
|         log['message'] = l.message | ||||
|         log['date'] = l.date.strftime('%x %X') | ||||
|         log["user"] = l.user | ||||
|         log["instance"] = l.instance | ||||
|         log["message"] = l.message | ||||
|         log["date"] = l.date.strftime("%x %X") | ||||
|         logs.append(log) | ||||
| 
 | ||||
|     return HttpResponse(json.dumps(logs)) | ||||
|  |  | |||
|  | @ -1,15 +1,21 @@ | |||
| import re | ||||
| 
 | ||||
| from django import forms | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| 
 | ||||
| 
 | ||||
| class AddNetPool(forms.Form): | ||||
|     name = forms.CharField(error_messages={'required': _('No pool name has been entered')}, | ||||
|                            max_length=20) | ||||
|     subnet = forms.CharField(error_messages={'required': _('No IPv4 subnet has been entered')}, | ||||
|                              max_length=20, required=False) | ||||
|     subnet6 = forms.CharField(error_messages={'required': _('No IPv6 subnet has been entered')}, | ||||
|                               max_length=42, required=False) | ||||
|     name = forms.CharField(error_messages={"required": _("No pool name has been entered")}, max_length=20) | ||||
|     subnet = forms.CharField( | ||||
|         error_messages={"required": _("No IPv4 subnet has been entered")}, | ||||
|         max_length=20, | ||||
|         required=False, | ||||
|     ) | ||||
|     subnet6 = forms.CharField( | ||||
|         error_messages={"required": _("No IPv6 subnet has been entered")}, | ||||
|         max_length=42, | ||||
|         required=False, | ||||
|     ) | ||||
|     forward = forms.CharField(max_length=100) | ||||
|     dhcp4 = forms.BooleanField(required=False) | ||||
|     dhcp6 = forms.BooleanField(required=False) | ||||
|  | @ -18,38 +24,38 @@ class AddNetPool(forms.Form): | |||
|     openvswitch = forms.BooleanField(required=False) | ||||
| 
 | ||||
|     def clean_name(self): | ||||
|         name = self.cleaned_data['name'] | ||||
|         have_symbol = re.match('^[a-zA-Z0-9\.\_\-]+$', name) | ||||
|         name = self.cleaned_data["name"] | ||||
|         have_symbol = re.match(r"^[a-zA-Z0-9\.\_\-]+$", name) | ||||
|         if not have_symbol: | ||||
|             raise forms.ValidationError(_('The pool name must not contain any special characters')) | ||||
|             raise forms.ValidationError(_("The pool name must not contain any special characters")) | ||||
|         elif len(name) > 20: | ||||
|             raise forms.ValidationError(_('The pool name must not exceed 20 characters')) | ||||
|             raise forms.ValidationError(_("The pool name must not exceed 20 characters")) | ||||
|         return name | ||||
| 
 | ||||
|     def clean_subnet(self): | ||||
|         subnet = self.cleaned_data['subnet'] | ||||
|         have_symbol = re.match('^[0-9./]+$', subnet if subnet else ".") | ||||
|         subnet = self.cleaned_data["subnet"] | ||||
|         have_symbol = re.match("^[0-9./]+$", subnet if subnet else ".") | ||||
|         if not have_symbol: | ||||
|             raise forms.ValidationError(_('The IPv4 subnet must not contain any special characters')) | ||||
|             raise forms.ValidationError(_("The IPv4 subnet must not contain any special characters")) | ||||
|         elif len(subnet) > 20: | ||||
|             raise forms.ValidationError(_('The IPv4 subnet must not exceed 20 characters')) | ||||
|             raise forms.ValidationError(_("The IPv4 subnet must not exceed 20 characters")) | ||||
|         return subnet | ||||
| 
 | ||||
|     def clean_subnet6(self): | ||||
|         subnet = self.cleaned_data['subnet6'] | ||||
|         have_symbol = re.match('^[0-9a-fA-F:/]+$', subnet if subnet else ":") | ||||
|         subnet = self.cleaned_data["subnet6"] | ||||
|         have_symbol = re.match("^[0-9a-fA-F:/]+$", subnet if subnet else ":") | ||||
|         if not have_symbol: | ||||
|             raise forms.ValidationError(_('The IPv6 subnet must not contain any special characters')) | ||||
|             raise forms.ValidationError(_("The IPv6 subnet must not contain any special characters")) | ||||
|         elif len(subnet) > 42: | ||||
|             raise forms.ValidationError(_('The IPv6 subnet must not exceed 42 characters')) | ||||
|             raise forms.ValidationError(_("The IPv6 subnet must not exceed 42 characters")) | ||||
|         return subnet | ||||
| 
 | ||||
|     def clean_bridge_name(self): | ||||
|         bridge_name = self.cleaned_data['bridge_name'] | ||||
|         if self.cleaned_data['forward'] in ['bridge', 'macvtap']: | ||||
|             have_symbol = re.match('^[a-zA-Z0-9\.\_\:\-]+$', bridge_name) | ||||
|         bridge_name = self.cleaned_data["bridge_name"] | ||||
|         if self.cleaned_data["forward"] in ["bridge", "macvtap"]: | ||||
|             have_symbol = re.match(r"^[a-zA-Z0-9\.\_\:\-]+$", bridge_name) | ||||
|             if not have_symbol: | ||||
|                 raise forms.ValidationError(_('The pool bridge name must not contain any special characters')) | ||||
|                 raise forms.ValidationError(_("The pool bridge name must not contain any special characters")) | ||||
|             elif len(bridge_name) > 20: | ||||
|                 raise forms.ValidationError(_('The pool bridge name must not exceed 20 characters')) | ||||
|                 raise forms.ValidationError(_("The pool bridge name must not exceed 20 characters")) | ||||
|             return bridge_name | ||||
|  |  | |||
|  | @ -30,35 +30,37 @@ def networks(request, compute_id): | |||
|             compute.type, | ||||
|         ) | ||||
|         networks = conn.get_networks_info() | ||||
|         dhcp4 = netmask4 = gateway4 = '' | ||||
|         dhcp6 = prefix6 = gateway6 = '' | ||||
|         dhcp4 = netmask4 = gateway4 = "" | ||||
|         dhcp6 = prefix6 = gateway6 = "" | ||||
|         ipv4 = ipv6 = False | ||||
| 
 | ||||
|         if request.method == 'POST': | ||||
|             if 'create' in request.POST: | ||||
|         if request.method == "POST": | ||||
|             if "create" in request.POST: | ||||
|                 form = AddNetPool(request.POST) | ||||
|                 if form.is_valid(): | ||||
|                     data = form.cleaned_data | ||||
|                     if data['name'] in networks: | ||||
|                     if data["name"] in networks: | ||||
|                         msg = _("Network pool name already in use") | ||||
|                         messages.error(request, msg) | ||||
|                         errors = True | ||||
|                     if data['forward'] in ['bridge', 'macvtap'] and data['bridge_name'] == '': | ||||
|                         messages.error(request, _('Please enter bridge/dev name')) | ||||
|                     if data["forward"] in ["bridge", "macvtap"] and data["bridge_name"] == "": | ||||
|                         messages.error(request, _("Please enter bridge/dev name")) | ||||
|                         errors = True | ||||
|                     if data['subnet']: | ||||
|                     if data["subnet"]: | ||||
|                         ipv4 = True | ||||
|                         gateway4, netmask4, dhcp4 = network_size(data['subnet'], data['dhcp4']) | ||||
|                     if data['subnet6']: | ||||
|                         gateway4, netmask4, dhcp4 = network_size(data["subnet"], data["dhcp4"]) | ||||
|                     if data["subnet6"]: | ||||
|                         ipv6 = True | ||||
|                         gateway6, prefix6, dhcp6 = network_size(data['subnet6'], data['dhcp6']) | ||||
|                         if prefix6 != '64': | ||||
|                             messages.error(request, _('For libvirt, the IPv6 network prefix must be /64')) | ||||
|                         gateway6, prefix6, dhcp6 = network_size(data["subnet6"], data["dhcp6"]) | ||||
|                         if prefix6 != "64": | ||||
|                             messages.error( | ||||
|                                 request, _("For libvirt, the IPv6 network prefix must be /64") | ||||
|                             ) | ||||
|                             errors = True | ||||
|                     if not errors: | ||||
|                         conn.create_network( | ||||
|                             data['name'], | ||||
|                             data['forward'], | ||||
|                             data["name"], | ||||
|                             data["forward"], | ||||
|                             ipv4, | ||||
|                             gateway4, | ||||
|                             netmask4, | ||||
|  | @ -67,11 +69,13 @@ def networks(request, compute_id): | |||
|                             gateway6, | ||||
|                             prefix6, | ||||
|                             dhcp6, | ||||
|                             data['bridge_name'], | ||||
|                             data['openvswitch'], | ||||
|                             data['fixed'], | ||||
|                             data["bridge_name"], | ||||
|                             data["openvswitch"], | ||||
|                             data["fixed"], | ||||
|                         ) | ||||
|                         return HttpResponseRedirect( | ||||
|                             reverse("network", args=[compute_id, data["name"]]) | ||||
|                         ) | ||||
|                         return HttpResponseRedirect(reverse('network', args=[compute_id, data['name']])) | ||||
|                 else: | ||||
|                     for msg_err in form.errors.values(): | ||||
|                         messages.error(request, msg_err.as_text()) | ||||
|  | @ -79,7 +83,7 @@ def networks(request, compute_id): | |||
|     except libvirtError as lib_err: | ||||
|         messages.error(request, lib_err) | ||||
| 
 | ||||
|     return render(request, 'networks.html', locals()) | ||||
|     return render(request, "networks.html", locals()) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
|  | @ -128,112 +132,119 @@ def network(request, compute_id, pool): | |||
|         xml = conn._XMLDesc(0) | ||||
|     except libvirtError as lib_err: | ||||
|         messages.error(request, lib_err) | ||||
|         return HttpResponseRedirect(reverse('networks', args=compute_id)) | ||||
|         return HttpResponseRedirect(reverse("networks", args=compute_id)) | ||||
| 
 | ||||
|     if request.method == 'POST': | ||||
|         if 'start' in request.POST: | ||||
|     if request.method == "POST": | ||||
|         if "start" in request.POST: | ||||
|             try: | ||||
|                 conn.start() | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             except libvirtError as lib_err: | ||||
|                 messages.error(request, lib_err) | ||||
|         if 'stop' in request.POST: | ||||
|         if "stop" in request.POST: | ||||
|             try: | ||||
|                 conn.stop() | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             except libvirtError as lib_err: | ||||
|                 messages.error(request, lib_err) | ||||
|         if 'delete' in request.POST: | ||||
|         if "delete" in request.POST: | ||||
|             try: | ||||
|                 conn.delete() | ||||
|                 return HttpResponseRedirect(reverse('networks', args=[compute_id])) | ||||
|                 return HttpResponseRedirect(reverse("networks", args=[compute_id])) | ||||
|             except libvirtError as lib_err: | ||||
|                 messages.error(request, lib_err) | ||||
|         if 'set_autostart' in request.POST: | ||||
|         if "set_autostart" in request.POST: | ||||
|             try: | ||||
|                 conn.set_autostart(1) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             except libvirtError as lib_err: | ||||
|                 messages.error(request, lib_err) | ||||
|         if 'unset_autostart' in request.POST: | ||||
|         if "unset_autostart" in request.POST: | ||||
|             try: | ||||
|                 conn.set_autostart(0) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             except libvirtError as lib_err: | ||||
|                 messages.error(request, lib_err) | ||||
|         if 'modify_fixed_address' in request.POST: | ||||
|             name = request.POST.get('name', '') | ||||
|             address = request.POST.get('address', '') | ||||
|             family = request.POST.get('family', 'ipv4') | ||||
|         if "modify_fixed_address" in request.POST: | ||||
|             name = request.POST.get("name", "") | ||||
|             address = request.POST.get("address", "") | ||||
|             family = request.POST.get("family", "ipv4") | ||||
| 
 | ||||
|             if family == 'ipv4': | ||||
|                 mac_duid = request.POST.get('mac', '') | ||||
|             if family == 'ipv6': | ||||
|                 mac_duid = request.POST.get('id', '') | ||||
|             if family == "ipv4": | ||||
|                 mac_duid = request.POST.get("mac", "") | ||||
|             if family == "ipv6": | ||||
|                 mac_duid = request.POST.get("id", "") | ||||
| 
 | ||||
|             try: | ||||
|                 ret_val = conn.modify_fixed_address(name, address, mac_duid, family) | ||||
|                 messages.success(request, _(f"{family.upper()} Fixed Address Operation Completed.")) | ||||
|                 messages.success(request, _("Fixed address operation completed for %(family)s") % {"family": family.upper()}) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             except libvirtError as lib_err: | ||||
|                 messages.error(request, lib_err) | ||||
|             except ValueError as val_err: | ||||
|                 messages.error(request, val_err) | ||||
|         if 'delete_fixed_address' in request.POST: | ||||
|             ip = request.POST.get('address', '') | ||||
|             family = request.POST.get('family', 'ipv4') | ||||
|         if "delete_fixed_address" in request.POST: | ||||
|             ip = request.POST.get("address", "") | ||||
|             family = request.POST.get("family", "ipv4") | ||||
|             conn.delete_fixed_address(ip, family) | ||||
|             messages.success(request, _(f"{family.upper()} Fixed Address is Deleted.")) | ||||
|             messages.success(request, _("%(family)s Fixed Address is Deleted.") % {"family": family.upper()}) | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'modify_dhcp_range' in request.POST: | ||||
|             range_start = request.POST.get('range_start', '') | ||||
|             range_end = request.POST.get('range_end', '') | ||||
|             family = request.POST.get('family', 'ipv4') | ||||
|         if "modify_dhcp_range" in request.POST: | ||||
|             range_start = request.POST.get("range_start", "") | ||||
|             range_end = request.POST.get("range_end", "") | ||||
|             family = request.POST.get("family", "ipv4") | ||||
|             try: | ||||
|                 conn.modify_dhcp_range(range_start, range_end, family) | ||||
|                 messages.success(request, _(f"{family.upper()} DHCP Range is Changed.")) | ||||
|                 messages.success(request, _("%(family)s DHCP Range is Changed.") % {"family": family.upper()}) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             except libvirtError as lib_err: | ||||
|                 messages.error(request, lib_err) | ||||
|         if 'edit_network' in request.POST: | ||||
|             edit_xml = request.POST.get('edit_xml', '') | ||||
|         if "edit_network" in request.POST: | ||||
|             edit_xml = request.POST.get("edit_xml", "") | ||||
|             if edit_xml: | ||||
|                 conn.edit_network(edit_xml) | ||||
|                 if conn.is_active(): | ||||
|                     messages.success(request, _("Network XML is changed. \\" "Stop and start network to activate new config.")) | ||||
|                     messages.success( | ||||
|                         request, | ||||
|                         _( | ||||
|                             "Network XML is changed. \\" | ||||
|                             "Stop and start network to activate new config." | ||||
|                         ), | ||||
|                     ) | ||||
|                 else: | ||||
|                     messages.success(request, _("Network XML is changed.")) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'set_qos' in request.POST: | ||||
|             qos_dir = request.POST.get('qos_direction', '') | ||||
|             average = request.POST.get('qos_average') or 0 | ||||
|             peak = request.POST.get('qos_peak') or 0 | ||||
|             burst = request.POST.get('qos_burst') or 0 | ||||
|         if "set_qos" in request.POST: | ||||
|             qos_dir = request.POST.get("qos_direction", "") | ||||
|             average = request.POST.get("qos_average") or 0 | ||||
|             peak = request.POST.get("qos_peak") or 0 | ||||
|             burst = request.POST.get("qos_burst") or 0 | ||||
| 
 | ||||
|             try: | ||||
|                 conn.set_qos(qos_dir, average, peak, burst) | ||||
|                 if conn.is_active(): | ||||
|                     messages.success( | ||||
|                         request, | ||||
|                         _(f"{qos_dir.capitalize()} QoS is set. Network XML is changed.") + | ||||
|                         _("Stop and start network to activate new config")) | ||||
|                         _("%(qos_dir)s QoS is updated. Network XML is changed. Stop and start network to activate new config") % {"qos_dir": qos_dir.capitalize()} | ||||
|                     ) | ||||
|                 else: | ||||
|                     messages.success(request, _("{} QoS is set").format(qos_dir.capitalize())) | ||||
|                     messages.success(request, _("%(qos_dir)s QoS is set") % {"qos_dir": qos_dir.capitalize()}) | ||||
|             except libvirtError as lib_err: | ||||
|                 messages.error(request, lib_err) | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'unset_qos' in request.POST: | ||||
|             qos_dir = request.POST.get('qos_direction', '') | ||||
|         if "unset_qos" in request.POST: | ||||
|             qos_dir = request.POST.get("qos_direction", "") | ||||
|             conn.unset_qos(qos_dir) | ||||
| 
 | ||||
|             if conn.is_active(): | ||||
|                 messages.success( | ||||
|                     request, | ||||
|                     _(f"{qos_dir.capitalize()} QoS is deleted. Network XML is changed. ") + | ||||
|                     _("Stop and start network to activate new config.")) | ||||
|                     _("%(qos_dir)s QoS is deleted. Network XML is changed. \ | ||||
|                         Stop and start network to activate new config") % {"qos_dir": qos_dir.capitalize()} | ||||
|                 ) | ||||
|             else: | ||||
|                 messages.success(request, _(f"{qos_dir.capitalize()} QoS is deleted")) | ||||
|                 messages.success(request, _("%(qos_dir)s QoS is deleted") % {"qos_dir": qos_dir.capitalize()}) | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
|     conn.close() | ||||
| 
 | ||||
|     return render(request, 'network.html', locals()) | ||||
|     return render(request, "network.html", locals()) | ||||
|  |  | |||
|  | @ -5,4 +5,4 @@ from django.apps import AppConfig | |||
| 
 | ||||
| 
 | ||||
| class NwfiltersConfig(AppConfig): | ||||
|     name = 'nwfilters' | ||||
|     name = "nwfilters" | ||||
|  |  | |||
|  | @ -25,48 +25,55 @@ def nwfilters(request, compute_id): | |||
|     try: | ||||
|         conn = wvmNWFilters(compute.hostname, compute.login, compute.password, compute.type) | ||||
| 
 | ||||
|         if request.method == 'POST': | ||||
|             if 'create_nwfilter' in request.POST: | ||||
|                 xml = request.POST.get('nwfilter_xml', '') | ||||
|         for nwf in conn.get_nwfilters(): | ||||
|             nwfilters_all.append(conn.get_nwfilter_info(nwf)) | ||||
| 
 | ||||
|         if request.method == "POST": | ||||
|             if "create_nwfilter" in request.POST: | ||||
|                 xml = request.POST.get("nwfilter_xml", "") | ||||
|                 if xml: | ||||
|                     try: | ||||
|                         util.etree.fromstring(xml) | ||||
|                         name = util.get_xml_path(xml, '/filter/@name') | ||||
|                         uuid = util.get_xml_path(xml, '/filter/uuid') | ||||
|                         name = util.get_xml_path(xml, "/filter/@name") | ||||
|                         uuid = util.get_xml_path(xml, "/filter/uuid") | ||||
|                     except util.etree.ParseError: | ||||
|                         name = None | ||||
| 
 | ||||
|                     for nwf in nwfilters: | ||||
|                         if name == nwf.name(): | ||||
|                     for nwf in nwfilters_all: | ||||
|                         if name == nwf["name"]: | ||||
|                             error_msg = _("A network filter with this name already exists") | ||||
|                             raise Exception(error_msg) | ||||
|                         if uuid == nwf.UUIDString(): | ||||
|                         if uuid == nwf["uuid"]: | ||||
|                             error_msg = _("A network filter with this UUID already exists") | ||||
|                             raise Exception(error_msg) | ||||
|                     else: | ||||
|                         try: | ||||
|                             msg = _("Creating NWFilter: %s" % name) | ||||
|                             msg = _("%(filter)s network filter is created") % {"filter": name} | ||||
|                             conn.create_nwfilter(xml) | ||||
|                             addlogmsg(request.user.username, compute.hostname, msg) | ||||
|                         except libvirtError as lib_err: | ||||
|                             messages.error(request, lib_err) | ||||
|                             addlogmsg(request.user.username, compute.hostname, lib_err) | ||||
| 
 | ||||
|             if 'del_nwfilter' in request.POST: | ||||
|                 name = request.POST.get('nwfiltername', '') | ||||
|                 msg = _(f"Deleting NWFilter: {name}") | ||||
|             if "del_nwfilter" in request.POST: | ||||
|                 name = request.POST.get("nwfiltername", "") | ||||
|                 msg = _("%(filter)s network filter is deleted") % {"filter": name} | ||||
|                 in_use = False | ||||
|                 nwfilter = conn.get_nwfilter(name) | ||||
| 
 | ||||
|                 is_conn = wvmInstances(compute.hostname, compute.login, compute.password, compute.type) | ||||
|                 is_conn = wvmInstances( | ||||
|                     compute.hostname, compute.login, compute.password, compute.type | ||||
|                 ) | ||||
|                 instances = is_conn.get_instances() | ||||
|                 for inst in instances: | ||||
|                     i_conn = wvmInstance(compute.hostname, compute.login, compute.password, compute.type, inst) | ||||
|                     i_conn = wvmInstance( | ||||
|                         compute.hostname, compute.login, compute.password, compute.type, inst | ||||
|                     ) | ||||
|                     dom_filterrefs = i_conn.get_filterrefs() | ||||
| 
 | ||||
|                     if name in dom_filterrefs: | ||||
|                         in_use = True | ||||
|                         msg = _(f"NWFilter is in use by {inst}. Cannot be deleted.") | ||||
|                         msg = _("NWFilter is in use by %(instance)s. Cannot be deleted.") % {"instance": inst} | ||||
|                         messages.error(request, msg) | ||||
|                         addlogmsg(request.user.username, compute.hostname, msg) | ||||
|                         i_conn.close() | ||||
|  | @ -77,18 +84,15 @@ def nwfilters(request, compute_id): | |||
|                     nwfilter.undefine() | ||||
|                     addlogmsg(request.user.username, compute.hostname, msg) | ||||
| 
 | ||||
|             if 'cln_nwfilter' in request.POST: | ||||
|             if "cln_nwfilter" in request.POST: | ||||
| 
 | ||||
|                 name = request.POST.get('nwfiltername', '') | ||||
|                 cln_name = request.POST.get('cln_name', name + '-clone') | ||||
|                 name = request.POST.get("nwfiltername", "") | ||||
|                 cln_name = request.POST.get("cln_name", name + "-clone") | ||||
| 
 | ||||
|                 conn.clone_nwfilter(name, cln_name) | ||||
|                 msg = _(f"Cloning NWFilter {name} as {cln_name}") | ||||
|                 msg = _("Cloning NWFilter %(name)s as %(clone)s") % {"name":name, "clone": cln_name} | ||||
|                 addlogmsg(request.user.username, compute.hostname, msg) | ||||
| 
 | ||||
|         for nwf in conn.get_nwfilters(): | ||||
|             nwfilters_all.append(conn.get_nwfilter_info(nwf)) | ||||
| 
 | ||||
|         conn.close() | ||||
|     except libvirtError as lib_err: | ||||
|         messages.error(request, lib_err) | ||||
|  | @ -97,10 +101,14 @@ def nwfilters(request, compute_id): | |||
|         messages.error(request, err) | ||||
|         addlogmsg(request.user.username, compute.hostname, err) | ||||
| 
 | ||||
|     return render(request, 'nwfilters.html', { | ||||
|         'nwfilters': nwfilters_all, | ||||
|         'compute': compute, | ||||
|     }) | ||||
|     return render( | ||||
|         request, | ||||
|         "nwfilters.html", | ||||
|         { | ||||
|             "nwfilters": nwfilters_all, | ||||
|             "compute": compute, | ||||
|         }, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def nwfilter(request, compute_id, nwfltr): | ||||
|  | @ -114,7 +122,9 @@ def nwfilter(request, compute_id, nwfltr): | |||
|     compute = get_object_or_404(Compute, pk=compute_id) | ||||
| 
 | ||||
|     try: | ||||
|         nwfilter = wvmNWFilter(compute.hostname, compute.login, compute.password, compute.type, nwfltr) | ||||
|         nwfilter = wvmNWFilter( | ||||
|             compute.hostname, compute.login, compute.password, compute.type, nwfltr | ||||
|         ) | ||||
|         conn = wvmNWFilters(compute.hostname, compute.login, compute.password, compute.type) | ||||
| 
 | ||||
|         for nwf in conn.get_nwfilters(): | ||||
|  | @ -126,10 +136,10 @@ def nwfilter(request, compute_id, nwfltr): | |||
|         rules = nwfilter.get_rules() | ||||
|         refs = nwfilter.get_filter_refs() | ||||
| 
 | ||||
|         if request.method == 'POST': | ||||
|         if request.method == "POST": | ||||
| 
 | ||||
|             if 'edit_nwfilter' in request.POST: | ||||
|                 new_xml = request.POST.get('edit_xml', '') | ||||
|             if "edit_nwfilter" in request.POST: | ||||
|                 new_xml = request.POST.get("edit_xml", "") | ||||
| 
 | ||||
|                 if new_xml: | ||||
|                     nwfilter.delete() | ||||
|  | @ -139,10 +149,10 @@ def nwfilter(request, compute_id, nwfltr): | |||
|                         conn.create_nwfilter(xml) | ||||
|                         raise libvirtError(lib_err) | ||||
| 
 | ||||
|             if 'del_nwfilter_rule' in request.POST: | ||||
|                 action = request.POST.get('action', '') | ||||
|                 direction = request.POST.get('direction', '') | ||||
|                 priority = request.POST.get('priority', '') | ||||
|             if "del_nwfilter_rule" in request.POST: | ||||
|                 action = request.POST.get("action", "") | ||||
|                 direction = request.POST.get("direction", "") | ||||
|                 priority = request.POST.get("priority", "") | ||||
| 
 | ||||
|                 new_xml = nwfilter.delete_rule(action, direction, priority) | ||||
|                 nwfilter.delete() | ||||
|  | @ -152,8 +162,8 @@ def nwfilter(request, compute_id, nwfltr): | |||
|                     conn.create_nwfilter(xml) | ||||
|                     raise libvirtError(lib_err) | ||||
| 
 | ||||
|             if 'del_nwfilter_ref' in request.POST: | ||||
|                 ref_name = request.POST.get('ref') | ||||
|             if "del_nwfilter_ref" in request.POST: | ||||
|                 ref_name = request.POST.get("ref") | ||||
|                 new_xml = nwfilter.delete_ref(ref_name) | ||||
|                 nwfilter.delete() | ||||
|                 try: | ||||
|  | @ -162,8 +172,8 @@ def nwfilter(request, compute_id, nwfltr): | |||
|                     conn.create_nwfilter(xml) | ||||
|                     raise libvirtError(lib_err) | ||||
| 
 | ||||
|             if 'add_nwfilter_rule' in request.POST: | ||||
|                 rule_xml = request.POST.get('nwfilterrule_xml', '') | ||||
|             if "add_nwfilter_rule" in request.POST: | ||||
|                 rule_xml = request.POST.get("nwfilterrule_xml", "") | ||||
|                 if not rule_xml: | ||||
|                     return HttpResponseRedirect(request.get_full_path()) | ||||
|                 new_xml = nwfilter.add_rule(rule_xml) | ||||
|  | @ -174,8 +184,8 @@ def nwfilter(request, compute_id, nwfltr): | |||
|                     conn.create_nwfilter(xml) | ||||
|                     raise libvirtError(lib_err) | ||||
| 
 | ||||
|             if 'add_nwfilter_ref' in request.POST: | ||||
|                 ref_name = request.POST.get('nwfilters_select', '') | ||||
|             if "add_nwfilter_ref" in request.POST: | ||||
|                 ref_name = request.POST.get("nwfilters_select", "") | ||||
|                 if not ref_name: | ||||
|                     return HttpResponseRedirect(request.get_full_path()) | ||||
|                 new_xml = nwfilter.add_ref(ref_name) | ||||
|  | @ -194,4 +204,4 @@ def nwfilter(request, compute_id, nwfltr): | |||
|     except Exception as error_msg: | ||||
|         messages.error(request, error_msg) | ||||
| 
 | ||||
|     return render(request, 'nwfilter.html', locals()) | ||||
|     return render(request, "nwfilter.html", locals()) | ||||
|  |  | |||
|  | @ -5,8 +5,14 @@ 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 libvirt import (VIR_SECRET_USAGE_TYPE_CEPH, VIR_SECRET_USAGE_TYPE_ISCSI, VIR_SECRET_USAGE_TYPE_NONE, | ||||
|                      VIR_SECRET_USAGE_TYPE_TLS, VIR_SECRET_USAGE_TYPE_VOLUME, libvirtError) | ||||
| from libvirt import ( | ||||
|     VIR_SECRET_USAGE_TYPE_CEPH, | ||||
|     VIR_SECRET_USAGE_TYPE_ISCSI, | ||||
|     VIR_SECRET_USAGE_TYPE_NONE, | ||||
|     VIR_SECRET_USAGE_TYPE_TLS, | ||||
|     VIR_SECRET_USAGE_TYPE_VOLUME, | ||||
|     libvirtError, | ||||
| ) | ||||
| from vrtManager.secrets import wvmSecrets | ||||
| 
 | ||||
| 
 | ||||
|  | @ -36,36 +42,38 @@ def secrets(request, compute_id): | |||
|             secrt = conn.get_secret(uuid) | ||||
|             try: | ||||
|                 secrt_value = conn.get_secret_value(uuid) | ||||
|             except libvirtError as lib_err: | ||||
|             except libvirtError: | ||||
|                 secrt_value = None | ||||
|             secrets_all.append({ | ||||
|                 'usage': secrt.usageID(), | ||||
|                 'uuid': secrt.UUIDString(), | ||||
|                 'usageType': secret_usage_types[secrt.usageType()], | ||||
|                 'value': secrt_value | ||||
|             }) | ||||
|         if request.method == 'POST': | ||||
|             if 'create' in request.POST: | ||||
|             secrets_all.append( | ||||
|                 { | ||||
|                     "usage": secrt.usageID(), | ||||
|                     "uuid": secrt.UUIDString(), | ||||
|                     "usageType": secret_usage_types[secrt.usageType()], | ||||
|                     "value": secrt_value, | ||||
|                 } | ||||
|             ) | ||||
|         if request.method == "POST": | ||||
|             if "create" in request.POST: | ||||
|                 form = AddSecret(request.POST) | ||||
|                 if form.is_valid(): | ||||
|                     data = form.cleaned_data | ||||
|                     conn.create_secret( | ||||
|                         data['ephemeral'], | ||||
|                         data['private'], | ||||
|                         data['usage_type'], | ||||
|                         data['data'], | ||||
|                         data["ephemeral"], | ||||
|                         data["private"], | ||||
|                         data["usage_type"], | ||||
|                         data["data"], | ||||
|                     ) | ||||
|                     return HttpResponseRedirect(request.get_full_path()) | ||||
|                 else: | ||||
|                     for msg_err in form.errors.values(): | ||||
|                         messages.error(request, msg_err.as_text()) | ||||
|             if 'delete' in request.POST: | ||||
|                 uuid = request.POST.get('uuid', '') | ||||
|             if "delete" in request.POST: | ||||
|                 uuid = request.POST.get("uuid", "") | ||||
|                 conn.delete_secret(uuid) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|             if 'set_value' in request.POST: | ||||
|                 uuid = request.POST.get('uuid', '') | ||||
|                 value = request.POST.get('value', '') | ||||
|             if "set_value" in request.POST: | ||||
|                 uuid = request.POST.get("uuid", "") | ||||
|                 value = request.POST.get("value", "") | ||||
|                 try: | ||||
|                     conn.set_secret_value(uuid, value) | ||||
|                 except Exception as err: | ||||
|  | @ -74,4 +82,4 @@ def secrets(request, compute_id): | |||
|     except libvirtError as err: | ||||
|         messages.error(request, err) | ||||
| 
 | ||||
|     return render(request, 'secrets.html', locals()) | ||||
|     return render(request, "secrets.html", locals()) | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import re | ||||
| 
 | ||||
| from django import forms | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ from django.utils.translation import gettext_lazy as _ | |||
| from libvirt import libvirtError | ||||
| 
 | ||||
| from admin.decorators import superuser_only | ||||
| from appsettings.models import AppSettings | ||||
| from appsettings.settings import app_settings | ||||
| from computes.models import Compute | ||||
| from storages.forms import AddStgPool, CloneImage, CreateVolumeForm | ||||
|  | @ -31,34 +30,46 @@ def storages(request, compute_id): | |||
|         storages = conn.get_storages_info() | ||||
|         secrets = conn.get_secrets() | ||||
| 
 | ||||
|         if request.method == 'POST': | ||||
|             if 'create' in request.POST: | ||||
|         if request.method == "POST": | ||||
|             if "create" in request.POST: | ||||
|                 form = AddStgPool(request.POST) | ||||
|                 if form.is_valid(): | ||||
|                     data = form.cleaned_data | ||||
|                     if data['name'] in storages: | ||||
|                     if data["name"] in storages: | ||||
|                         msg = _("Pool name already use") | ||||
|                         messages.error(request, msg) | ||||
|                         errors = True | ||||
|                     if data['stg_type'] == 'rbd': | ||||
|                         if not data['secret']: | ||||
|                     if data["stg_type"] == "rbd": | ||||
|                         if not data["secret"]: | ||||
|                             msg = _("You need create secret for pool") | ||||
|                             messages.error(request, msg) | ||||
|                             errors = True | ||||
|                         if not data['ceph_pool'] and not data['ceph_host'] and not data['ceph_user']: | ||||
|                         if not data["ceph_pool"] and not data["ceph_host"] and not data["ceph_user"]: | ||||
|                             msg = _("You need input all fields for creating ceph pool") | ||||
|                             messages.error(request, msg) | ||||
|                             errors = True | ||||
|                     if not errors: | ||||
|                         if data['stg_type'] == 'rbd': | ||||
|                             conn.create_storage_ceph(data['stg_type'], data['name'], data['ceph_pool'], data['ceph_host'], | ||||
|                                                      data['ceph_user'], data['secret']) | ||||
|                         elif data['stg_type'] == 'netfs': | ||||
|                             conn.create_storage_netfs(data['stg_type'], data['name'], data['netfs_host'], data['source'], | ||||
|                                                       data['source_format'], data['target']) | ||||
|                         if data["stg_type"] == "rbd": | ||||
|                             conn.create_storage_ceph( | ||||
|                                 data["stg_type"], | ||||
|                                 data["name"], | ||||
|                                 data["ceph_pool"], | ||||
|                                 data["ceph_host"], | ||||
|                                 data["ceph_user"], | ||||
|                                 data["secret"], | ||||
|                             ) | ||||
|                         elif data["stg_type"] == "netfs": | ||||
|                             conn.create_storage_netfs( | ||||
|                                 data["stg_type"], | ||||
|                                 data["name"], | ||||
|                                 data["netfs_host"], | ||||
|                                 data["source"], | ||||
|                                 data["source_format"], | ||||
|                                 data["target"], | ||||
|                             ) | ||||
|                         else: | ||||
|                             conn.create_storage(data['stg_type'], data['name'], data['source'], data['target']) | ||||
|                         return HttpResponseRedirect(reverse('storage', args=[compute_id, data['name']])) | ||||
|                             conn.create_storage(data["stg_type"], data["name"], data["source"], data["target"]) | ||||
|                         return HttpResponseRedirect(reverse("storage", args=[compute_id, data["name"]])) | ||||
|                 else: | ||||
|                     for msg_err in form.errors.values(): | ||||
|                         messages.error(request, msg_err.as_text()) | ||||
|  | @ -66,7 +77,7 @@ def storages(request, compute_id): | |||
|     except libvirtError as lib_err: | ||||
|         messages.error(request, lib_err) | ||||
| 
 | ||||
|     return render(request, 'storages.html', locals()) | ||||
|     return render(request, "storages.html", locals()) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
|  | @ -77,9 +88,10 @@ def storage(request, compute_id, pool): | |||
|     :param pool: | ||||
|     :return: | ||||
|     """ | ||||
| 
 | ||||
|     def handle_uploaded_file(path, f_name): | ||||
|         target = path + '/' + str(f_name) | ||||
|         destination = open(target, 'wb+') | ||||
|         target = path + "/" + str(f_name) | ||||
|         destination = open(target, "wb+") | ||||
|         for chunk in f_name.chunks(): | ||||
|             destination.write(chunk) | ||||
|         destination.close() | ||||
|  | @ -93,7 +105,7 @@ def storage(request, compute_id, pool): | |||
|     storages = conn.get_storages() | ||||
|     state = conn.is_active() | ||||
|     size, free = conn.get_size() | ||||
|     used = (size - free) | ||||
|     used = size - free | ||||
|     if state: | ||||
|         percent = (used * 100) // size | ||||
|     else: | ||||
|  | @ -109,55 +121,58 @@ def storage(request, compute_id, pool): | |||
|     else: | ||||
|         volumes = None | ||||
| 
 | ||||
|     if request.method == 'POST': | ||||
|         if 'start' in request.POST: | ||||
|     if request.method == "POST": | ||||
|         if "start" in request.POST: | ||||
|             conn.start() | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'stop' in request.POST: | ||||
|         if "stop" in request.POST: | ||||
|             conn.stop() | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'delete' in request.POST: | ||||
|         if "delete" in request.POST: | ||||
|             conn.delete() | ||||
|             return HttpResponseRedirect(reverse('storages', args=[compute_id])) | ||||
|         if 'set_autostart' in request.POST: | ||||
|             return HttpResponseRedirect(reverse("storages", args=[compute_id])) | ||||
|         if "set_autostart" in request.POST: | ||||
|             conn.set_autostart(1) | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'unset_autostart' in request.POST: | ||||
|         if "unset_autostart" in request.POST: | ||||
|             conn.set_autostart(0) | ||||
|             return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'del_volume' in request.POST: | ||||
|             volname = request.POST.get('volname', '') | ||||
|         if "del_volume" in request.POST: | ||||
|             volname = request.POST.get("volname", "") | ||||
|             vol = conn.get_volume(volname) | ||||
|             vol.delete(0) | ||||
|             messages.success(request, _(f"Volume: {volname} is deleted.")) | ||||
|             return redirect(reverse('storage', args=[compute.id, pool])) | ||||
|             messages.success(request, _("Volume: %(volume)s is deleted.") % {"vol": volname}) | ||||
|             return redirect(reverse("storage", args=[compute.id, pool])) | ||||
|             # return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'iso_upload' in request.POST: | ||||
|             if str(request.FILES['file']) in conn.update_volumes(): | ||||
|         if "iso_upload" in request.POST: | ||||
|             if str(request.FILES["file"]) in conn.update_volumes(): | ||||
|                 error_msg = _("ISO image already exist") | ||||
|                 messages.error(request, error_msg) | ||||
|             else: | ||||
|                 handle_uploaded_file(path, request.FILES['file']) | ||||
|                 messages.success(request, _(f"ISO: {request.FILES['file']} is uploaded.")) | ||||
|                 handle_uploaded_file(path, request.FILES["file"]) | ||||
|                 messages.success(request, _("ISO: %(file)s is uploaded.") % {"file": request.FILES["file"]}) | ||||
|                 return HttpResponseRedirect(request.get_full_path()) | ||||
|         if 'cln_volume' in request.POST: | ||||
|         if "cln_volume" in request.POST: | ||||
|             form = CloneImage(request.POST) | ||||
|             if form.is_valid(): | ||||
|                 data = form.cleaned_data | ||||
|                 img_name = data['name'] | ||||
|                 img_name = data["name"] | ||||
|                 meta_prealloc = 0 | ||||
|                 if img_name in conn.update_volumes(): | ||||
|                     msg = _("Name of volume already in use") | ||||
|                     messages.error(request, msg) | ||||
|                 if data['convert']: | ||||
|                     format = data['format'] | ||||
|                     if data['meta_prealloc'] and data['format'] == 'qcow2': | ||||
|                 if data["convert"]: | ||||
|                     format = data["format"] | ||||
|                     if data["meta_prealloc"] and data["format"] == "qcow2": | ||||
|                         meta_prealloc = True | ||||
|                 else: | ||||
|                     format = None | ||||
|                 try: | ||||
|                     name = conn.clone_volume(data['image'], data['name'], format, meta_prealloc) | ||||
|                     messages.success(request, _(f"{data['image']} image cloned as {name} successfully")) | ||||
|                     name = conn.clone_volume(data["image"], data["name"], format, meta_prealloc) | ||||
|                     messages.success( | ||||
|                         request, | ||||
|                         _("%(image)s image cloned as %(clone)s successfully") % {"image": data["image"], "name": name}, | ||||
|                     ) | ||||
|                     return HttpResponseRedirect(request.get_full_path()) | ||||
|                 except libvirtError as lib_err: | ||||
|                     messages.error(request, lib_err) | ||||
|  | @ -167,11 +182,17 @@ def storage(request, compute_id, pool): | |||
| 
 | ||||
|     conn.close() | ||||
| 
 | ||||
|     return render(request, 'storage.html', locals()) | ||||
|     return render(request, "storage.html", locals()) | ||||
| 
 | ||||
| 
 | ||||
| @superuser_only | ||||
| def create_volume(request, compute_id, pool): | ||||
|     """ | ||||
|     :param request: | ||||
|     :param compute_id: compute id | ||||
|     :param pool: pool name | ||||
|     :return: | ||||
|     """ | ||||
|     compute = get_object_or_404(Compute, pk=compute_id) | ||||
|     meta_prealloc = False | ||||
| 
 | ||||
|  | @ -182,26 +203,26 @@ def create_volume(request, compute_id, pool): | |||
|     form = CreateVolumeForm(request.POST or None) | ||||
|     if form.is_valid(): | ||||
|         data = form.cleaned_data | ||||
|         if data['meta_prealloc'] and data['format'] == 'qcow2': | ||||
|         if data["meta_prealloc"] and data["format"] == "qcow2": | ||||
|             meta_prealloc = True | ||||
| 
 | ||||
|         disk_owner_uid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID) | ||||
|         disk_owner_gid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_GID) | ||||
| 
 | ||||
|         name = conn.create_volume( | ||||
|             data['name'], | ||||
|             data['size'], | ||||
|             data['format'], | ||||
|             data["name"], | ||||
|             data["size"], | ||||
|             data["format"], | ||||
|             meta_prealloc, | ||||
|             disk_owner_uid, | ||||
|             disk_owner_gid, | ||||
|         ) | ||||
|         messages.success(request, _(f"Image file {name} is created successfully")) | ||||
|         messages.success(request, _("Image file %(name)s is created successfully") % {"name": name}) | ||||
|     else: | ||||
|         for msg_err in form.errors.values(): | ||||
|             messages.error(request, msg_err.as_text()) | ||||
| 
 | ||||
|     return redirect(reverse('storage', args=[compute.id, pool])) | ||||
|     return redirect(reverse("storage", args=[compute.id, pool])) | ||||
| 
 | ||||
| 
 | ||||
| def get_volumes(request, compute_id, pool): | ||||
|  | @ -216,7 +237,7 @@ def get_volumes(request, compute_id, pool): | |||
|     try: | ||||
|         conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pool) | ||||
|         conn.refresh() | ||||
|         data['vols'] = sorted(conn.get_volumes()) | ||||
|         data["vols"] = sorted(conn.get_volumes()) | ||||
|     except libvirtError: | ||||
|         pass | ||||
|     return HttpResponse(json.dumps(data)) | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ Further Information might be available at: | |||
| https://github.com/haypo/python-ipy | ||||
| """ | ||||
| 
 | ||||
| __version__ = '1.00' | ||||
| __version__ = "1.00" | ||||
| 
 | ||||
| import bisect | ||||
| import collections | ||||
|  | @ -17,16 +17,16 @@ import types | |||
| # this should include www.iana.org/assignments/ipv4-address-space | ||||
| # and www.iana.org/assignments/multicast-addresses | ||||
| IPv4ranges = { | ||||
|     '0': 'PUBLIC',  # fall back | ||||
|     '00000000': 'PRIVATE',  # 0/8 | ||||
|     '00001010': 'PRIVATE',  # 10/8 | ||||
|     '0110010001': 'CARRIER_GRADE_NAT',  # 100.64/10 | ||||
|     '01111111': 'LOOPBACK',  # 127.0/8 | ||||
|     '1': 'PUBLIC',  # fall back | ||||
|     '1010100111111110': 'PRIVATE',  # 169.254/16 | ||||
|     '101011000001': 'PRIVATE',  # 172.16/12 | ||||
|     '1100000010101000': 'PRIVATE',  # 192.168/16 | ||||
|     '111': 'RESERVED',  # 224/3 | ||||
|     "0": "PUBLIC",  # fall back | ||||
|     "00000000": "PRIVATE",  # 0/8 | ||||
|     "00001010": "PRIVATE",  # 10/8 | ||||
|     "0110010001": "CARRIER_GRADE_NAT",  # 100.64/10 | ||||
|     "01111111": "LOOPBACK",  # 127.0/8 | ||||
|     "1": "PUBLIC",  # fall back | ||||
|     "1010100111111110": "PRIVATE",  # 169.254/16 | ||||
|     "101011000001": "PRIVATE",  # 172.16/12 | ||||
|     "1100000010101000": "PRIVATE",  # 192.168/16 | ||||
|     "111": "RESERVED",  # 224/3 | ||||
| } | ||||
| 
 | ||||
| # Definition of the Ranges for IPv6 IPs | ||||
|  | @ -34,92 +34,92 @@ IPv4ranges = { | |||
| # http://www.iana.org/assignments/ipv6-unicast-address-assignments/ | ||||
| # http://www.iana.org/assignments/ipv6-multicast-addresses/ | ||||
| IPv6ranges = { | ||||
|     '00000000': 'RESERVED',  # ::/8 | ||||
|     '0' * 96: 'RESERVED',  # ::/96 Formerly IPV4COMP [RFC4291] | ||||
|     '0' * 128: 'UNSPECIFIED',  # ::/128 | ||||
|     '0' * 127 + '1': 'LOOPBACK',  # ::1/128 | ||||
|     '0' * 80 + '1' * 16: 'IPV4MAP',  # ::ffff:0:0/96 | ||||
|     '00000000011001001111111110011011' + '0' * 64: 'WKP46TRANS',  # 0064:ff9b::/96 Well-Known-Prefix [RFC6052] | ||||
|     '00000001': 'UNASSIGNED',  # 0100::/8 | ||||
|     '0000001': 'RESERVED',  # 0200::/7 Formerly NSAP [RFC4048] | ||||
|     '0000010': 'RESERVED',  # 0400::/7 Formerly IPX [RFC3513] | ||||
|     '0000011': 'RESERVED',  # 0600::/7 | ||||
|     '00001': 'RESERVED',  # 0800::/5 | ||||
|     '0001': 'RESERVED',  # 1000::/4 | ||||
|     '001': 'GLOBAL-UNICAST',  # 2000::/3 [RFC4291] | ||||
|     '00100000000000010000000': 'SPECIALPURPOSE',  # 2001::/23 [RFC4773] | ||||
|     '00100000000000010000000000000000': 'TEREDO',  # 2001::/32 [RFC4380] | ||||
|     '00100000000000010000000000000010' + '0' * 16: 'BMWG',  # 2001:0002::/48 Benchmarking [RFC5180] | ||||
|     '0010000000000001000000000001': 'ORCHID',  # 2001:0010::/28 (Temp until 2014-03-21) [RFC4843] | ||||
|     '00100000000000010000001': 'ALLOCATED APNIC',  # 2001:0200::/23 | ||||
|     '00100000000000010000010': 'ALLOCATED ARIN',  # 2001:0400::/23 | ||||
|     '00100000000000010000011': 'ALLOCATED RIPE NCC',  # 2001:0600::/23 | ||||
|     '00100000000000010000100': 'ALLOCATED RIPE NCC',  # 2001:0800::/23 | ||||
|     '00100000000000010000101': 'ALLOCATED RIPE NCC',  # 2001:0a00::/23 | ||||
|     '00100000000000010000110': 'ALLOCATED APNIC',  # 2001:0c00::/23 | ||||
|     '00100000000000010000110110111000': 'DOCUMENTATION',  # 2001:0db8::/32 [RFC3849] | ||||
|     '00100000000000010000111': 'ALLOCATED APNIC',  # 2001:0e00::/23 | ||||
|     '00100000000000010001001': 'ALLOCATED LACNIC',  # 2001:1200::/23 | ||||
|     '00100000000000010001010': 'ALLOCATED RIPE NCC',  # 2001:1400::/23 | ||||
|     '00100000000000010001011': 'ALLOCATED RIPE NCC',  # 2001:1600::/23 | ||||
|     '00100000000000010001100': 'ALLOCATED ARIN',  # 2001:1800::/23 | ||||
|     '00100000000000010001101': 'ALLOCATED RIPE NCC',  # 2001:1a00::/23 | ||||
|     '0010000000000001000111': 'ALLOCATED RIPE NCC',  # 2001:1c00::/22 | ||||
|     '00100000000000010010': 'ALLOCATED RIPE NCC',  # 2001:2000::/20 | ||||
|     '001000000000000100110': 'ALLOCATED RIPE NCC',  # 2001:3000::/21 | ||||
|     '0010000000000001001110': 'ALLOCATED RIPE NCC',  # 2001:3800::/22 | ||||
|     '0010000000000001001111': 'RESERVED',  # 2001:3c00::/22 Possible future allocation to RIPE NCC | ||||
|     '00100000000000010100000': 'ALLOCATED RIPE NCC',  # 2001:4000::/23 | ||||
|     '00100000000000010100001': 'ALLOCATED AFRINIC',  # 2001:4200::/23 | ||||
|     '00100000000000010100010': 'ALLOCATED APNIC',  # 2001:4400::/23 | ||||
|     '00100000000000010100011': 'ALLOCATED RIPE NCC',  # 2001:4600::/23 | ||||
|     '00100000000000010100100': 'ALLOCATED ARIN',  # 2001:4800::/23 | ||||
|     '00100000000000010100101': 'ALLOCATED RIPE NCC',  # 2001:4a00::/23 | ||||
|     '00100000000000010100110': 'ALLOCATED RIPE NCC',  # 2001:4c00::/23 | ||||
|     '00100000000000010101': 'ALLOCATED RIPE NCC',  # 2001:5000::/20 | ||||
|     '0010000000000001100': 'ALLOCATED APNIC',  # 2001:8000::/19 | ||||
|     '00100000000000011010': 'ALLOCATED APNIC',  # 2001:a000::/20 | ||||
|     '00100000000000011011': 'ALLOCATED APNIC',  # 2001:b000::/20 | ||||
|     '0010000000000010': '6TO4',  # 2002::/16 "6to4" [RFC3056] | ||||
|     '001000000000001100': 'ALLOCATED RIPE NCC',  # 2003::/18 | ||||
|     '001001000000': 'ALLOCATED APNIC',  # 2400::/12 | ||||
|     '001001100000': 'ALLOCATED ARIN',  # 2600::/12 | ||||
|     '00100110000100000000000': 'ALLOCATED ARIN',  # 2610::/23 | ||||
|     '00100110001000000000000': 'ALLOCATED ARIN',  # 2620::/23 | ||||
|     '001010000000': 'ALLOCATED LACNIC',  # 2800::/12 | ||||
|     '001010100000': 'ALLOCATED RIPE NCC',  # 2a00::/12 | ||||
|     '001011000000': 'ALLOCATED AFRINIC',  # 2c00::/12 | ||||
|     '00101101': 'RESERVED',  # 2d00::/8 | ||||
|     '0010111': 'RESERVED',  # 2e00::/7 | ||||
|     '0011': 'RESERVED',  # 3000::/4 | ||||
|     '010': 'RESERVED',  # 4000::/3 | ||||
|     '011': 'RESERVED',  # 6000::/3 | ||||
|     '100': 'RESERVED',  # 8000::/3 | ||||
|     '101': 'RESERVED',  # a000::/3 | ||||
|     '110': 'RESERVED',  # c000::/3 | ||||
|     '1110': 'RESERVED',  # e000::/4 | ||||
|     '11110': 'RESERVED',  # f000::/5 | ||||
|     '111110': 'RESERVED',  # f800::/6 | ||||
|     '1111110': 'ULA',  # fc00::/7 [RFC4193] | ||||
|     '111111100': 'RESERVED',  # fe00::/9 | ||||
|     '1111111010': 'LINKLOCAL',  # fe80::/10 | ||||
|     '1111111011': 'RESERVED',  # fec0::/10 Formerly SITELOCAL [RFC4291] | ||||
|     '11111111': 'MULTICAST',  # ff00::/8 | ||||
|     '1111111100000001': 'NODE-LOCAL MULTICAST',  # ff01::/16 | ||||
|     '1111111100000010': 'LINK-LOCAL MULTICAST',  # ff02::/16 | ||||
|     '1111111100000100': 'ADMIN-LOCAL MULTICAST',  # ff04::/16 | ||||
|     '1111111100000101': 'SITE-LOCAL MULTICAST',  # ff05::/16 | ||||
|     '1111111100001000': 'ORG-LOCAL MULTICAST',  # ff08::/16 | ||||
|     '1111111100001110': 'GLOBAL MULTICAST',  # ff0e::/16 | ||||
|     '1111111100001111': 'RESERVED MULTICAST',  # ff0f::/16 | ||||
|     '111111110011': 'PREFIX-BASED MULTICAST',  # ff30::/12 [RFC3306] | ||||
|     '111111110111': 'RP-EMBEDDED MULTICAST',  # ff70::/12 [RFC3956] | ||||
|     "00000000": "RESERVED",  # ::/8 | ||||
|     "0" * 96: "RESERVED",  # ::/96 Formerly IPV4COMP [RFC4291] | ||||
|     "0" * 128: "UNSPECIFIED",  # ::/128 | ||||
|     "0" * 127 + "1": "LOOPBACK",  # ::1/128 | ||||
|     "0" * 80 + "1" * 16: "IPV4MAP",  # ::ffff:0:0/96 | ||||
|     "00000000011001001111111110011011" + "0" * 64: "WKP46TRANS",  # 0064:ff9b::/96 Well-Known-Prefix [RFC6052] | ||||
|     "00000001": "UNASSIGNED",  # 0100::/8 | ||||
|     "0000001": "RESERVED",  # 0200::/7 Formerly NSAP [RFC4048] | ||||
|     "0000010": "RESERVED",  # 0400::/7 Formerly IPX [RFC3513] | ||||
|     "0000011": "RESERVED",  # 0600::/7 | ||||
|     "00001": "RESERVED",  # 0800::/5 | ||||
|     "0001": "RESERVED",  # 1000::/4 | ||||
|     "001": "GLOBAL-UNICAST",  # 2000::/3 [RFC4291] | ||||
|     "00100000000000010000000": "SPECIALPURPOSE",  # 2001::/23 [RFC4773] | ||||
|     "00100000000000010000000000000000": "TEREDO",  # 2001::/32 [RFC4380] | ||||
|     "00100000000000010000000000000010" + "0" * 16: "BMWG",  # 2001:0002::/48 Benchmarking [RFC5180] | ||||
|     "0010000000000001000000000001": "ORCHID",  # 2001:0010::/28 (Temp until 2014-03-21) [RFC4843] | ||||
|     "00100000000000010000001": "ALLOCATED APNIC",  # 2001:0200::/23 | ||||
|     "00100000000000010000010": "ALLOCATED ARIN",  # 2001:0400::/23 | ||||
|     "00100000000000010000011": "ALLOCATED RIPE NCC",  # 2001:0600::/23 | ||||
|     "00100000000000010000100": "ALLOCATED RIPE NCC",  # 2001:0800::/23 | ||||
|     "00100000000000010000101": "ALLOCATED RIPE NCC",  # 2001:0a00::/23 | ||||
|     "00100000000000010000110": "ALLOCATED APNIC",  # 2001:0c00::/23 | ||||
|     "00100000000000010000110110111000": "DOCUMENTATION",  # 2001:0db8::/32 [RFC3849] | ||||
|     "00100000000000010000111": "ALLOCATED APNIC",  # 2001:0e00::/23 | ||||
|     "00100000000000010001001": "ALLOCATED LACNIC",  # 2001:1200::/23 | ||||
|     "00100000000000010001010": "ALLOCATED RIPE NCC",  # 2001:1400::/23 | ||||
|     "00100000000000010001011": "ALLOCATED RIPE NCC",  # 2001:1600::/23 | ||||
|     "00100000000000010001100": "ALLOCATED ARIN",  # 2001:1800::/23 | ||||
|     "00100000000000010001101": "ALLOCATED RIPE NCC",  # 2001:1a00::/23 | ||||
|     "0010000000000001000111": "ALLOCATED RIPE NCC",  # 2001:1c00::/22 | ||||
|     "00100000000000010010": "ALLOCATED RIPE NCC",  # 2001:2000::/20 | ||||
|     "001000000000000100110": "ALLOCATED RIPE NCC",  # 2001:3000::/21 | ||||
|     "0010000000000001001110": "ALLOCATED RIPE NCC",  # 2001:3800::/22 | ||||
|     "0010000000000001001111": "RESERVED",  # 2001:3c00::/22 Possible future allocation to RIPE NCC | ||||
|     "00100000000000010100000": "ALLOCATED RIPE NCC",  # 2001:4000::/23 | ||||
|     "00100000000000010100001": "ALLOCATED AFRINIC",  # 2001:4200::/23 | ||||
|     "00100000000000010100010": "ALLOCATED APNIC",  # 2001:4400::/23 | ||||
|     "00100000000000010100011": "ALLOCATED RIPE NCC",  # 2001:4600::/23 | ||||
|     "00100000000000010100100": "ALLOCATED ARIN",  # 2001:4800::/23 | ||||
|     "00100000000000010100101": "ALLOCATED RIPE NCC",  # 2001:4a00::/23 | ||||
|     "00100000000000010100110": "ALLOCATED RIPE NCC",  # 2001:4c00::/23 | ||||
|     "00100000000000010101": "ALLOCATED RIPE NCC",  # 2001:5000::/20 | ||||
|     "0010000000000001100": "ALLOCATED APNIC",  # 2001:8000::/19 | ||||
|     "00100000000000011010": "ALLOCATED APNIC",  # 2001:a000::/20 | ||||
|     "00100000000000011011": "ALLOCATED APNIC",  # 2001:b000::/20 | ||||
|     "0010000000000010": "6TO4",  # 2002::/16 "6to4" [RFC3056] | ||||
|     "001000000000001100": "ALLOCATED RIPE NCC",  # 2003::/18 | ||||
|     "001001000000": "ALLOCATED APNIC",  # 2400::/12 | ||||
|     "001001100000": "ALLOCATED ARIN",  # 2600::/12 | ||||
|     "00100110000100000000000": "ALLOCATED ARIN",  # 2610::/23 | ||||
|     "00100110001000000000000": "ALLOCATED ARIN",  # 2620::/23 | ||||
|     "001010000000": "ALLOCATED LACNIC",  # 2800::/12 | ||||
|     "001010100000": "ALLOCATED RIPE NCC",  # 2a00::/12 | ||||
|     "001011000000": "ALLOCATED AFRINIC",  # 2c00::/12 | ||||
|     "00101101": "RESERVED",  # 2d00::/8 | ||||
|     "0010111": "RESERVED",  # 2e00::/7 | ||||
|     "0011": "RESERVED",  # 3000::/4 | ||||
|     "010": "RESERVED",  # 4000::/3 | ||||
|     "011": "RESERVED",  # 6000::/3 | ||||
|     "100": "RESERVED",  # 8000::/3 | ||||
|     "101": "RESERVED",  # a000::/3 | ||||
|     "110": "RESERVED",  # c000::/3 | ||||
|     "1110": "RESERVED",  # e000::/4 | ||||
|     "11110": "RESERVED",  # f000::/5 | ||||
|     "111110": "RESERVED",  # f800::/6 | ||||
|     "1111110": "ULA",  # fc00::/7 [RFC4193] | ||||
|     "111111100": "RESERVED",  # fe00::/9 | ||||
|     "1111111010": "LINKLOCAL",  # fe80::/10 | ||||
|     "1111111011": "RESERVED",  # fec0::/10 Formerly SITELOCAL [RFC4291] | ||||
|     "11111111": "MULTICAST",  # ff00::/8 | ||||
|     "1111111100000001": "NODE-LOCAL MULTICAST",  # ff01::/16 | ||||
|     "1111111100000010": "LINK-LOCAL MULTICAST",  # ff02::/16 | ||||
|     "1111111100000100": "ADMIN-LOCAL MULTICAST",  # ff04::/16 | ||||
|     "1111111100000101": "SITE-LOCAL MULTICAST",  # ff05::/16 | ||||
|     "1111111100001000": "ORG-LOCAL MULTICAST",  # ff08::/16 | ||||
|     "1111111100001110": "GLOBAL MULTICAST",  # ff0e::/16 | ||||
|     "1111111100001111": "RESERVED MULTICAST",  # ff0f::/16 | ||||
|     "111111110011": "PREFIX-BASED MULTICAST",  # ff30::/12 [RFC3306] | ||||
|     "111111110111": "RP-EMBEDDED MULTICAST",  # ff70::/12 [RFC3956] | ||||
| } | ||||
| 
 | ||||
| MAX_IPV4_ADDRESS = 0xffffffff | ||||
| MAX_IPV6_ADDRESS = 0xffffffffffffffffffffffffffffffff | ||||
| IPV6_TEST_MAP = 0xffffffffffffffffffffffff00000000 | ||||
| IPV6_MAP_MASK = 0x00000000000000000000ffff00000000 | ||||
| MAX_IPV4_ADDRESS = 0xFFFFFFFF | ||||
| MAX_IPV6_ADDRESS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF | ||||
| IPV6_TEST_MAP = 0xFFFFFFFFFFFFFFFFFFFFFFFF00000000 | ||||
| IPV6_MAP_MASK = 0x00000000000000000000FFFF00000000 | ||||
| 
 | ||||
| if sys.version_info >= (3,): | ||||
|     INT_TYPES = (int,) | ||||
|  | @ -202,7 +202,7 @@ class IPint(object): | |||
|         elif isinstance(data, STR_TYPES): | ||||
|             # TODO: refactor me! | ||||
|             # splitting of a string into IP and prefixlen et. al. | ||||
|             x = data.split('-') | ||||
|             x = data.split("-") | ||||
|             if len(x) == 2: | ||||
|                 # a.b.c.0-a.b.c.255 specification ? | ||||
|                 (ip, last) = x | ||||
|  | @ -219,10 +219,10 @@ class IPint(object): | |||
|                 # make sure the broadcast is the same as the last ip | ||||
|                 # otherwise it will return /16 for something like: | ||||
|                 # 192.168.0.0-192.168.191.255 | ||||
|                 if IP('%s/%s' % (ip, 32 - netbits)).broadcast().int() != last: | ||||
|                 if IP("%s/%s" % (ip, 32 - netbits)).broadcast().int() != last: | ||||
|                     raise ValueError("the range %s is not on a network boundary." % data) | ||||
|             elif len(x) == 1: | ||||
|                 x = data.split('/') | ||||
|                 x = data.split("/") | ||||
|                 # if no prefix is given use defaults | ||||
|                 if len(x) == 1: | ||||
|                     ip = x[0] | ||||
|  | @ -231,7 +231,7 @@ class IPint(object): | |||
|                     raise ValueError("only one '/' allowed in IP Address") | ||||
|                 else: | ||||
|                     (ip, prefixlen) = x | ||||
|                     if prefixlen.find('.') != -1: | ||||
|                     if prefixlen.find(".") != -1: | ||||
|                         # check if the user might have used a netmask like | ||||
|                         # a.b.c.d/255.255.255.0 | ||||
|                         (netmask, vers) = parseAddress(prefixlen) | ||||
|  | @ -255,8 +255,7 @@ class IPint(object): | |||
|             if make_net: | ||||
|                 self.ip = self.ip & _prefixlenToNetmask(self._prefixlen, self._ipversion) | ||||
| 
 | ||||
|             if not _checkNetaddrWorksWithPrefixlen(self.ip, | ||||
|                                                    self._prefixlen, self._ipversion): | ||||
|             if not _checkNetaddrWorksWithPrefixlen(self.ip, self._prefixlen, self._ipversion): | ||||
|                 raise ValueError("%s has invalid prefix length (%s)" % (repr(self), self._prefixlen)) | ||||
|         else: | ||||
|             raise TypeError("Unsupported data type: %s" % type(data)) | ||||
|  | @ -314,8 +313,7 @@ class IPint(object): | |||
|         want == 3               -lastip                  1.2.3.0-1.2.3.255 | ||||
|         """ | ||||
| 
 | ||||
|         if (self._ipversion == 4 and self._prefixlen == 32) or \ | ||||
|                 (self._ipversion == 6 and self._prefixlen == 128): | ||||
|         if (self._ipversion == 4 and self._prefixlen == 32) or (self._ipversion == 6 and self._prefixlen == 128): | ||||
|             if self.NoPrefixForSingleIp: | ||||
|                 want = 0 | ||||
|         if want is None: | ||||
|  | @ -335,7 +333,7 @@ class IPint(object): | |||
|                 # default | ||||
|                 return "/%d" % (self._prefixlen) | ||||
|         else: | ||||
|             return '' | ||||
|             return "" | ||||
| 
 | ||||
|         # We have different flavours to convert to: | ||||
|         # strFullsize   127.0.0.1    2001:0658:022a:cafe:0200:c0ff:fe8d:08fa | ||||
|  | @ -357,7 +355,7 @@ class IPint(object): | |||
|         if self.WantPrefixLen is None and wantprefixlen is None: | ||||
|             wantprefixlen = 0 | ||||
|         ret = _intToBin(self.ip) | ||||
|         return '0' * (bits - len(ret)) + ret + self._printPrefix(wantprefixlen) | ||||
|         return "0" * (bits - len(ret)) + ret + self._printPrefix(wantprefixlen) | ||||
| 
 | ||||
|     def strCompressed(self, wantprefixlen=None): | ||||
|         """Return a string representation in compressed format using '::' Notation. | ||||
|  | @ -376,12 +374,12 @@ class IPint(object): | |||
|         if self._ipversion == 4: | ||||
|             return self.strFullsize(wantprefixlen) | ||||
|         else: | ||||
|             if self.ip >> 32 == 0xffff: | ||||
|             if self.ip >> 32 == 0xFFFF: | ||||
|                 ipv4 = intToIp(self.ip & MAX_IPV4_ADDRESS, 4) | ||||
|                 text = "::ffff:" + ipv4 + self._printPrefix(wantprefixlen) | ||||
|                 return text | ||||
|             # find the longest sequence of '0' | ||||
|             hextets = [int(x, 16) for x in self.strFullsize(0).split(':')] | ||||
|             hextets = [int(x, 16) for x in self.strFullsize(0).split(":")] | ||||
|             # every element of followingzeros will contain the number of zeros | ||||
|             # following the corresponding element of hextets | ||||
|             followingzeros = [0] * 8 | ||||
|  | @ -392,15 +390,15 @@ class IPint(object): | |||
|             if max(followingzeros) > 1: | ||||
|                 # genererate string with the longest number of zeros cut out | ||||
|                 # now we need hextets as strings | ||||
|                 hextets = [x for x in self.strNormal(0).split(':')] | ||||
|                 while compressionpos < len(hextets) and hextets[compressionpos] == '0': | ||||
|                     del (hextets[compressionpos]) | ||||
|                 hextets.insert(compressionpos, '') | ||||
|                 hextets = [x for x in self.strNormal(0).split(":")] | ||||
|                 while compressionpos < len(hextets) and hextets[compressionpos] == "0": | ||||
|                     del hextets[compressionpos] | ||||
|                 hextets.insert(compressionpos, "") | ||||
|                 if compressionpos + 1 >= len(hextets): | ||||
|                     hextets.append('') | ||||
|                     hextets.append("") | ||||
|                 if compressionpos == 0: | ||||
|                     hextets = [''] + hextets | ||||
|                 return ':'.join(hextets) + self._printPrefix(wantprefixlen) | ||||
|                     hextets = [""] + hextets | ||||
|                 return ":".join(hextets) + self._printPrefix(wantprefixlen) | ||||
|             else: | ||||
|                 return self.strNormal(0) + self._printPrefix(wantprefixlen) | ||||
| 
 | ||||
|  | @ -419,7 +417,7 @@ class IPint(object): | |||
|         if self._ipversion == 4: | ||||
|             ret = self.strFullsize(0) | ||||
|         elif self._ipversion == 6: | ||||
|             ret = ':'.join(["%x" % x for x in [int(x, 16) for x in self.strFullsize(0).split(':')]]) | ||||
|             ret = ":".join(["%x" % x for x in [int(x, 16) for x in self.strFullsize(0).split(":")]]) | ||||
|         else: | ||||
|             raise ValueError("only IPv4 and IPv6 supported") | ||||
| 
 | ||||
|  | @ -451,7 +449,7 @@ class IPint(object): | |||
|         if self.WantPrefixLen is None and wantprefixlen is None: | ||||
|             wantprefixlen = 0 | ||||
| 
 | ||||
|         x = '0x%x' % self.ip | ||||
|         x = "0x%x" % self.ip | ||||
|         return x + self._printPrefix(wantprefixlen) | ||||
| 
 | ||||
|     def strDec(self, wantprefixlen=None): | ||||
|  | @ -466,7 +464,7 @@ class IPint(object): | |||
|         if self.WantPrefixLen is None and wantprefixlen is None: | ||||
|             wantprefixlen = 0 | ||||
| 
 | ||||
|         x = '%d' % self.ip | ||||
|         x = "%d" % self.ip | ||||
|         return x + self._printPrefix(wantprefixlen) | ||||
| 
 | ||||
|     def iptype(self): | ||||
|  | @ -581,10 +579,8 @@ class IPint(object): | |||
|             raise ValueError("Only adjacent networks can be added together.") | ||||
|         ret = IP(self.int(), ipversion=self._ipversion) | ||||
|         ret._prefixlen = self.prefixlen() - 1 | ||||
|         if not _checkNetaddrWorksWithPrefixlen(ret.ip, ret._prefixlen, | ||||
|                                                ret._ipversion): | ||||
|             raise ValueError("The resulting %s has invalid prefix length (%s)" | ||||
|                              % (repr(ret), ret._prefixlen)) | ||||
|         if not _checkNetaddrWorksWithPrefixlen(ret.ip, ret._prefixlen, ret._ipversion): | ||||
|             raise ValueError("The resulting %s has invalid prefix length (%s)" % (repr(ret), ret._prefixlen)) | ||||
|         return ret | ||||
| 
 | ||||
|     def __sub__(self, other): | ||||
|  | @ -692,7 +688,7 @@ class IPint(object): | |||
|         IP('10.0.0.0/24') | ||||
|         """ | ||||
| 
 | ||||
|         return ("IPint('%s')" % (self.strCompressed(1))) | ||||
|         return "IPint('%s')" % (self.strCompressed(1)) | ||||
| 
 | ||||
|     def __cmp__(self, other): | ||||
|         """Called by comparison operations. | ||||
|  | @ -777,7 +773,7 @@ class IPint(object): | |||
|         thehash = int(-1) | ||||
|         ip = self.ip | ||||
|         while ip > 0: | ||||
|             thehash = thehash ^ (ip & 0x7fffffff) | ||||
|             thehash = thehash ^ (ip & 0x7FFFFFFF) | ||||
|             ip = ip >> 32 | ||||
|         thehash = thehash ^ self._prefixlen | ||||
|         return int(thehash) | ||||
|  | @ -811,17 +807,17 @@ class IP(IPint): | |||
| 
 | ||||
|         >>> IP('10.0.0.0/8').netmask() | ||||
|         IP('255.0.0.0') | ||||
|          """ | ||||
|         """ | ||||
|         return IP(IPint.netmask(self), ipversion=self._ipversion) | ||||
| 
 | ||||
|     def _getIPv4Map(self): | ||||
|         if self._ipversion != 6: | ||||
|             return None | ||||
|         if (self.ip >> 32) != 0xffff: | ||||
|         if (self.ip >> 32) != 0xFFFF: | ||||
|             return None | ||||
|         ipv4 = self.ip & MAX_IPV4_ADDRESS | ||||
|         if self._prefixlen != 128: | ||||
|             ipv4 = '%s/%s' % (ipv4, 32 - (128 - self._prefixlen)) | ||||
|             ipv4 = "%s/%s" % (ipv4, 32 - (128 - self._prefixlen)) | ||||
|         return IP(ipv4, ipversion=4) | ||||
| 
 | ||||
|     def reverseNames(self): | ||||
|  | @ -872,7 +868,7 @@ class IP(IPint): | |||
|                 raise NotImplementedError("can't create IPv6 reverse names at sub nibble level") | ||||
|             s = list(s) | ||||
|             s.reverse() | ||||
|             s = '.'.join(s) | ||||
|             s = ".".join(s) | ||||
|             first_nibble_index = int(32 - (self._prefixlen // 4)) * 2 | ||||
|             return ["%s.ip6.arpa." % s[first_nibble_index:]] | ||||
|         else: | ||||
|  | @ -897,32 +893,34 @@ class IP(IPint): | |||
| 
 | ||||
|         if self._ipversion == 4: | ||||
|             s = self.strFullsize(0) | ||||
|             s = s.split('.') | ||||
|             s = s.split(".") | ||||
|             s.reverse() | ||||
|             first_byte_index = int(4 - (self._prefixlen // 8)) | ||||
|             if self._prefixlen % 8 != 0: | ||||
|                 nibblepart = "%s-%s" % ( | ||||
|                 s[3 - (self._prefixlen // 8)], intToIp(self.ip + self.len() - 1, 4).split('.')[-1]) | ||||
|                 nibblepart += '.' | ||||
|                     s[3 - (self._prefixlen // 8)], | ||||
|                     intToIp(self.ip + self.len() - 1, 4).split(".")[-1], | ||||
|                 ) | ||||
|                 nibblepart += "." | ||||
|             else: | ||||
|                 nibblepart = "" | ||||
| 
 | ||||
|             s = '.'.join(s[first_byte_index:]) | ||||
|             s = ".".join(s[first_byte_index:]) | ||||
|             return "%s%s.in-addr.arpa." % (nibblepart, s) | ||||
| 
 | ||||
|         elif self._ipversion == 6: | ||||
|             ipv4 = self._getIPv4Map() | ||||
|             if ipv4 is not None: | ||||
|                 return ipv4.reverseName() | ||||
|             s = '%032x' % self.ip | ||||
|             s = "%032x" % self.ip | ||||
|             if self._prefixlen % 4 != 0: | ||||
|                 nibblepart = "%s-%x" % (s[self._prefixlen:], self.ip + self.len() - 1) | ||||
|                 nibblepart += '.' | ||||
|                 nibblepart = "%s-%x" % (s[self._prefixlen :], self.ip + self.len() - 1) | ||||
|                 nibblepart += "." | ||||
|             else: | ||||
|                 nibblepart = "" | ||||
|             s = list(s) | ||||
|             s.reverse() | ||||
|             s = '.'.join(s) | ||||
|             s = ".".join(s) | ||||
|             first_nibble_index = int(32 - (self._prefixlen // 4)) * 2 | ||||
|             return "%s%s.ip6.arpa." % (nibblepart, s[first_nibble_index:]) | ||||
|         else: | ||||
|  | @ -937,9 +935,9 @@ class IP(IPint): | |||
|         >>> print(IP('127.0.0.1').make_net('255.0.0.0')) | ||||
|         127.0.0.0/8 | ||||
|         """ | ||||
|         if '/' in str(netmask): | ||||
|         if "/" in str(netmask): | ||||
|             raise ValueError("invalid netmask (%s)" % netmask) | ||||
|         return IP('%s/%s' % (self, netmask), make_net=True) | ||||
|         return IP("%s/%s" % (self, netmask), make_net=True) | ||||
| 
 | ||||
|     def __getitem__(self, key): | ||||
|         """Called to implement evaluation of self[key]. | ||||
|  | @ -968,7 +966,7 @@ class IP(IPint): | |||
|         IP('10.0.0.0/8') | ||||
|         """ | ||||
| 
 | ||||
|         return ("IP('%s')" % (self.strCompressed(1))) | ||||
|         return "IP('%s')" % (self.strCompressed(1)) | ||||
| 
 | ||||
|     def get_mac(self): | ||||
|         """ | ||||
|  | @ -980,15 +978,15 @@ class IP(IPint): | |||
|         """ | ||||
|         if self._ipversion != 6: | ||||
|             return None | ||||
|         if (self.ip & 0x20000ffff000000) != 0x20000fffe000000: | ||||
|         if (self.ip & 0x20000FFFF000000) != 0x20000FFFE000000: | ||||
|             return None | ||||
|         return '%02x:%02x:%02x:%02x:%02x:%02x' % ( | ||||
|             (((self.ip >> 56) & 0xff) & 0xfd), | ||||
|             (self.ip >> 48) & 0xff, | ||||
|             (self.ip >> 40) & 0xff, | ||||
|             (self.ip >> 16) & 0xff, | ||||
|             (self.ip >> 8) & 0xff, | ||||
|             self.ip & 0xff, | ||||
|         return "%02x:%02x:%02x:%02x:%02x:%02x" % ( | ||||
|             (((self.ip >> 56) & 0xFF) & 0xFD), | ||||
|             (self.ip >> 48) & 0xFF, | ||||
|             (self.ip >> 40) & 0xFF, | ||||
|             (self.ip >> 16) & 0xFF, | ||||
|             (self.ip >> 8) & 0xFF, | ||||
|             self.ip & 0xFF, | ||||
|         ) | ||||
| 
 | ||||
|     def v46map(self): | ||||
|  | @ -1003,14 +1001,11 @@ class IP(IPint): | |||
|         IP('192.168.1.1') | ||||
|         """ | ||||
|         if self._ipversion == 4: | ||||
|             return IP(str(IPV6_MAP_MASK + self.ip) + | ||||
|                       "/%s" % (self._prefixlen + 96)) | ||||
|             return IP(str(IPV6_MAP_MASK + self.ip) + "/%s" % (self._prefixlen + 96)) | ||||
|         else: | ||||
|             if self.ip & IPV6_TEST_MAP == IPV6_MAP_MASK: | ||||
|                 return IP(str(self.ip - IPV6_MAP_MASK) + | ||||
|                           "/%s" % (self._prefixlen - 96)) | ||||
|         raise ValueError("%s cannot be converted to an IPv4 address." | ||||
|                          % repr(self)) | ||||
|                 return IP(str(self.ip - IPV6_MAP_MASK) + "/%s" % (self._prefixlen - 96)) | ||||
|         raise ValueError("%s cannot be converted to an IPv4 address." % repr(self)) | ||||
| 
 | ||||
| 
 | ||||
| class IPSet(collections.MutableSet): | ||||
|  | @ -1022,7 +1017,7 @@ class IPSet(collections.MutableSet): | |||
|         # Make sure we only accept IP objects | ||||
|         for prefix in iterable: | ||||
|             if not isinstance(prefix, IP): | ||||
|                 raise ValueError('Only IP objects can be added to an IPSet') | ||||
|                 raise ValueError("Only IP objects can be added to an IPSet") | ||||
| 
 | ||||
|         # Store and optimize | ||||
|         self.prefixes = iterable[:] | ||||
|  | @ -1083,7 +1078,7 @@ class IPSet(collections.MutableSet): | |||
|             return IPSet(result) | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return '%s([' % self.__class__.__name__ + ', '.join(map(repr, self.prefixes)) + '])' | ||||
|         return "%s([" % self.__class__.__name__ + ", ".join(map(repr, self.prefixes)) + "])" | ||||
| 
 | ||||
|     def len(self): | ||||
|         return sum(prefix.len() for prefix in self.prefixes) | ||||
|  | @ -1096,7 +1091,7 @@ class IPSet(collections.MutableSet): | |||
|         # Check type | ||||
|         for prefix in value: | ||||
|             if not isinstance(prefix, IP): | ||||
|                 raise ValueError('Only IP objects can be added to an IPSet') | ||||
|                 raise ValueError("Only IP objects can be added to an IPSet") | ||||
| 
 | ||||
|         # Append and optimize | ||||
|         self.prefixes.extend(value) | ||||
|  | @ -1114,7 +1109,7 @@ class IPSet(collections.MutableSet): | |||
|         # Remove | ||||
|         for del_prefix in value: | ||||
|             if not isinstance(del_prefix, IP): | ||||
|                 raise ValueError('Only IP objects can be removed from an IPSet') | ||||
|                 raise ValueError("Only IP objects can be removed from an IPSet") | ||||
| 
 | ||||
|             # First check if this prefix contains anything in our list | ||||
|             found = False | ||||
|  | @ -1134,7 +1129,7 @@ class IPSet(collections.MutableSet): | |||
|             found = False | ||||
|             for i in range(len(self.prefixes)): | ||||
|                 if del_prefix in self.prefixes[i]: | ||||
|                     self.prefixes[i:i + 1] = self.prefixes[i] - del_prefix | ||||
|                     self.prefixes[i : i + 1] = self.prefixes[i] - del_prefix | ||||
|                     break | ||||
| 
 | ||||
|         self.optimize() | ||||
|  | @ -1279,13 +1274,13 @@ def _parseAddressIPv6(ipstr): | |||
|             fill_pos = len(items) | ||||
|             index += 2 | ||||
|             continue | ||||
|         pos = text.find(':') | ||||
|         pos = text.find(":") | ||||
|         if pos == 0: | ||||
|             # Invalid IPv6, eg. '1::2:' | ||||
|             raise ValueError("%r: Invalid IPv6 address" % ipstr) | ||||
|         if pos != -1: | ||||
|             items.append(text[:pos]) | ||||
|             if text[pos:pos + 2] == "::": | ||||
|             if text[pos : pos + 2] == "::": | ||||
|                 index += pos | ||||
|             else: | ||||
|                 index += pos + 1 | ||||
|  | @ -1297,13 +1292,13 @@ def _parseAddressIPv6(ipstr): | |||
|             items.append(text) | ||||
|             break | ||||
| 
 | ||||
|     if items and '.' in items[-1]: | ||||
|     if items and "." in items[-1]: | ||||
|         # IPv6 ending with IPv4 like '::ffff:192.168.0.1' | ||||
|         if (fill_pos is not None) and not (fill_pos <= len(items) - 1): | ||||
|             # Invalid IPv6: 'ffff:192.168.0.1::' | ||||
|             raise ValueError("%r: Invalid IPv6 address: '::' after IPv4" % ipstr) | ||||
|         value = parseAddress(items[-1])[0] | ||||
|         items = items[:-1] + ["%04x" % (value >> 16), "%04x" % (value & 0xffff)] | ||||
|         items = items[:-1] + ["%04x" % (value >> 16), "%04x" % (value & 0xFFFF)] | ||||
| 
 | ||||
|     # Expand fill_pos to fill with '0' | ||||
|     # ['1','2'] with fill_pos=1 => ['1', '0', '0', '0', '0', '0', '0', '2'] | ||||
|  | @ -1311,7 +1306,7 @@ def _parseAddressIPv6(ipstr): | |||
|         diff = 8 - len(items) | ||||
|         if diff <= 0: | ||||
|             raise ValueError("%r: Invalid IPv6 address: '::' is not needed" % ipstr) | ||||
|         items = items[:fill_pos] + ['0'] * diff + items[fill_pos:] | ||||
|         items = items[:fill_pos] + ["0"] * diff + items[fill_pos:] | ||||
| 
 | ||||
|     # Here we have a list of 8 strings | ||||
|     if len(items) != 8: | ||||
|  | @ -1324,7 +1319,7 @@ def _parseAddressIPv6(ipstr): | |||
|     for item in items: | ||||
|         try: | ||||
|             item = int(item, 16) | ||||
|             error = not (0 <= item <= 0xffff) | ||||
|             error = not (0 <= item <= 0xFFFF) | ||||
|         except ValueError: | ||||
|             error = True | ||||
|         if error: | ||||
|  | @ -1388,7 +1383,7 @@ def parseAddress(ipstr, ipversion=0): | |||
|     except ValueError: | ||||
|         intval = None | ||||
| 
 | ||||
|     if ipstr.startswith('0x') and hexval is not None: | ||||
|     if ipstr.startswith("0x") and hexval is not None: | ||||
|         if hexval > MAX_IPV6_ADDRESS: | ||||
|             raise ValueError("IP Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, hexval)) | ||||
|         if hexval <= MAX_IPV4_ADDRESS: | ||||
|  | @ -1396,19 +1391,19 @@ def parseAddress(ipstr, ipversion=0): | |||
|         else: | ||||
|             return (hexval, 6) | ||||
| 
 | ||||
|     if ipstr.find(':') != -1: | ||||
|     if ipstr.find(":") != -1: | ||||
|         return (_parseAddressIPv6(ipstr), 6) | ||||
| 
 | ||||
|     elif len(ipstr) == 32 and hexval is not None: | ||||
|         # assume IPv6 in pure hexadecimal notation | ||||
|         return (hexval, 6) | ||||
| 
 | ||||
|     elif ipstr.find('.') != -1 or (intval is not None and intval < 256 and ipversion != 6): | ||||
|     elif ipstr.find(".") != -1 or (intval is not None and intval < 256 and ipversion != 6): | ||||
|         # assume IPv4  ('127' gets interpreted as '127.0.0.0') | ||||
|         bytes = ipstr.split('.') | ||||
|         bytes = ipstr.split(".") | ||||
|         if len(bytes) > 4: | ||||
|             raise ValueError("IPv4 Address with more than 4 bytes") | ||||
|         bytes += ['0'] * (4 - len(bytes)) | ||||
|         bytes += ["0"] * (4 - len(bytes)) | ||||
|         bytes = [int(x) for x in bytes] | ||||
|         for x in bytes: | ||||
|             if x > 255 or x < 0: | ||||
|  | @ -1438,12 +1433,12 @@ def intToIp(ip, version): | |||
|     if ip < 0: | ||||
|         raise ValueError("IPs can't be negative: %d" % (ip)) | ||||
| 
 | ||||
|     ret = '' | ||||
|     ret = "" | ||||
|     if version == 4: | ||||
|         if ip > MAX_IPV4_ADDRESS: | ||||
|             raise ValueError("IPv4 Address can't be larger than %x: %x" % (MAX_IPV4_ADDRESS, ip)) | ||||
|         for l in xrange(4): | ||||
|             ret = str(ip & 0xff) + '.' + ret | ||||
|             ret = str(ip & 0xFF) + "." + ret | ||||
|             ip = ip >> 8 | ||||
|         ret = ret[:-1] | ||||
|     elif version == 6: | ||||
|  | @ -1453,7 +1448,7 @@ def intToIp(ip, version): | |||
|         for x in xrange(1, 33): | ||||
|             ret = l[-x] + ret | ||||
|             if x % 4 == 0: | ||||
|                 ret = ':' + ret | ||||
|                 ret = ":" + ret | ||||
|         ret = ret[1:] | ||||
|     else: | ||||
|         raise ValueError("only IPv4 and IPv6 supported") | ||||
|  | @ -1494,10 +1489,24 @@ def _countFollowingZeros(l): | |||
|         return 1 + _countFollowingZeros(l[1:]) | ||||
| 
 | ||||
| 
 | ||||
| _BitTable = {'0': '0000', '1': '0001', '2': '0010', '3': '0011', | ||||
|              '4': '0100', '5': '0101', '6': '0110', '7': '0111', | ||||
|              '8': '1000', '9': '1001', 'a': '1010', 'b': '1011', | ||||
|              'c': '1100', 'd': '1101', 'e': '1110', 'f': '1111'} | ||||
| _BitTable = { | ||||
|     "0": "0000", | ||||
|     "1": "0001", | ||||
|     "2": "0010", | ||||
|     "3": "0011", | ||||
|     "4": "0100", | ||||
|     "5": "0101", | ||||
|     "6": "0110", | ||||
|     "7": "0111", | ||||
|     "8": "1000", | ||||
|     "9": "1001", | ||||
|     "a": "1010", | ||||
|     "b": "1011", | ||||
|     "c": "1100", | ||||
|     "d": "1101", | ||||
|     "e": "1110", | ||||
|     "f": "1111", | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| def _intToBin(val): | ||||
|  | @ -1506,11 +1515,11 @@ def _intToBin(val): | |||
|     if val < 0: | ||||
|         raise ValueError("Only positive values allowed") | ||||
|     s = "%x" % val | ||||
|     ret = '' | ||||
|     ret = "" | ||||
|     for x in s: | ||||
|         ret += _BitTable[x] | ||||
|     # remove leading zeros | ||||
|     while ret[0] == '0' and len(ret) > 1: | ||||
|     while ret[0] == "0" and len(ret) > 1: | ||||
|         ret = ret[1:] | ||||
|     return ret | ||||
| 
 | ||||
|  | @ -1595,7 +1604,7 @@ def _checkNetmask(netmask, masklen): | |||
| def _checkNetaddrWorksWithPrefixlen(net, prefixlen, version): | ||||
|     """Check if a base addess of a network is compatible with a prefixlen""" | ||||
|     try: | ||||
|         return (net & _prefixlenToNetmask(prefixlen, version) == net) | ||||
|         return net & _prefixlenToNetmask(prefixlen, version) == net | ||||
|     except ValueError: | ||||
|         return False | ||||
| 
 | ||||
|  | @ -1637,8 +1646,8 @@ def _remove_subprefix(prefix, subprefix): | |||
| 
 | ||||
|     # Start cutting in half, recursively | ||||
|     prefixes = [ | ||||
|         IP('%s/%d' % (prefix[0], prefix._prefixlen + 1)), | ||||
|         IP('%s/%d' % (prefix[int(prefix.len() / 2)], prefix._prefixlen + 1)), | ||||
|         IP("%s/%d" % (prefix[0], prefix._prefixlen + 1)), | ||||
|         IP("%s/%d" % (prefix[int(prefix.len() / 2)], prefix._prefixlen + 1)), | ||||
|     ] | ||||
|     if subprefix in prefixes[0]: | ||||
|         return _remove_subprefix(prefixes[0], subprefix) + IPSet([prefixes[1]]) | ||||
|  |  | |||
|  | @ -1,11 +1,12 @@ | |||
| import libvirt | ||||
| import threading | ||||
| import socket | ||||
| import re | ||||
| from vrtManager import util | ||||
| from vrtManager.rwlock import ReadWriteLock | ||||
| import socket | ||||
| import threading | ||||
| 
 | ||||
| import libvirt | ||||
| from django.conf import settings | ||||
| from libvirt import libvirtError | ||||
| from vrtManager import util | ||||
| from vrtManager.rwlock import ReadWriteLock | ||||
| 
 | ||||
| CONN_SOCKET = 4 | ||||
| CONN_TLS = 3 | ||||
|  | @ -18,6 +19,7 @@ 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 | ||||
|  | @ -25,7 +27,7 @@ class wvmEventLoop(threading.Thread): | |||
|         libvirt.virEventRegisterDefaultImpl() | ||||
| 
 | ||||
|         if name is None: | ||||
|             name = 'libvirt event loop' | ||||
|             name = "libvirt event loop" | ||||
| 
 | ||||
|         super(wvmEventLoop, self).__init__(group, target, name, args, kwargs) | ||||
| 
 | ||||
|  | @ -46,6 +48,7 @@ class wvmConnection(object): | |||
|     class representing a single connection stored in the Connection Manager | ||||
|     # to-do: may also need some locking to ensure to not connect simultaniously in 2 threads | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, host, login, passwd, conn): | ||||
|         """ | ||||
|         Sets all class attributes and tries to open the connection | ||||
|  | @ -86,10 +89,12 @@ class wvmConnection(object): | |||
|                     #     * set keep alive interval | ||||
|                     #     * set connection close/fail handler | ||||
|                     try: | ||||
|                         self.connection.setKeepAlive(connection_manager.keepalive_interval, connection_manager.keepalive_count) | ||||
|                         self.connection.setKeepAlive( | ||||
|                             connection_manager.keepalive_interval, connection_manager.keepalive_count | ||||
|                         ) | ||||
|                         try: | ||||
|                             self.connection.registerCloseCallback(self.__connection_close_callback, None) | ||||
|                         except: | ||||
|                         except Exception: | ||||
|                             # Temporary fix for libvirt > libvirt-0.10.2-41 | ||||
|                             pass | ||||
|                     except libvirtError as e: | ||||
|  | @ -134,49 +139,49 @@ class wvmConnection(object): | |||
|     def __connect_tcp(self): | ||||
|         flags = [libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_PASSPHRASE] | ||||
|         auth = [flags, self.__libvirt_auth_credentials_callback, None] | ||||
|         uri = f'qemu+tcp://{self.host}/system' | ||||
|         uri = f"qemu+tcp://{self.host}/system" | ||||
| 
 | ||||
|         try: | ||||
|             self.connection = libvirt.openAuth(uri, auth, 0) | ||||
|             self.last_error = None | ||||
| 
 | ||||
|         except libvirtError as e: | ||||
|             self.last_error = f'Connection Failed: {str(e)}' | ||||
|             self.last_error = f"Connection Failed: {str(e)}" | ||||
|             self.connection = None | ||||
| 
 | ||||
|     def __connect_ssh(self): | ||||
|         uri = 'qemu+ssh://%s@%s/system' % (self.login, self.host) | ||||
|         uri = "qemu+ssh://%s@%s/system" % (self.login, self.host) | ||||
| 
 | ||||
|         try: | ||||
|             self.connection = libvirt.open(uri) | ||||
|             self.last_error = None | ||||
| 
 | ||||
|         except libvirtError as e: | ||||
|             self.last_error = f'Connection Failed: {str(e)} --- ' + repr(libvirt.virGetLastError()) | ||||
|             self.last_error = f"Connection Failed: {str(e)} --- " + repr(libvirt.virGetLastError()) | ||||
|             self.connection = None | ||||
| 
 | ||||
|     def __connect_tls(self): | ||||
|         flags = [libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_PASSPHRASE] | ||||
|         auth = [flags, self.__libvirt_auth_credentials_callback, None] | ||||
|         uri = 'qemu+tls://%s@%s/system' % (self.login, self.host) | ||||
|         uri = "qemu+tls://%s@%s/system" % (self.login, self.host) | ||||
| 
 | ||||
|         try: | ||||
|             self.connection = libvirt.openAuth(uri, auth, 0) | ||||
|             self.last_error = None | ||||
| 
 | ||||
|         except libvirtError as e: | ||||
|             self.last_error = f'Connection Failed: {str(e)}' | ||||
|             self.last_error = f"Connection Failed: {str(e)}" | ||||
|             self.connection = None | ||||
| 
 | ||||
|     def __connect_socket(self): | ||||
|         uri = 'qemu:///system' | ||||
|         uri = "qemu:///system" | ||||
| 
 | ||||
|         try: | ||||
|             self.connection = libvirt.open(uri) | ||||
|             self.last_error = None | ||||
| 
 | ||||
|         except libvirtError as e: | ||||
|             self.last_error = f'Connection Failed: {str(e)}' | ||||
|             self.last_error = f"Connection Failed: {str(e)}" | ||||
|             self.connection = None | ||||
| 
 | ||||
|     def close(self): | ||||
|  | @ -202,23 +207,23 @@ class wvmConnection(object): | |||
|             # unregister callback (as it is no longer valid if this instance gets deleted) | ||||
|             try: | ||||
|                 self.connection.unregisterCloseCallback() | ||||
|             except: | ||||
|             except Exception: | ||||
|                 pass | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         if self.type == CONN_TCP: | ||||
|             type_str = 'tcp' | ||||
|             type_str = "tcp" | ||||
|         elif self.type == CONN_SSH: | ||||
|             type_str = 'ssh' | ||||
|             type_str = "ssh" | ||||
|         elif self.type == CONN_TLS: | ||||
|             type_str = 'tls' | ||||
|             type_str = "tls" | ||||
|         else: | ||||
|             type_str = 'invalid_type' | ||||
|             type_str = "invalid_type" | ||||
| 
 | ||||
|         return f'qemu+{type_str}://{self.login}@{self.host}/system' | ||||
|         return f"qemu+{type_str}://{self.login}@{self.host}/system" | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return f'<wvmConnection {str(self)}>' | ||||
|         return f"<wvmConnection {str(self)}>" | ||||
| 
 | ||||
| 
 | ||||
| class wvmConnectionManager(object): | ||||
|  | @ -307,7 +312,7 @@ class wvmConnectionManager(object): | |||
|             socket_host = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||||
|             socket_host.settimeout(1) | ||||
|             if conn_type == CONN_SSH: | ||||
|                 if ':' in hostname: | ||||
|                 if ":" in hostname: | ||||
|                     libvirt_host, PORT = hostname.split(":") | ||||
|                     PORT = int(PORT) | ||||
|                 else: | ||||
|  | @ -320,7 +325,7 @@ class wvmConnectionManager(object): | |||
|                 socket_host.connect((hostname, TLS_PORT)) | ||||
|             if conn_type == CONN_SOCKET: | ||||
|                 socket_host = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||||
|                 socket_host.connect('/var/run/libvirt/libvirt-sock') | ||||
|                 socket_host.connect("/var/run/libvirt/libvirt-sock") | ||||
|             socket_host.close() | ||||
|             return True | ||||
|         except Exception as err: | ||||
|  | @ -328,8 +333,8 @@ class wvmConnectionManager(object): | |||
| 
 | ||||
| 
 | ||||
| connection_manager = wvmConnectionManager( | ||||
|     settings.LIBVIRT_KEEPALIVE_INTERVAL if hasattr(settings, 'LIBVIRT_KEEPALIVE_INTERVAL') else 5, | ||||
|     settings.LIBVIRT_KEEPALIVE_COUNT if hasattr(settings, 'LIBVIRT_KEEPALIVE_COUNT') else 5, | ||||
|     settings.LIBVIRT_KEEPALIVE_INTERVAL if hasattr(settings, "LIBVIRT_KEEPALIVE_INTERVAL") else 5, | ||||
|     settings.LIBVIRT_KEEPALIVE_COUNT if hasattr(settings, "LIBVIRT_KEEPALIVE_COUNT") else 5, | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -353,15 +358,16 @@ class wvmConnect(object): | |||
|     def get_dom_cap_xml(self, arch, machine): | ||||
|         """ Return domain capabilities xml""" | ||||
|         emulatorbin = self.get_emulator(arch) | ||||
|         virttype = 'kvm' if 'kvm' in self.get_hypervisors_domain_types()[arch] else 'qemu' | ||||
|         virttype = "kvm" if "kvm" in self.get_hypervisors_domain_types()[arch] else "qemu" | ||||
| 
 | ||||
|         machine_types = self.get_machine_types(arch) | ||||
|         if not machine or machine not in machine_types: | ||||
|             machine = 'pc' if 'pc' in machine_types else machine_types[0] | ||||
|             machine = "pc" if "pc" in machine_types else machine_types[0] | ||||
|         return self.wvm.getDomainCapabilities(emulatorbin, arch, machine, virttype) | ||||
| 
 | ||||
|     def get_capabilities(self, arch): | ||||
|         """ Host Capabilities for specified architecture """ | ||||
| 
 | ||||
|         def guests(ctx): | ||||
|             result = dict() | ||||
|             for arch_el in ctx.xpath("/capabilities/guest/arch[@name='{}']".format(arch)): | ||||
|  | @ -371,11 +377,9 @@ class wvmConnect(object): | |||
| 
 | ||||
|                 result["machines"] = [] | ||||
|                 for m in arch_el.xpath("machine"): | ||||
|                     result["machines"].append({ | ||||
|                         "machine": m.text, | ||||
|                         "max_cpu": m.get("maxCpus"), | ||||
|                         "canonical": m.get("canonical") | ||||
|                     }) | ||||
|                     result["machines"].append( | ||||
|                         {"machine": m.text, "max_cpu": m.get("maxCpus"), "canonical": m.get("canonical")} | ||||
|                     ) | ||||
| 
 | ||||
|                 guest_el = arch_el.getparent() | ||||
|                 for f in guest_el.xpath("features"): | ||||
|  | @ -400,7 +404,7 @@ class wvmConnect(object): | |||
|         result["os_support"] = util.get_xml_path(xml, "/domainCapabilities/os/@supported") | ||||
| 
 | ||||
|         result["loader_support"] = util.get_xml_path(xml, "/domainCapabilities/os/loader/@supported") | ||||
|         if result["loader_support"] == 'yes': | ||||
|         if result["loader_support"] == "yes": | ||||
|             result["loaders"] = self.get_os_loaders(arch, machine) | ||||
|             result["loader_enums"] = self.get_os_loader_enums(arch, machine) | ||||
| 
 | ||||
|  | @ -410,27 +414,29 @@ class wvmConnect(object): | |||
|             result["cpu_custom_models"] = self.get_cpu_custom_types(arch, machine) | ||||
| 
 | ||||
|         result["disk_support"] = util.get_xml_path(xml, "/domainCapabilities/devices/disk/@supported") | ||||
|         if result["disk_support"] == 'yes': | ||||
|         if result["disk_support"] == "yes": | ||||
|             result["disk_devices"] = self.get_disk_device_types(arch, machine) | ||||
|             result["disk_bus"] = self.get_disk_bus_types(arch, machine) | ||||
| 
 | ||||
|         result["graphics_support"] = util.get_xml_path(xml, "/domainCapabilities/devices/graphics/@supported") | ||||
|         if result["graphics_support"] == 'yes': | ||||
|         if result["graphics_support"] == "yes": | ||||
|             result["graphics_types"] = self.get_graphics_types(arch, machine) | ||||
| 
 | ||||
|         result["video_support"] = util.get_xml_path(xml, "/domainCapabilities/devices/video/@supported") | ||||
|         if result["video_support"] == 'yes': | ||||
|         if result["video_support"] == "yes": | ||||
|             result["video_types"] = self.get_video_models(arch, machine) | ||||
| 
 | ||||
|         result["hostdev_support"] = util.get_xml_path(xml, "/domainCapabilities/devices/hostdev/@supported") | ||||
|         if result["hostdev_support"] == 'yes': | ||||
|         if result["hostdev_support"] == "yes": | ||||
|             result["hostdev_types"] = self.get_hostdev_modes(arch, machine) | ||||
|             result["hostdev_startup_policies"] = self.get_hostdev_startup_policies(arch, machine) | ||||
|             result["hostdev_subsys_types"] = self.get_hostdev_subsys_types(arch, machine) | ||||
| 
 | ||||
|         result["features_gic_support"] = util.get_xml_path(xml, "/domainCapabilities/features/gic/@supported") | ||||
|         result["features_genid_support"] = util.get_xml_path(xml, "/domainCapabilities/features/genid/@supported") | ||||
|         result["features_vmcoreinfo_support"] = util.get_xml_path(xml, "/domainCapabilities/features/vmcoreinfo/@supported") | ||||
|         result["features_vmcoreinfo_support"] = util.get_xml_path( | ||||
|             xml, "/domainCapabilities/features/vmcoreinfo/@supported" | ||||
|         ) | ||||
|         result["features_sev_support"] = util.get_xml_path(xml, "/domainCapabilities/features/sev/@supported") | ||||
| 
 | ||||
|         return result | ||||
|  | @ -510,12 +516,12 @@ class wvmConnect(object): | |||
|         :return: Get cache available modes | ||||
|         """ | ||||
|         return { | ||||
|             'default': 'Default', | ||||
|             'none': 'Disabled', | ||||
|             'writethrough': 'Write through', | ||||
|             'writeback': 'Write back', | ||||
|             'directsync': 'Direct sync',  # since libvirt 0.9.5 | ||||
|             'unsafe': 'Unsafe',  # since libvirt 0.9.7 | ||||
|             "default": "Default", | ||||
|             "none": "Disabled", | ||||
|             "writethrough": "Write through", | ||||
|             "writeback": "Write back", | ||||
|             "directsync": "Direct sync",  # since libvirt 0.9.5 | ||||
|             "unsafe": "Unsafe",  # since libvirt 0.9.7 | ||||
|         } | ||||
| 
 | ||||
|     def get_io_modes(self): | ||||
|  | @ -523,9 +529,9 @@ class wvmConnect(object): | |||
|         :return: available io modes | ||||
|         """ | ||||
|         return { | ||||
|             'default': 'Default', | ||||
|             'native': 'Native', | ||||
|             'threads': 'Threads', | ||||
|             "default": "Default", | ||||
|             "native": "Native", | ||||
|             "threads": "Threads", | ||||
|         } | ||||
| 
 | ||||
|     def get_discard_modes(self): | ||||
|  | @ -533,9 +539,9 @@ class wvmConnect(object): | |||
|         :return: available discard modes | ||||
|         """ | ||||
|         return { | ||||
|             'default': 'Default', | ||||
|             'ignore': 'Ignore', | ||||
|             'unmap': 'Unmap', | ||||
|             "default": "Default", | ||||
|             "ignore": "Ignore", | ||||
|             "unmap": "Unmap", | ||||
|         } | ||||
| 
 | ||||
|     def get_detect_zeroes_modes(self): | ||||
|  | @ -543,21 +549,22 @@ class wvmConnect(object): | |||
|         :return: available detect zeroes modes | ||||
|         """ | ||||
|         return { | ||||
|             'default': 'Default', | ||||
|             'on': 'On', | ||||
|             'off': 'Off', | ||||
|             'unmap': 'Unmap', | ||||
|             "default": "Default", | ||||
|             "on": "On", | ||||
|             "off": "Off", | ||||
|             "unmap": "Unmap", | ||||
|         } | ||||
| 
 | ||||
|     def get_hypervisors_domain_types(self): | ||||
|         """ | ||||
|         :return: hypervisor domain types | ||||
|         """ | ||||
| 
 | ||||
|         def hypervisors(ctx): | ||||
|             result = {} | ||||
|             for arch in ctx.xpath('/capabilities/guest/arch'): | ||||
|                 domain_types = arch.xpath('domain/@type') | ||||
|                 arch_name = arch.xpath('@name')[0] | ||||
|             for arch in ctx.xpath("/capabilities/guest/arch"): | ||||
|                 domain_types = arch.xpath("domain/@type") | ||||
|                 arch_name = arch.xpath("@name")[0] | ||||
|                 result[arch_name] = domain_types | ||||
|             return result | ||||
| 
 | ||||
|  | @ -567,9 +574,10 @@ class wvmConnect(object): | |||
|         """ | ||||
|         :return: hypervisor and its machine types | ||||
|         """ | ||||
| 
 | ||||
|         def machines(ctx): | ||||
|             result = dict() | ||||
|             for arche in ctx.xpath('/capabilities/guest/arch'): | ||||
|             for arche in ctx.xpath("/capabilities/guest/arch"): | ||||
|                 arch = arche.get("name") | ||||
| 
 | ||||
|                 result[arch] = self.get_machine_types(arch) | ||||
|  | @ -587,6 +595,7 @@ class wvmConnect(object): | |||
|         """ | ||||
|         :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)) | ||||
|  | @ -602,22 +611,24 @@ class wvmConnect(object): | |||
|         """ | ||||
|         :return: host emulators list | ||||
|         """ | ||||
| 
 | ||||
|         def emulators(ctx): | ||||
|             result = {} | ||||
|             for arch in ctx.xpath('/capabilities/guest/arch'): | ||||
|                 emulator = arch.xpath('emulator') | ||||
|                 arch_name = arch.xpath('@name')[0] | ||||
|             for arch in ctx.xpath("/capabilities/guest/arch"): | ||||
|                 emulator = arch.xpath("emulator") | ||||
|                 arch_name = arch.xpath("@name")[0] | ||||
|                 result[arch_name] = emulator | ||||
|             return result | ||||
| 
 | ||||
|         return util.get_xml_path(self.get_cap_xml(), func=emulators) | ||||
| 
 | ||||
|     def get_os_loaders(self, arch='x86_64', machine='pc'): | ||||
|     def get_os_loaders(self, arch="x86_64", machine="pc"): | ||||
|         """ | ||||
|         :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")] | ||||
| 
 | ||||
|  | @ -629,6 +640,7 @@ class wvmConnect(object): | |||
|         :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")] | ||||
|  | @ -645,6 +657,7 @@ class wvmConnect(object): | |||
|         :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")] | ||||
| 
 | ||||
|  | @ -657,6 +670,7 @@ class wvmConnect(object): | |||
|         :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")] | ||||
| 
 | ||||
|  | @ -669,6 +683,7 @@ class wvmConnect(object): | |||
|         :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")] | ||||
| 
 | ||||
|  | @ -680,6 +695,7 @@ class wvmConnect(object): | |||
|         :param machine: | ||||
|         :return: available cpu modes | ||||
|         """ | ||||
| 
 | ||||
|         def get_cpu_modes(ctx): | ||||
|             return [v for v in ctx.xpath("/domainCapabilities/cpu/mode[@supported='yes']/@name")] | ||||
| 
 | ||||
|  | @ -691,6 +707,7 @@ class wvmConnect(object): | |||
|         :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']" | ||||
|  | @ -706,6 +723,7 @@ class wvmConnect(object): | |||
|         :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")] | ||||
| 
 | ||||
|  | @ -717,6 +735,7 @@ class wvmConnect(object): | |||
|         :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")] | ||||
| 
 | ||||
|  | @ -728,6 +747,7 @@ class wvmConnect(object): | |||
|         :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")] | ||||
| 
 | ||||
|  | @ -737,19 +757,19 @@ class wvmConnect(object): | |||
|         """ | ||||
|         :return: network card models | ||||
|         """ | ||||
|         return ['default', 'e1000', 'virtio'] | ||||
|         return ["default", "e1000", "virtio"] | ||||
| 
 | ||||
|     def get_image_formats(self): | ||||
|         """ | ||||
|         :return: available image formats | ||||
|         """ | ||||
|         return ['raw', 'qcow', 'qcow2'] | ||||
|         return ["raw", "qcow", "qcow2"] | ||||
| 
 | ||||
|     def get_file_extensions(self): | ||||
|         """ | ||||
|         :return: available image filename extensions | ||||
|         """ | ||||
|         return ['img', 'qcow', 'qcow2'] | ||||
|         return ["img", "qcow", "qcow2"] | ||||
| 
 | ||||
|     def get_video_models(self, arch, machine): | ||||
|         """ | ||||
|  | @ -757,9 +777,10 @@ class wvmConnect(object): | |||
|         :param machine: | ||||
|         :return: available graphics video types | ||||
|         """ | ||||
| 
 | ||||
|         def get_video_list(ctx): | ||||
|             result = [] | ||||
|             for video_enum in ctx.xpath('/domainCapabilities/devices/video/enum'): | ||||
|             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) | ||||
|  | @ -787,8 +808,8 @@ class wvmConnect(object): | |||
| 
 | ||||
|     def get_network_forward(self, net_name): | ||||
|         def get_forward(doc): | ||||
|             forward_mode = util.get_xpath(doc, '/network/forward/@mode') | ||||
|             return forward_mode or 'isolated' | ||||
|             forward_mode = util.get_xpath(doc, "/network/forward/@mode") | ||||
|             return forward_mode or "isolated" | ||||
| 
 | ||||
|         net = self.get_network(net_name) | ||||
|         xml = net.XMLDesc(0) | ||||
|  | @ -825,14 +846,14 @@ class wvmConnect(object): | |||
|         netdevice = [] | ||||
| 
 | ||||
|         def get_info(doc): | ||||
|             dev_type = util.get_xpath(doc, '/device/capability/@type') | ||||
|             interface = util.get_xpath(doc, '/device/capability/interface') | ||||
|             dev_type = util.get_xpath(doc, "/device/capability/@type") | ||||
|             interface = util.get_xpath(doc, "/device/capability/interface") | ||||
|             return dev_type, interface | ||||
| 
 | ||||
|         for dev in self.wvm.listAllDevices(0): | ||||
|             xml = dev.XMLDesc(0) | ||||
|             (dev_type, interface) = util.get_xml_path(xml, func=get_info) | ||||
|             if dev_type == 'net': | ||||
|             if dev_type == "net": | ||||
|                 netdevice.append(interface) | ||||
|         return netdevice | ||||
| 
 | ||||
|  | @ -850,9 +871,9 @@ class wvmConnect(object): | |||
|             else: | ||||
|                 vcpu = util.get_xpath(doc, "/domain/vcpu") | ||||
|             title = util.get_xpath(doc, "/domain/title") | ||||
|             title = title if title else '' | ||||
|             title = title if title else "" | ||||
|             description = util.get_xpath(doc, "/domain/description") | ||||
|             description = description if description else '' | ||||
|             description = description if description else "" | ||||
|             return mem, vcpu, title, description | ||||
| 
 | ||||
|         for name in self.get_instances(): | ||||
|  | @ -860,12 +881,12 @@ class wvmConnect(object): | |||
|             xml = dom.XMLDesc(0) | ||||
|             (mem, vcpu, title, description) = util.get_xml_path(xml, func=get_info) | ||||
|             vname[dom.name()] = { | ||||
|                 'status': dom.info()[0], | ||||
|                 'uuid': dom.UUIDString(), | ||||
|                 'vcpu': vcpu, | ||||
|                 'memory': mem, | ||||
|                 'title': title, | ||||
|                 'description': description, | ||||
|                 "status": dom.info()[0], | ||||
|                 "uuid": dom.UUIDString(), | ||||
|                 "vcpu": vcpu, | ||||
|                 "memory": mem, | ||||
|                 "title": title, | ||||
|                 "description": description, | ||||
|             } | ||||
|         return vname | ||||
| 
 | ||||
|  | @ -882,20 +903,20 @@ class wvmConnect(object): | |||
|             else: | ||||
|                 vcpu = util.get_xpath(ctx, "/domain/vcpu") | ||||
|             title = util.get_xpath(ctx, "/domain/title") | ||||
|             title = title if title else '' | ||||
|             title = title if title else "" | ||||
|             description = util.get_xpath(ctx, "/domain/description") | ||||
|             description = description if description else '' | ||||
|             description = description if description else "" | ||||
|             return mem, vcpu, title, description | ||||
| 
 | ||||
|         (mem, vcpu, title, description) = util.get_xml_path(xml, func=get_info) | ||||
|         return { | ||||
|             'name': dom.name(), | ||||
|             'status': dom.info()[0], | ||||
|             'uuid': dom.UUIDString(), | ||||
|             'vcpu': vcpu, | ||||
|             'memory': mem, | ||||
|             'title': title, | ||||
|             'description': description, | ||||
|             "name": dom.name(), | ||||
|             "status": dom.info()[0], | ||||
|             "uuid": dom.UUIDString(), | ||||
|             "vcpu": vcpu, | ||||
|             "memory": mem, | ||||
|             "title": title, | ||||
|             "description": description, | ||||
|         } | ||||
| 
 | ||||
|     def close(self): | ||||
|  | @ -931,7 +952,7 @@ class wvmConnect(object): | |||
|         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} | ||||
| 
 | ||||
|  | @ -945,15 +966,17 @@ class wvmConnect(object): | |||
|         """ | ||||
|         Return True if libvirt advertises support for proper UEFI setup | ||||
|         """ | ||||
|         return ("readonly" in loader_enums and "yes" in loader_enums.get("readonly")) | ||||
|         return "readonly" in loader_enums and "yes" in loader_enums.get("readonly") | ||||
| 
 | ||||
|     def is_supports_virtio(self, arch, machine): | ||||
|         if not self.is_qemu(): | ||||
|             return False | ||||
| 
 | ||||
|         # These _only_ support virtio so don't check the OS | ||||
|         if arch in ["aarch64", "armv7l", "ppc64", "ppc64le", "s390x", "riscv64", "riscv32"] and \ | ||||
|                 machine in ["virt", "pseries"]: | ||||
|         if arch in ["aarch64", "armv7l", "ppc64", "ppc64le", "s390x", "riscv64", "riscv32"] and machine in [ | ||||
|             "virt", | ||||
|             "pseries", | ||||
|         ]: | ||||
|             return True | ||||
| 
 | ||||
|         if arch in ["x86_64", "i686"]: | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import string | ||||
| 
 | ||||
| from vrtManager import util | ||||
| from vrtManager.connection import wvmConnect | ||||
| 
 | ||||
|  | @ -12,15 +13,15 @@ def get_rbd_storage_data(stg): | |||
|         for host in doc.xpath("/pool/source/host"): | ||||
|             name = host.prop("name") | ||||
|             if name: | ||||
|                 hosts.append({'name': name, 'port': host.prop("port")}) | ||||
|                 hosts.append({"name": name, "port": host.prop("port")}) | ||||
|         return hosts | ||||
| 
 | ||||
|     ceph_hosts = util.get_xml_path(xml, func=get_ceph_hosts) | ||||
|     secret_uuid = util.get_xml_path(xml, "/pool/source/auth/secret/@uuid") | ||||
|     return ceph_user, secret_uuid, ceph_hosts | ||||
| 
 | ||||
| 
 | ||||
| class wvmCreate(wvmConnect): | ||||
| 
 | ||||
|     def get_storages_images(self): | ||||
|         """ | ||||
|         Function return all images on all storages | ||||
|  | @ -31,10 +32,10 @@ class wvmCreate(wvmConnect): | |||
|             stg = self.get_storage(storage) | ||||
|             try: | ||||
|                 stg.refresh(0) | ||||
|             except: | ||||
|             except Exception: | ||||
|                 pass | ||||
|             for img in stg.listVolumes(): | ||||
|                 if img.lower().endswith('.iso'): | ||||
|                 if img.lower().endswith(".iso"): | ||||
|                     pass | ||||
|                 else: | ||||
|                     images.append(img) | ||||
|  | @ -52,11 +53,11 @@ class wvmCreate(wvmConnect): | |||
|         size = int(size) * 1073741824 | ||||
|         stg = self.get_storage(storage) | ||||
|         storage_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") | ||||
|         if storage_type == 'dir': | ||||
|             if image_format in ('qcow', 'qcow2'): | ||||
|                 name += '.' + image_format | ||||
|         if storage_type == "dir": | ||||
|             if image_format in ("qcow", "qcow2"): | ||||
|                 name += "." + image_format | ||||
|             else: | ||||
|                 name += '.img' | ||||
|                 name += ".img" | ||||
|             alloc = 0 | ||||
|         else: | ||||
|             alloc = size | ||||
|  | @ -91,12 +92,12 @@ class wvmCreate(wvmConnect): | |||
|     def get_volume_type(self, path): | ||||
|         vol = self.get_volume_by_path(path) | ||||
|         vol_type = util.get_xml_path(vol.XMLDesc(0), "/volume/target/format/@type") | ||||
|         if vol_type == 'unknown' or vol_type == 'iso': | ||||
|             return 'raw' | ||||
|         if vol_type == "unknown" or vol_type == "iso": | ||||
|             return "raw" | ||||
|         if vol_type: | ||||
|             return vol_type | ||||
|         else: | ||||
|             return 'raw' | ||||
|             return "raw" | ||||
| 
 | ||||
|     def get_volume_path(self, volume, pool=None): | ||||
|         if not pool: | ||||
|  | @ -125,8 +126,8 @@ class wvmCreate(wvmConnect): | |||
| 
 | ||||
|         storage_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") | ||||
|         format = util.get_xml_path(vol.XMLDesc(0), "/volume/target/format/@type") | ||||
|         if storage_type == 'dir': | ||||
|             clone += '.img' | ||||
|         if storage_type == "dir": | ||||
|             clone += ".img" | ||||
|         else: | ||||
|             metadata = False | ||||
|         xml = f""" | ||||
|  | @ -159,9 +160,27 @@ class wvmCreate(wvmConnect): | |||
|         vol = self.get_volume_by_path(path) | ||||
|         vol.delete() | ||||
| 
 | ||||
|     def create_instance(self, name, memory, vcpu, vcpu_mode, uuid, arch, machine, firmware, volumes, | ||||
|                         networks, nwfilter, graphics, virtio, listen_addr, | ||||
|                         video="vga", console_pass="random", mac=None, qemu_ga=True): | ||||
|     def create_instance( | ||||
|         self, | ||||
|         name, | ||||
|         memory, | ||||
|         vcpu, | ||||
|         vcpu_mode, | ||||
|         uuid, | ||||
|         arch, | ||||
|         machine, | ||||
|         firmware, | ||||
|         volumes, | ||||
|         networks, | ||||
|         nwfilter, | ||||
|         graphics, | ||||
|         virtio, | ||||
|         listen_addr, | ||||
|         video="vga", | ||||
|         console_pass="random", | ||||
|         mac=None, | ||||
|         qemu_ga=True, | ||||
|     ): | ||||
|         """ | ||||
|         Create VM function | ||||
|         """ | ||||
|  | @ -178,33 +197,37 @@ class wvmCreate(wvmConnect): | |||
|                   <memory unit='KiB'>{memory}</memory> | ||||
|                   <vcpu>{vcpu}</vcpu>""" | ||||
| 
 | ||||
|         if dom_caps["os_support"] == 'yes': | ||||
|         if dom_caps["os_support"] == "yes": | ||||
|             xml += f"""<os> | ||||
|                           <type arch='{arch}' machine='{machine}'>{caps["os_type"]}</type>""" | ||||
|             xml += """    <boot dev='hd'/> | ||||
|                           <boot dev='cdrom'/> | ||||
|                           <bootmenu enable='yes'/>""" | ||||
|             if firmware: | ||||
|                 if firmware["secure"] == 'yes': | ||||
|                     xml += """<loader readonly='%s' type='%s' secure='%s'>%s</loader>""" % (firmware["readonly"], | ||||
|                                                                                             firmware["type"], | ||||
|                                                                                             firmware["secure"], | ||||
|                                                                                             firmware["loader"]) | ||||
|                 if firmware["secure"] == 'no': | ||||
|                     xml += """<loader readonly='%s' type='%s'>%s</loader>""" % (firmware["readonly"], | ||||
|                                                                                 firmware["type"], | ||||
|                                                                                 firmware["loader"]) | ||||
|                 if firmware["secure"] == "yes": | ||||
|                     xml += """<loader readonly='%s' type='%s' secure='%s'>%s</loader>""" % ( | ||||
|                         firmware["readonly"], | ||||
|                         firmware["type"], | ||||
|                         firmware["secure"], | ||||
|                         firmware["loader"], | ||||
|                     ) | ||||
|                 if firmware["secure"] == "no": | ||||
|                     xml += """<loader readonly='%s' type='%s'>%s</loader>""" % ( | ||||
|                         firmware["readonly"], | ||||
|                         firmware["type"], | ||||
|                         firmware["loader"], | ||||
|                     ) | ||||
|             xml += """</os>""" | ||||
| 
 | ||||
|         if caps["features"]: | ||||
|             xml += """<features>""" | ||||
|             if 'acpi' in caps["features"]: | ||||
|             if "acpi" in caps["features"]: | ||||
|                 xml += """<acpi/>""" | ||||
|             if 'apic' in caps["features"]: | ||||
|             if "apic" in caps["features"]: | ||||
|                 xml += """<apic/>""" | ||||
|             if 'pae' in caps["features"]: | ||||
|             if "pae" in caps["features"]: | ||||
|                 xml += """<pae/>""" | ||||
|             if  firmware.get("secure", 'no') == 'yes': | ||||
|             if firmware.get("secure", "no") == "yes": | ||||
|                 xml += """<smm state="on"/>""" | ||||
|             xml += """</features>""" | ||||
| 
 | ||||
|  | @ -235,56 +258,69 @@ class wvmCreate(wvmConnect): | |||
| 
 | ||||
|         for volume in volumes: | ||||
| 
 | ||||
|             disk_opts = '' | ||||
|             if volume['cache_mode'] is not None and volume['cache_mode'] != 'default': | ||||
|             disk_opts = "" | ||||
|             if volume["cache_mode"] is not None and volume["cache_mode"] != "default": | ||||
|                 disk_opts += f"cache='{volume['cache_mode']}' " | ||||
|             if volume['io_mode'] is not None and volume['io_mode'] != 'default': | ||||
|             if volume["io_mode"] is not None and volume["io_mode"] != "default": | ||||
|                 disk_opts += f"io='{volume['io_mode']}' " | ||||
|             if volume['discard_mode'] is not None and volume['discard_mode'] != 'default': | ||||
|             if volume["discard_mode"] is not None and volume["discard_mode"] != "default": | ||||
|                 disk_opts += f"discard='{volume['discard_mode']}' " | ||||
|             if volume['detect_zeroes_mode'] is not None and volume['detect_zeroes_mode'] != 'default': | ||||
|             if volume["detect_zeroes_mode"] is not None and volume["detect_zeroes_mode"] != "default": | ||||
|                 disk_opts += f"detect_zeroes='{volume['detect_zeroes_mode']}' " | ||||
| 
 | ||||
|             stg = self.get_storage_by_vol_path(volume['path']) | ||||
|             stg = self.get_storage_by_vol_path(volume["path"]) | ||||
|             stg_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") | ||||
| 
 | ||||
|             if volume['device'] == 'cdrom': add_cd = False | ||||
|             if volume["device"] == "cdrom": | ||||
|                 add_cd = False | ||||
| 
 | ||||
|             if stg_type == 'rbd': | ||||
|             if stg_type == "rbd": | ||||
|                 ceph_user, secret_uuid, ceph_hosts = get_rbd_storage_data(stg) | ||||
|                 xml += """<disk type='network' device='disk'> | ||||
|                             <driver name='qemu' type='%s' %s />""" % (volume['type'], disk_opts) | ||||
|                             <driver name='qemu' type='%s' %s />""" % ( | ||||
|                     volume["type"], | ||||
|                     disk_opts, | ||||
|                 ) | ||||
|                 xml += """  <auth username='%s'> | ||||
|                                 <secret type='ceph' uuid='%s'/> | ||||
|                             </auth> | ||||
|                             <source protocol='rbd' name='%s'>""" % (ceph_user, secret_uuid, volume['path']) | ||||
|                             <source protocol='rbd' name='%s'>""" % ( | ||||
|                     ceph_user, | ||||
|                     secret_uuid, | ||||
|                     volume["path"], | ||||
|                 ) | ||||
|                 if isinstance(ceph_hosts, list): | ||||
|                     for host in ceph_hosts: | ||||
|                         if host.get('port'): | ||||
|                         if host.get("port"): | ||||
|                             xml += """ | ||||
|                                    <host name='%s' port='%s'/>""" % (host.get('name'), host.get('port')) | ||||
|                                    <host name='%s' port='%s'/>""" % ( | ||||
|                                 host.get("name"), | ||||
|                                 host.get("port"), | ||||
|                             ) | ||||
|                         else: | ||||
|                             xml += """ | ||||
|                                    <host name='%s'/>""" % host.get('name') | ||||
|                                    <host name='%s'/>""" % host.get( | ||||
|                                 "name" | ||||
|                             ) | ||||
|                 xml += """</source>""" | ||||
|             else: | ||||
|                 xml += """<disk type='file' device='%s'>""" % volume['device'] | ||||
|                 xml += """ <driver name='qemu' type='%s' %s/>""" % (volume['type'], disk_opts) | ||||
|                 xml += f""" <source file='%s'/>""" % volume['path'] | ||||
|                 xml += """<disk type='file' device='%s'>""" % volume["device"] | ||||
|                 xml += """ <driver name='qemu' type='%s' %s/>""" % (volume["type"], disk_opts) | ||||
|                 xml += """ <source file='%s'/>""" % volume["path"] | ||||
| 
 | ||||
|             if volume.get('bus') == 'virtio': | ||||
|                 xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), volume.get('bus')) | ||||
|             elif volume.get('bus') == 'ide': | ||||
|                 xml += """<target dev='hd%s' bus='%s'/>""" % (hd_disk_letters.pop(0), volume.get('bus')) | ||||
|             elif volume.get('bus') == 'fdc': | ||||
|                 xml += """<target dev='fd%s' bus='%s'/>""" % (fd_disk_letters.pop(0), volume.get('bus')) | ||||
|             elif volume.get('bus') == 'sata' or volume.get('bus') == 'scsi': | ||||
|                 xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), volume.get('bus')) | ||||
|             if volume.get("bus") == "virtio": | ||||
|                 xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), volume.get("bus")) | ||||
|             elif volume.get("bus") == "ide": | ||||
|                 xml += """<target dev='hd%s' bus='%s'/>""" % (hd_disk_letters.pop(0), volume.get("bus")) | ||||
|             elif volume.get("bus") == "fdc": | ||||
|                 xml += """<target dev='fd%s' bus='%s'/>""" % (fd_disk_letters.pop(0), volume.get("bus")) | ||||
|             elif volume.get("bus") == "sata" or volume.get("bus") == "scsi": | ||||
|                 xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), volume.get("bus")) | ||||
|             else: | ||||
|                 xml += """<target dev='sd%s'/>""" % sd_disk_letters.pop(0) | ||||
|             xml += """</disk>""" | ||||
| 
 | ||||
|             if volume.get('bus') == 'scsi': | ||||
|             if volume.get("bus") == "scsi": | ||||
|                 xml += f"""<controller type='scsi' model='{volume.get('scsi_model')}'/>""" | ||||
| 
 | ||||
|         if add_cd: | ||||
|  | @ -292,17 +328,17 @@ class wvmCreate(wvmConnect): | |||
|                           <driver name='qemu' type='raw'/> | ||||
|                           <source file = '' /> | ||||
|                           <readonly/>""" | ||||
|             if 'ide' in dom_caps['disk_bus']: | ||||
|                 xml += """<target dev='hd%s' bus='%s'/>""" % (hd_disk_letters.pop(0), 'ide') | ||||
|             elif 'sata' in dom_caps['disk_bus']: | ||||
|                 xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), 'sata') | ||||
|             elif 'scsi' in dom_caps['disk_bus']: | ||||
|                 xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), 'scsi') | ||||
|             if "ide" in dom_caps["disk_bus"]: | ||||
|                 xml += """<target dev='hd%s' bus='%s'/>""" % (hd_disk_letters.pop(0), "ide") | ||||
|             elif "sata" in dom_caps["disk_bus"]: | ||||
|                 xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), "sata") | ||||
|             elif "scsi" in dom_caps["disk_bus"]: | ||||
|                 xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), "scsi") | ||||
|             else: | ||||
|                 xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), 'virtio') | ||||
|                 xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), "virtio") | ||||
|             xml += """</disk>""" | ||||
| 
 | ||||
|         for net in networks.split(','): | ||||
|         for net in networks.split(","): | ||||
|             xml += """<interface type='network'>""" | ||||
|             if mac: | ||||
|                 xml += f"""<mac address='{mac}'/>""" | ||||
|  | @ -319,10 +355,10 @@ class wvmCreate(wvmConnect): | |||
|             if not console_pass == "": | ||||
|                 console_pass = "passwd='" + console_pass + "'" | ||||
| 
 | ||||
|         if 'usb' in dom_caps['disk_bus']: | ||||
|             xml += """<input type='mouse' bus='{}'/>""".format('virtio' if virtio else 'usb') | ||||
|             xml += """<input type='keyboard' bus='{}'/>""".format('virtio' if virtio else 'usb') | ||||
|             xml += """<input type='tablet' bus='{}'/>""".format('virtio' if virtio else 'usb') | ||||
|         if "usb" in dom_caps["disk_bus"]: | ||||
|             xml += """<input type='mouse' bus='{}'/>""".format("virtio" if virtio else "usb") | ||||
|             xml += """<input type='keyboard' bus='{}'/>""".format("virtio" if virtio else "usb") | ||||
|             xml += """<input type='tablet' bus='{}'/>""".format("virtio" if virtio else "usb") | ||||
|         else: | ||||
|             xml += """<input type='mouse'/>""" | ||||
|             xml += """<input type='keyboard'/>""" | ||||
|  |  | |||
|  | @ -1,14 +1,15 @@ | |||
| import time | ||||
| 
 | ||||
| from vrtManager.connection import wvmConnect | ||||
| from vrtManager.util import get_xml_path | ||||
| 
 | ||||
| 
 | ||||
| def cpu_version(doc): | ||||
|     for info in doc.xpath('/sysinfo/processor/entry'): | ||||
|         elem = info.xpath('@name')[0] | ||||
|         if elem == 'version': | ||||
|     for info in doc.xpath("/sysinfo/processor/entry"): | ||||
|         elem = info.xpath("@name")[0] | ||||
|         if elem == "version": | ||||
|             return info.text | ||||
|     return 'Unknown' | ||||
|     return "Unknown" | ||||
| 
 | ||||
| 
 | ||||
| class wvmHostDetails(wvmConnect): | ||||
|  | @ -19,14 +20,12 @@ class wvmHostDetails(wvmConnect): | |||
|         all_mem = self.wvm.getInfo()[1] * 1048576 | ||||
|         freemem = self.wvm.getMemoryStats(-1, 0) | ||||
|         if isinstance(freemem, dict): | ||||
|             free = (freemem['buffers'] + | ||||
|                     freemem['free'] + | ||||
|                     freemem['cached']) * 1024 | ||||
|             free = (freemem["buffers"] + freemem["free"] + freemem["cached"]) * 1024 | ||||
|             percent = abs(100 - ((free * 100) // all_mem)) | ||||
|             usage = (all_mem - free) | ||||
|             mem_usage = {'total': all_mem, 'usage': usage, 'percent': percent} | ||||
|             usage = all_mem - free | ||||
|             mem_usage = {"total": all_mem, "usage": usage, "percent": percent} | ||||
|         else: | ||||
|             mem_usage = {'total': None, 'usage': None, 'percent': None} | ||||
|             mem_usage = {"total": None, "usage": None, "percent": None} | ||||
|         return mem_usage | ||||
| 
 | ||||
|     def get_cpu_usage(self): | ||||
|  | @ -38,7 +37,7 @@ class wvmHostDetails(wvmConnect): | |||
|         cpu = self.wvm.getCPUStats(-1, 0) | ||||
|         if isinstance(cpu, dict): | ||||
|             for num in range(2): | ||||
|                 idle = self.wvm.getCPUStats(-1, 0)['idle'] | ||||
|                 idle = self.wvm.getCPUStats(-1, 0)["idle"] | ||||
|                 total = sum(self.wvm.getCPUStats(-1, 0).values()) | ||||
|                 diff_idle = idle - prev_idle | ||||
|                 diff_total = total - prev_total | ||||
|  | @ -51,8 +50,8 @@ class wvmHostDetails(wvmConnect): | |||
|                     if diff_usage < 0: | ||||
|                         diff_usage = 0 | ||||
|         else: | ||||
|             return {'usage': None} | ||||
|         return {'usage': diff_usage} | ||||
|             return {"usage": None} | ||||
|         return {"usage": diff_usage} | ||||
| 
 | ||||
|     def get_node_info(self): | ||||
|         """ | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,8 +1,8 @@ | |||
| from xml.etree import ElementTree | ||||
| from libvirt import VIR_INTERFACE_XML_INACTIVE | ||||
| from vrtManager.connection import wvmConnect | ||||
| from vrtManager import util | ||||
| 
 | ||||
| from libvirt import VIR_INTERFACE_XML_INACTIVE | ||||
| from vrtManager import util | ||||
| from vrtManager.connection import wvmConnect | ||||
| 
 | ||||
| 
 | ||||
| class wvmInterfaces(wvmConnect): | ||||
|  | @ -12,36 +12,37 @@ class wvmInterfaces(wvmConnect): | |||
|         mac = iface.MACString() | ||||
|         itype = util.get_xml_path(xml, "/interface/@type") | ||||
|         state = iface.isActive() | ||||
|         return {'name': name, 'type': itype, 'state': state, 'mac': mac} | ||||
|         return {"name": name, "type": itype, "state": state, "mac": mac} | ||||
| 
 | ||||
|     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): | ||||
|     def create_iface( | ||||
|         self, name, itype, mode, netdev, ipv4_type, ipv4_addr, ipv4_gw, ipv6_type, ipv6_addr, ipv6_gw, stp, delay | ||||
|     ): | ||||
|         xml = f"""<interface type='{itype}' name='{name}'> | ||||
|                     <start mode='{mode}'/>""" | ||||
|         if ipv4_type == 'dhcp': | ||||
|         if ipv4_type == "dhcp": | ||||
|             xml += """<protocol family='ipv4'> | ||||
|                         <dhcp/> | ||||
|                       </protocol>""" | ||||
|         if ipv4_type == 'static': | ||||
|             address, prefix = ipv4_addr.split('/') | ||||
|         if ipv4_type == "static": | ||||
|             address, prefix = ipv4_addr.split("/") | ||||
|             xml += f"""<protocol family='ipv4'> | ||||
|                         <ip address='{address}' prefix='{prefix}'/> | ||||
|                         <route gateway='{ipv4_gw}'/> | ||||
|                       </protocol>""" | ||||
|         if ipv6_type == 'dhcp': | ||||
|         if ipv6_type == "dhcp": | ||||
|             xml += """<protocol family='ipv6'> | ||||
|                         <dhcp/> | ||||
|                       </protocol>""" | ||||
|         if ipv6_type == 'static': | ||||
|             address, prefix = ipv6_addr.split('/') | ||||
|         if ipv6_type == "static": | ||||
|             address, prefix = ipv6_addr.split("/") | ||||
|             xml += f"""<protocol family='ipv6'> | ||||
|                         <ip address='{address}' prefix='{prefix}'/> | ||||
|                         <route gateway='{ipv6_gw}'/> | ||||
|                       </protocol>""" | ||||
|         if itype == 'bridge': | ||||
|         if itype == "bridge": | ||||
|             xml += f"""<bridge stp='{stp}' delay='{delay}'> | ||||
|                         <interface name='{netdev}' type='ethernet'/> | ||||
|                       </bridge>""" | ||||
|  | @ -85,9 +86,9 @@ class wvmInterface(wvmConnect): | |||
|             xml = self._XMLDesc(VIR_INTERFACE_XML_INACTIVE) | ||||
|             ipaddr = util.get_xml_path(xml, "/interface/protocol[@family='ipv4']/ip/@address") | ||||
|             if ipaddr: | ||||
|                 return 'static' | ||||
|                 return "static" | ||||
|             else: | ||||
|                 return 'dhcp' | ||||
|                 return "dhcp" | ||||
|         except: | ||||
|             return None | ||||
| 
 | ||||
|  | @ -98,16 +99,16 @@ class wvmInterface(wvmConnect): | |||
|         if not int_ipv4_ip or not int_ipv4_mask: | ||||
|             return None | ||||
|         else: | ||||
|             return int_ipv4_ip + '/' + int_ipv4_mask | ||||
|             return int_ipv4_ip + "/" + int_ipv4_mask | ||||
| 
 | ||||
|     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") | ||||
|             if ipaddr: | ||||
|                 return 'static' | ||||
|                 return "static" | ||||
|             else: | ||||
|                 return 'dhcp' | ||||
|                 return "dhcp" | ||||
|         except: | ||||
|             return None | ||||
| 
 | ||||
|  | @ -118,15 +119,15 @@ class wvmInterface(wvmConnect): | |||
|         if not int_ipv6_ip or not int_ipv6_mask: | ||||
|             return None | ||||
|         else: | ||||
|             return int_ipv6_ip + '/' + int_ipv6_mask | ||||
|             return int_ipv6_ip + "/" + int_ipv6_mask | ||||
| 
 | ||||
|     def get_bridge(self): | ||||
|         bridge = None | ||||
|         if self.get_type() == 'bridge': | ||||
|         if self.get_type() == "bridge": | ||||
|             bridge = util.get_xml_path(self._XMLDesc(), "/interface/bridge/interface/@name") | ||||
|             for iface in self.get_bridge_slave_ifaces(): | ||||
|                 if iface.get('state') == 'up' and iface.get('speed') is not 'unknown': | ||||
|                     bridge = iface.get('name') | ||||
|                 if iface.get("state") == "up" and iface.get("speed") != "unknown": | ||||
|                     bridge = iface.get("name") | ||||
|                     return bridge | ||||
|             return bridge | ||||
|         else: | ||||
|  | @ -134,20 +135,20 @@ class wvmInterface(wvmConnect): | |||
| 
 | ||||
|     def get_bridge_slave_ifaces(self): | ||||
|         ifaces = list() | ||||
|         if self.get_type() == 'bridge': | ||||
|         if self.get_type() == "bridge": | ||||
|             tree = ElementTree.fromstring(self._XMLDesc()) | ||||
|             for iface in tree.findall("./bridge/"): | ||||
|                 address = state = speed = None | ||||
|                 name = iface.get('name') | ||||
|                 if_type = iface.get('type') | ||||
|                 link = iface.find('link') | ||||
|                 name = iface.get("name") | ||||
|                 if_type = iface.get("type") | ||||
|                 link = iface.find("link") | ||||
|                 if link is not None: | ||||
|                     state = link.get('state') | ||||
|                     speed = link.get('speed') | ||||
|                 mac = iface.find('mac') | ||||
|                     state = link.get("state") | ||||
|                     speed = link.get("speed") | ||||
|                 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}) | ||||
|                     address = mac.get("address") | ||||
|                 ifaces.append({"name": name, "type": if_type, "state": state, "speed": speed, "mac": address}) | ||||
|             return ifaces | ||||
|         else: | ||||
|             return None | ||||
|  |  | |||
|  | @ -1,11 +1,15 @@ | |||
| from libvirt import ( | ||||
|     VIR_NETWORK_SECTION_IP_DHCP_HOST, | ||||
|     VIR_NETWORK_UPDATE_AFFECT_CONFIG, | ||||
|     VIR_NETWORK_UPDATE_AFFECT_LIVE, | ||||
|     VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, | ||||
|     VIR_NETWORK_UPDATE_COMMAND_DELETE, | ||||
|     VIR_NETWORK_UPDATE_COMMAND_MODIFY, libvirtError) | ||||
| from lxml import etree | ||||
| from libvirt import libvirtError | ||||
| 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 | ||||
| from vrtManager.IPy import IP | ||||
| 
 | ||||
| 
 | ||||
| def network_size(subnet, dhcp=None): | ||||
|     """ | ||||
|  | @ -17,7 +21,7 @@ def network_size(subnet, dhcp=None): | |||
|     if addr.version() == 4: | ||||
|         dhcp_pool = [addr[2].strCompressed(), addr[addr.len() - 2].strCompressed()] | ||||
|     if addr.version() == 6: | ||||
|         mask = mask.lstrip('/') if '/' in mask else mask | ||||
|         mask = mask.lstrip("/") if "/" in mask else mask | ||||
|         dhcp_pool = [IP(addr[0].strCompressed() + hex(256)), IP(addr[0].strCompressed() + hex(512 - 1))] | ||||
|     if dhcp: | ||||
|         return gateway, mask, dhcp_pool | ||||
|  | @ -26,7 +30,6 @@ def network_size(subnet, dhcp=None): | |||
| 
 | ||||
| 
 | ||||
| class wvmNetworks(wvmConnect): | ||||
| 
 | ||||
|     def get_networks_info(self): | ||||
|         get_networks = self.get_networks() | ||||
|         networks = [] | ||||
|  | @ -39,44 +42,55 @@ class wvmNetworks(wvmConnect): | |||
|                 net_bridge = util.get_xml_path(net.XMLDesc(0), "/network/forward/interface/@dev") | ||||
| 
 | ||||
|             net_forward = util.get_xml_path(net.XMLDesc(0), "/network/forward/@mode") | ||||
|             networks.append({'name': network, 'status': net_status, | ||||
|                              'device': net_bridge, 'forward': net_forward}) | ||||
|             networks.append({"name": network, "status": net_status, "device": net_bridge, "forward": net_forward}) | ||||
|         return networks | ||||
| 
 | ||||
|     def define_network(self, xml): | ||||
|         self.wvm.networkDefineXML(xml) | ||||
| 
 | ||||
|     def create_network(self, name, forward, | ||||
|                        ipv4, gateway, mask, dhcp4, | ||||
|                        ipv6, gateway6, prefix6, dhcp6, | ||||
|                        bridge, openvswitch, fixed=False): | ||||
|     def create_network( | ||||
|         self, | ||||
|         name, | ||||
|         forward, | ||||
|         ipv4, | ||||
|         gateway, | ||||
|         mask, | ||||
|         dhcp4, | ||||
|         ipv6, | ||||
|         gateway6, | ||||
|         prefix6, | ||||
|         dhcp6, | ||||
|         bridge, | ||||
|         openvswitch, | ||||
|         fixed=False, | ||||
|     ): | ||||
|         xml = f""" | ||||
|             <network> | ||||
|                 <name>{name}</name>""" | ||||
|         if forward in ['nat', 'route', 'bridge']: | ||||
|         if forward in ["nat", "route", "bridge"]: | ||||
|             xml += f"""<forward mode='{forward}'/>""" | ||||
|         if forward == 'macvtap': | ||||
|         if forward == "macvtap": | ||||
|             xml += f"""<forward mode='bridge'> | ||||
|                           <interface dev='{bridge}'/> | ||||
|                        </forward>""" | ||||
|         else: | ||||
|             xml += """<bridge """ | ||||
|             if forward in ['nat', 'route', 'none']: | ||||
|             if forward in ["nat", "route", "none"]: | ||||
|                 xml += """stp='on' delay='0'""" | ||||
|             if forward == 'bridge': | ||||
|             if forward == "bridge": | ||||
|                 xml += f"""name='{bridge}'""" | ||||
|             xml += """/>""" | ||||
|             if openvswitch is True: | ||||
|                 xml += """<virtualport type='openvswitch'/>""" | ||||
|         if forward not in ['bridge', 'macvtap']: | ||||
|         if forward not in ["bridge", "macvtap"]: | ||||
|             if ipv4: | ||||
|                 xml += f"""<ip address='{gateway}' netmask='{mask}'>""" | ||||
|                 if dhcp4: | ||||
|                     xml += f"""<dhcp> | ||||
|                                 <range start='{dhcp4[0]}' end='{dhcp4[1]}' />""" | ||||
|                     if fixed: | ||||
|                         fist_oct = int(dhcp4[0].strip().split('.')[3]) | ||||
|                         last_oct = int(dhcp4[1].strip().split('.')[3]) | ||||
|                         fist_oct = int(dhcp4[0].strip().split(".")[3]) | ||||
|                         last_oct = int(dhcp4[1].strip().split(".")[3]) | ||||
|                         for ip in range(fist_oct, last_oct + 1): | ||||
|                             xml += f"""<host mac='{util.randomMAC()}' ip='{gateway[:-2]}.{ip}' />""" | ||||
|                     xml += """</dhcp>""" | ||||
|  | @ -144,23 +158,23 @@ class wvmNetwork(wvmConnect): | |||
|         if util.get_xml_path(xml, "/network/ip") is None: | ||||
|             return ip_networks | ||||
|         tree = etree.fromstring(xml) | ||||
|         ips = tree.findall('.ip') | ||||
|         ips = tree.findall(".ip") | ||||
|         for ip in ips: | ||||
|             address_str = ip.get('address') | ||||
|             netmask_str = ip.get('netmask') | ||||
|             prefix = ip.get('prefix') | ||||
|             family = ip.get('family', 'ipv4') | ||||
|             base = 32 if family == 'ipv4' else 128 | ||||
|             address_str = ip.get("address") | ||||
|             netmask_str = ip.get("netmask") | ||||
|             prefix = ip.get("prefix") | ||||
|             family = ip.get("family", "ipv4") | ||||
|             base = 32 if family == "ipv4" else 128 | ||||
|             if prefix: | ||||
|                 prefix = int(prefix) | ||||
|                 binstr = ((prefix * "1") + ((base - prefix) * "0")) | ||||
|                 binstr = (prefix * "1") + ((base - prefix) * "0") | ||||
|                 netmask_str = str(IP(int(binstr, base=2))) | ||||
| 
 | ||||
|             if netmask_str: | ||||
|                 netmask = IP(netmask_str) | ||||
|                 gateway = IP(address_str) | ||||
|                 network = IP(gateway.int() & netmask.int()) | ||||
|                 netmask_str = netmask_str if family == 'ipv4' else str(prefix) | ||||
|                 netmask_str = netmask_str if family == "ipv4" else str(prefix) | ||||
|                 ret = IP(str(network) + "/" + netmask_str) | ||||
|             else: | ||||
|                 ret = IP(str(address_str)) | ||||
|  | @ -178,12 +192,12 @@ class wvmNetwork(wvmConnect): | |||
|         forward_dev = util.get_xml_path(xml, "/network/forward/@dev") | ||||
|         return [fw, forward_dev] | ||||
| 
 | ||||
|     def get_dhcp_range(self, family='ipv4'): | ||||
|     def get_dhcp_range(self, family="ipv4"): | ||||
|         xml = self._XMLDesc(0) | ||||
|         if family == 'ipv4': | ||||
|         if family == "ipv4": | ||||
|             dhcpstart = util.get_xml_path(xml, "/network/ip[not(@family='ipv6')]/dhcp/range[1]/@start") | ||||
|             dhcpend = util.get_xml_path(xml, "/network/ip[not(@family='ipv6')]/dhcp/range[1]/@end") | ||||
|         if family == 'ipv6': | ||||
|         if family == "ipv6": | ||||
|             dhcpstart = util.get_xml_path(xml, "/network/ip[@family='ipv6']/dhcp/range[1]/@start") | ||||
|             dhcpend = util.get_xml_path(xml, "/network/ip[@family='ipv6']/dhcp/range[1]/@end") | ||||
| 
 | ||||
|  | @ -192,13 +206,13 @@ class wvmNetwork(wvmConnect): | |||
| 
 | ||||
|         return [IP(dhcpstart), IP(dhcpend)] | ||||
| 
 | ||||
|     def get_dhcp_range_start(self, family='ipv4'): | ||||
|     def get_dhcp_range_start(self, family="ipv4"): | ||||
|         dhcp = self.get_dhcp_range(family) | ||||
|         if not dhcp: | ||||
|             return None | ||||
|         return dhcp[0] | ||||
| 
 | ||||
|     def get_dhcp_range_end(self, family='ipv4'): | ||||
|     def get_dhcp_range_end(self, family="ipv4"): | ||||
|         dhcp = self.get_dhcp_range(family) | ||||
|         if not dhcp: | ||||
|             return None | ||||
|  | @ -211,74 +225,77 @@ class wvmNetwork(wvmConnect): | |||
|             return True | ||||
|         return bool(util.get_xml_path(xml, "/network/ip/dhcp/bootp/@file")) | ||||
| 
 | ||||
|     def get_dhcp_host_addr(self, family='ipv4'): | ||||
|     def get_dhcp_host_addr(self, family="ipv4"): | ||||
|         result = list() | ||||
|         tree = etree.fromstring(self._XMLDesc(0)) | ||||
| 
 | ||||
|         for ipdhcp in tree.findall("./ip"): | ||||
|             if family == 'ipv4': | ||||
|                 if ipdhcp.get('family') is None: | ||||
|                     hosts = ipdhcp.findall('./dhcp/host') | ||||
|             if family == "ipv4": | ||||
|                 if ipdhcp.get("family") is None: | ||||
|                     hosts = ipdhcp.findall("./dhcp/host") | ||||
|                     for host in hosts: | ||||
|                         host_ip = host.get('ip') | ||||
|                         mac = host.get('mac') | ||||
|                         name = host.get('name', '') | ||||
|                         result.append({'ip': host_ip, 'mac': mac, 'name': name}) | ||||
|                         host_ip = host.get("ip") | ||||
|                         mac = host.get("mac") | ||||
|                         name = host.get("name", "") | ||||
|                         result.append({"ip": host_ip, "mac": mac, "name": name}) | ||||
|                     return result | ||||
|                 else: | ||||
|                     continue | ||||
|             if family == 'ipv6': | ||||
|             if family == "ipv6": | ||||
|                 hosts = tree.xpath("./ip[@family='ipv6']/dhcp/host") | ||||
|                 for host in hosts: | ||||
|                     host_ip = host.get('ip') | ||||
|                     host_id = host.get('id') | ||||
|                     name = host.get('name', '') | ||||
|                     result.append({'ip': host_ip, 'id': host_id, 'name': name}) | ||||
|                     host_ip = host.get("ip") | ||||
|                     host_id = host.get("id") | ||||
|                     name = host.get("name", "") | ||||
|                     result.append({"ip": host_ip, "id": host_id, "name": name}) | ||||
|                 return result | ||||
| 
 | ||||
|     def modify_dhcp_range(self, range_start, range_end, family='ipv4'): | ||||
|     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': | ||||
|             if family == "ipv4": | ||||
|                 dhcp_range = tree.xpath("./ip[not(@family='ipv6')]/dhcp/range") | ||||
|             if family == 'ipv6': | ||||
|             if family == "ipv6": | ||||
|                 dhcp_range = tree.xpath("./ip[@family='ipv6']/dhcp/range") | ||||
|             dhcp_range[0].set('start', range_start) | ||||
|             dhcp_range[0].set('end', range_end) | ||||
|             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'): | ||||
|     def delete_fixed_address(self, ip, family="ipv4"): | ||||
|         tree = etree.fromstring(self._XMLDesc(0)) | ||||
|         if family == 'ipv4': | ||||
|         if family == "ipv4": | ||||
|             hosts = tree.xpath("/network/ip[not(@family='ipv6')]/dhcp/host") | ||||
|             parent_index = self.parent_count - 2 | ||||
|         if family == 'ipv6': | ||||
|         if family == "ipv6": | ||||
|             hosts = tree.xpath("/network/ip[@family='ipv6']/dhcp/host") | ||||
|             parent_index = self.parent_count - 1 | ||||
|         for h in hosts: | ||||
|             if h.get('ip') == ip: | ||||
|                 if family == 'ipv4': | ||||
|                     new_xml = '<host mac="{}" name="{}" ip="{}"/>'.format(h.get('mac'), h.get('name'), ip) | ||||
|                 if family == 'ipv6': | ||||
|                     new_xml = '<host id="{}" name="{}" ip="{}"/>'.format(h.get('id'), h.get('name'), ip) | ||||
|             if h.get("ip") == ip: | ||||
|                 if family == "ipv4": | ||||
|                     new_xml = '<host mac="{}" name="{}" ip="{}"/>'.format(h.get("mac"), h.get("name"), ip) | ||||
|                 if family == "ipv6": | ||||
|                     new_xml = '<host id="{}" name="{}" ip="{}"/>'.format(h.get("id"), h.get("name"), ip) | ||||
| 
 | ||||
|                 self.update(VIR_NETWORK_UPDATE_COMMAND_DELETE, VIR_NETWORK_SECTION_IP_DHCP_HOST, | ||||
|                             new_xml, | ||||
|                             parent_index, | ||||
|                             VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG) | ||||
|                 self.update( | ||||
|                     VIR_NETWORK_UPDATE_COMMAND_DELETE, | ||||
|                     VIR_NETWORK_SECTION_IP_DHCP_HOST, | ||||
|                     new_xml, | ||||
|                     parent_index, | ||||
|                     VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG, | ||||
|                 ) | ||||
|                 break | ||||
| 
 | ||||
|     def modify_fixed_address(self, name, address, mac_duid, family='ipv4'): | ||||
|     def modify_fixed_address(self, name, address, mac_duid, family="ipv4"): | ||||
|         tree = etree.fromstring(self._XMLDesc(0)) | ||||
|         if family == 'ipv4': | ||||
|             new_xml = '<host mac="{}" {} ip="{}"/>'.format(mac_duid, 'name="' + name + '"' if name else '', IP(address)) | ||||
|         if family == "ipv4": | ||||
|             new_xml = '<host mac="{}" {} ip="{}"/>'.format(mac_duid, 'name="' + name + '"' if name else "", IP(address)) | ||||
|             hosts = tree.xpath("./ip[not(@family='ipv6')]/dhcp/host") | ||||
|             compare_var = 'mac' | ||||
|             compare_var = "mac" | ||||
|             parent_index = self.parent_count - 2 | ||||
|         if family == 'ipv6': | ||||
|             new_xml = '<host id="{}" {} ip="{}"/>'.format(mac_duid, 'name="' + name + '"' if name else '', IP(address)) | ||||
|         if family == "ipv6": | ||||
|             new_xml = '<host id="{}" {} ip="{}"/>'.format(mac_duid, 'name="' + name + '"' if name else "", IP(address)) | ||||
|             hosts = tree.xpath("./ip[@family='ipv6']/dhcp/host") | ||||
|             compare_var = 'id' | ||||
|             compare_var = "id" | ||||
|             parent_index = self.parent_count - 1 | ||||
|         new_host_xml = etree.fromstring(new_xml) | ||||
| 
 | ||||
|  | @ -288,17 +305,25 @@ class wvmNetwork(wvmConnect): | |||
|                 host = h | ||||
|                 break | ||||
|         if host is None: | ||||
|             self.update(VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, VIR_NETWORK_SECTION_IP_DHCP_HOST, new_xml, | ||||
|                         parent_index, | ||||
|                         VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG) | ||||
|             self.update( | ||||
|                 VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, | ||||
|                 VIR_NETWORK_SECTION_IP_DHCP_HOST, | ||||
|                 new_xml, | ||||
|                 parent_index, | ||||
|                 VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG, | ||||
|             ) | ||||
|         else: | ||||
|             # change the host | ||||
|             if host.get('name') == new_host_xml.get('name') and host.get('ip') == new_host_xml.get('ip'): | ||||
|             if host.get("name") == new_host_xml.get("name") and host.get("ip") == new_host_xml.get("ip"): | ||||
|                 return False | ||||
|             else: | ||||
|                 self.update(VIR_NETWORK_UPDATE_COMMAND_MODIFY, VIR_NETWORK_SECTION_IP_DHCP_HOST, new_xml, | ||||
|                             parent_index, | ||||
|                             VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG) | ||||
|                 self.update( | ||||
|                     VIR_NETWORK_UPDATE_COMMAND_MODIFY, | ||||
|                     VIR_NETWORK_SECTION_IP_DHCP_HOST, | ||||
|                     new_xml, | ||||
|                     parent_index, | ||||
|                     VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG, | ||||
|                 ) | ||||
| 
 | ||||
|     def get_qos(self): | ||||
|         qos_values = dict() | ||||
|  | @ -307,19 +332,19 @@ class wvmNetwork(wvmConnect): | |||
|         if qos: | ||||
|             qos = qos[0] | ||||
| 
 | ||||
|             in_qos = qos.find('inbound') | ||||
|             in_qos = qos.find("inbound") | ||||
|             if in_qos is not None: | ||||
|                 in_av = in_qos.get('average') | ||||
|                 in_peak = in_qos.get('peak') | ||||
|                 in_burst = in_qos.get('burst') | ||||
|                 qos_values['inbound'] = {'average': in_av, 'peak': in_peak, 'burst': in_burst} | ||||
|                 in_av = in_qos.get("average") | ||||
|                 in_peak = in_qos.get("peak") | ||||
|                 in_burst = in_qos.get("burst") | ||||
|                 qos_values["inbound"] = {"average": in_av, "peak": in_peak, "burst": in_burst} | ||||
| 
 | ||||
|             out_qos = qos.find('outbound') | ||||
|             out_qos = qos.find("outbound") | ||||
|             if out_qos is not None: | ||||
|                 out_av = out_qos.get('average') | ||||
|                 out_peak = out_qos.get('peak') | ||||
|                 out_burst = out_qos.get('burst') | ||||
|                 qos_values['outbound'] = {'average': out_av, 'peak': out_peak, 'burst': out_burst} | ||||
|                 out_av = out_qos.get("average") | ||||
|                 out_peak = out_qos.get("peak") | ||||
|                 out_burst = out_qos.get("burst") | ||||
|                 qos_values["outbound"] = {"average": out_av, "peak": out_peak, "burst": out_burst} | ||||
|         return qos_values | ||||
| 
 | ||||
|     def set_qos(self, direction, average, peak, burst): | ||||
|  | @ -328,7 +353,7 @@ class wvmNetwork(wvmConnect): | |||
|         elif direction == "outbound": | ||||
|             xml = f"<outbound average='{average}' peak='{peak}' burst='{burst}'/>" | ||||
|         else: | ||||
|             raise Exception('Direction must be inbound or outbound') | ||||
|             raise Exception("Direction must be inbound or outbound") | ||||
| 
 | ||||
|         tree = etree.fromstring(self._XMLDesc(0)) | ||||
| 
 | ||||
|  | @ -363,7 +388,7 @@ class wvmNetwork(wvmConnect): | |||
|             self.leases = self.net.DHCPLeases() | ||||
|         except Exception as e: | ||||
|             self.leases = [] | ||||
|             raise f"Error getting {self} DHCP leases: {e}" | ||||
|             raise "Error getting {} DHCP leases: {}".format(self, e) | ||||
| 
 | ||||
|     def get_dhcp_leases(self): | ||||
|         if self.leases is None: | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| from xml.etree import ElementTree | ||||
| 
 | ||||
| from vrtManager.connection import wvmConnect | ||||
| 
 | ||||
| 
 | ||||
|  | @ -7,7 +8,7 @@ class wvmNWFilters(wvmConnect): | |||
|         nwfilter = self.get_nwfilter(name) | ||||
|         xml = nwfilter.XMLDesc(0) | ||||
|         uuid = nwfilter.UUIDString() | ||||
|         return {'name': name, 'uuid': uuid, 'xml': xml} | ||||
|         return {"name": name, "uuid": uuid, "xml": xml} | ||||
| 
 | ||||
|     def create_nwfilter(self, xml): | ||||
|         self.wvm.nwfilterDefineXML(xml) | ||||
|  | @ -16,8 +17,8 @@ class wvmNWFilters(wvmConnect): | |||
|         nwfilter = self.get_nwfilter(name) | ||||
|         if nwfilter: | ||||
|             tree = ElementTree.fromstring(nwfilter.XMLDesc(0)) | ||||
|             tree.set('name', cln_name) | ||||
|             uuid = tree.find('uuid') | ||||
|             tree.set("name", cln_name) | ||||
|             uuid = tree.find("uuid") | ||||
|             tree.remove(uuid) | ||||
|             self.create_nwfilter(ElementTree.tostring(tree).decode()) | ||||
| 
 | ||||
|  | @ -41,7 +42,7 @@ class wvmNWFilter(wvmConnect): | |||
| 
 | ||||
|     def get_xml(self): | ||||
|         tree = ElementTree.fromstring(self._XMLDesc(0)) | ||||
|         uuid = tree.find('uuid') | ||||
|         uuid = tree.find("uuid") | ||||
|         tree.remove(uuid) | ||||
|         return ElementTree.tostring(tree).decode() | ||||
| 
 | ||||
|  | @ -49,7 +50,7 @@ class wvmNWFilter(wvmConnect): | |||
|         refs = [] | ||||
|         tree = ElementTree.fromstring(self._XMLDesc(0)) | ||||
|         for ref in tree.findall("./filterref"): | ||||
|             refs.append(ref.get('filter')) | ||||
|             refs.append(ref.get("filter")) | ||||
|         return refs | ||||
| 
 | ||||
|     def get_rules(self): | ||||
|  | @ -57,10 +58,10 @@ class wvmNWFilter(wvmConnect): | |||
| 
 | ||||
|         tree = ElementTree.fromstring(self._XMLDesc(0)) | ||||
|         for r in tree.findall("./rule"): | ||||
|             rule_action = r.get('action') | ||||
|             rule_direction = r.get('direction') | ||||
|             rule_priority = r.get('priority') | ||||
|             rule_statematch = r.get('statematch') | ||||
|             rule_action = r.get("action") | ||||
|             rule_direction = r.get("direction") | ||||
|             rule_priority = r.get("priority") | ||||
|             rule_statematch = r.get("statematch") | ||||
| 
 | ||||
|             rule_directives = r.find("./") | ||||
|             if rule_directives is not None: | ||||
|  | @ -71,7 +72,7 @@ class wvmNWFilter(wvmConnect): | |||
|                 "direction": rule_direction, | ||||
|                 "priority": rule_priority, | ||||
|                 "statematch": rule_statematch, | ||||
|                 "directives": rule_directives | ||||
|                 "directives": rule_directives, | ||||
|             } | ||||
| 
 | ||||
|             rules.append(rule_info) | ||||
|  | @ -81,7 +82,7 @@ class wvmNWFilter(wvmConnect): | |||
|     def delete_ref(self, name): | ||||
|         tree = ElementTree.fromstring(self._XMLDesc(0)) | ||||
|         for ref in tree.findall("./filterref"): | ||||
|             if name == ref.get('filter'): | ||||
|             if name == ref.get("filter"): | ||||
|                 tree.remove(ref) | ||||
|                 break | ||||
|         return ElementTree.tostring(tree).decode() | ||||
|  | @ -89,7 +90,9 @@ class wvmNWFilter(wvmConnect): | |||
|     def delete_rule(self, action, direction, priority): | ||||
|         tree = ElementTree.fromstring(self._XMLDesc(0)) | ||||
| 
 | ||||
|         rule_tree = tree.findall("./rule[@action='%s'][@direction='%s'][@priority='%s']" % (action, direction, priority)) | ||||
|         rule_tree = tree.findall( | ||||
|             "./rule[@action='%s'][@direction='%s'][@priority='%s']" % (action, direction, priority) | ||||
|         ) | ||||
|         if rule_tree: | ||||
|             tree.remove(rule_tree[0]) | ||||
| 
 | ||||
|  | @ -98,7 +101,7 @@ class wvmNWFilter(wvmConnect): | |||
|     def add_ref(self, name): | ||||
|         tree = ElementTree.fromstring(self._XMLDesc(0)) | ||||
|         element = ElementTree.Element("filterref") | ||||
|         element.attrib['filter'] = name | ||||
|         element.attrib["filter"] = name | ||||
|         tree.append(element) | ||||
|         return ElementTree.tostring(tree).decode() | ||||
| 
 | ||||
|  | @ -106,19 +109,21 @@ class wvmNWFilter(wvmConnect): | |||
|         tree = ElementTree.fromstring(self._XMLDesc(0)) | ||||
|         rule = ElementTree.fromstring(xml) | ||||
| 
 | ||||
|         rule_action = rule.get('action') | ||||
|         rule_direction = rule.get('direction') | ||||
|         rule_priority = rule.get('priority') | ||||
|         rule_action = rule.get("action") | ||||
|         rule_direction = rule.get("direction") | ||||
|         rule_priority = rule.get("priority") | ||||
|         rule_directives = rule.find("./") | ||||
|         rule_tree = tree.findall("./rule[@action='%s'][@direction='%s'][@priority='%s']" % (rule_action, rule_direction, rule_priority)) | ||||
|         rule_tree = tree.findall( | ||||
|             "./rule[@action='%s'][@direction='%s'][@priority='%s']" % (rule_action, rule_direction, rule_priority) | ||||
|         ) | ||||
| 
 | ||||
|         if rule_tree: | ||||
|             rule_tree[0].append(rule_directives) | ||||
|         else: | ||||
|             element = ElementTree.Element("rule") | ||||
|             element.attrib['action'] = rule_action | ||||
|             element.attrib['direction'] = rule_direction | ||||
|             element.attrib['priority'] = rule_priority | ||||
|             element.attrib["action"] = rule_action | ||||
|             element.attrib["direction"] = rule_direction | ||||
|             element.attrib["priority"] = rule_priority | ||||
|             element.append(rule_directives) | ||||
|             tree.append(element) | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,11 +11,9 @@ found at: http://code.activestate.com/recipes/502283-read-write-lock-class-rlock | |||
| 
 | ||||
| # Imports | ||||
| # ------- | ||||
| 
 | ||||
| from threading import Condition, Lock, currentThread | ||||
| from time import time | ||||
| 
 | ||||
| 
 | ||||
| # Read write lock | ||||
| # --------------- | ||||
| 
 | ||||
|  | @ -138,9 +136,7 @@ class ReadWriteLock(object): | |||
|                     # else also wants to upgrade, there is no way we can do | ||||
|                     # this except if one of us releases all his read locks. | ||||
|                     # Signal this to user. | ||||
|                     raise ValueError( | ||||
|                         "Inevitable dead lock, denying write lock" | ||||
|                     ) | ||||
|                     raise ValueError("Inevitable dead lock, denying write lock") | ||||
|                 upgradewriter = True | ||||
|                 self.__upgradewritercount = self.__readers.pop(me) | ||||
|             else: | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import base64 | ||||
| 
 | ||||
| from vrtManager.connection import wvmConnect | ||||
| 
 | ||||
| 
 | ||||
|  | @ -6,11 +7,11 @@ class wvmSecrets(wvmConnect): | |||
|     def create_secret(self, ephemeral, private, secret_type, data): | ||||
|         xml = f"""<secret ephemeral='{ephemeral}' private='{private}'> | ||||
|                     <usage type='{secret_type}'>""" | ||||
|         if secret_type == 'ceph': | ||||
|         if secret_type == "ceph": | ||||
|             xml += f"""<name>{data}</name>""" | ||||
|         if secret_type == 'volume': | ||||
|         if secret_type == "volume": | ||||
|             xml += f"""<volume>{data}</volume>""" | ||||
|         if secret_type == 'iscsi': | ||||
|         if secret_type == "iscsi": | ||||
|             xml += f"""<target>{data}</target>""" | ||||
|         xml += """</usage> | ||||
|                  </secret>""" | ||||
|  |  | |||
|  | @ -16,13 +16,7 @@ class wvmStorages(wvmConnect): | |||
|                 stg_vol = None | ||||
|             stg_size = stg.info()[1] | ||||
|             storages.append( | ||||
|                 { | ||||
|                     "name": pool, | ||||
|                     "status": stg_status, | ||||
|                     "type": stg_type, | ||||
|                     "volumes": stg_vol, | ||||
|                     "size": stg_size | ||||
|                 } | ||||
|                 {"name": pool, "status": stg_status, "type": stg_type, "volumes": stg_vol, "size": stg_size} | ||||
|             ) | ||||
|         return storages | ||||
| 
 | ||||
|  | @ -103,12 +97,7 @@ class wvmStorage(wvmConnect): | |||
|         return self.pool.name() | ||||
| 
 | ||||
|     def get_status(self): | ||||
|         status = [ | ||||
|             "Not running", | ||||
|             "Initializing pool, not available", | ||||
|             "Running normally", | ||||
|             "Running degraded" | ||||
|         ] | ||||
|         status = ["Not running", "Initializing pool, not available", "Running normally", "Running degraded"] | ||||
|         try: | ||||
|             return status[self.pool.info()[0]] | ||||
|         except ValueError: | ||||
|  | @ -217,12 +206,12 @@ class wvmStorage(wvmConnect): | |||
|                     "name": volname, | ||||
|                     "size": self.get_volume_size(volname), | ||||
|                     "allocation": self.get_volume_allocation(volname), | ||||
|                     "type": self.get_volume_type(volname) | ||||
|                     "type": self.get_volume_type(volname), | ||||
|                 } | ||||
|             ) | ||||
|         return vol_list | ||||
| 
 | ||||
|     def create_volume(self, name, size, vol_fmt='qcow2', metadata=False, disk_owner_uid=0, disk_owner_gid=0): | ||||
|     def create_volume(self, name, size, vol_fmt="qcow2", metadata=False, disk_owner_uid=0, disk_owner_gid=0): | ||||
|         size = int(size) * 1073741824 | ||||
|         storage_type = self.get_type() | ||||
|         alloc = size | ||||
|  | @ -258,7 +247,17 @@ class wvmStorage(wvmConnect): | |||
|         self._createXML(xml, metadata) | ||||
|         return name | ||||
| 
 | ||||
|     def clone_volume(self, name, target_file, vol_fmt=None, metadata=False, mode='0644', file_suffix='img', disk_owner_uid=0, disk_owner_gid=0): | ||||
|     def clone_volume( | ||||
|         self, | ||||
|         name, | ||||
|         target_file, | ||||
|         vol_fmt=None, | ||||
|         metadata=False, | ||||
|         mode="0644", | ||||
|         file_suffix="img", | ||||
|         disk_owner_uid=0, | ||||
|         disk_owner_gid=0, | ||||
|     ): | ||||
|         vol = self.get_volume(name) | ||||
|         if not vol_fmt: | ||||
|             vol_fmt = self.get_volume_type(name) | ||||
|  | @ -266,10 +265,10 @@ class wvmStorage(wvmConnect): | |||
|         storage_type = self.get_type() | ||||
|         if storage_type == "dir": | ||||
|             if vol_fmt in ["qcow", "qcow2"]: | ||||
|                 target_file += '.' + vol_fmt | ||||
|                 target_file += "." + vol_fmt | ||||
|             else: | ||||
|                 suffix = '.' + file_suffix | ||||
|                 target_file += suffix if len(suffix) > 1 else '' | ||||
|                 suffix = "." + file_suffix | ||||
|                 target_file += suffix if len(suffix) > 1 else "" | ||||
| 
 | ||||
|         xml = f""" | ||||
|             <volume> | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| import random | ||||
| import string | ||||
| import re | ||||
| import lxml.etree as etree | ||||
| import string | ||||
| 
 | ||||
| import libvirt | ||||
| import lxml.etree as etree | ||||
| 
 | ||||
| 
 | ||||
| def is_kvm_available(xml): | ||||
|  | @ -18,10 +19,8 @@ def randomMAC(): | |||
|     # qemu MAC | ||||
|     oui = [0x52, 0x54, 0x00] | ||||
| 
 | ||||
|     mac = oui + [random.randint(0x00, 0xff), | ||||
|                  random.randint(0x00, 0xff), | ||||
|                  random.randint(0x00, 0xff)] | ||||
|     return ':'.join(map(lambda x: "%02x" % x, mac)) | ||||
|     mac = oui + [random.randint(0x00, 0xFF), random.randint(0x00, 0xFF), random.randint(0x00, 0xFF)] | ||||
|     return ":".join(map(lambda x: "%02x" % x, mac)) | ||||
| 
 | ||||
| 
 | ||||
| def randomUUID(): | ||||
|  | @ -29,18 +28,17 @@ def randomUUID(): | |||
|     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) | ||||
|     return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2, | ||||
|                      "%02x" * 6]) % tuple(u) | ||||
|     return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2, "%02x" * 6]) % tuple(u) | ||||
| 
 | ||||
| 
 | ||||
| def randomPasswd(length=12, alphabet=string.ascii_letters + string.digits): | ||||
|     """Generate a random password""" | ||||
|     return ''.join([random.choice(alphabet) for i in range(length)]) | ||||
|     return "".join([random.choice(alphabet) for i in range(length)]) | ||||
| 
 | ||||
| 
 | ||||
| def get_max_vcpus(conn, type=None): | ||||
|     """@param conn: libvirt connection to poll for max possible vcpus | ||||
|        @type type: optional guest type (kvm, etc.)""" | ||||
|     @type type: optional guest type (kvm, etc.)""" | ||||
|     if type is None: | ||||
|         type = conn.getType() | ||||
|     try: | ||||
|  | @ -57,7 +55,7 @@ def xml_escape(str): | |||
| 
 | ||||
|     str = str.replace("&", "&") | ||||
|     str = str.replace("'", "'") | ||||
|     str = str.replace("\"", """) | ||||
|     str = str.replace('"', """) | ||||
|     str = str.replace("<", "<") | ||||
|     str = str.replace(">", ">") | ||||
|     return str | ||||
|  | @ -109,7 +107,7 @@ def get_xpath(doc, path): | |||
|     if ret is not None: | ||||
|         if isinstance(ret, list): | ||||
|             if len(ret) >= 1: | ||||
|                 if hasattr(ret[0], 'text'): | ||||
|                 if hasattr(ret[0], "text"): | ||||
|                     result = ret[0].text | ||||
|                 else: | ||||
|                     result = ret[0] | ||||
|  | @ -146,11 +144,11 @@ def validate_uuid(val): | |||
|             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.") | ||||
|                 "omit hyphens altogether." | ||||
|             ) | ||||
| 
 | ||||
|         else:   # UUID had no dashes, so add them in | ||||
|             val = (val[0:8] + "-" + val[8:12] + "-" + val[12:16] + | ||||
|                    "-" + val[16:20] + "-" + val[20:32]) | ||||
|         else:  # UUID had no dashes, so add them in | ||||
|             val = val[0:8] + "-" + val[8:12] + "-" + val[12:16] + "-" + val[16:20] + "-" + val[20:32] | ||||
|     return val | ||||
| 
 | ||||
| 
 | ||||
|  | @ -163,7 +161,7 @@ def validate_macaddr(val): | |||
| 
 | ||||
|     form = re.match("^([0-9a-fA-F]{1,2}:){5}[0-9a-fA-F]{1,2}$", val) | ||||
|     if form is None: | ||||
|         raise ValueError(f"MAC address must be of the format AA:BB:CC:DD:EE:FF, was {val}") | ||||
|         raise ValueError("MAC address must be of the format AA:BB:CC:DD:EE:FF, was {}".format(val)) | ||||
| 
 | ||||
| 
 | ||||
| # Mapping of UEFI binary names to their associated architectures. We | ||||
|  | @ -177,7 +175,8 @@ UEFI_ARCH_PATTERNS = { | |||
|         r".*OVMF_CODE\.fd",  # RHEL | ||||
|         r".*ovmf-x64/OVMF.*\.fd",  # gerd's firmware repo | ||||
|         r".*ovmf-x86_64-.*",  # SUSE | ||||
|         r".*ovmf.*", ".*OVMF.*",  # generic attempt at a catchall | ||||
|         r".*ovmf.*", | ||||
|         ".*OVMF.*",  # generic attempt at a catchall | ||||
|     ], | ||||
|     "aarch64": [ | ||||
|         r".*AAVMF_CODE\.fd",  # RHEL | ||||
|  |  | |||
|  | @ -1,29 +1,30 @@ | |||
| from django import template | ||||
| import re | ||||
| 
 | ||||
| from django import template | ||||
| 
 | ||||
| register = template.Library() | ||||
| 
 | ||||
| 
 | ||||
| @register.simple_tag | ||||
| def app_active(request, app_name): | ||||
|     if request.resolver_match.app_name == app_name: | ||||
|         return 'active' | ||||
|     return '' | ||||
|         return "active" | ||||
|     return "" | ||||
| 
 | ||||
| 
 | ||||
| @register.simple_tag | ||||
| def view_active(request, view_name): | ||||
|     if request.resolver_match.view_name == view_name: | ||||
|         return 'active' | ||||
|     return '' | ||||
|         return "active" | ||||
|     return "" | ||||
| 
 | ||||
| 
 | ||||
| @register.simple_tag | ||||
| def class_active(request, pattern): | ||||
|     if re.search(pattern, request.path): | ||||
|         # Not sure why 'class="active"' returns class=""active"" | ||||
|         return 'active' | ||||
|     return '' | ||||
|         return "active" | ||||
|     return "" | ||||
| 
 | ||||
| 
 | ||||
| @register.simple_tag | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ class ExceptionMiddleware: | |||
|         if isinstance(exception, libvirtError): | ||||
|             messages.error( | ||||
|                 request, | ||||
|                 _('libvirt Error - %(exception)s') % {'exception': exception}, | ||||
|                 _("libvirt Error - %(exception)s") % {"exception": exception}, | ||||
|             ) | ||||
|             return render(request, '500.html', status=500) | ||||
|             return render(request, "500.html", status=500) | ||||
|             # TODO: check connecting to host via VPN | ||||
|  |  | |||
|  | @ -20,9 +20,7 @@ MIDDLEWARE += [ | |||
| ] | ||||
| 
 | ||||
| # DebugToolBar | ||||
| INTERNAL_IPS = ( | ||||
|     "127.0.0.1", | ||||
| ) | ||||
| INTERNAL_IPS = ("127.0.0.1",) | ||||
| DEBUG_TOOLBAR_CONFIG = { | ||||
|     "INTERCEPT_REDIRECTS": False, | ||||
| } | ||||
|  |  | |||
|  | @ -8,102 +8,102 @@ import os | |||
| # Build paths inside the project like this: os.path.join(BASE_DIR, ...) | ||||
| BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||||
| 
 | ||||
| SECRET_KEY = '' | ||||
| SECRET_KEY = "" | ||||
| 
 | ||||
| DEBUG = False | ||||
| 
 | ||||
| ALLOWED_HOSTS = ['*'] | ||||
| ALLOWED_HOSTS = ["*"] | ||||
| 
 | ||||
| # Application definition | ||||
| INSTALLED_APPS = [ | ||||
|     'django.contrib.auth', | ||||
|     'django.contrib.contenttypes', | ||||
|     'django.contrib.sessions', | ||||
|     'django.contrib.messages', | ||||
|     'django.contrib.staticfiles', | ||||
|     'bootstrap4', | ||||
|     'django_icons', | ||||
|     'django_otp', | ||||
|     'django_otp.plugins.otp_totp', | ||||
|     'accounts', | ||||
|     'admin', | ||||
|     'appsettings', | ||||
|     'computes', | ||||
|     'console', | ||||
|     'datasource', | ||||
|     'networks', | ||||
|     'instances', | ||||
|     'interfaces', | ||||
|     'nwfilters', | ||||
|     'storages', | ||||
|     'secrets', | ||||
|     'logs', | ||||
|     'qr_code', | ||||
|     "django.contrib.auth", | ||||
|     "django.contrib.contenttypes", | ||||
|     "django.contrib.sessions", | ||||
|     "django.contrib.messages", | ||||
|     "django.contrib.staticfiles", | ||||
|     "bootstrap4", | ||||
|     "django_icons", | ||||
|     "django_otp", | ||||
|     "django_otp.plugins.otp_totp", | ||||
|     "accounts", | ||||
|     "admin", | ||||
|     "appsettings", | ||||
|     "computes", | ||||
|     "console", | ||||
|     "datasource", | ||||
|     "networks", | ||||
|     "instances", | ||||
|     "interfaces", | ||||
|     "nwfilters", | ||||
|     "storages", | ||||
|     "secrets", | ||||
|     "logs", | ||||
|     "qr_code", | ||||
| ] | ||||
| 
 | ||||
| MIDDLEWARE = [ | ||||
|     'django.middleware.security.SecurityMiddleware', | ||||
|     'django.contrib.sessions.middleware.SessionMiddleware', | ||||
|     'django.middleware.locale.LocaleMiddleware', | ||||
|     'django.middleware.common.CommonMiddleware', | ||||
|     'django.middleware.csrf.CsrfViewMiddleware', | ||||
|     'django.contrib.auth.middleware.AuthenticationMiddleware', | ||||
|     'django_otp.middleware.OTPMiddleware', | ||||
|     'login_required.middleware.LoginRequiredMiddleware', | ||||
|     'django.contrib.auth.middleware.RemoteUserMiddleware', | ||||
|     'django.contrib.messages.middleware.MessageMiddleware', | ||||
|     'django.middleware.clickjacking.XFrameOptionsMiddleware', | ||||
|     'appsettings.middleware.AppSettingsMiddleware', | ||||
|     'webvirtcloud.middleware.ExceptionMiddleware', | ||||
|     "django.middleware.security.SecurityMiddleware", | ||||
|     "django.contrib.sessions.middleware.SessionMiddleware", | ||||
|     "django.middleware.locale.LocaleMiddleware", | ||||
|     "django.middleware.common.CommonMiddleware", | ||||
|     "django.middleware.csrf.CsrfViewMiddleware", | ||||
|     "django.contrib.auth.middleware.AuthenticationMiddleware", | ||||
|     "django_otp.middleware.OTPMiddleware", | ||||
|     "login_required.middleware.LoginRequiredMiddleware", | ||||
|     "django.contrib.auth.middleware.RemoteUserMiddleware", | ||||
|     "django.contrib.messages.middleware.MessageMiddleware", | ||||
|     "django.middleware.clickjacking.XFrameOptionsMiddleware", | ||||
|     "appsettings.middleware.AppSettingsMiddleware", | ||||
|     "webvirtcloud.middleware.ExceptionMiddleware", | ||||
| ] | ||||
| 
 | ||||
| ROOT_URLCONF = 'webvirtcloud.urls' | ||||
| ROOT_URLCONF = "webvirtcloud.urls" | ||||
| 
 | ||||
| TEMPLATES = [ | ||||
|     { | ||||
|         'BACKEND': 'django.template.backends.django.DjangoTemplates', | ||||
|         'DIRS': [ | ||||
|             os.path.join(BASE_DIR, 'templates'), | ||||
|         "BACKEND": "django.template.backends.django.DjangoTemplates", | ||||
|         "DIRS": [ | ||||
|             os.path.join(BASE_DIR, "templates"), | ||||
|         ], | ||||
|         'APP_DIRS': True, | ||||
|         'OPTIONS': { | ||||
|             'context_processors': [ | ||||
|                 'django.template.context_processors.debug', | ||||
|                 'django.template.context_processors.request', | ||||
|                 'django.contrib.auth.context_processors.auth', | ||||
|                 'django.contrib.messages.context_processors.messages', | ||||
|                 'appsettings.context_processors.app_settings', | ||||
|         "APP_DIRS": True, | ||||
|         "OPTIONS": { | ||||
|             "context_processors": [ | ||||
|                 "django.template.context_processors.debug", | ||||
|                 "django.template.context_processors.request", | ||||
|                 "django.contrib.auth.context_processors.auth", | ||||
|                 "django.contrib.messages.context_processors.messages", | ||||
|                 "appsettings.context_processors.app_settings", | ||||
|             ], | ||||
|             'libraries': { | ||||
|                 'common_tags': 'webvirtcloud.common_tags', | ||||
|             "libraries": { | ||||
|                 "common_tags": "webvirtcloud.common_tags", | ||||
|             }, | ||||
|         }, | ||||
|     }, | ||||
| ] | ||||
| 
 | ||||
| WSGI_APPLICATION = 'webvirtcloud.wsgi.application' | ||||
| WSGI_APPLICATION = "webvirtcloud.wsgi.application" | ||||
| 
 | ||||
| # Database | ||||
| # https://docs.djangoproject.com/en/3.0/ref/settings/#databases | ||||
| 
 | ||||
| DATABASES = { | ||||
|     'default': { | ||||
|         'ENGINE': 'django.db.backends.sqlite3', | ||||
|         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), | ||||
|     "default": { | ||||
|         "ENGINE": "django.db.backends.sqlite3", | ||||
|         "NAME": os.path.join(BASE_DIR, "db.sqlite3"), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| AUTHENTICATION_BACKENDS = [ | ||||
|     'django.contrib.auth.backends.ModelBackend', | ||||
|     "django.contrib.auth.backends.ModelBackend", | ||||
| ] | ||||
| 
 | ||||
| LOGIN_URL = '/accounts/login/' | ||||
| LOGIN_URL = "/accounts/login/" | ||||
| 
 | ||||
| LOGOUT_REDIRECT_URL = '/accounts/login/' | ||||
| LOGOUT_REDIRECT_URL = "/accounts/login/" | ||||
| 
 | ||||
| LANGUAGE_CODE = 'en-us' | ||||
| LANGUAGE_CODE = "en-us" | ||||
| 
 | ||||
| TIME_ZONE = 'UTC' | ||||
| TIME_ZONE = "UTC" | ||||
| 
 | ||||
| USE_I18N = True | ||||
| 
 | ||||
|  | @ -111,30 +111,27 @@ USE_L10N = True | |||
| 
 | ||||
| USE_TZ = True | ||||
| 
 | ||||
| STATIC_URL = '/static/' | ||||
| STATIC_URL = "/static/" | ||||
| 
 | ||||
| STATICFILES_DIRS = [ | ||||
|     os.path.join(BASE_DIR, "static"), | ||||
| ] | ||||
| 
 | ||||
| LOCALE_PATHS = [ | ||||
|     'locale/', | ||||
|     "locale/", | ||||
| ] | ||||
| 
 | ||||
| LOGGING = { | ||||
|     "version": 1, | ||||
|     "disable_existing_loggers": False, | ||||
|     "handlers": { | ||||
|         "mail_admins": { | ||||
|             "level": "ERROR", | ||||
|             "class": "django.utils.log.AdminEmailHandler" | ||||
|         } | ||||
|         "mail_admins": {"level": "ERROR", "class": "django.utils.log.AdminEmailHandler"} | ||||
|     }, | ||||
|     "loggers": { | ||||
|         "django.request": { | ||||
|             "handlers": ["mail_admins"], | ||||
|             "level": "ERROR", | ||||
|             "propagate": True | ||||
|             "propagate": True, | ||||
|         } | ||||
|     }, | ||||
| } | ||||
|  | @ -147,7 +144,7 @@ LOGGING = { | |||
| WS_PORT = 6080 | ||||
| 
 | ||||
| # Websock host | ||||
| WS_HOST = '0.0.0.0' | ||||
| WS_HOST = "0.0.0.0" | ||||
| 
 | ||||
| # Websock public port - 80 or 443 if reverse-proxy, else 6080 | ||||
| WS_PUBLIC_PORT = 6080 | ||||
|  | @ -156,22 +153,53 @@ WS_PUBLIC_PORT = 6080 | |||
| WS_PUBLIC_HOST = None | ||||
| 
 | ||||
| # Websock public path | ||||
| WS_PUBLIC_PATH = '/novncd/' | ||||
| WS_PUBLIC_PATH = "/novncd/" | ||||
| 
 | ||||
| # Websock Certificate for SSL | ||||
| WS_CERT = None | ||||
| 
 | ||||
| # List of console listen addresses | ||||
| QEMU_CONSOLE_LISTEN_ADDRESSES = ( | ||||
|     ('127.0.0.1', 'Localhost'), | ||||
|     ('0.0.0.0', 'All interfaces'), | ||||
|     ("127.0.0.1", "Localhost"), | ||||
|     ("0.0.0.0", "All interfaces"), | ||||
| ) | ||||
| 
 | ||||
| # List taken from http://qemu.weilnetz.de/qemu-doc.html#sec_005finvocation | ||||
| QEMU_KEYMAPS = ['ar', 'da', 'de', 'de-ch', 'en-gb', 'en-us', 'es', 'et', 'fi', | ||||
|                 'fo', 'fr', 'fr-be', 'fr-ca', 'fr-ch', 'hr', 'hu', 'is', 'it', | ||||
|                 'ja', 'lt', 'lv', 'mk', 'nl', 'nl-be', 'no', 'pl', 'pt', | ||||
|                 'pt-br', 'ru', 'sl', 'sv', 'th', 'tr'] | ||||
| QEMU_KEYMAPS = [ | ||||
|     "ar", | ||||
|     "da", | ||||
|     "de", | ||||
|     "de-ch", | ||||
|     "en-gb", | ||||
|     "en-us", | ||||
|     "es", | ||||
|     "et", | ||||
|     "fi", | ||||
|     "fo", | ||||
|     "fr", | ||||
|     "fr-be", | ||||
|     "fr-ca", | ||||
|     "fr-ch", | ||||
|     "hr", | ||||
|     "hu", | ||||
|     "is", | ||||
|     "it", | ||||
|     "ja", | ||||
|     "lt", | ||||
|     "lv", | ||||
|     "mk", | ||||
|     "nl", | ||||
|     "nl-be", | ||||
|     "no", | ||||
|     "pl", | ||||
|     "pt", | ||||
|     "pt-br", | ||||
|     "ru", | ||||
|     "sl", | ||||
|     "sv", | ||||
|     "th", | ||||
|     "tr", | ||||
| ] | ||||
| 
 | ||||
| # Keepalive interval and count for libvirt connections | ||||
| LIBVIRT_KEEPALIVE_INTERVAL = 5 | ||||
|  | @ -183,5 +211,4 @@ SHOW_PROFILE_EDIT_PASSWORD = True | |||
| 
 | ||||
| OTP_ENABLED = False | ||||
| 
 | ||||
| LOGIN_REQUIRED_IGNORE_VIEW_NAMES = ['accounts:email_otp'] | ||||
| 
 | ||||
| LOGIN_REQUIRED_IGNORE_VIEW_NAMES = ["accounts:email_otp"] | ||||
|  |  | |||
|  | @ -1,21 +1,20 @@ | |||
| from django.conf import settings | ||||
| from django.urls import include, path | ||||
| 
 | ||||
| from appsettings.views import appsettings | ||||
| from console.views import console | ||||
| from django.conf import settings | ||||
| from django.urls import include, path | ||||
| from instances.views import index | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|     path('', index, name='index'), | ||||
|     path('admin/', include(('admin.urls', 'admin'), namespace='admin')), | ||||
|     path('accounts/', include('accounts.urls')), | ||||
|     path('appsettings/', appsettings, name='appsettings'), | ||||
|     path('computes/', include('computes.urls')), | ||||
|     path('console/', console, name='console'), | ||||
|     path('datasource/', include('datasource.urls')), | ||||
|     path('instances/', include('instances.urls')), | ||||
|     path('i18n/', include('django.conf.urls.i18n')), | ||||
|     path('logs/', include('logs.urls')), | ||||
|     path("", index, name="index"), | ||||
|     path("admin/", include(("admin.urls", "admin"), namespace="admin")), | ||||
|     path("accounts/", include("accounts.urls")), | ||||
|     path("appsettings/", appsettings, name="appsettings"), | ||||
|     path("computes/", include("computes.urls")), | ||||
|     path("console/", console, name="console"), | ||||
|     path("datasource/", include("datasource.urls")), | ||||
|     path("instances/", include("instances.urls")), | ||||
|     path("i18n/", include("django.conf.urls.i18n")), | ||||
|     path("logs/", include("logs.urls")), | ||||
| ] | ||||
| 
 | ||||
| if settings.DEBUG: | ||||
|  | @ -23,7 +22,7 @@ if settings.DEBUG: | |||
|         import debug_toolbar | ||||
| 
 | ||||
|         urlpatterns += [ | ||||
|             path('__debug__/', include(debug_toolbar.urls)), | ||||
|             path("__debug__/", include(debug_toolbar.urls)), | ||||
|         ] | ||||
|     except ImportError: | ||||
|         pass | ||||
|  |  | |||
|  | @ -11,6 +11,6 @@ import os | |||
| 
 | ||||
| from django.core.wsgi import get_wsgi_application | ||||
| 
 | ||||
| os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webvirtcloud.settings') | ||||
| os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webvirtcloud.settings") | ||||
| 
 | ||||
| application = get_wsgi_application() | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ exec( | |||
|     compile( | ||||
|         open("/srv/webvirtcloud/venv/bin/activate", "rb").read(), | ||||
|         "/srv/webvirtcloud/venv/bin/activate", | ||||
|         "exec" | ||||
|         "exec", | ||||
|     ) | ||||
| ) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue