diff --git a/instances/models.py b/instances/models.py index 978d118..2946715 100644 --- a/instances/models.py +++ b/instances/models.py @@ -173,10 +173,6 @@ class Instance(models.Model): def snapshots(self): return sorted(self.proxy.get_snapshot(), reverse=True, key=lambda k: k["date"]) - @cached_property - def external_snapshots(self): - return sorted(self.proxy.get_external_snapshots(), reverse=True, key=lambda k: k["date"]) - @cached_property def inst_xml(self): return self.proxy._XMLDesc(VIR_DOMAIN_XML_SECURE) diff --git a/instances/templates/allinstances.html b/instances/templates/allinstances.html index 457d9f6..095d99c 100644 --- a/instances/templates/allinstances.html +++ b/instances/templates/allinstances.html @@ -25,12 +25,10 @@ {% endif %} {% endfor %}
- {% if 'instances.view_instances' in perms %} - {% if app_settings.VIEW_INSTANCES_LIST_STYLE == 'grouped' and request.user.is_superuser %} - {% include 'allinstances_index_grouped.html' %} - {% else %} - {% include 'allinstances_index_nongrouped.html' %} - {% endif %} + {% if app_settings.VIEW_INSTANCES_LIST_STYLE == 'grouped' and request.user.is_superuser or 'instances.view_instances' in perms %} + {% include 'allinstances_index_grouped.html' %} + {% else %} + {% include 'allinstances_index_nongrouped.html' %} {% endif %}
{% endblock content %} diff --git a/instances/templates/instance.html b/instances/templates/instance.html index 748c0df..bf48bbe 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -679,7 +679,7 @@ } }); } - if (~$.inArray(hash, ['#resize', "#resizevm_cpu", "#resizevm_mem", "#resizevm_disk"])) { + if (~$.inArray(hash, ['#resize', "resizevm_cpu", "resizevm_mem", "resizevm_disk"])) { var btnsect = $('#navbtn>li>a'); $(btnsect).each(function () { if ($(this).attr('href') === '#resize') { @@ -702,7 +702,7 @@ } }); } - if (~$.inArray(hash, ['#takesnapshot', "#takeextsnapshot", "#managesnapshot"])) { + if (~$.inArray(hash, ['#takesnapshot', '#managesnapshot'])) { var btnsect = $('#navbtn>li>a'); $(btnsect).each(function () { if ($(this).attr('href') === '#snapshots') { diff --git a/instances/templates/instance_actions.html b/instances/templates/instance_actions.html index 1948b42..f67dc1d 100644 --- a/instances/templates/instance_actions.html +++ b/instances/templates/instance_actions.html @@ -7,7 +7,7 @@ {% icon 'clone' %} {% else %} - + {% icon 'play' %} {% endif %} @@ -32,7 +32,7 @@ {% endif %} {% if instance.proxy.instance.info.0 == 1 %} - {% icon 'play' %} + {% icon 'play' %} {% icon 'pause' %} {% icon 'power-off' %} diff --git a/instances/templates/instances/power_tab.html b/instances/templates/instances/power_tab.html index 3811490..cf4fe1e 100644 --- a/instances/templates/instances/power_tab.html +++ b/instances/templates/instances/power_tab.html @@ -68,7 +68,7 @@

{% trans "This action forcibly powers off the instance and may cause data corruption." %}

-
+ {% csrf_token %}
@@ -119,7 +119,7 @@

{% trans "Template instance cannot be started." %}

{% else %} - + {% endif %}
diff --git a/instances/templates/instances/snapshots_tab.html b/instances/templates/instances/snapshots_tab.html old mode 100755 new mode 100644 index 5048e7e..d6eb88e --- a/instances/templates/instances/snapshots_tab.html +++ b/instances/templates/instances/snapshots_tab.html @@ -5,12 +5,7 @@
- -
- {% if instance.status != 5 %} -

{% trans "You can get external snapshots within this tab." %}

-

{% trans "External snapshots are experimental in this stage, use it if you know what you are doing. It may require manual intervention." %}

- {% else %} -

{% trans "Create an external snapshot" %}

- {% endif %} -

{% trans "Give your External Snapshot a distinctive description so it wouldn't get mixed with other snapshots." %}

-
- {% csrf_token %} -
- - | - - {% if instance.external_snapshots|length > 0 or instance.snapshots|length > 0 %} - - {% else %} - - {% endif %} -
-

{% trans "WebVirtCloud supports only one external snapshot at the moment." %}

-
-
-
+
- {% if instance.snapshots or instance.external_snapshots %} + {% if instance.snapshots %}

{% trans "Choose a snapshot for restore/delete" %}

- + - {% if instance.snapshots %} - {% for snap in instance.snapshots %} - - - - - - - - {% endfor %} - {% elif instance.external_snapshots %} - {% for ext_snap in instance.external_snapshots %} - - - - - - - - {% endfor %} - {% endif %} + {% for snap in instance.snapshots %} + + + + + + + + {% endfor %}
{% trans "Date" %} {% trans "Name" %}{% trans "Type - Description" %}{% trans "Description" %} {% trans "Action" %}
{{ snap.date|date:"M d H:i:s" }}{{ snap.name }}({% trans "Internal" %}) - {{ snap.description }} -
- {% csrf_token %} - - {% if instance.status == 5 %} - - {% else %} - - {% endif %} -
-
-
{% csrf_token %} - - -
-
{{ ext_snap.date|date:"M d H:i:s" }}{{ ext_snap.name }}({% trans "External" %}) - {{ ext_snap.description }} -
- {% csrf_token %} - - - - -
-
-
{% csrf_token %} - - -
-
{{ snap.date|date:"M d H:i:s" }}{{ snap.name }}{{ snap.description }} +
+ {% csrf_token %} + + {% if instance.status == 5 %} + + {% else %} + + {% endif %} +
+
+
{% csrf_token %} + + +
+
{% else %}

{% trans "You do not have any snapshots" %}

{% endif %} -
- - + + + diff --git a/instances/urls.py b/instances/urls.py old mode 100755 new mode 100644 index acb5444..c7a74f9 --- a/instances/urls.py +++ b/instances/urls.py @@ -39,9 +39,6 @@ urlpatterns = [ path("/snapshot/", views.snapshot, name="snapshot"), path("/delete_snapshot/", views.delete_snapshot, name="delete_snapshot"), path("/revert_snapshot/", views.revert_snapshot, name="revert_snapshot"), - path("/create_external_snapshot/", views.create_external_snapshot, name="create_external_snapshot"), - path("/revert_external_snapshot/", views.revert_external_snapshot, name="revert_external_snapshot"), - path("/delete_external_snapshot/", views.delete_external_snapshot, name="delete_external_snapshot"), path("/set_vcpu/", views.set_vcpu, name="set_vcpu"), path("/set_vcpu_hotplug/", views.set_vcpu_hotplug, name="set_vcpu_hotplug"), path("/set_autostart/", views.set_autostart, name="set_autostart"), diff --git a/instances/views.py b/instances/views.py old mode 100755 new mode 100644 index 5ba91e9..3b018bb --- a/instances/views.py +++ b/instances/views.py @@ -20,9 +20,7 @@ from django.http import Http404, HttpResponse, JsonResponse from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from libvirt import (VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, - VIR_DOMAIN_UNDEFINE_NVRAM, - VIR_DOMAIN_START_PAUSED, +from libvirt import (VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, VIR_DOMAIN_UNDEFINE_NVRAM, libvirtError) from logs.views import addlogmsg from vrtManager import util @@ -148,7 +146,7 @@ def instance(request, pk): instance.drbd = drbd_status(request, pk) instance.save() - return render(request, "instance.html", locals(),) + return render(request, "instance.html", locals()) def status(request, pk): @@ -1017,81 +1015,6 @@ def revert_snapshot(request, pk): return redirect(request.META.get("HTTP_REFERER") + "#managesnapshot") -def create_external_snapshot(request, pk): - instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) - - if allow_admin_or_not_template and request.user.has_perm( - "instances.snapshot_instances" - ): - name = request.POST.get("name", "") - desc = request.POST.get("description", "") - instance.proxy.create_external_snapshot("s1." + name, instance, desc=desc) - msg = _("Create external snapshot: %(snap)s") % {"snap": name} - addlogmsg(request.user.username, instance.compute.name, instance.name, msg) - return redirect(request.META.get("HTTP_REFERER") + "#managesnapshot") - - -def get_external_snapshots(request, pk): - instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) - - if allow_admin_or_not_template and request.user.has_perm( - "instances.snapshot_instances" - ): - external_snapshots = instance.proxy.get_external_snapshots() - return external_snapshots - - -def revert_external_snapshot(request, pk): - instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) - - if allow_admin_or_not_template and request.user.has_perm( - "instances.snapshot_instances" - ): - instance_state = True if instance.proxy.get_status() != 5 else False - name = request.POST.get("name", "") - date = request.POST.get("date", "") - desc = request.POST.get("desc", "") - instance.proxy.force_shutdown() if instance_state else None - instance.proxy.revert_external_snapshot(name, date, desc) - instance.proxy.start() if instance_state else None - msg = _("Revert external snapshot: %(snap)s") % {"snap": name} - addlogmsg(request.user.username, instance.compute.name, instance.name, msg) - return redirect(request.META.get("HTTP_REFERER") + "#managesnapshot") - - -def delete_external_snapshot(request, pk): - instance = get_instance(request.user, pk) - instance_state = True if instance.proxy.get_status() == 5 else False - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) - - if allow_admin_or_not_template and request.user.has_perm( - "instances.snapshot_instances" - ): - name = request.POST.get("name", "") - - instance.proxy.start(VIR_DOMAIN_START_PAUSED) if instance_state else None - - try: - instance.proxy.delete_external_snapshot(name) - msg = _("Delete external snapshot: %(snap)s") % {"snap": name} - addlogmsg(request.user.username, instance.compute.name, instance.name, msg) - finally: - instance.proxy.force_shutdown() if instance_state else None - - return redirect(request.META.get("HTTP_REFERER") + "#managesnapshot") - - @superuser_only def set_vcpu(request, pk): instance = get_instance(request.user, pk) diff --git a/vrtManager/instance.py b/vrtManager/instance.py index b85f0a0..e51f8bc 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -2,7 +2,6 @@ import contextlib import json import os.path import time -import subprocess try: from libvirt import ( @@ -19,14 +18,6 @@ try: VIR_MIGRATE_POSTCOPY, VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_UNSAFE, - VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, - VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, - VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL, - VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, - VIR_DOMAIN_BLOCK_COMMIT_DELETE, - VIR_DOMAIN_BLOCK_COMMIT_ACTIVE, - VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT, - VIR_DOMAIN_START_PAUSED, libvirtError, ) from libvirt_qemu import VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, qemuAgentCommand @@ -43,6 +34,7 @@ from vrtManager import util from vrtManager.connection import wvmConnect from vrtManager.storage import wvmStorage, wvmStorages + class wvmInstances(wvmConnect): def get_instance_status(self, name): inst = self.get_instance(name) @@ -210,8 +202,8 @@ class wvmInstance(wvmConnect): return info_results - def start(self, flags=0): - self.instance.createWithFlags(flags) + def start(self): + self.instance.create() def shutdown(self): self.instance.shutdown() @@ -457,7 +449,6 @@ class wvmInstance(wvmConnect): disk_format = used_size = disk_size = None disk_cache = disk_io = disk_discard = disk_zeroes = "default" readonly = shareable = serial = None - backing_file = None device = disk.xpath("@device")[0] if device == "disk": @@ -489,9 +480,6 @@ class wvmInstance(wvmConnect): with contextlib.suppress(Exception): disk_zeroes = disk.xpath("driver/@detect_zeroes")[0] - with contextlib.suppress(Exception): - backing_file = disk.xpath("backingStore/source/@file")[0] - readonly = bool(disk.xpath("readonly")) shareable = bool(disk.xpath("shareable")) serial = ( @@ -521,7 +509,6 @@ class wvmInstance(wvmConnect): "storage": storage, "path": src_file, "format": disk_format, - "backing_file": backing_file, "size": disk_size, "used": used_size, "cache": disk_cache, @@ -1296,87 +1283,9 @@ class wvmInstance(wvmConnect): ) self._defineXML(xml_temp) - def create_external_snapshot(self, name, date=None, desc=None): - creation_time = time.time() - state = "shutoff" if self.get_status() == 5 else "running" - # - xml = """ - %s - %s - %s - %d - """ % ( - name, - desc, - state, - creation_time, - ) - - self.change_snapshot_xml() - xml += self._XMLDesc(VIR_DOMAIN_XML_SECURE) - xml += """0 - """ - - self._snapshotCreateXML(xml, VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) - - - def get_external_snapshots(self): - return self.get_snapshot(VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL) - - def delete_external_snapshot(self, name): - disk_info = self.get_disk_devices() - for disk in disk_info: - target_dev = disk["dev"] - backing_file = disk["backing_file"] - snap_source_file = disk["path"] - self.instance.blockCommit(target_dev, backing_file, snap_source_file, - flags=VIR_DOMAIN_BLOCK_COMMIT_DELETE| - VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) - while True: - info = self.instance.blockJobInfo(target_dev, 0) - if info.get('cur') == info.get('end'): - self.instance.blockJobAbort(target_dev,flags=VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT) - time.sleep(2) - break - # Check again pool for snapshot delta volume; if it exist, remove it manually - with contextlib.suppress(libvirtError): - vol_snap = self.get_volume_by_path(snap_source_file) - pool = vol_snap.storagePoolLookupByVolume() - pool.refresh(0) - vol_snap.delete(0) - - snap = self.instance.snapshotLookupByName(name, 0) - snap.delete(VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) - - - def revert_external_snapshot(self, name, date, desc): - pool = None - snap = self.instance.snapshotLookupByName(name, 0) - snap_xml = snap.getXMLDesc(0) - snapXML = ElementTree.fromstring(snap_xml) - disks = snapXML.findall('inactiveDomain/devices/disk') - if not disks: disks = snapXML.findall('domain/devices/disk') - - self.start(flags=VIR_DOMAIN_START_PAUSED) if self.get_status() == 5 else None - - disk_info = self.get_disk_devices() - for disk in disk_info: - vol_snap = self.get_volume_by_path(disk["path"]) - pool = vol_snap.storagePoolLookupByVolume() - pool.refresh(0) - vol_snap.delete(0) - self.force_shutdown() - - snap.delete(VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) - for disk in disks: - self.instance.updateDeviceFlags(ElementTree.tostring(disk).decode("UTF-8")) - name = name.replace("s1", "s2") - self.create_external_snapshot(name, date, desc) - pool.refresh() if pool else None - - def get_snapshot(self, flag=VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL): + def get_snapshot(self): snapshots = [] - snapshot_list = self.instance.snapshotListNames(flag) + snapshot_list = self.instance.snapshotListNames(0) for snapshot in snapshot_list: snap = self.instance.snapshotLookupByName(snapshot, 0) snap_description = util.get_xml_path(