mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-09 11:46:49 +00:00
- The state filter is a row of pills, All and each state, counting the VMs the search finds (the chosen state aside); a state without any is hidden unless chosen (All never), and a status line tells screen readers how many VMs match. Every state keeps its pill. - A labelled "New VM" button replaces the bare green plus; "Find IP" says "Find IP / MAC", which it finds. - States are badges; a shut-off VM is grey, not red: it is not a fault. - A VM's cell holds its name, its title, and for those who see owners its first owner as a badge, "+N" for the others (named for screen readers and on hover); the separate user column goes. - Each row has the same button group for a superuser or the VM's owners, from the actions the user may use (states.allowed_actions), all of it disabled on a VM an administrator paused; view-only users get none. It holds Console, the power action the state calls for (Start, Resume, Shut down, or Clone for a template) and a menu of the others (Suspend, Force off, Power cycle), what does not apply now disabled. The power button is an icon, named on hover and for screen readers, so every group is as wide and they line up from row to row; the power cut confirmations stay. On a phone Console shows its icon only too. - A grouped host's row has its name, a Connected or Not connected badge, its VM count and a labelled host memory bar; an unreachable host's row is table-warning. Its collapse control and the one for all hosts are buttons, with aria-expanded kept. - vCPUs and memory hide on a phone in both layouts, and table cells keep Bootstrap's own padding there: Zephyr doubles it and a list's last column no longer fit the screen.
63 lines
2.3 KiB
Python
63 lines
2.3 KiB
Python
"""
|
|
libvirt VM states: their labels, and the actions each one allows a user.
|
|
The lists and the VM page use these through templatetags/vm_states.py.
|
|
"""
|
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
# state (virDomainState): label, Bootstrap color
|
|
STATES = {
|
|
0: (_("No state"), "secondary"),
|
|
1: (_("Active"), "success"),
|
|
2: (_("Blocked"), "success"), # running, waiting for a resource
|
|
3: (_("Suspended"), "warning"),
|
|
4: (_("Shutting down"), "warning"),
|
|
5: (_("Off"), "secondary"), # shut off is not a fault
|
|
6: (_("Crashed"), "danger"),
|
|
7: (_("PM suspended"), "warning"), # suspended by the guest
|
|
}
|
|
UNKNOWN = (_("Unknown"), "secondary") # the VM cannot be read
|
|
|
|
RUNNING = {"suspend", "poweroff", "powercycle", "console"}
|
|
STATE_ACTIONS = {
|
|
1: RUNNING,
|
|
2: RUNNING,
|
|
3: {"resume", "force_off"},
|
|
5: {"poweron"},
|
|
# shutting down, crashed, suspended by the guest: a forced power off ends
|
|
# it, and the VM can be started again
|
|
4: {"force_off"},
|
|
6: {"force_off"},
|
|
7: {"force_off"},
|
|
}
|
|
SUPERUSER_ONLY = {"suspend", "resume"} # their views are for superusers
|
|
|
|
|
|
def state_label(state):
|
|
"""(label, color) of a state; None for a VM that cannot be read."""
|
|
return UNKNOWN if state is None else STATES.get(state, STATES[0])
|
|
|
|
|
|
def manages(user, instance):
|
|
"""Superusers and a VM's owners: the users its power actions are for."""
|
|
# the lists prefetch userinstance_set
|
|
return user.is_superuser or any(ui.user_id == user.id for ui in instance.userinstance_set.all())
|
|
|
|
|
|
def allowed_actions(user, instance, state):
|
|
"""
|
|
The power actions the state allows and the user may use: superusers all,
|
|
a VM's owners all but suspend and resume, nobody else any (the
|
|
view_instances permission is read-only). A VM suspended by an
|
|
administrator offers its owner nothing. A shut-off template is not
|
|
started but cloned, by anyone with the clone permission who sees it.
|
|
"""
|
|
if state == 5 and instance.is_template:
|
|
return {"clone"} if user.has_perm("instances.clone_instances") else set()
|
|
if user.is_superuser:
|
|
return STATE_ACTIONS.get(state, set())
|
|
if not manages(user, instance):
|
|
return set()
|
|
if state == 3:
|
|
return set()
|
|
return STATE_ACTIONS.get(state, set()) - SUPERUSER_ONLY
|