mirror of
https://github.com/retspen/webvirtcloud
synced 2024-12-24 23:25:24 +00:00
Merge pull request #385 from catborise/master
black & isort linter fixes- bug fixes
This commit is contained in:
commit
9aed7c7716
63 changed files with 6874 additions and 2143 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,7 +35,7 @@ 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.
|
||||
|
@ -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())
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
|
@ -817,11 +813,11 @@ class IP(IPint):
|
|||
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 += "."
|
||||
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
|
||||
|
@ -1279,7 +1274,7 @@ 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)
|
||||
|
@ -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"],
|
||||
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["loader"],
|
||||
)
|
||||
if firmware["secure"] == "no":
|
||||
xml += """<loader readonly='%s' type='%s'>%s</loader>""" % (
|
||||
firmware["readonly"],
|
||||
firmware["type"],
|
||||
firmware["loader"])
|
||||
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,
|
||||
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)
|
||||
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,
|
||||
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)
|
||||
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,
|
||||
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)
|
||||
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,13 +28,12 @@ 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):
|
||||
|
@ -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])
|
||||
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…
Reference in a new issue