1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-09 19:56:48 +00:00
webvirtcloud/instances/tests/test_index_host_alerts.py
catborise b89f280076 fix(instances): VM list columns, hosts for viewers, flavor units
- On a narrow screen the grouped list hid the User, VCPU and Memory
  headings but not the VMs' cells, so values sat under the wrong headings;
  the cells now hide with their headings. Memory says MiB.
- A user with the view_instances permission sees each VM's host in the
  list, as the host alerts already name them; the host page link stays a
  superuser's.
- A flavor's memory and disk are labelled MiB and GiB, and each value is at
  least 1, so "4" is no longer saved as a 4 MiB preset by mistake.
2026-10-26 16:14:37 +03:00

70 lines
3.6 KiB
Python

"""Host connection errors on the instance list: administrators see which host
and why; other users only learn that a host of their own VMs is unreachable."""
from unittest.mock import PropertyMock, patch
from accounts.models import UserInstance
from computes.models import Compute
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.test import TestCase
from django.urls import reverse
from instances.models import Instance
USER_MESSAGE = "A host of some of your virtual machines cannot be reached right now."
class IndexHostAlertTests(TestCase):
def setUp(self):
User = get_user_model()
self.user = User.objects.create_user(username="tenant", password="pwd")
self.mine = Compute.objects.create(name="mine-host", hostname="10.0.0.1", type=1, login="u", password="p")
self.other = Compute.objects.create(name="other-host", hostname="10.0.0.2", type=1, login="u", password="p")
vm = Instance.objects.create(compute=self.mine, name="tenant-vm", uuid="11111111-1111-1111-1111-111111111111")
UserInstance.objects.create(instance=vm, user=self.user)
def get(self, user, down):
def status(compute):
return compute.name not in down
def error(compute):
return None if status(compute) else f"Connection Failed: no route to {compute.hostname}"
self.client.force_login(user)
with patch("instances.views.utils.refr"), patch.object(Compute, "status", property(status)), patch.object(
Compute, "connection_error", property(error)
), patch.object(Instance, "info", new_callable=PropertyMock, return_value=None):
response = self.client.get(reverse("instances:index"))
self.assertEqual(response.status_code, 200)
return response
def test_user_sees_no_infrastructure_details(self):
response = self.get(self.user, down={"mine-host", "other-host"})
self.assertContains(response, USER_MESSAGE, count=1)
for text in ("mine-host", "other-host", "10.0.0.1", "10.0.0.2", "Connection Failed"):
self.assertNotContains(response, text)
def test_user_is_not_told_about_hosts_without_their_vms(self):
response = self.get(self.user, down={"other-host"})
self.assertNotContains(response, USER_MESSAGE)
self.assertNotContains(response, "other-host")
def test_superuser_sees_each_host_and_its_error(self):
admin = get_user_model().objects.create_superuser(username="root", password="pwd", email="r@example.com")
response = self.get(admin, down={"mine-host", "other-host"})
self.assertContains(response, "Connection Failed: no route to 10.0.0.1")
self.assertContains(response, "Connection Failed: no route to 10.0.0.2")
self.assertNotContains(response, USER_MESSAGE)
def test_global_viewer_sees_each_host_and_its_error(self):
viewer = get_user_model().objects.create_user(username="viewer", password="pwd")
viewer.user_permissions.add(Permission.objects.get(codename="view_instances"))
response = self.get(viewer, down={"other-host"})
self.assertContains(response, "Connection Failed: no route to 10.0.0.2")
def test_global_viewer_sees_each_vms_host_without_the_host_page(self):
viewer = get_user_model().objects.create_user(username="viewer2", password="pwd")
viewer.user_permissions.add(Permission.objects.get(codename="view_instances"))
response = self.get(viewer, down=set())
self.assertContains(response, "mine-host")
self.assertNotContains(response, reverse("overview", args=[self.mine.id]))