mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-11 04:36:48 +00:00
The instance lists read each VM from libvirt while rendering. When that failed, the libvirt error replaced the whole page with the error page: one VM removed out of band, or a host that is down, took the index or a compute's instances page with it. To avoid that, both index views left out every VM of a host that was not connected, so users saw their VMs disappear. - Instance.info is None when the VM cannot be read. The row then shows the name and owners from the database, the state "Unknown", and no title, vCPU, memory or actions. - Both index views list the VMs of a host that is down. The grouped view marks the host "Not Connected" and leaves out its CPU and memory. - A compute's instances page shows the connection error, and no longer says the hypervisor has no instances when it cannot be reached. Checked against the test hosts with an unreachable compute added: both index views list its VM as unknown next to the real VMs. The first load takes 5.5 s (one bounded connection attempt), the next ones 0.1 s. The new tests fail on the previous code (VMs left out, error pages).
116 lines
6.2 KiB
HTML
116 lines
6.2 KiB
HTML
{% load i18n %}
|
|
{% load bootstrap_icons %}
|
|
<table class="table table-hover sortable-theme-bootstrap" data-sortable>
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" data-sortable="false"><a class="link-primary" href="#" id="hide-all-instances" onclick="hide_all_host_instances()">#</a></th>
|
|
<th scope="col">{% trans "Name" %}<br>{% trans "Description" %}</th>
|
|
<th scope="col" class="d-none d-sm-table-cell">{% trans "User"%}</th>
|
|
<th scope="col">{% trans "Status" %}</th>
|
|
{% if app_settings.VM_DRBD_STATUS == 'True' %}
|
|
<th scope="col">{% trans "Role/Disk" %}</th>
|
|
{% endif %}
|
|
<th scope="col" class="d-none d-sm-table-cell">{% trans "VCPU" %}</th>
|
|
<th scope="col" class="d-none d-sm-table-cell">{% trans "Memory" %}</th>
|
|
<th scope="col" style="width:200px;" data-sortable="false">{% trans "Actions" %} & {% trans "Mem Usage" %}</th>
|
|
</tr>
|
|
</thead>
|
|
{% for compute in computes %}
|
|
<tbody class="searchable">
|
|
{% if compute.instance_set.count > 0 %}
|
|
<tr class="table-secondary fw-bold border-bottom border-dark">
|
|
<td>
|
|
<span id="collapse_host_instances_{{ compute.id }}" onclick="hide_host_instances('{{ compute.id }}');" class="bi bi-chevron-up" ></span>
|
|
</td>
|
|
<td>
|
|
<a class="link-dark" href="{% url 'overview' compute.id %}">{{ compute.name }}</a>
|
|
<span id="inst_count_badge_{{ compute.id }}" class="badge bg-secondary d-none">{{ compute.instance_set.count }}</span>
|
|
</td>
|
|
<td class="d-none d-sm-table-cell"></td>
|
|
<td>
|
|
{% if compute.status is True %}
|
|
<span class="text-success">{% trans "Connected" %}</span>
|
|
{% else %}
|
|
<span class="text-danger">{% trans "Not Connected" %}</span>
|
|
{% endif %}
|
|
</td>
|
|
{% if app_settings.VM_DRBD_STATUS == 'True' %}
|
|
<td class="d-none d-sm-table-cell"></td>
|
|
{% endif %}
|
|
{% if compute.status is True %}
|
|
<td class="d-none d-sm-table-cell text-center">{{ compute.cpu_count }}</td>
|
|
<td class="d-none d-sm-table-cell text-right">{{ compute.ram_size|filesizeformat }}</td>
|
|
<td>
|
|
<div class="progress">
|
|
<div class="progress-bar bg-success" role="progressbar" style="width: {{ compute.ram_usage }}%"
|
|
aria-valuenow="{{ compute.ram_usage }}" aria-valuemin="0" aria-valuemax="100">{{ compute.ram_usage }}%
|
|
</div>
|
|
</div>
|
|
</td>
|
|
{% else %}
|
|
<td class="d-none d-sm-table-cell"></td>
|
|
<td class="d-none d-sm-table-cell"></td>
|
|
<td></td>
|
|
{% endif %}
|
|
</tr>
|
|
{% for instance in compute.instance_set.all %}
|
|
<tr host="{{ compute.id }}">
|
|
<td class="text-right">{{ forloop.counter }} </td>
|
|
<td>
|
|
<a class="link-primary" href="{% url 'instances:instance' instance.id %}">{{ instance.name }}</a>
|
|
<br>
|
|
{% if instance.info %}<p class="m-0 small fst-italic">{{ instance.title }}</p>{% endif %}
|
|
</td>
|
|
<td>
|
|
<em>
|
|
{% 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 %}
|
|
</em>
|
|
</td>
|
|
<td>
|
|
{% if instance.info.0 == 1 %}<span class="text-success">{% trans "Active" %}</span>{% endif %}
|
|
{% if instance.info.0 == 5 %}<span class="text-danger">{% trans "Off" %}</span>{% endif %}
|
|
{% if instance.info.0 == 3 %}
|
|
<span class="text-warning">{% trans "Suspended" %}</span>
|
|
{% endif %}
|
|
{% if instance.info is None %}<span class="text-secondary">{% trans "Unknown" %}</span>{% endif %}
|
|
</td>
|
|
{% if app_settings.VM_DRBD_STATUS == 'True' %}
|
|
<td>
|
|
{% if instance.drbd == "Primary/OK" or instance.drbd == "Secondary/OK" %}<span class="text-success">{% else %}<span class="text-danger">{% endif %}{{ instance.drbd }}</span>
|
|
</td>
|
|
{% endif %}
|
|
<td>{{ instance.info.3 }}</td>
|
|
<td>{% if instance.info %}{% widthratio instance.info.2 1024 1 %} MB{% endif %}</td>
|
|
<td class="text-nowrap">
|
|
{% include 'instance_actions.html' %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</tbody>
|
|
{% endfor %}
|
|
</table>
|
|
|
|
{% block script %}
|
|
<script>
|
|
function hide_all_host_instances() {
|
|
var rows = $('table tr');
|
|
all_host_rows = rows.filter('[host]');
|
|
all_host_rows.toggle();
|
|
$('span[id^=collapse_host_instances_]').toggleClass("bi bi-chevron-down ").toggleClass("bi bi-chevron-up");
|
|
$('span[id^=inst_count_badge_]').toggleClass("d-none");
|
|
}
|
|
function hide_host_instances(host) {
|
|
var rows = $('table tr');
|
|
host_rows = rows.filter("[host='"+host+"']");
|
|
host_rows.toggle();
|
|
$("span[id='collapse_host_instances_"+host+"']").toggleClass("bi bi-chevron-down ").toggleClass("bi bi-chevron-up");
|
|
$("span[id='inst_count_badge_"+host+"']").toggleClass("d-none");
|
|
}
|
|
</script>
|
|
{% endblock %}
|