diff --git a/computes/templates/computes/capacity_memory.html b/computes/templates/computes/capacity_memory.html index 08d65ad9..263a8aea 100644 --- a/computes/templates/computes/capacity_memory.html +++ b/computes/templates/computes/capacity_memory.html @@ -1,10 +1,11 @@ {% load i18n %} {# the memory a host has given its VMs: given, from views.shown_capacity #} -
{% blocktrans with all=given.assigned.all|filesizeformat memory=given.memory|filesizeformat %}{{ all }} given of {{ memory }}{% endblocktrans %}
+
{{ given.memory_percent }} %
+
{{ given.assigned.all|filesizeformat }} / {{ given.memory|filesizeformat }}
-
{% blocktrans with running=given.assigned.running|filesizeformat %}{{ running }} of it running{% endblocktrans %}
+
{% blocktrans with running=given.assigned.running|filesizeformat %}{{ running }} running{% endblocktrans %}
diff --git a/computes/templates/overview.html b/computes/templates/overview.html index fda5fcb3..31b27aff 100644 --- a/computes/templates/overview.html +++ b/computes/templates/overview.html @@ -13,7 +13,7 @@ {% block page_heading %}{{ compute.name }}{% endblock page_heading %} {% block content %} -

+

{% if connected %} {% trans "Connected" %} @@ -23,13 +23,13 @@ {{ compute.hostname }} {% if compute.details %}{{ compute.details }}{% endif %} -

+
{% include "computes/host_nav.html" with section="overview" %} {% if not connected %} @@ -39,108 +39,150 @@ {% endif %} - {% if given %}
-
-
{% trans "VMs" %}
+
+
{% bs_icon 'server' %} {% trans "VMs" %}
+
{{ given.vm_count }}
{% blocktrans with running=given.vms.running shutoff=given.vms.shutoff %}{{ running }} running, {{ shutoff }} shut off{% endblocktrans %}{% if given.vms.paused %}, {% blocktrans with paused=given.vms.paused %}{{ paused }} paused{% endblocktrans %}{% endif %}{% if given.vms.other %}, {% blocktrans with other=given.vms.other %}{{ other }} other{% endblocktrans %}{% endif %}
{% trans "Instances" %} → -
+
+
-
-
{% trans "vCPUs" %}
+
+
{% bs_icon 'cpu' %} {% trans "vCPUs" %}
+
{% include "computes/capacity_vcpus.html" %} -
+
+
-
-
{% trans "Memory" %}
+
+
{% bs_icon 'memory' %} {% trans "Memory" %}
+
{% include "computes/capacity_memory.html" %} -
+
+
-
-
{% trans "Storage" %}
+
+
{% bs_icon 'device-hdd' %} {% trans "Storage" %}
+
{% include "computes/capacity_storage.html" %} {% trans "Storages" %} → -
+
+
{% else %} -

{% trans "The capacity could not be read." %}

+
{% trans "The capacity could not be read." %}
{% endif %} {# the load is read on its own: shown also when the details could not be #} -
-
-
{% trans "CPU in use" %} –
+
+
+ {% bs_icon 'speedometer2' %} {% trans "CPU in use" %} – +
+
-
+
+
-
-
{% trans "Memory in use" %} –
+
+
+ {% bs_icon 'memory' %} {% trans "Memory in use" %} – +
+
-
+
+
-

+

{% trans "The last 10 readings, one every 5 seconds. Memory in use leaves out the host's buffers and cache." %} {% trans "Waiting for the first reading." %} -

+
{% if host %} -
+
- -
-
{% trans "Hostname" %}
-
{{ host.hostname }}
-
{% trans "Architecture" %}
-
{{ host.arch }}
-
{% trans "Processor" %}
-
{{ host.processor|default:"–" }}
-
{% trans "Logical CPUs" %}
-
{{ host.topology.cpus }}
-
{% trans "Physical cores" %}
-
{{ host.topology.cores|default:"–" }}
-
{% trans "Sockets" %}
-
{{ host.topology.sockets|default:"–" }}
-
{% trans "NUMA nodes" %}
-
{{ host.topology.nodes|default:"–" }}
-
{% trans "Clock" %}
-
{{ host.topology.mhz }} MHz
-
{% trans "Memory" %}
-
{{ host.memory|filesizeformat }}
-
+
+
{% bs_icon 'cpu' %} {% trans "Hardware" %}
+
    +
  • + {% trans "Processor" %} + {{ host.processor|default:"–" }} +
  • +
  • + {% trans "Architecture" %} + {{ host.arch }} +
  • +
  • + {% trans "Logical CPUs" %} + {{ host.topology.cpus }} +
  • +
  • + {% trans "Physical cores" %} + {{ host.topology.cores|default:"–" }} +
  • +
  • + {% trans "Sockets" %} + {{ host.topology.sockets|default:"–" }} +
  • +
  • + {% trans "NUMA nodes" %} + {{ host.topology.nodes|default:"–" }} +
  • +
  • + {% trans "Clock" %} + {{ host.ghz }} GHz +
  • +
  • + {% trans "Memory" %} + {{ host.memory|filesizeformat }} +
  • +
+
- -
-
{% trans "Hypervisor" %}
-
{{ host.hypervisor }} {{ host.hypervisor_version }}
-
libvirt
-
{{ host.libvirt_version }}
-
{% trans "Emulator" %}
-
{{ host.emulator|default:"–" }}
-
{% trans "Guest architectures" %}
-
- {% for arch, types in host.guest_archs.items %} -
{{ arch }} ({{ types|join:", " }})
- {% endfor %} -
-
{% trans "Connection" %}
-
{{ host.uri }}
-
+
+
{% bs_icon 'layers' %} {% trans "Software and connection" %}
+
    +
  • + {% trans "Hostname" %} + {{ host.hostname }} +
  • +
  • + {{ host.hypervisor }} + {{ host.hypervisor_version }} +
  • +
  • + libvirt + {{ host.libvirt_version }} +
  • +
  • + {% trans "Guest architectures" %} + {% for arch, types in host.guest_archs.items %}{{ arch }} {{ types|join:" · " }}{% endfor %} +
  • +
  • + {% trans "Emulator" %} + {{ host.emulator|default:"–" }} +
  • +
  • + {% trans "Connection" %} + {{ host.uri }} +
  • +
+
{% endif %} diff --git a/computes/tests/test_capacity.py b/computes/tests/test_capacity.py index d7cb6107..5e88203a 100644 --- a/computes/tests/test_capacity.py +++ b/computes/tests/test_capacity.py @@ -74,8 +74,8 @@ class ComputesPageTests(TestCase): self.assertIn("host-one", cells[0]) self.assertIn("2.5:1", cells[1]) self.assertIn("40 vCPUs on 16 CPUs 24 running", cells[1]) - self.assertIn("48.0 GB given of 64.0 GB", cells[2]) - self.assertIn("32.0 GB of it running", cells[2]) + self.assertIn("75 % 48.0 GB / 64.0 GB", cells[2]) + self.assertIn("32.0 GB running", cells[2]) self.assertIn("120.0 GB free of 500.0 GB", cells[3]) # host-two could not be read: one cell says so self.assertIn("capacity could not be read", " ".join(two.text_content().split())) diff --git a/computes/tests/test_overview.py b/computes/tests/test_overview.py index e482efc8..2e33db30 100644 --- a/computes/tests/test_overview.py +++ b/computes/tests/test_overview.py @@ -49,27 +49,26 @@ class OverviewTestCase(TestCase): conn.get_emulator.return_value = "/usr/libexec/qemu-kvm" conn.get_hypervisors_domain_types.return_value = {"i686": ["kvm", "qemu"], "x86_64": ["kvm", "qemu"]} page = self.page() - self.assertIn("Connected", text(page, "//p[span]")) - self.assertIn("rack 4", text(page, "//p[span]")) - cards = [" ".join(" ".join(card.itertext()).split()) for card in page.xpath("//div[@class='card-body' or contains(@class,'card-body ')]")] + self.assertIn("Connected", text(page, "//div[@id='host_status']")) + self.assertIn("rack 4", text(page, "//div[@id='host_status']")) + cards = [" ".join(" ".join(card.itertext()).split()) for card in page.xpath("//div[@class='card h-100']")] self.assertIn("VMs 6 3 running, 2 shut off, 1 paused Instances →", cards) self.assertTrue(any(card.startswith("vCPUs 1.5:1 12 vCPUs on 8 CPUs 6 running") for card in cards), cards) - self.assertTrue(any("24.0 GB given of 32.0 GB" in card for card in cards), cards) + self.assertTrue(any(card.startswith("Memory 75 % 24.0 GB / 32.0 GB") for card in cards), cards) self.assertTrue(any("120.0 GB free of 500.0 GB" in card for card in cards), cards) - hardware = text(page, "//h4[.='Hardware']/following-sibling::dl") - self.assertIn("Logical CPUs 8 Physical cores 4 Sockets 2", hardware) - self.assertIn("NUMA nodes 2", hardware) - software = text(page, "//h4[.='Software and connection']/following-sibling::dl") - self.assertIn("Hypervisor QEMU 10.1.0", software) - self.assertIn("x86_64 (kvm, qemu)", software) - # the charts poll only for a host that was read + hardware = text(page, "//div[@class='card-header'][normalize-space()='Hardware']/..") + self.assertIn("Processor Xeon Architecture x86_64 Logical CPUs 8 Physical cores 4 Sockets 2 NUMA nodes 2 " + "Clock 2.4 GHz Memory 32.0 GB", hardware) + software = text(page, "//div[@class='card-header'][normalize-space()='Software and connection']/..") + self.assertIn("QEMU 10.1.0 libvirt 11.10.0", software) + self.assertIn("x86_64 kvm · qemu", software) self.assertTrue(page.xpath("//canvas[@id='cpuChart']")) @patch("computes.views.wvmHostDetails") def test_a_host_the_panel_cannot_reach_keeps_its_page_with_the_reason(self, details): page = self.page(connected=False, given=None) details.assert_not_called() - self.assertIn("Not connected", text(page, "//p[span]")) + self.assertIn("Not connected", text(page, "//div[@id='host_status']")) self.assertIn("did not answer within 5 s", text(page, "//div[@role='alert']")) # the way back: its sections, its connection and its removal self.assertTrue(page.xpath("//nav[@aria-label='Host sections']")) @@ -83,10 +82,10 @@ class OverviewTestCase(TestCase): details.return_value.get_lib_version.side_effect = libvirtError("cannot read the version") page = self.page() self.assertIn("cannot read the version", text(page, "//div[@role='alert']")) - self.assertTrue(page.xpath("//h5[.='VMs']")) + self.assertTrue(page.xpath("//div[@class='card-header'][normalize-space()='VMs']")) # the load is read on its own, by the charts self.assertTrue(page.xpath("//canvas[@id='cpuChart']")) - self.assertFalse(page.xpath("//h4[.='Hardware']")) + self.assertFalse(page.xpath("//div[@class='card-header'][normalize-space()='Hardware']")) def test_the_list_links_the_overview_of_a_host_it_cannot_reach(self): with patch.object(Compute, "status", new_callable=PropertyMock, return_value=False): diff --git a/computes/views.py b/computes/views.py index a941875a..f25b5953 100644 --- a/computes/views.py +++ b/computes/views.py @@ -84,9 +84,10 @@ def overview(request, compute_id): try: conn = wvmHostDetails(compute.hostname, compute.login, compute.password, compute.type) hostname, arch, memory, _cpus, processor, uri = conn.get_node_info() + topology = conn.get_cpu_topology() context["host"] = { "hostname": hostname, "arch": arch, "memory": memory, "processor": processor, "uri": uri, - "topology": conn.get_cpu_topology(), + "topology": topology, "ghz": round(topology["mhz"] / 1000, 1), "hypervisor": conn.wvm.getType(), "hypervisor_version": conn.get_version(), "libvirt_version": conn.get_lib_version(), "emulator": conn.get_emulator(arch), "guest_archs": conn.get_hypervisors_domain_types(), diff --git a/static/icon_cache/cpu_None_None_None.svg b/static/icon_cache/cpu_None_None_None.svg new file mode 100644 index 00000000..63769638 --- /dev/null +++ b/static/icon_cache/cpu_None_None_None.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/static/icon_cache/layers_None_None_None.svg b/static/icon_cache/layers_None_None_None.svg new file mode 100644 index 00000000..cc0ac302 --- /dev/null +++ b/static/icon_cache/layers_None_None_None.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/static/icon_cache/memory_None_None_None.svg b/static/icon_cache/memory_None_None_None.svg new file mode 100644 index 00000000..bbec3765 --- /dev/null +++ b/static/icon_cache/memory_None_None_None.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/static/icon_cache/speedometer2_None_None_None.svg b/static/icon_cache/speedometer2_None_None_None.svg new file mode 100644 index 00000000..6d246824 --- /dev/null +++ b/static/icon_cache/speedometer2_None_None_None.svg @@ -0,0 +1,11 @@ + + + + + + + + + + +