1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 19:26:48 +00:00
webvirtcloud/computes/tests/test_capacity.py
catborise 321749f8fa feat(computes): the Computes list on Bootstrap's cards, badges, bars and menus
- Totals above the list: hosts connected of all, VMs running of all,
  vCPUs given on the CPUs, memory given of the memory of the hosts the
  panel reads, as cards; the connected count is red while a host is
  not.
- A host's name links its overview; its state is a Connected or Not
  connected badge (the dot goes), beside a badge of how the panel
  reaches it (TCP, SSH, TLS, Socket); its address in monospace.
- A VMs column: the host's VMs, linked to its Instances, and how many
  run.
- The vCPUs have a bar like the memory's: running VMs' and shut-off
  VMs' vCPUs against the CPUs, amber over 2:1 and red over 4:1 as the
  ratio is; the overview's vCPU card shares it.
- The three coloured buttons of each row are one menu: Overview, Edit
  connection and Remove from panel (its popper fixed, as the table's
  scrolling box would cut it off).
- The four green add buttons are one "Add host" menu that says what
  each kind of connection is.
- The table is table-hover; a host the panel cannot reach has a
  table-warning row.
2026-10-27 21:52:08 +03:00

110 lines
5.9 KiB
Python

"""What each compute has given its VMs (Compute.capacity) and the Computes
page that shows it."""
from unittest.mock import patch
from computes.models import Compute
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse
from libvirt import libvirtError
from lxml import html
GIB = 1024 ** 3
VMS = {"running": 3, "paused": 1, "shutoff": 2, "other": 0}
class CapacityTests(TestCase):
def setUp(self):
self.compute = Compute(name="host-one", hostname="192.0.2.1", login="u", password="p", type=1)
self.compute.status = True
@patch("computes.models.wvmHostDetails")
def test_a_host_tells_what_it_gave(self, details):
details.return_value.get_capacity.return_value = {"cpus": 16, "vcpus": {"all": 24, "running": 8}}
self.assertEqual(self.compute.capacity, {"cpus": 16, "vcpus": {"all": 24, "running": 8}, "ratio": 1.5})
@patch("computes.models.wvmHostDetails")
def test_a_host_whose_read_fails_has_no_capacity(self, details):
# a VM that goes while the host is read, for one
details.return_value.get_capacity.side_effect = libvirtError("Domain not found")
self.assertIsNone(self.compute.capacity)
@patch("computes.models.wvmHostDetails")
def test_a_down_host_is_not_read(self, details):
self.compute.status = False
self.assertIsNone(self.compute.capacity)
details.assert_not_called()
class ComputesPageTests(TestCase):
def test_the_list_shows_what_each_compute_has_given(self):
admin = get_user_model().objects.create_superuser("cap-admin", "cap@example.com", "pw")
self.client.force_login(admin)
c1 = Compute.objects.create(name="host-one", hostname="192.0.2.1", login="u", password="p", type=1)
Compute.objects.create(name="host-two", hostname="192.0.2.2", login="u", password="p", type=1)
found = {c1.id: {"cpus": 16, "memory": 64 * GIB, "vcpus": {"all": 40, "running": 24},
"assigned": {"all": 48 * GIB, "running": 32 * GIB}, "ratio": 2.5, "vms": VMS}}
with patch.object(Compute, "capacity", new=property(lambda c: found.get(c.id))), \
patch.object(Compute, "status", new=True):
page = html.fromstring(self.client.get(reverse("computes")).content)
headers = [" ".join(th.text_content().split()) for th in page.xpath("//thead//th")]
# no pools: measuring their space scans each pool of each host (views.host_pools)
self.assertEqual(headers, ["Host", "VMs", "vCPUs", "Memory", "Actions"])
one, two = page.xpath("//tbody/tr")
cells = [" ".join(td.text_content().split()) for td in one.xpath("td")]
self.assertIn("host-one Connected TCP 192.0.2.1", cells[0])
self.assertEqual(cells[1], "6 3 running")
self.assertIn("2.5:1", cells[2])
self.assertIn("40 vCPUs on 16 CPUs", cells[2])
self.assertIn("24 running", cells[2])
self.assertIn("75 % 48.0 GB / 64.0 GB", cells[3])
self.assertIn("32.0 GB running", cells[3])
# the totals of the hosts read: host-two's capacity could not be
totals = [" ".join(card.text_content().split()) for card in page.xpath("//div[@class='card-body']")]
self.assertEqual(totals, ["Hosts 2 / 2 connected", "VMs 3 / 6 running", "vCPUs given 40 on 16 CPUs",
"Memory given 48.0 GB of 64.0 GB"])
# host-two could not be read: one cell says so
self.assertIn("capacity could not be read", " ".join(two.text_content().split()))
class SingularTests(TestCase):
def test_one_vcpu_on_one_cpu_is_singular(self):
admin = get_user_model().objects.create_superuser("cap-one", "one@example.com", "pw")
self.client.force_login(admin)
c = Compute.objects.create(name="host-one", hostname="192.0.2.1", login="u", password="p", type=1)
given = {"cpus": 1, "memory": 4 * GIB, "vcpus": {"all": 1, "running": 1},
"assigned": {"all": GIB, "running": GIB}, "ratio": 1.0, "vms": VMS}
with patch.object(Compute, "capacity", new=given), patch.object(Compute, "status", new=True):
page = html.fromstring(self.client.get(reverse("computes")).content)
line = self.client.get(reverse("compute_capacity", args=[c.id])).content.decode()
(cell,) = page.xpath("//tbody/tr/td[3]")
self.assertIn("1 vCPU on 1 CPU", " ".join(cell.text_content().split()))
self.assertEqual(" ".join(line.split()), "Given to VMs: 1 vCPU (1.0:1), 1.0 GB memory.")
class NewVmDialogLineTests(TestCase):
"""The new-VM dialog loads one line per host when it opens."""
def setUp(self):
admin = get_user_model().objects.create_superuser("cap-line", "line@example.com", "pw")
self.client.force_login(admin)
self.compute = Compute.objects.create(name="host-one", hostname="192.0.2.1", login="u", password="p", type=1)
def line(self, given):
with patch.object(Compute, "capacity", new=given):
response = self.client.get(reverse("compute_capacity", args=[self.compute.id]))
self.assertEqual(response["Content-Type"], "text/plain; charset=utf-8")
return " ".join(response.content.decode().split())
def test_the_line_tells_what_the_host_has_given(self):
given = {"cpus": 16, "memory": 64 * GIB, "vcpus": {"all": 24, "running": 8},
"assigned": {"all": 48 * GIB, "running": 32 * GIB}, "ratio": 1.5,
}
self.assertEqual(self.line(given), "Given to VMs: 24 vCPUs (1.5:1), 48.0 GB memory.")
def test_a_host_without_pools_or_capacity_says_so(self):
given = {"cpus": 2, "memory": 4 * GIB, "vcpus": {"all": 0, "running": 0},
"assigned": {"all": 0, "running": 0}, "ratio": 0}
self.assertEqual(self.line(given), "Given to VMs: 0 vCPUs (0.0:1), 0 bytes memory.")
self.assertEqual(self.line(None), "The capacity could not be read.")