mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 11:16:47 +00:00
fix(instances): the VM lists ask before a forced power off or power cycle
In the VM lists, Force Off and Power Cycle ran on a single click, though both cut the VM off as a power failure does. Each button now asks first, naming the VM and saying that what the guest has not written to disk is lost. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
961b43a42e
commit
bf6b736aef
2 changed files with 19 additions and 2 deletions
|
|
@ -39,7 +39,9 @@
|
|||
{% elif "force_off" in actions %}
|
||||
<form action="{% url 'instances:force_off' instance.id %}" method="post" style="display:inline;">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-secondary" title="{% trans "Force Off" %}">{% bs_icon 'power' %}</button>
|
||||
<button type="submit" class="btn btn-sm btn-secondary" title="{% trans "Force Off" %}"
|
||||
data-confirm="{% blocktrans with name=instance.name %}Force off {{ name }}? It stops at once, as after a power cut; what the guest has not written to disk is lost.{% endblocktrans %}"
|
||||
onclick="return confirm(this.dataset.confirm)">{% bs_icon 'power' %}</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<button class="btn btn-sm btn-secondary disabled" title="{% trans "Power Off" %}" disabled>{% bs_icon 'power' %}</button>
|
||||
|
|
@ -48,7 +50,9 @@
|
|||
{% if "powercycle" in actions %}
|
||||
<form action="{% url 'instances:powercycle' instance.id %}" method="post" style="display:inline;">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-secondary" title="{% trans "Power Cycle" %}">{% bs_icon 'repeat' %}</button>
|
||||
<button type="submit" class="btn btn-sm btn-secondary" title="{% trans "Power Cycle" %}"
|
||||
data-confirm="{% blocktrans with name=instance.name %}Power cycle {{ name }}? It stops at once, as after a power cut, and starts again; what the guest has not written to disk is lost.{% endblocktrans %}"
|
||||
onclick="return confirm(this.dataset.confirm)">{% bs_icon 'repeat' %}</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<button class="btn btn-sm btn-secondary disabled" title="{% trans "Power Cycle" %}" disabled>{% bs_icon 'repeat' %}</button>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from django.test import TestCase
|
|||
from django.urls import reverse
|
||||
from instances.models import Instance
|
||||
from instances.states import allowed_actions
|
||||
from lxml import html
|
||||
|
||||
LABELS = {0: "No state", 1: "Active", 2: "Blocked", 3: "Suspended", 4: "Shutting down", 5: "Off", 6: "Crashed", 7: "PM suspended"}
|
||||
# actions offered per state, for a superuser
|
||||
|
|
@ -89,6 +90,18 @@ class StateTests(TestCase):
|
|||
with self.subTest(url=url, state=state):
|
||||
self.assertEqual(self.offered(page, vm), ACTIONS[state])
|
||||
|
||||
def test_forced_power_actions_in_the_lists_ask_first(self):
|
||||
# one click in a list row would cut the VM off as a power failure does
|
||||
for url in (reverse("instances:index"), reverse("instances", args=[self.compute.id])):
|
||||
page = html.fromstring(self.get(self.admin, url))
|
||||
for state, vm in self.vms.items():
|
||||
for action in {"force_off", "powercycle"} & ACTIONS[state]:
|
||||
button = page.xpath(f"//form[@action='{reverse(f'instances:{action}', args=[vm.id])}']//button")[0]
|
||||
with self.subTest(url=url, vm=vm.name, action=action):
|
||||
self.assertEqual(button.get("onclick"), "return confirm(this.dataset.confirm)")
|
||||
self.assertIn(vm.name, button.get("data-confirm"))
|
||||
self.assertIn("power cut", button.get("data-confirm"))
|
||||
|
||||
def test_owner_is_not_offered_suspend_or_resume(self):
|
||||
# both views are for superusers only; a VM an administrator suspended
|
||||
# stays as it is for its owner, as on the VM page
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue