diff --git a/instances/states.py b/instances/states.py index ed8c972e..ea74d7d2 100644 --- a/instances/states.py +++ b/instances/states.py @@ -12,7 +12,7 @@ STATES = { 2: (_("Blocked"), "success"), # running, waiting for a resource 3: (_("Suspended"), "warning"), 4: (_("Shutting down"), "warning"), - 5: (_("Off"), "danger"), + 5: (_("Off"), "secondary"), # shut off is not a fault 6: (_("Crashed"), "danger"), 7: (_("PM suspended"), "warning"), # suspended by the guest } @@ -38,6 +38,12 @@ def state_label(state): 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, @@ -50,8 +56,7 @@ def allowed_actions(user, instance, state): return {"clone"} if user.has_perm("instances.clone_instances") else set() if user.is_superuser: return STATE_ACTIONS.get(state, set()) - # the lists prefetch userinstance_set - if not any(ui.user_id == user.id for ui in instance.userinstance_set.all()): + if not manages(user, instance): return set() if state == 3: return set() diff --git a/instances/templates/allinstances.html b/instances/templates/allinstances.html index e3d5e000..4841db37 100644 --- a/instances/templates/allinstances.html +++ b/instances/templates/allinstances.html @@ -5,22 +5,16 @@ {% block page_heading %}{% trans "Instances" %}{% endblock page_heading %} {% block page_heading_extra %} -{% if request.user.is_superuser %} - {% include 'create_inst_block.html' %} -{% endif %} - {# the list's filters (state, text) and the address search, as one control #} -
-
- +
+ {# the list's search and the address search, as one control #} +
+ data-bs-toggle="modal" data-bs-target="#find-address">{% trans "Find IP / MAC" %}
+ {% if request.user.is_superuser %} + {% include 'create_inst_block.html' %} + {% endif %}
{% endblock page_heading_extra %} @@ -45,6 +39,23 @@
{% endif %}
+ {% if instances.exists %} + {# the state filter: table_filter.js counts each state's VMs the search finds #} + + +
+ {% endif %} {% if not instances.exists %}

{% trans "There are no VMs here yet." %}

{% elif app_settings.VIEW_INSTANCES_LIST_STYLE == 'grouped' and request.user.is_superuser %} diff --git a/instances/templates/allinstances_index_grouped.html b/instances/templates/allinstances_index_grouped.html index 69a796ae..cdfd118a 100644 --- a/instances/templates/allinstances_index_grouped.html +++ b/instances/templates/allinstances_index_grouped.html @@ -4,48 +4,51 @@ - - - + + {% if app_settings.VM_DRBD_STATUS == 'True' %} {% endif %} - + - + {% for compute in computes %} - + {% if compute.instance_set.count > 0 %} - + - - - - {% if app_settings.VM_DRBD_STATUS == 'True' %} - - {% endif %} {% if compute.status is True %} - - + + {% else %} @@ -58,21 +61,7 @@ {# searched for its name, title and owners, not its buttons #} - - + @@ -83,7 +72,7 @@ {% endif %} - @@ -100,8 +89,11 @@ // search (table_filter.js, the hidden attribute) can still hide them too function set_host_collapsed(tbody, collapsed) { $(tbody).toggleClass('host-collapsed', collapsed); + $(tbody).find('[aria-controls]').attr('aria-expanded', !collapsed); $(tbody).find('span[id^=collapse_host_instances_]').toggleClass('bi-chevron-down', collapsed).toggleClass('bi-chevron-up', !collapsed); $(tbody).find('span[id^=inst_count_badge_]').toggleClass('d-none', !collapsed); + // expanded while any host is, as the next click collapses them all + $('#hide-all-instances').attr('aria-expanded', $('tbody.searchable').not('.host-collapsed').length > 0); } // every host the same way: collapsed, unless all already are function hide_all_host_instances() { diff --git a/instances/templates/allinstances_index_nongrouped.html b/instances/templates/allinstances_index_nongrouped.html index 7e57119f..97038f9c 100644 --- a/instances/templates/allinstances_index_nongrouped.html +++ b/instances/templates/allinstances_index_nongrouped.html @@ -3,42 +3,28 @@
#{% trans "Name" %}
{% trans "Description" %}
{% trans "User"%} + + {% trans "Name" %} {% trans "Status" %}{% trans "Role/Disk" %}{% trans "VCPU" %}{% trans "vCPUs" %} {% trans "Memory" %}{% trans "Actions" %} & {% trans "Mem Usage" %}{% trans "Actions" %}
- + - {{ compute.name }} - {{ compute.instance_set.count }} + +
+ {{ compute.name }} + {% if compute.status is True %} + {% trans "Connected" %} + {% else %} + {% trans "Not connected" %} + {% endif %} + {% blocktrans count counter=compute.instance_set.count %}{{ counter }} VM{% plural %}{{ counter }} VMs{% endblocktrans %} + {% trans "collapsed" %} +
- {% if compute.status is True %} - {% trans "Connected" %} - {% else %} - {% trans "Not Connected" %} - {% endif %} - {{ compute.cpu_count }}{{ compute.ram_size|filesizeformat }}{{ compute.cpu_count }}{{ compute.ram_size|filesizeformat }} -
-
{{ compute.ram_usage }}% -
+
{% blocktrans with percent=compute.ram_usage %}host memory {{ percent }}% in use{% endblocktrans %}
+
+
- {{ instance.name }} -
- {% if instance.info %}

{{ instance.title }}

{% endif %} -
- - {% if instance.userinstance_set.all.count > 0 %} - {{ instance.userinstance_set.all.0.user }} - {% if instance.userinstance_set.all.count > 1 %} - (+{{ instance.userinstance_set.all.count|add:"-1" }}) - {% endif %} - {% endif %} - - {% include 'instance_name_cell.html' with owners=True %} {% include 'instance_state.html' %} {{ instance.info.3 }} {% if instance.info %}{% widthratio instance.info.2 1024 1 %} MiB{% endif %} + {% include 'instance_actions.html' %}
- + {% if show_hosts %} - + {% endif %} {% if app_settings.VM_DRBD_STATUS == 'True' %} {% endif %} - - - + + + {% for instance in instances %} {# searched for its name, title, host and owners, not its buttons #} - + {% if show_hosts %} {% endif %} {% endif %} - - - + + diff --git a/instances/templates/create_inst_block.html b/instances/templates/create_inst_block.html index d9c72304..915ec304 100644 --- a/instances/templates/create_inst_block.html +++ b/instances/templates/create_inst_block.html @@ -1,8 +1,8 @@ {% load i18n %} {% load bootstrap_icons %} - - - +
{% trans 'Name' %}
{% trans 'Description' %}
{% trans 'Name' %}{% trans 'Host' %}
{% trans 'User' %}
{% trans 'Host' %}{% trans 'Status' %}{% trans 'Role/Disk' %}{% trans 'VCPU' %}{% trans 'Memory' %}{% trans 'Actions' %}{% trans 'vCPUs' %}{% trans 'Memory' %}{% trans 'Actions' %}
- - {{ instance.name }} - -
- {% if instance.info %}

{{ instance.title }}

{% endif %} -
{% include 'instance_name_cell.html' with owners=show_hosts %} {# the host pages are a superuser's #} - {% if request.user.is_superuser %}{{ instance.compute.name }}{% else %}{{ instance.compute.name }}{% endif %}
- - {% if instance.userinstance_set.all.count > 0 %} - {{ instance.userinstance_set.all.0.user }} - {% if instance.userinstance_set.all.count > 1 %} - (+{{ instance.userinstance_set.all.count|add:"-1" }}) - {% endif %} - {% endif %} - + {% if request.user.is_superuser %}{{ instance.compute.name }}{% else %}{{ instance.compute.name }}{% endif %}
@@ -49,9 +35,9 @@ {% if instance.drbd == "Primary/OK" or instance.drbd == "Secondary/OK" %}{% else %}{% endif %}{{ instance.drbd }} {{ instance.info.3 }}{% if instance.info %}{% widthratio instance.info.2 1024 1 %} MiB{% endif %} + {{ instance.info.3 }}{% if instance.info %}{% widthratio instance.info.2 1024 1 %} MiB{% endif %} {% include 'instance_actions.html' %}