1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00
webvirtcloud/instances/tests/test_access_tab.py
catborise 60f12cefa1 feat(instances): a VM's access in one strip, its console password kept to its rule
The Access tab hid the console, the root password, the SSH key and the
remote viewer behind four sub-tabs. The owner chose a compact layout
from three rendered options: the state, a strip with the console and
the remote viewer, then two rows for root's password and key, each
saying why it waits when it does.

Codex reviewed access end to end; these are fixed:

- console.vv carries the console password only for users with the
  passwordless console permission, as the console page passes it; it
  gave it to every user who may open the console.
- The root password field is a labelled password input, not plain text
  with a 24-character limit.
- Without a saved public key the key row is disabled and points to the
  profile, instead of offering "None".
- A paused VM's console opens, as the console view allows.
- The remote viewer address and console.vv show only for a VNC or SPICE
  console that listens beyond the host's loopback; a viewer on the
  user's computer cannot reach the others, and a serial console gave a
  pty://…:None address.
2026-10-30 20:39:40 +03:00

50 lines
2.6 KiB
Python

"""The Access tab: the console of a running or paused VM, a remote viewer
only where it can reach the console, and root's password and keys when the
VM can take them."""
from types import SimpleNamespace
from django.template.loader import render_to_string
from django.test import SimpleTestCase
from lxml import html
UUID = "abcdabcd-0000-0000-0000-000000000000"
def tab(status=1, vdi_reachable=True, guest_access_ready=True, publickeys=("laptop",)):
instance = SimpleNamespace(id=1, uuid=UUID, status=status, console_type="vnc")
page = render_to_string("instances/access_tab.html", {
"instance": instance, "compute": SimpleNamespace(id=1), "can_open_console": True, "can_change": True,
"app_settings": SimpleNamespace(SHOW_ACCESS_ROOT_PASSWORD="True", SHOW_ACCESS_SSH_KEYS="True"),
"publickeys": [SimpleNamespace(id=n, keyname=name) for n, name in enumerate(publickeys, 1)],
"vdi_reachable": vdi_reachable, "guest_access_ready": guest_access_ready,
})
return html.fromstring(page)
class AccessTabTests(SimpleTestCase):
def test_a_running_or_paused_vm_opens_its_console(self):
for status, console in ((1, True), (3, True), (5, False)):
with self.subTest(status=status):
self.assertEqual(bool(tab(status=status).xpath("//button[@id='console_button']")), console)
def test_a_remote_viewer_is_offered_only_where_it_reaches_the_console(self):
for reachable in (True, False):
with self.subTest(reachable=reachable):
doc = tab(vdi_reachable=reachable)
self.assertEqual(bool(doc.xpath("//a[@id='vdi_url'] | //input[@id='vdi_url_input']")), reachable)
self.assertEqual(bool(doc.xpath("//a[contains(@href, 'getvvfile')]")), reachable)
def test_root_s_password_is_hidden_and_waits_for_a_vm_that_can_take_it(self):
for ready in (True, False):
with self.subTest(ready=ready):
doc = tab(guest_access_ready=ready)
(field,) = doc.xpath("//input[@name='passwd']")
self.assertEqual((field.get("type"), field.get("autocomplete")), ("password", "new-password"))
self.assertEqual(field.xpath("ancestor::fieldset")[0].get("disabled") is not None, not ready)
def test_without_a_saved_key_the_tab_points_to_the_profile(self):
doc = tab(publickeys=())
self.assertIsNotNone(doc.xpath("//select[@name='sshkeyid']/ancestor::fieldset")[0].get("disabled"))
self.assertEqual(doc.xpath("//select[@name='sshkeyid']/option"), [])
self.assertEqual(doc.xpath("//a[text()='Add one in your profile.']/@href"), ["/accounts/profile/"])