1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-10 04:06:47 +00:00

fix(admin): Removed VMs shows the host a VM left and confirms a delete

A tombstone kept the VM's name and UUID but not its compute, so the page
could not say where the VM had been. It now stores the compute's name (as
text: the compute may be the one deleted) and the list shows it; records
made before this have no host. Deleting a record says so, and the admin
tables use scope="col" instead of the invalid span="col".

Closes #217
This commit is contained in:
catborise 2026-10-26 11:23:44 +03:00
parent f7279610a8
commit 6c2704f97d
9 changed files with 47 additions and 19 deletions

View file

@ -26,8 +26,8 @@
<table class="table table-striped table-hover">
<thead>
<tr>
<th span="col">{% trans "Group Name" %}</th>
<th span="col">{% trans "Actions" %}</th>
<th scope="col">{% trans "Group Name" %}</th>
<th scope="col">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody class="searchable">

View file

@ -24,12 +24,13 @@
<table class="table table-striped table-hover">
<thead>
<tr>
<th span="col">{% trans "Name" %}</th>
<th span="col">{% trans "UUID" %}</th>
<th span="col">{% trans "Owners" %}</th>
<th span="col">{% trans "Removed" %}</th>
<th span="col">{% trans "Expires" %}</th>
<th span="col">{% trans "Actions" %}</th>
<th scope="col">{% trans "Name" %}</th>
<th scope="col">{% trans "UUID" %}</th>
<th scope="col">{% trans "Host" %}</th>
<th scope="col">{% trans "Owners" %}</th>
<th scope="col">{% trans "Removed" %}</th>
<th scope="col">{% trans "Expires" %}</th>
<th scope="col">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody class="searchable">
@ -40,6 +41,7 @@
{% if tombstone.is_template %}<span class="badge bg-secondary">{% trans "Template" %}</span>{% endif %}
</td>
<td>{{ tombstone.uuid }}</td>
<td>{{ tombstone.host }}</td>
<td>{{ tombstone.owner_names|join:", " }}</td>
<td>{{ tombstone.removed|date:"Y-m-d H:i" }}</td>
<td>{{ tombstone.expires|date:"Y-m-d H:i" }}</td>

View file

@ -29,14 +29,14 @@
<table class="table table-striped table-hover">
<thead>
<tr>
<th span="col">{% trans "Username" %}</th>
<th span="col">{% trans "Status" %}</th>
<th span="col">{% trans "Last Login" %}</th>
<th span="col">{% trans "Template editor" %}</th>
<th span="col">{% trans "Superuser" %}</th>
<th span="col">{% trans "Can Clone" %}</th>
<th span="col">{% trans "API tokens" %}</th>
<th span="col">{% trans "Actions" %}</th>
<th scope="col">{% trans "Username" %}</th>
<th scope="col">{% trans "Status" %}</th>
<th scope="col">{% trans "Last Login" %}</th>
<th scope="col">{% trans "Template editor" %}</th>
<th scope="col">{% trans "Superuser" %}</th>
<th scope="col">{% trans "Can Clone" %}</th>
<th scope="col">{% trans "API tokens" %}</th>
<th scope="col">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody class="searchable">

View file

@ -19,6 +19,7 @@ class TombstoneTests(TestCase):
self.tombstone = InstanceTombstone.objects.create(
uuid=UUID,
name="ts-vm",
host="ts-host",
owners=[
{"user": self.owner.id, "is_change": True, "is_delete": False, "is_vnc": True},
{"user": 999999, "is_change": False, "is_delete": False, "is_vnc": False},
@ -37,6 +38,8 @@ class TombstoneTests(TestCase):
self.assertContains(response, "ts-vm")
self.assertContains(response, UUID)
self.assertContains(response, "ts-owner")
self.assertContains(response, "<td>ts-host</td>", html=True)
self.assertContains(response, '<th scope="col">Host</th>', html=True)
def test_only_superusers_see_or_remove_them(self):
self.client.force_login(self.owner)
@ -51,6 +54,7 @@ class TombstoneTests(TestCase):
self.assertTrue(InstanceTombstone.objects.exists())
def test_a_post_removes_it(self):
response = self.client.post(reverse("admin:tombstone_delete", args=[self.tombstone.pk]))
response = self.client.post(reverse("admin:tombstone_delete", args=[self.tombstone.pk]), follow=True)
self.assertRedirects(response, reverse("admin:tombstone_list"))
self.assertContains(response, "Removed VM ts-vm deleted")
self.assertFalse(InstanceTombstone.objects.exists())

View file

@ -338,6 +338,7 @@ def tombstone_delete(request, pk):
if request.method == "POST":
with audit(request, None, f"Removed VM {tombstone.name} ({tombstone.uuid})", "delete"):
tombstone.delete()
messages.success(request, _("Removed VM %(name)s deleted") % {"name": tombstone.name})
return redirect("admin:tombstone_list")
return render(