diff --git a/computes/views.py b/computes/views.py index 5152c91..c95bf25 100644 --- a/computes/views.py +++ b/computes/views.py @@ -14,7 +14,7 @@ def computes(request): """ if not request.user.is_authenticated(): - return HttpResponseRedirect(reverse('login')) + return HttpResponseRedirect(reverse('index')) def get_hosts_status(computes): """ @@ -23,13 +23,13 @@ def computes(request): compute_data = [] for compute in computes: compute_data.append({'id': compute.id, - 'name': compute.name, - 'hostname': compute.hostname, - 'status': connection_manager.host_is_up(compute.type, compute.hostname), - 'type': compute.type, - 'login': compute.login, - 'password': compute.password - }) + 'name': compute.name, + 'hostname': compute.hostname, + 'status': connection_manager.host_is_up(compute.type, compute.hostname), + 'type': compute.type, + 'login': compute.login, + 'password': compute.password + }) return compute_data computes = Compute.objects.filter() @@ -44,7 +44,7 @@ def compute(request, compute_id): """ if not request.user.is_authenticated(): - return HttpResponseRedirect(reverse('login')) + return HttpResponseRedirect(reverse('index')) errors = [] diff --git a/instances/views.py b/instances/views.py index 037be61..00911e7 100644 --- a/instances/views.py +++ b/instances/views.py @@ -26,7 +26,7 @@ def instances(request): """ if not request.user.is_authenticated(): - return HttpResponseRedirect(reverse('login')) + return HttpResponseRedirect(reverse('index')) computes = Compute.objects.filter() all_host_vms = {} @@ -50,6 +50,6 @@ def instance(request, comptes_id, vname): """ if not request.user.is_authenticated(): - return HttpResponseRedirect(reverse('login')) + return HttpResponseRedirect(reverse('index')) return render(request, 'instances.html', locals()) \ No newline at end of file diff --git a/interfaces/forms.py b/interfaces/forms.py new file mode 100644 index 0000000..cebd8a9 --- /dev/null +++ b/interfaces/forms.py @@ -0,0 +1,73 @@ +import re +from django import forms +from django.utils.translation import ugettext_lazy as _ + + +class AddInterface(forms.Form): + name = forms.CharField(max_length=10, required=True) + itype = forms.ChoiceField(required=True, choices=(('bridge', 'bridge'), ('ethernet', 'ethernet'))) + start_mode = forms.ChoiceField(required=True, + choices=(('none', 'none'), ('onboot', 'onboot'), ('hotplug', 'hotplug'))) + netdev = forms.CharField(max_length=15, required=True) + ipv4_type = forms.ChoiceField(required=True, choices=(('dhcp', 'dhcp'), ('static', 'static'), ('none', 'none'))) + ipv4_addr = forms.CharField(max_length=18, required=False) + ipv4_gw = forms.CharField(max_length=15, required=False) + ipv6_type = forms.ChoiceField(required=True, choices=(('dhcp', 'dhcp'), ('static', 'static'), ('none', 'none'))) + ipv6_addr = forms.CharField(max_length=100, required=False) + ipv6_gw = forms.CharField(max_length=100, required=False) + stp = forms.ChoiceField(required=False, choices=(('on', 'on'), ('off', 'off'))) + delay = forms.IntegerField(required=False) + + def clean_ipv4_addr(self): + ipv4_addr = self.cleaned_data['ipv4_addr'] + have_symbol = re.match('^[0-9./]+$', ipv4_addr) + if not have_symbol: + raise forms.ValidationError(_('The ipv4 must not contain any special characters')) + elif len(ipv4_addr) > 20: + raise forms.ValidationError(_('The ipv4 must not exceed 20 characters')) + return ipv4_addr + + def clean_ipv4_gw(self): + ipv4_gw = self.cleaned_data['ipv4_gw'] + have_symbol = re.match('^[0-9.]+$', ipv4_gw) + if not have_symbol: + raise forms.ValidationError(_('The ipv4 gateway must not contain any special characters')) + elif len(ipv4_gw) > 20: + raise forms.ValidationError(_('The ipv4 gateway must not exceed 20 characters')) + return ipv4_gw + + def clean_ipv6_addr(self): + ipv6_addr = self.cleaned_data['ipv6_addr'] + have_symbol = re.match('^[0-9a-f./:]+$', ipv6_addr) + if not have_symbol: + raise forms.ValidationError(_('The ipv6 must not contain any special characters')) + elif len(ipv6_addr) > 100: + raise forms.ValidationError(_('The ipv6 must not exceed 100 characters')) + return ipv6_addr + + def clean_ipv6_gw(self): + ipv6_gw = self.cleaned_data['ipv6_gw'] + have_symbol = re.match('^[0-9.]+$', ipv6_gw) + if not have_symbol: + raise forms.ValidationError(_('The ipv6 gateway must not contain any special characters')) + elif len(ipv6_gw) > 100: + raise forms.ValidationError(_('The ipv6 gateway must not exceed 100 characters')) + return ipv6_gw + + def clean_name(self): + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-z0-9.]+$', name) + if not have_symbol: + raise forms.ValidationError(_('The interface must not contain any special characters')) + elif len(name) > 10: + raise forms.ValidationError(_('The interface must not exceed 10 characters')) + return name + + def clean_netdev(self): + netdev = self.cleaned_data['netdev'] + have_symbol = re.match('^[a-z0-9.]+$', netdev) + if not have_symbol: + raise forms.ValidationError(_('The interface must not contain any special characters')) + elif len(netdev) > 10: + raise forms.ValidationError(_('The interface must not exceed 10 characters')) + return netdev diff --git a/interfaces/views.py b/interfaces/views.py index 91ea44a..6b06be4 100644 --- a/interfaces/views.py +++ b/interfaces/views.py @@ -1,3 +1,97 @@ from django.shortcuts import render +from django.http import HttpResponseRedirect +from django.core.urlresolvers import reverse +from computes.models import Compute +from interfaces.forms import AddInterface +from vrtManager.interface import wvmInterface, wvmInterfaces +from libvirt import libvirtError -# Create your views here. + +def interfaces(request, compute_id): + """ + :param request: + :return: + """ + + if not request.user.is_authenticated(): + return HttpResponseRedirect(reverse('index')) + + errors = [] + ifaces_all = [] + compute = Compute.objects.get(id=compute_id) + + try: + conn = wvmInterfaces(compute.hostname, + compute.login, + compute.password, + compute.type) + ifaces = conn.get_ifaces() + try: + netdevs = conn.get_net_device() + except: + netdevs = ['eth0', 'eth1'] + + for iface in ifaces: + ifaces_all.append(conn.get_iface_info(iface)) + + 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']) + return HttpResponseRedirect(request.get_full_path()) + conn.close() + except libvirtError as err: + errors.append(err) + + return render(request, 'interfaces.html', locals()) + + +def interface(request, compute_id, iface): + """ + :param request: + :return: + """ + + if not request.user.is_authenticated(): + return HttpResponseRedirect(reverse('index')) + + errors = [] + ifaces_all = [] + compute = Compute.objects.get(id=compute_id) + + try: + conn = wvmInterface(compute.hostname, + compute.login, + compute.password, + compute.type, + iface) + start_mode = conn.get_start_mode() + state = conn.is_active() + mac = conn.get_mac() + itype = conn.get_type() + ipv4 = conn.get_ipv4() + ipv4_type = conn.get_ipv4_type() + ipv6 = conn.get_ipv6() + ipv6_type = conn.get_ipv6_type() + bridge = conn.get_bridge() + + if request.method == 'POST': + if 'stop' in request.POST: + conn.stop_iface() + return HttpResponseRedirect(request.get_full_path()) + if 'start' in request.POST: + conn.start_iface() + return HttpResponseRedirect(request.get_full_path()) + if 'delete' in request.POST: + conn.delete_iface() + return HttpResponseRedirect(reverse('interfaces', args=[host_id])) + conn.close() + except libvirtError as err: + errors.append(err) + + return render(request, 'interface.html', locals()) diff --git a/networks/forms.py b/networks/forms.py new file mode 100644 index 0000000..3d44433 --- /dev/null +++ b/networks/forms.py @@ -0,0 +1,43 @@ +import re +from django import forms +from django.utils.translation import ugettext_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 subnet has been entered')}, + max_length=20) + forward = forms.CharField(max_length=100) + dhcp = forms.BooleanField(required=False) + fixed = forms.BooleanField(required=False) + bridge_name = forms.CharField(max_length=20, required=False) + openvswitch = forms.BooleanField(required=False) + + def clean_name(self): + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-zA-Z0-9._-]+$', name) + if not have_symbol: + 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')) + return name + + def clean_subnet(self): + subnet = self.cleaned_data['subnet'] + have_symbol = re.match('^[0-9./]+$', subnet) + if not have_symbol: + raise forms.ValidationError(_('The pool subnet must not contain any special characters')) + elif len(subnet) > 20: + raise forms.ValidationError(_('The pool subnet must not exceed 20 characters')) + return subnet + + def clean_bridge_name(self): + bridge_name = self.cleaned_data['bridge_name'] + if self.cleaned_data['forward'] == 'bridge': + have_symbol = re.match('^[a-zA-Z0-9._-]+$', bridge_name) + if not have_symbol: + 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')) + return bridge_name diff --git a/networks/views.py b/networks/views.py index 91ea44a..ae59255 100644 --- a/networks/views.py +++ b/networks/views.py @@ -1,3 +1,121 @@ from django.shortcuts import render +from django.http import HttpResponseRedirect +from django.utils.translation import ugettext_lazy as _ +from django.core.urlresolvers import reverse +from computes.models import Compute +from networks.forms import AddNetPool +from vrtManager.network import wvmNetwork, wvmNetworks +from vrtManager.network import network_size +from libvirt import libvirtError -# Create your views here. + +def networks(request, compute_id): + """ + :param request: + :return: + """ + + if not request.user.is_authenticated(): + return HttpResponseRedirect(reverse('index')) + + errors = [] + compute = Compute.objects.get(id=compute_id) + + try: + conn = wvmNetworks(compute.hostname, + compute.login, + compute.password, + compute.type) + networks = conn.get_networks_info() + + 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: + msg = _("Pool name already in use") + errors.append(msg) + if data['forward'] == 'bridge' and data['bridge_name'] == '': + errors.append('Please enter bridge name') + try: + gateway, netmask, dhcp = network_size(data['subnet'], data['dhcp']) + except: + msg = _("Input subnet pool error") + errors.append(msg) + if not errors: + conn.create_network(data['name'], data['forward'], gateway, netmask, + dhcp, data['bridge_name'], data['openvswitch'], data['fixed']) + return HttpResponseRedirect(reverse('network', args=[host_id, data['name']])) + conn.close() + except libvirtError as err: + errors.append(err) + + return render(request, 'network.html', locals()) + + +def network(request, compute_id, pool): + """ + :param request: + :return: + """ + + if not request.user.is_authenticated(): + return HttpResponseRedirect(reverse('index')) + + errors = [] + compute = Compute.objects.get(id=compute_id) + + try: + conn = wvmNetwork(compute.hostname, + compute.login, + compute.password, + compute.type, + pool) + networks = conn.get_networks() + state = conn.is_active() + device = conn.get_bridge_device() + autostart = conn.get_autostart() + ipv4_forward = conn.get_ipv4_forward() + ipv4_dhcp_range_start = conn.get_ipv4_dhcp_range_start() + ipv4_dhcp_range_end = conn.get_ipv4_dhcp_range_end() + ipv4_network = conn.get_ipv4_network() + fixed_address = conn.get_mac_ipaddr() + except libvirtError as err: + errors.append(err) + + if request.method == 'POST': + if 'start' in request.POST: + try: + conn.start() + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'stop' in request.POST: + try: + conn.stop() + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'delete' in request.POST: + try: + conn.delete() + return HttpResponseRedirect(reverse('networks', args=[host_id])) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'set_autostart' in request.POST: + try: + conn.set_autostart(1) + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'unset_autostart' in request.POST: + try: + conn.set_autostart(0) + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + + conn.close() + + return render(request, 'network.html', locals()) diff --git a/secrets/forms.py b/secrets/forms.py new file mode 100644 index 0000000..7ae478e --- /dev/null +++ b/secrets/forms.py @@ -0,0 +1,8 @@ +from django import forms + + +class AddSecret(forms.Form): + ephemeral = forms.ChoiceField(required=True, choices=(('no', 'no'), ('yes', 'yes'))) + private = forms.ChoiceField(required=True, choices=(('no', 'no'), ('yes', 'yes'))) + usage_type = forms.ChoiceField(required=True, choices=(('ceph', 'ceph'), ('volume', 'volume'), ('iscsi', 'iscsi'))) + data = forms.CharField(max_length=100, required=True) diff --git a/secrets/views.py b/secrets/views.py index 91ea44a..af03f93 100644 --- a/secrets/views.py +++ b/secrets/views.py @@ -1,3 +1,59 @@ from django.shortcuts import render +from django.http import HttpResponseRedirect +from django.core.urlresolvers import reverse +from computes.models import Compute +from secrets.forms import AddSecret +from vrtManager.secrets import wvmSecrets +from libvirt import libvirtError -# Create your views here. + +def secrets(request, compute_id): + """ + :param request: + :return: + """ + + if not request.user.is_authenticated(): + return HttpResponseRedirect(reverse('index')) + + errors = [] + secrets_all = [] + compute = Compute.objects.get(id=compute_id) + + try: + conn = wvmSecrets(compute.hostname, + compute.login, + compute.password, + compute.type) + secrets = conn.get_secrets() + for uuid in secrets: + secrt = conn.get_secret(uuid) + try: + secret_value = conn.get_secret_value(uuid) + except: + secret_value = '' + secrets_all.append({'usage': secrt.usageID(), + 'uuid': secrt.UUIDString(), + 'usageType': secrt.usageType(), + 'value': secret_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']) + return HttpResponseRedirect(request.get_full_path()) + 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', '') + conn.set_secret_value(uuid, value) + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as err: + errors.append(err) + + return render(request, 'secrets.html', locals()) diff --git a/stotages/__init__.py b/storages/__init__.py similarity index 100% rename from stotages/__init__.py rename to storages/__init__.py diff --git a/stotages/admin.py b/storages/admin.py similarity index 100% rename from stotages/admin.py rename to storages/admin.py diff --git a/storages/forms.py b/storages/forms.py new file mode 100644 index 0000000..e2114ee --- /dev/null +++ b/storages/forms.py @@ -0,0 +1,87 @@ +import re +from django import forms +from django.utils.translation import ugettext_lazy as _ + + +class AddStgPool(forms.Form): + name = forms.CharField(error_messages={'required': _('No pool name has been entered')}, + max_length=20) + stg_type = forms.CharField(max_length=10) + target = forms.CharField(error_messages={'required': _('No path has been entered')}, + max_length=100, + required=False) + source = forms.CharField(max_length=100, required=False) + ceph_user = forms.CharField(required=False) + ceph_host = forms.CharField(required=False) + ceph_pool = forms.CharField(required=False) + secret = forms.CharField(required=False) + netfs_host = forms.CharField(required=False) + source_format = forms.CharField(required=False) + + def clean_name(self): + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-zA-Z0-9._-]+$', name) + if not have_symbol: + 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')) + return name + + def clean_target(self): + storage_type = self.cleaned_data['stg_type'] + target = self.cleaned_data['target'] + have_symbol = re.match('^[a-zA-Z0-9/]+$', target) + if not have_symbol: + raise forms.ValidationError(_('The target must not contain any special characters')) + if storage_type == 'dir': + if not target: + raise forms.ValidationError(_('No path has been entered')) + return target + + def clean_source(self): + storage_type = self.cleaned_data['stg_type'] + source = self.cleaned_data['source'] + have_symbol = re.match('^[a-zA-Z0-9\/]+$', source) + if storage_type == 'logical' or storage_type == 'netfs': + if not source: + raise forms.ValidationError(_('No device has been entered')) + if not have_symbol: + raise forms.ValidationError(_('The source must not contain any special characters')) + return source + + +class AddImage(forms.Form): + name = forms.CharField(max_length=20) + format = forms.ChoiceField(required=True, choices=(('qcow2', 'qcow2 (recommended)'), + ('qcow', 'qcow'), + ('raw', 'raw'))) + size = forms.IntegerField() + meta_prealloc = forms.BooleanField(required=False) + + def clean_name(self): + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-zA-Z0-9._-]+$', name) + if not have_symbol: + raise forms.ValidationError(_('The image name must not contain any special characters')) + elif len(name) > 20: + raise forms.ValidationError(_('The image name must not exceed 20 characters')) + return name + + +class CloneImage(forms.Form): + name = forms.CharField(max_length=20) + image = forms.CharField(max_length=20) + convert = forms.BooleanField(required=False) + format = forms.ChoiceField(required=False, choices=(('qcow2', 'qcow2 (recommended)'), + ('qcow', 'qcow'), + ('raw', 'raw'))) + meta_prealloc = forms.BooleanField(required=False) + + def clean_name(self): + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-zA-Z0-9._-]+$', name) + if not have_symbol: + raise forms.ValidationError(_('The image name must not contain any special characters')) + elif len(name) > 20: + raise forms.ValidationError(_('The image name must not exceed 20 characters')) + return name diff --git a/stotages/migrations/__init__.py b/storages/migrations/__init__.py similarity index 100% rename from stotages/migrations/__init__.py rename to storages/migrations/__init__.py diff --git a/stotages/models.py b/storages/models.py similarity index 100% rename from stotages/models.py rename to storages/models.py diff --git a/stotages/tests.py b/storages/tests.py similarity index 100% rename from stotages/tests.py rename to storages/tests.py diff --git a/storages/views.py b/storages/views.py new file mode 100644 index 0000000..0b5351b --- /dev/null +++ b/storages/views.py @@ -0,0 +1,193 @@ +from django.shortcuts import render +from django.http import HttpResponseRedirect +from django.utils.translation import ugettext_lazy as _ +from django.core.urlresolvers import reverse +from computes.models import Compute +from storages.forms import AddStgPool, AddImage, CloneImage +from vrtManager.storage import wvmStorage, wvmStorages +from libvirt import libvirtError + + +def storages(request, compute_id): + """ + :param request: + :return: + """ + + if not request.user.is_authenticated(): + return HttpResponseRedirect(reverse('index')) + + errors = [] + compute = Compute.objects.get(id=compute_id) + + try: + conn = wvmStorages(compute.hostname, + compute.login, + compute.password, + compute.type) + storages = conn.get_storages_info() + secrets = conn.get_secrets() + + 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: + msg = _("Pool name already use") + errors.append(msg) + if data['stg_type'] == 'rbd': + if not data['secret']: + msg = _("You need create secret for pool") + errors.append(msg) + 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") + errors.append(msg) + 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']) + else: + conn.create_storage(data['stg_type'], data['name'], data['source'], data['target']) + return HttpResponseRedirect(reverse('storage', args=[host_id, data['name']])) + conn.close() + except libvirtError as err: + errors.append(err) + + return render(request, 'storages.html', locals()) + + +def storage(request, compute_id, pool): + """ + :param request: + :return: + """ + + if not request.user.is_authenticated(): + return HttpResponseRedirect(reverse('index')) + + def handle_uploaded_file(path, f_name): + target = path + '/' + str(f_name) + destination = open(target, 'wb+') + for chunk in f_name.chunks(): + destination.write(chunk) + destination.close() + + errors = [] + compute = Compute.objects.get(id=compute_id) + meta_prealloc = False + + try: + conn = wvmStorage(compute.hostname, + compute.login, + compute.password, + compute.type, + pool) + + storages = conn.get_storages() + state = conn.is_active() + size, free = conn.get_size() + used = (size - free) + if state: + percent = (used * 100) / size + else: + percent = 0 + status = conn.get_status() + path = conn.get_target_path() + type = conn.get_type() + autostart = conn.get_autostart() + + if state: + conn.refresh() + volumes = conn.update_volumes() + else: + volumes = None + except libvirtError as err: + errors.append(err) + + if request.method == 'POST': + if 'start' in request.POST: + try: + conn.start() + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'stop' in request.POST: + try: + conn.stop() + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'delete' in request.POST: + try: + conn.delete() + return HttpResponseRedirect(reverse('storages', args=[host_id])) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'set_autostart' in request.POST: + try: + conn.set_autostart(1) + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'unset_autostart' in request.POST: + try: + conn.set_autostart(0) + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'add_volume' in request.POST: + form = AddImage(request.POST) + if form.is_valid(): + data = form.cleaned_data + if data['meta_prealloc'] and data['format'] == 'qcow2': + meta_prealloc = True + try: + conn.create_volume(data['name'], data['size'], data['format'], meta_prealloc) + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as err: + errors.append(err) + if 'del_volume' in request.POST: + volname = request.POST.get('volname', '') + try: + vol = conn.get_volume(volname) + vol.delete(0) + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as error_msg: + errors.append(error_msg.message) + if 'iso_upload' in request.POST: + if str(request.FILES['file']) in conn.update_volumes(): + msg = _("ISO image already exist") + errors.append(msg) + else: + handle_uploaded_file(path, request.FILES['file']) + return HttpResponseRedirect(request.get_full_path()) + if 'cln_volume' in request.POST: + form = CloneImage(request.POST) + if form.is_valid(): + data = form.cleaned_data + img_name = data['name'] + '.img' + meta_prealloc = 0 + if img_name in conn.update_volumes(): + msg = _("Name of volume name already use") + errors.append(msg) + if not errors: + if data['convert']: + format = data['format'] + if data['meta_prealloc'] and data['format'] == 'qcow2': + meta_prealloc = True + else: + format = None + try: + conn.clone_volume(data['image'], data['name'], format, meta_prealloc) + return HttpResponseRedirect(request.get_full_path()) + except libvirtError as err: + errors.append(err) + conn.close() + + return render(request, 'storage.html', locals()) diff --git a/stotages/views.py b/stotages/views.py deleted file mode 100644 index 91ea44a..0000000 --- a/stotages/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/templates/compute.html b/templates/compute.html index 92f11b1..068a0f9 100644 --- a/templates/compute.html +++ b/templates/compute.html @@ -9,15 +9,47 @@
-

Computes

+

{{ compute.name }}

-
- - Error: Better check yourself, you're not looking too good. + {% include 'errors.html' %} + +

{% trans "Basic details" %}

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{% trans "Connection" %}{{ uri_conn }}
{% trans "Hostname" %}{{ hostname }}
{% trans "Hypervisor" %}{{ hypervisor }}
{% trans "Memory" %}{{ host_memory|filesizeformat }}
{% trans "Logical CPUs" %}{{ logical_cpu }}
{% trans "Processor" %}{{ model_cpu }}
{% trans "Architecture" %}{{ host_arch }}
- -
diff --git a/templates/computes.html b/templates/computes.html index 18ff94b..03eb4cf 100644 --- a/templates/computes.html +++ b/templates/computes.html @@ -11,10 +11,7 @@

Computes

-
- - Error: Better check yourself, you're not looking too good. -
+ {% include 'errors.html' %}
{% if computes_info %} diff --git a/templates/dashboard.html b/templates/dashboard.html deleted file mode 100644 index c8f7ef6..0000000 --- a/templates/dashboard.html +++ /dev/null @@ -1,17 +0,0 @@ -{% load static %} -{% include 'header.html' %} - -
-
- - {% include 'sidebar.html' %} - -
-

Dashboard

- - -
-
-
- -{% include 'footer.html' %} diff --git a/templates/errors.html b/templates/errors.html new file mode 100644 index 0000000..0399b80 --- /dev/null +++ b/templates/errors.html @@ -0,0 +1,8 @@ + {% if errors %} + {% for error in errors %} +
+ + Error: Better check yourself, you're not looking too good. +
+ {% endfor %} + {% endif %} \ No newline at end of file diff --git a/templates/instances.html b/templates/instances.html index 12bef53..cb005a4 100644 --- a/templates/instances.html +++ b/templates/instances.html @@ -11,10 +11,7 @@

Instances

-
- - Error: Better check yourself, you're not looking too good. -
+ {% include 'errors.html' %}
diff --git a/webvirtcloud/urls.py b/webvirtcloud/urls.py index aa5de51..060d115 100644 --- a/webvirtcloud/urls.py +++ b/webvirtcloud/urls.py @@ -15,18 +15,17 @@ urlpatterns = patterns('', url(r'^computes/$', 'computes.views.computes', name='computes'), url(r'^compute/(\d+)/$', 'computes.views.compute', name='compute'), - # url(r'^storages/$', 'storages.views.storages', name='storages'), - # url(r'^storage/(\d+)/([\w\-\.]+)/$', 'storages.views.storage', name='storage'), - # - # url(r'^networks/$', 'networks.views.networks', name='networks'), - # url(r'^network/(\d+)/([\w\-\.]+)/$', 'networks.views.network', name='network'), - # - # url(r'^interfaces/$', 'interfaces.views.interfaces', name='interfaces'), - # url(r'^interface/(\d+)/([\w\.]+)$', 'interfaces.views.interface', name='interface'), - # - # url(r'^secrets/$', 'secrets.views.secrets', name='secrets'), - # url(r'^secret/(\d+)/([\w\.]+)$', 'secrets.views.secret', name='secret'), - # + url(r'^storages/(\d+)/$', 'storages.views.storages', name='storages'), + url(r'^storage/(\d+)/([\w\-\.]+)/$', 'storages.views.storage', name='storage'), + + url(r'^networks/(\d+)/$', 'networks.views.networks', name='networks'), + url(r'^network/(\d+)/([\w\-\.]+)/$', 'networks.views.network', name='network'), + + url(r'^interfaces/(\d+)/$', 'interfaces.views.interfaces', name='interfaces'), + url(r'^interface/(\d+)/([\w\.]+)$', 'interfaces.views.interface', name='interface'), + + url(r'^secret/(\d+)/$', 'secrets.views.secrets', name='secrets'), + # url(r'^accounts/$', 'accounts.views.accounts', name='accounts'), # url(r'^account/(\d+)/$', 'accounts.views.account', name='account'), #