mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
A running VM's page read its addresses while it rendered: the guest agent, when its channel is connected but it does not answer, holds the page (and a gunicorn worker) for its whole 10 s timeout, on every load. The page now shows them once it has loaded: vm_addresses.js asks the new instances/<pk>/addresses/ for each NIC's addresses and fills the header's IPv4 and each network card's IPv4 and IPv6.
140 lines
9.2 KiB
HTML
140 lines
9.2 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
{% load vm_states %}
|
|
{% load i18n %}
|
|
{% load operations %}
|
|
{% load bootstrap_icons %}
|
|
|
|
{% block title %}{% trans "Instance" %} - {{ instance.name }}{% endblock %}
|
|
|
|
{% block page_header %}{% endblock page_header %}{# the card below has the heading #}
|
|
|
|
{% block content %}
|
|
{% include 'pleasewaitdialog.html' %}
|
|
{# the VM at a glance in one card: who and where it is, what it has, and its sections as the card's footer #}
|
|
<section class="card mb-3" aria-labelledby="vm-name" id="vm-summary" data-status="{{ instance.status }}"
|
|
data-status-url="{% url 'instances:status' instance.id %}" data-osinfo-url="{% url 'instances:osinfo' instance.id %}"
|
|
data-opens-on="{% if instance.is_template and can_clone %}#clone{% endif %}"
|
|
data-random-mac-url="{% url 'instances:random_mac_address' %}"
|
|
{% if can_open_console and vdi_reachable %}data-vdi-url="{% url 'vdi_url' compute.id instance.name %}"{% endif %}>
|
|
<div class="card-body p-3">
|
|
<div class="d-flex flex-wrap justify-content-between align-items-start gap-2">
|
|
<div>
|
|
<div class="d-flex align-items-center gap-2">
|
|
<h1 class="h4 mb-0" id="vm-name">{{ instance.name }}</h1>
|
|
{% vm_state instance.status as state %}
|
|
<span class="badge text-bg-{{ state.1 }}">{{ state.0 }}</span>
|
|
{% if instance.is_template %}<span class="badge text-bg-light border">{% trans "Template" %}</span>{% endif %}
|
|
</div>
|
|
{% if instance.title %}<p class="text-body-secondary mb-1">{{ instance.title }}</p>{% endif %}
|
|
{% include 'instances/host_link.html' %}
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
{% if instance.is_template and can_clone %}
|
|
<button type="button" class="btn btn-sm btn-primary" id="clone-button">{% bs_icon 'copy' %} {% trans "Clone" %}</button>
|
|
{% endif %}
|
|
{% if instance.guest_agent_ready %}
|
|
<button type="button" class="btn btn-sm btn-secondary" id="os-details-button">{% bs_icon 'info-circle' %} {% trans "OS details" %}</button>
|
|
{% endif %}
|
|
<a class="btn btn-sm btn-secondary" href="{% url 'instances:instance' instance.id %}">{% bs_icon 'arrow-clockwise' %} {% trans "Refresh" %}</a>
|
|
</div>
|
|
</div>
|
|
{% if not instance.is_template %}
|
|
<div class="d-flex flex-wrap column-gap-3 row-gap-1 small mt-2">
|
|
{% if not instance.guest_agent %}
|
|
<span>{% bs_icon 'dash-circle' %} {% trans "Guest agent off" %}</span>
|
|
{% elif instance.guest_agent_ready %}
|
|
<span><span class="text-success">{% bs_icon 'check-circle' %}</span> {% trans "Guest agent connected" %}</span>
|
|
{% else %}
|
|
<span><span class="text-warning">{% bs_icon 'exclamation-circle' %}</span> {% trans "Guest agent not connected" %}</span>
|
|
{% endif %}
|
|
<span>{% bs_icon 'camera' %} {% blocktrans count counter=instance.snapshots|length %}{{ counter }} snapshot{% plural %}{{ counter }} snapshots{% endblocktrans %}</span>
|
|
</div>
|
|
{% endif %}
|
|
<dl class="row g-2 small mb-0 mt-1">
|
|
<div class="col-6 col-lg-2">
|
|
<dt class="fw-normal text-body-secondary">{% trans "CPU" %}</dt>
|
|
<dd class="mb-0">{% firstof instance.cur_vcpu instance.vcpu %} {% trans "of" %} {{ instance.vcpu }} {% trans "vCPU" %}</dd>
|
|
</div>
|
|
<div class="col-6 col-lg-2">
|
|
<dt class="fw-normal text-body-secondary">{% trans "Memory" %}</dt>
|
|
<dd class="mb-0">{{ instance.cur_memory }} MiB</dd>
|
|
</div>
|
|
<div class="col-6 col-lg-5">
|
|
<dt class="fw-normal text-body-secondary">{% trans "Disks" %}</dt>
|
|
<dd class="mb-0">{% for disk in instance.disks %}{{ disk.dev }} {{ disk.size|filesizeformat }}{% if not forloop.last %} · {% endif %}{% empty %}{% trans "None" %}{% endfor %}</dd>
|
|
</div>
|
|
{% if not instance.is_template %}
|
|
<div class="col-6 col-lg-3">
|
|
<dt class="fw-normal text-body-secondary">{% trans "IPv4" %}</dt>
|
|
<dd class="mb-0 font-monospace" data-address-mac="{% for nic in instance.networks %}{{ nic.mac }} {% endfor %}" data-address-family="ipv4" data-empty="—">{% trans "Reading…" %}</dd>
|
|
</div>
|
|
{% endif %}
|
|
</dl>
|
|
</div>
|
|
<div class="card-footer p-2">
|
|
<ul class="nav nav-pills nav-fill flex-wrap flex-lg-nowrap gap-1 small" id="navbtn" role="tablist" aria-label="{% trans "Instance actions" %}">
|
|
{# a template is cloned, not run: no power, access, snapshots or stats #}
|
|
{% if not instance.is_template %}
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link text-nowrap active" id="power-tab" aria-controls="power" data-bs-toggle="pill" data-bs-target="#power" type="button" role="tab" aria-selected="true">{% bs_icon 'power' %} {% trans "Power" %}</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link text-nowrap" id="access-tab" aria-controls="access" data-bs-toggle="pill" data-bs-target="#access" type="button" role="tab" aria-selected="false">{% bs_icon 'lock' %} {% trans "Access" %}</button>
|
|
</li>
|
|
{% endif %}
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link text-nowrap" id="resize-tab" aria-controls="resize" data-bs-toggle="pill" data-bs-target="#resize" type="button" role="tab" aria-selected="false">{% bs_icon 'arrows-angle-expand' %} {% trans "Resize" %}</button>
|
|
</li>
|
|
{% if can_snapshot and not instance.is_template %}
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link text-nowrap" id="snapshots-tab" aria-controls="snapshots" data-bs-toggle="pill" data-bs-target="#snapshots" type="button" role="tab" aria-selected="false">{% bs_icon 'camera' %} {% trans "Snapshot" %}</button>
|
|
</li>
|
|
{% endif %}
|
|
{% if show_settings %}
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link text-nowrap" id="settings-tab" aria-controls="settings" data-bs-toggle="pill" data-bs-target="#settings" type="button" role="tab" aria-selected="false">{% bs_icon 'gear-wide-connected' %} {% trans "Settings" %}</button>
|
|
</li>
|
|
{% endif %}
|
|
{% if not instance.is_template %}
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link text-nowrap" id="graphics-tab" aria-controls="graphics" data-bs-toggle="pill" data-bs-target="#graphics" type="button" role="tab" aria-selected="false">{% bs_icon 'bar-chart-line' %} {% trans "Stats" %}</button>
|
|
</li>
|
|
{% endif %}
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link text-nowrap" id="undefine-tab" aria-controls="undefine" data-bs-toggle="pill" data-bs-target="#undefine" type="button" role="tab" aria-selected="false">{% bs_icon 'trash' %} {% trans "Destroy" %}</button>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
|
|
<div id="job-panel" aria-live="polite"></div>
|
|
<div id="mainTabMenu">
|
|
<!-- Tab panes -->
|
|
<div class="tab-content" id=mainTabMenuContent>
|
|
{% if not instance.is_template %}
|
|
{% include 'instances/power_tab.html' %}
|
|
{% include 'instances/access_tab.html' %}
|
|
{% endif %}
|
|
{% include 'instances/resize_tab.html' %}
|
|
{% if can_snapshot and not instance.is_template %}{% include 'instances/snapshots_tab.html' %}{% endif %}
|
|
{% if show_settings %}{% include 'instances/settings_tab.html' %}{% endif %}
|
|
{% if not instance.is_template %}{% include 'instances/stats_tab.html' %}{% endif %}
|
|
{% include 'instances/destroy_tab.html' %}
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %}
|
|
{% block script %}
|
|
<script src="{% static 'js/ace/ace.js' %}" type="text/javascript" charset="utf-8"></script>
|
|
<script src="{% static 'js/xml_editor.js' %}"></script>
|
|
<script src="{% static 'js/chart.umd.min.js' %}"></script>
|
|
<script src="{% static 'js/charts.js' %}"></script>
|
|
<script src="{% static 'js/poll.js' %}"></script>
|
|
{% if not instance.is_template %}<script src="{% static 'js/instance_stats.js' %}"></script>{% endif %}
|
|
<script src="{% static 'js/instance_status.js' %}"></script>
|
|
<script src="{% static 'js/vm_addresses.js' %}" data-url="{% url 'instances:nic_addresses' instance.id %}"></script>
|
|
{% job_panel_script job_resource %}
|
|
<script src="{% static 'js/instance_tabs.js' %}"></script>
|
|
<script src="{% static 'js/instance_page.js' %}"></script>
|
|
{% endblock %}
|