1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2024-12-24 15:15:22 +00:00

Reworked some computes forms and views

This commit is contained in:
Real-Gecko 2020-05-29 19:25:36 +06:00
parent 5ab22ba947
commit 7103c52380
8 changed files with 136 additions and 380 deletions

View file

@ -2,131 +2,51 @@ import re
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from computes.models import Compute from computes.models import Compute
from vrtManager.connection import CONN_TCP, CONN_SSH, CONN_TLS, CONN_SOCKET
from .validators import validate_hostname
class ComputeAddTcpForm(forms.Form): class TcpComputeForm(forms.ModelForm):
name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, hostname = forms.CharField(validators=[validate_hostname])
max_length=64) type = forms.IntegerField(widget=forms.HiddenInput, initial=CONN_TCP)
hostname = forms.CharField(error_messages={'required': _('No IP / Domain name has been entered')},
max_length=100)
login = forms.CharField(error_messages={'required': _('No login has been entered')},
max_length=100)
password = forms.CharField(error_messages={'required': _('No password has been entered')},
max_length=100)
details = forms.CharField(max_length=50, required=False)
def clean_name(self): class Meta:
name = self.cleaned_data['name'] model = Compute
have_symbol = re.match('[^a-zA-Z0-9._-]+', name) fields = '__all__'
if have_symbol:
raise forms.ValidationError(_('The host name must not contain any special characters'))
elif len(name) > 20:
raise forms.ValidationError(_('The host name must not exceed 20 characters'))
try:
Compute.objects.get(name=name)
except Compute.DoesNotExist:
return name
raise forms.ValidationError(_('This host is already connected'))
def clean_hostname(self):
hostname = self.cleaned_data['hostname']
have_symbol = re.match('[^a-z0-9.-]+', hostname)
wrong_ip = re.match('^0.|^255.', hostname)
if have_symbol:
raise forms.ValidationError(_('Hostname must contain only numbers, or the domain name separated by "."'))
elif wrong_ip:
raise forms.ValidationError(_('Wrong IP address'))
try:
Compute.objects.get(hostname=hostname)
except Compute.DoesNotExist:
return hostname
raise forms.ValidationError(_('This host is already connected'))
class ComputeAddSshForm(forms.Form): class SshComputeForm(forms.ModelForm):
name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, hostname = forms.CharField(validators=[validate_hostname], label=_("FQDN/IP"))
max_length=64) type = forms.IntegerField(widget=forms.HiddenInput, initial=CONN_SSH)
hostname = forms.CharField(error_messages={'required': _('No IP / Domain name has been entered')},
max_length=100)
login = forms.CharField(error_messages={'required': _('No login has been entered')},
max_length=20)
details = forms.CharField(max_length=50, required=False)
def clean_name(self): class Meta:
name = self.cleaned_data['name'] model = Compute
have_symbol = re.match('[^a-zA-Z0-9._-]+', name) exclude = ['password']
if have_symbol:
raise forms.ValidationError(_('The name of the host must not contain any special characters'))
elif len(name) > 20:
raise forms.ValidationError(_('The name of the host must not exceed 20 characters'))
try:
Compute.objects.get(name=name)
except Compute.DoesNotExist:
return name
raise forms.ValidationError(_('This host is already connected'))
def clean_hostname(self):
hostname = self.cleaned_data['hostname']
have_symbol = re.match('[^a-zA-Z0-9._-]+', hostname)
wrong_ip = re.match('^0.|^255.', hostname)
if have_symbol:
raise forms.ValidationError(_('Hostname must contain only numbers, or the domain name separated by "."'))
elif wrong_ip:
raise forms.ValidationError(_('Wrong IP address'))
try:
Compute.objects.get(hostname=hostname)
except Compute.DoesNotExist:
return hostname
raise forms.ValidationError(_('This host is already connected'))
class ComputeAddTlsForm(forms.Form): class TlsComputeForm(forms.ModelForm):
name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, hostname = forms.CharField(validators=[validate_hostname])
max_length=64) type = forms.IntegerField(widget=forms.HiddenInput, initial=CONN_TLS)
hostname = forms.CharField(error_messages={'required': _('No IP / Domain name has been entered')},
max_length=100)
login = forms.CharField(error_messages={'required': _('No login has been entered')},
max_length=100)
password = forms.CharField(error_messages={'required': _('No password has been entered')},
max_length=100)
details = forms.CharField(max_length=50, required=False)
def clean_name(self): class Meta:
name = self.cleaned_data['name'] model = Compute
have_symbol = re.match('[^a-zA-Z0-9._-]+', name) fields = '__all__'
if have_symbol:
raise forms.ValidationError(_('The host name must not contain any special characters'))
elif len(name) > 20:
raise forms.ValidationError(_('The host name must not exceed 20 characters'))
try:
Compute.objects.get(name=name)
except Compute.DoesNotExist:
return name
raise forms.ValidationError(_('This host is already connected'))
def clean_hostname(self):
hostname = self.cleaned_data['hostname'] class SocketComputeForm(forms.ModelForm):
have_symbol = re.match('[^a-z0-9.-]+', hostname) hostname = forms.CharField(widget=forms.HiddenInput, initial='localhost')
wrong_ip = re.match('^0.|^255.', hostname) type = forms.IntegerField(widget=forms.HiddenInput, initial=CONN_SOCKET)
if have_symbol:
raise forms.ValidationError(_('Hostname must contain only numbers, or the domain name separated by "."')) class Meta:
elif wrong_ip: model = Compute
raise forms.ValidationError(_('Wrong IP address')) fields = ['name', 'details', 'hostname', 'type']
try:
Compute.objects.get(hostname=hostname)
except Compute.DoesNotExist:
return hostname
raise forms.ValidationError(_('This host is already connected'))
class ComputeEditHostForm(forms.Form): class ComputeEditHostForm(forms.Form):
host_id = forms.CharField() host_id = forms.CharField()
name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, max_length=64)
max_length=64) hostname = forms.CharField(error_messages={'required': _('No IP / Domain name has been entered')}, max_length=100)
hostname = forms.CharField(error_messages={'required': _('No IP / Domain name has been entered')}, login = forms.CharField(error_messages={'required': _('No login has been entered')}, max_length=100)
max_length=100)
login = forms.CharField(error_messages={'required': _('No login has been entered')},
max_length=100)
password = forms.CharField(max_length=100) password = forms.CharField(max_length=100)
details = forms.CharField(max_length=50, required=False) details = forms.CharField(max_length=50, required=False)
@ -148,21 +68,3 @@ class ComputeEditHostForm(forms.Form):
elif wrong_ip: elif wrong_ip:
raise forms.ValidationError(_('Wrong IP address')) raise forms.ValidationError(_('Wrong IP address'))
return hostname return hostname
class ComputeAddSocketForm(forms.Form):
name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, max_length=64)
details = forms.CharField(error_messages={'required': _('No details has been entred')}, max_length=50)
def clean_name(self):
name = self.cleaned_data['name']
have_symbol = re.match('[^a-zA-Z0-9._-]+', name)
if have_symbol:
raise forms.ValidationError(_('The host name must not contain any special characters'))
elif len(name) > 20:
raise forms.ValidationError(_('The host name must not exceed 20 characters'))
try:
Compute.objects.get(name=name)
except Compute.DoesNotExist:
return name
raise forms.ValidationError(_('This host is already connected'))

View file

@ -0,0 +1,18 @@
# Generated by Django 2.2.12 on 2020-05-29 13:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('computes', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='compute',
name='name',
field=models.CharField(max_length=64, unique=True),
),
]

View file

@ -2,7 +2,7 @@ from django.db.models import Model, CharField, IntegerField
class Compute(Model): class Compute(Model):
name = CharField(max_length=64) name = CharField(max_length=64, unique=True)
hostname = CharField(max_length=64) hostname = CharField(max_length=64)
login = CharField(max_length=20) login = CharField(max_length=20)
password = CharField(max_length=14, blank=True, null=True) password = CharField(max_length=14, blank=True, null=True)

View file

@ -0,0 +1,29 @@
{% extends "base.html" %}
{% load bootstrap3 %}
{% load font_awesome %}
{% load i18n %}
{% block title %}{% trans "Add Compute" %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-12">
<h2 class="page-header">{% trans "Create Compute" %}</h2>
</div>
</div>
{% bootstrap_messages %}
<div class="row">
<div class="thumbnail col-sm-10 col-sm-offset-1">
<form id="create-update" action="" method="post" class="form-horizontal">
{% csrf_token %}
{% bootstrap_form form layout='horizontal' %}
</form>
<div class="form-group pull-right">
<a class="btn btn-primary" href="javascript:history.back()">{% icon 'times' %} {% trans "Cancel" %}</a>
<button type="submit" form="create-update" class="btn btn-success">
{% icon 'check' %} {% trans "Save" %}
</button>
</div>
</div>
</div>
{% endblock content %}

View file

@ -1,185 +1,9 @@
{% load i18n %} {% load i18n %}
{% if request.user.is_superuser %} {% load bootstrap3 %}
<a href="#addHost" type="button" class="btn btn-success pull-right" data-toggle="modal"> <div class"pull-right">{% trans "Add Connection" %}</div>
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <div class="btn-group pull-right">
</a> <a href="{% url 'add_tcp_host' %}" class="btn btn-success">{% trans "TCP" %}</a>
<a href="{% url 'add_ssh_host' %}" class="btn btn-success">{% trans "SSH" %}</a>
<!-- Modal --> <a href="{% url 'add_tls_host' %}" class="btn btn-success">{% trans "TLS" %}</a>
<div class="modal fade" id="addHost" tabindex="-1" role="dialog" aria-labelledby="addHostLabel" aria-hidden="true"> <a href="{% url 'add_socket_host' %}" class="btn btn-success">{% trans "Local" %}</a>
<div class="modal-dialog"> </div>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times</button>
<h4 class="modal-title">{% trans "Add Connection" %}</h4>
</div>
<div class="tabbable">
<ul class="nav nav-tabs">
<li class="active">
<a href="#1" data-toggle="tab">{% trans "TCP Connections" %}</a>
</li>
<li><a href="#2" data-toggle="tab">{% trans "SSH Connections" %}</a></li>
<li><a href="#3" data-toggle="tab">{% trans "TLS Connection" %}</a></li>
<li><a href="#4" data-toggle="tab">{% trans "Local Socket" %}</a></li>
</ul>
</div>
<div class="tab-content">
<div class="tab-pane active" id="1">
<div class="modal-body">
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Label" %}</label>
<div class="col-sm-6">
<input type="text" name="name" class="form-control" placeholder="Label Name" maxlength="20" required pattern="[a-z0-9\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "FQDN / IP" %}</label>
<div class="col-sm-6">
<input type="text" name="hostname" class="form-control" placeholder="{% trans "FQDN or IP Address" %}" required pattern="[a-z0-9\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Username" %}</label>
<div class="col-sm-6">
<input type="text" name="login" class="form-control" placeholder="{% trans "Username" %}">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Password" %}</label>
<div class="col-sm-6">
<input type="password" name="password" class="form-control" placeholder="{% trans "Password" %}">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Details" %}</label>
<div class="col-sm-6">
<input type="text" name="details" class="form-control" placeholder="{% trans "Details" %}">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
{% trans "Close" %}
</button>
<button type="submit" class="btn btn-primary" name="host_tcp_add">
{% trans "Add" %}
</button>
</div>
</form>
</div>
<div class="tab-pane" id="2">
<div class="modal-body">
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<p class="modal-body">{% trans "You must create ssh <a href='https://github.com/retspen/webvirtmgr/wiki/Setup-SSH-Authorization'>authorization key</a>. If you have another SSH port on your server, you can add IP:PORT like '192.168.1.1:2222'." %}</p>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Label" %}</label>
<div class="col-sm-6">
<input type="text" name="name" class="form-control" placeholder="Label Name" maxlength="20" required pattern="[a-z0-9\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "FQDN / IP" %}</label>
<div class="col-sm-6">
<input type="text" name="hostname" class="form-control" placeholder="{% trans "FQDN or IP Address" %}" required pattern="[a-z0-9\:\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Username" %}</label>
<div class="col-sm-6">
<input type="text" name="login" class="form-control" placeholder="{% trans "Username" %}">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Details" %}</label>
<div class="col-sm-6">
<input type="text" name="details" class="form-control" placeholder="{% trans "Details" %}">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
{% trans "Close" %}
</button>
<button type="submit" class="btn btn-primary" name="host_ssh_add">
{% trans "Add" %}
</button>
</div>
</form>
</div>
<div class="tab-pane" id="3">
<div class="modal-body">
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Label" %}</label>
<div class="col-sm-6">
<input type="text" name="name" class="form-control" placeholder="Label Name" maxlength="20" required pattern="[a-z0-9\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "FQDN / IP" %}</label>
<div class="col-sm-6">
<input type="text" name="hostname" class="form-control" placeholder="{% trans "FQDN or IP Address" %}" required pattern="[a-z0-9\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Username" %}</label>
<div class="col-sm-6">
<input type="text" name="login" class="form-control" placeholder="{% trans "Username" %}">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Password" %}</label>
<div class="col-sm-6">
<input type="password" name="password" class="form-control" placeholder="{% trans "Password" %}">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Details" %}</label>
<div class="col-sm-6">
<input type="text" name="details" class="form-control" placeholder="{% trans "Details" %}">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
{% trans "Close" %}
</button>
<button type="submit" class="btn btn-primary" name="host_tls_add">
{% trans "Add" %}
</button>
</div>
</form>
</div>
<div class="tab-pane" id="4">
<div class="modal-body">
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Label" %}</label>
<div class="col-sm-6">
<input type="text" name="name" class="form-control" placeholder="Label Name" maxlength="20" required pattern="[a-z0-9\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Details" %}</label>
<div class="col-sm-6">
<input type="text" name="details" class="form-control" placeholder="{% trans "Details" %}">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
{% trans "Close" %}
</button>
<button type="submit" class="btn btn-primary" name="host_socket_add">
{% trans "Add" %}
</button>
</div>
</form>
</div>
</div> <!-- /.tab-content -->
</div> <!-- /.modal-content -->
</div> <!-- /.modal-dialog -->
</div><!-- /.modal -->
{% endif %}

View file

@ -9,9 +9,14 @@ from interfaces.views import interface, interfaces
from networks.views import network, networks from networks.views import network, networks
from nwfilters.views import nwfilter, nwfilters from nwfilters.views import nwfilter, nwfilters
from storages.views import get_volumes, storage, storages from storages.views import get_volumes, storage, storages
from . import forms
urlpatterns = [ urlpatterns = [
path('', views.computes, name='computes'), path('', views.computes, name='computes'),
path('add_tcp_host/', views.add_host, {'FormClass': forms.TcpComputeForm}, name='add_tcp_host'),
path('add_ssh_host/', views.add_host, {'FormClass': forms.SshComputeForm}, name='add_ssh_host'),
path('add_tls_host/', views.add_host, {'FormClass': forms.TlsComputeForm}, name='add_tls_host'),
path('add_socket_host/', views.add_host, {'FormClass': forms.SocketComputeForm}, name='add_socket_host'),
path('<int:compute_id>/', views.overview, name='overview'), path('<int:compute_id>/', views.overview, name='overview'),
path('<int:compute_id>/statistics/', views.compute_graph, name='compute_graph'), path('<int:compute_id>/statistics/', views.compute_graph, name='compute_graph'),
path('<int:compute_id>/instances/', instances, name='instances'), path('<int:compute_id>/instances/', instances, name='instances'),

24
computes/validators.py Normal file
View file

@ -0,0 +1,24 @@
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
import re
have_symbol = re.compile('[^a-zA-Z0-9._-]+')
wrong_ip = re.compile('^0.|^255.')
wrong_name = re.compile('[^a-zA-Z0-9._-]+')
def validate_hostname(value):
sym = have_symbol.match(value)
wip = wrong_ip.match(value)
if sym:
raise ValidationError(_('Hostname must contain only numbers, or the domain name separated by "."'))
elif wip:
raise ValidationError(_('Wrong IP address'))
def validate_name(value):
have_symbol = wrong_name.match('[^a-zA-Z0-9._-]+')
if have_symbol:
raise ValidationError(_('The host name must not contain any special characters'))

View file

@ -1,16 +1,19 @@
import json import json
from django.utils import timezone
from django.contrib import messages
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render, reverse
from django.urls import reverse from django.urls import reverse
from django.shortcuts import render, get_object_or_404 from django.utils import timezone
from libvirt import libvirtError
from accounts.models import UserInstance
from admin.decorators import superuser_only
from computes.forms import (ComputeEditHostForm, SocketComputeForm, SshComputeForm, TcpComputeForm, TlsComputeForm)
from computes.models import Compute from computes.models import Compute
from instances.models import Instance from instances.models import Instance
from accounts.models import UserInstance from vrtManager.connection import (CONN_SOCKET, CONN_SSH, CONN_TCP, CONN_TLS, connection_manager, wvmConnect)
from computes.forms import ComputeAddTcpForm, ComputeAddSshForm, ComputeEditHostForm, ComputeAddTlsForm, ComputeAddSocketForm
from vrtManager.hostdetails import wvmHostDetails from vrtManager.hostdetails import wvmHostDetails
from vrtManager.connection import CONN_SSH, CONN_TCP, CONN_TLS, CONN_SOCKET, connection_manager, wvmConnect
from libvirt import libvirtError
from admin.decorators import superuser_only
@superuser_only @superuser_only
@ -55,65 +58,6 @@ def computes(request):
del_host = Compute.objects.get(id=compute_id) del_host = Compute.objects.get(id=compute_id)
del_host.delete() del_host.delete()
return HttpResponseRedirect(request.get_full_path()) return HttpResponseRedirect(request.get_full_path())
if 'host_tcp_add' in request.POST:
form = ComputeAddTcpForm(request.POST)
if form.is_valid():
data = form.cleaned_data
new_tcp_host = Compute(name=data['name'],
hostname=data['hostname'],
type=CONN_TCP,
login=data['login'],
password=data['password'],
details=data['details'])
new_tcp_host.save()
return HttpResponseRedirect(request.get_full_path())
else:
for msg_err in form.errors.values():
error_messages.append(msg_err.as_text())
if 'host_ssh_add' in request.POST:
form = ComputeAddSshForm(request.POST)
if form.is_valid():
data = form.cleaned_data
new_ssh_host = Compute(name=data['name'],
hostname=data['hostname'],
type=CONN_SSH,
login=data['login'],
details=data['details'])
new_ssh_host.save()
return HttpResponseRedirect(request.get_full_path())
else:
for msg_err in form.errors.values():
error_messages.append(msg_err.as_text())
if 'host_tls_add' in request.POST:
form = ComputeAddTlsForm(request.POST)
if form.is_valid():
data = form.cleaned_data
new_tls_host = Compute(name=data['name'],
hostname=data['hostname'],
type=CONN_TLS,
login=data['login'],
password=data['password'],
details=data['details'])
new_tls_host.save()
return HttpResponseRedirect(request.get_full_path())
else:
for msg_err in form.errors.values():
error_messages.append(msg_err.as_text())
if 'host_socket_add' in request.POST:
form = ComputeAddSocketForm(request.POST)
if form.is_valid():
data = form.cleaned_data
new_socket_host = Compute(name=data['name'],
details=data['details'],
hostname='localhost',
type=CONN_SOCKET,
login='',
password='')
new_socket_host.save()
return HttpResponseRedirect(request.get_full_path())
else:
for msg_err in form.errors.values():
error_messages.append(msg_err.as_text())
if 'host_edit' in request.POST: if 'host_edit' in request.POST:
form = ComputeEditHostForm(request.POST) form = ComputeEditHostForm(request.POST)
if form.is_valid(): if form.is_valid():
@ -274,3 +218,13 @@ def get_dom_capabilities(request, compute_id, arch, machine):
pass pass
return HttpResponse(json.dumps(data)) return HttpResponse(json.dumps(data))
@superuser_only
def add_host(request, FormClass):
form = FormClass(request.POST or None)
if form.is_valid():
form.save()
return redirect(reverse('computes'))
return render(request, 'computes/form.html', {'form': form})