From f94b3cee7a2bc5255fe1a5f2249db93b3a9d6e9d Mon Sep 17 00:00:00 2001 From: catborise Date: Sun, 4 Oct 2026 11:09:25 +0300 Subject: [PATCH] chore: drop references to the local roadmap from code and tests Comments, docstrings and live test names cited item IDs of a roadmap that is not part of the repository. They now say what is meant, or nothing where the sentence stands without them. Test assertions and behavior are unchanged. --- accounts/apps.py | 2 +- accounts/test_admin_email_otp.py | 2 +- accounts/test_admin_password.py | 2 +- accounts/test_first_login_password.py | 2 +- computes/test_ownership.py | 2 +- computes/urls.py | 2 +- computes/utils.py | 4 +- conf/daemon/gstfsd | 2 +- console/socketiod | 2 +- console/test_socketiod_disabled.py | 2 +- console/tests.py | 6 +-- console/views.py | 2 +- instances/api/viewsets.py | 2 +- instances/models.py | 2 +- instances/test_clone_permission.py | 5 +-- instances/test_console_rule.py | 6 +-- instances/test_create_rollback.py | 2 +- instances/test_disk_isolation.py | 3 +- instances/test_gstfsd.py | 2 +- instances/test_live_clone.py | 2 +- instances/test_live_create.py | 2 +- instances/test_live_dataloss.py | 46 +++++++++++------------ instances/test_live_iso.py | 2 +- instances/test_live_xml.py | 2 +- instances/test_root_pass.py | 4 +- instances/test_security_mutations.py | 2 +- instances/test_template_flag.py | 2 +- instances/test_xss.py | 6 +-- instances/utils.py | 2 +- instances/views.py | 4 +- vrtManager/instance.py | 8 ++-- vrtManager/test_change_network.py | 2 +- vrtManager/test_connection.py | 2 +- vrtManager/test_iso_media.py | 2 +- vrtManager/test_persistent_edits.py | 2 +- vrtManager/test_xml_safety.py | 4 +- webvirtcloud/test_authorization_matrix.py | 30 +++++++-------- 37 files changed, 87 insertions(+), 89 deletions(-) diff --git a/accounts/apps.py b/accounts/apps.py index 2358bd20..eb6a7d58 100644 --- a/accounts/apps.py +++ b/accounts/apps.py @@ -53,7 +53,7 @@ def _store_generated_password(password): """ Write the generated admin password to data/admin_password (mode 0600) instead of printing it, so it does not end up in install logs or - `docker logs` (ROADMAP O-02). Abort provisioning if private storage fails. + `docker logs`. Abort provisioning if private storage fails. """ path = admin_password_path() try: diff --git a/accounts/test_admin_email_otp.py b/accounts/test_admin_email_otp.py index 1ade4005..1cb139e1 100644 --- a/accounts/test_admin_email_otp.py +++ b/accounts/test_admin_email_otp.py @@ -6,7 +6,7 @@ from django.urls import reverse class AdminEmailOtpTestCase(TestCase): - """ROADMAP S-11: sending the OTP QR code by email must not happen on GET.""" + """Sending the OTP QR code by email must not happen on GET.""" def setUp(self): User = get_user_model() diff --git a/accounts/test_admin_password.py b/accounts/test_admin_password.py index a6c21639..7b64ce7f 100644 --- a/accounts/test_admin_password.py +++ b/accounts/test_admin_password.py @@ -1,4 +1,4 @@ -"""ROADMAP O-02: the generated admin password must not be printed to the log.""" +"""The generated admin password must not be printed to the log.""" import io import os import stat diff --git a/accounts/test_first_login_password.py b/accounts/test_first_login_password.py index 132e5ced..a547f8ea 100644 --- a/accounts/test_first_login_password.py +++ b/accounts/test_first_login_password.py @@ -1,4 +1,4 @@ -"""ROADMAP O-17: the generated admin password must be replaced at first login.""" +"""The generated admin password must be replaced at first login.""" import tempfile from pathlib import Path diff --git a/computes/test_ownership.py b/computes/test_ownership.py index e7d58f3b..1cbe07f6 100644 --- a/computes/test_ownership.py +++ b/computes/test_ownership.py @@ -1,4 +1,4 @@ -"""R-05: ownership survives a VM's temporary disappearance or an out-of-band move.""" +"""Ownership survives a VM's temporary disappearance or an out-of-band move.""" from datetime import timedelta from unittest.mock import MagicMock diff --git a/computes/urls.py b/computes/urls.py index 00588c01..80732d50 100644 --- a/computes/urls.py +++ b/computes/urls.py @@ -13,7 +13,7 @@ from . import forms, views def superuser_only_patterns(patterns): """ Wrap every view below these patterns with superuser_only. Everything under - /computes/ is host administration (ROADMAP S-10), so the check is applied + /computes/ is host administration, so the check is applied to the whole namespace instead of per view, and a view added here later cannot be exposed by forgetting a decorator. """ diff --git a/computes/utils.py b/computes/utils.py index 96f3f28b..c08722f2 100644 --- a/computes/utils.py +++ b/computes/utils.py @@ -207,7 +207,7 @@ def refresh_instance_database(compute): Libvirt is the single source of truth: - VMs removed in virt-manager/virsh are deleted from the database; their ownership is moved to the same UUID on another compute or kept in a - tombstone for INSTANCE_OWNERSHIP_RETENTION_DAYS (R-05). + tombstone for INSTANCE_OWNERSHIP_RETENTION_DAYS. - VMs created in virt-manager/virsh are added to the database. - VMs renamed in virt-manager/virsh have their name updated without losing UserInstance permission relationships (matched by UUID). @@ -265,7 +265,7 @@ def refresh_instance_database(compute): # 2. Instances gone from this compute. Their ownership goes to the # same UUID on another compute (an out-of-band move) or is kept - # in a tombstone in case the VM comes back (R-05). + # in a tombstone in case the VM comes back. for inst in db_instances: if inst.uuid not in host_domains: elsewhere = Instance.objects.filter(uuid=inst.uuid).exclude(compute=compute).first() diff --git a/conf/daemon/gstfsd b/conf/daemon/gstfsd index cf5c4136..bf1a3754 100644 --- a/conf/daemon/gstfsd +++ b/conf/daemon/gstfsd @@ -24,7 +24,7 @@ def is_loopback(host): # gstfsd is an unauthenticated root service that rewrites any VM's # /etc/shadow and authorized_keys, so it only listens on loopback unless -# explicitly allowed (ROADMAP S-08). +# explicitly allowed. if not is_loopback(ADDRESS) and os.environ.get("GSTFSD_ALLOW_REMOTE") != "1": sys.stderr.write( "gstfsd: refusing to listen on %s (unauthenticated root service). " diff --git a/console/socketiod b/console/socketiod index ecc93fdb..41c132e2 100755 --- a/console/socketiod +++ b/console/socketiod @@ -19,7 +19,7 @@ django.setup() from django.conf import settings as django_settings -# socketiod does not authenticate connections yet (ROADMAP S-01): any client +# socketiod does not authenticate connections yet: any client # that can reach the port can read and write an open serial console. Refuse # to start unless an admin explicitly opts in. if not getattr(django_settings, "SERIAL_CONSOLE_ENABLED", False): diff --git a/console/test_socketiod_disabled.py b/console/test_socketiod_disabled.py index d28619d6..5e986628 100644 --- a/console/test_socketiod_disabled.py +++ b/console/test_socketiod_disabled.py @@ -11,7 +11,7 @@ SOCKETIOD = ROOT / "console" / "socketiod" class SocketiodDisabledTestCase(unittest.TestCase): - """ROADMAP S-01: socketiod must refuse to start unless explicitly enabled.""" + """socketiod must refuse to start unless explicitly enabled.""" def test_socketiod_exits_when_serial_console_disabled(self): # The settings module lives in a temporary directory, so the test does diff --git a/console/tests.py b/console/tests.py index 5181e9d0..68d959cf 100644 --- a/console/tests.py +++ b/console/tests.py @@ -140,7 +140,7 @@ class ConsoleViewsTestCase(TestCase): @override_settings(SERIAL_CONSOLE_ENABLED=False) @patch("console.views.wvmInstance") def test_console_pty_refused_when_serial_console_disabled(self, mock_wvm): - # ROADMAP S-01: socketiod is unauthenticated, so the serial console is + # socketiod is unauthenticated, so the serial console is # disabled unless an admin explicitly enables it. mock_conn = MagicMock() mock_conn.get_console_type.return_value = "pty" @@ -194,7 +194,7 @@ class ConsoleViewsTestCase(TestCase): @patch("console.views.wvmInstance") def test_console_token_cookie_flags(self, mock_wvm): - # ROADMAP S-11: the token cookie is only read by novncd, never by JS. + # The token cookie is only read by novncd, never by JS. mock_conn = MagicMock() mock_conn.get_console_type.return_value = "vnc" mock_conn.get_console_websocket_port.return_value = None @@ -209,7 +209,7 @@ class ConsoleViewsTestCase(TestCase): @patch("console.views.wvmInstance") def test_console_view_instances_perm_does_not_open_console(self, mock_wvm): - # ROADMAP S-09: global view_instances is a read-only role; the console + # Global view_instances is a read-only role; the console # is for superusers and VM owners only. mock_conn = MagicMock() mock_conn.get_console_type.return_value = "vnc" diff --git a/console/views.py b/console/views.py index 83ba5e03..e45751b8 100644 --- a/console/views.py +++ b/console/views.py @@ -129,7 +129,7 @@ def console(request): elif console_type == "pty" and not getattr( settings, "SERIAL_CONSOLE_ENABLED", False ): - # socketiod does not authenticate connections yet (ROADMAP S-01), so + # socketiod does not authenticate connections yet, so # the serial console stays off unless an admin explicitly enables it. console_error = _( "Serial console is disabled on this server. " diff --git a/instances/api/viewsets.py b/instances/api/viewsets.py index 6c34b686..298edc32 100644 --- a/instances/api/viewsets.py +++ b/instances/api/viewsets.py @@ -313,7 +313,7 @@ class CreateInstanceViewSet(viewsets.ViewSet): qemu_ga=serializer.validated_data["qemu_ga"], ) except Exception as err: - # R-08: a failed definition must not leave the new disk behind + # A failed definition must not leave the new disk behind if path: try: conn.delete_volume(path) diff --git a/instances/models.py b/instances/models.py index d85e625e..91fb4472 100644 --- a/instances/models.py +++ b/instances/models.py @@ -300,7 +300,7 @@ class CreateInstance(models.Model): class InstanceTombstone(models.Model): - """Ownership of a VM that disappeared from its compute (R-05). + """Ownership of a VM that disappeared from its compute. Kept for INSTANCE_OWNERSHIP_RETENTION_DAYS so that the owners come back when the same UUID shows up again, on this or another compute. diff --git a/instances/test_clone_permission.py b/instances/test_clone_permission.py index f517872b..9b103532 100644 --- a/instances/test_clone_permission.py +++ b/instances/test_clone_permission.py @@ -1,7 +1,6 @@ """ -Regression tests for ROADMAP Wave 0 item 4 (S-05): cloning another user's VM -must require change permission on it (templates excepted), and the clone -data must not be taken blindly from the POST body. +Cloning another user's VM must require change permission on it (templates +excepted), and the clone data must not be taken blindly from the POST body. """ from contextlib import contextmanager from unittest.mock import patch diff --git a/instances/test_console_rule.py b/instances/test_console_rule.py index 903b5604..cdf07069 100644 --- a/instances/test_console_rule.py +++ b/instances/test_console_rule.py @@ -1,7 +1,7 @@ """ -ROADMAP Wave 0 item 5 (S-09): one rule decides who may open a VM's console -(noVNC page, novncd, the virt-viewer .vv file, the VDI URL): a superuser or -an owner of the VM. The global view_instances permission is read-only. +One rule decides who may open a VM's console (noVNC page, novncd, the +virt-viewer .vv file, the VDI URL): a superuser or an owner of the VM. The +global view_instances permission is read-only. """ from unittest.mock import MagicMock, patch diff --git a/instances/test_create_rollback.py b/instances/test_create_rollback.py index 7c6f717d..5df2aeec 100644 --- a/instances/test_create_rollback.py +++ b/instances/test_create_rollback.py @@ -16,7 +16,7 @@ FORM = { class CreateRollbackTestCase(TestCase): - """R-08: volumes are removed only while the VM is not defined yet.""" + """Volumes are removed only while the VM is not defined yet.""" def setUp(self): admin = get_user_model().objects.create_superuser("rb_admin", "r@example.com", "pw") diff --git a/instances/test_disk_isolation.py b/instances/test_disk_isolation.py index 0bf5657f..26ec1036 100644 --- a/instances/test_disk_isolation.py +++ b/instances/test_disk_isolation.py @@ -1,6 +1,5 @@ """ -Regression tests for ROADMAP Wave 0 item 1 (S-02, S-03, S-04): -disk and media mutation views must be superuser-only (matching the UI, where +Disk and media mutation views must be superuser-only (matching the UI, where the Disk tab is only rendered for superusers), and even for superusers the views must not act on volumes or option values taken blindly from the client. """ diff --git a/instances/test_gstfsd.py b/instances/test_gstfsd.py index 32c3d71c..2cc198c9 100644 --- a/instances/test_gstfsd.py +++ b/instances/test_gstfsd.py @@ -48,7 +48,7 @@ def free_port(family=socket.AF_INET, host="127.0.0.1"): class GstfsdTestCase(unittest.TestCase): - """ROADMAP S-08: gstfsd hardening.""" + """gstfsd hardening.""" def setUp(self): # novncd (imported by other tests) sets SIGCHLD to SIG_IGN, which hides exit codes. diff --git a/instances/test_live_clone.py b/instances/test_live_clone.py index 174f4f5f..cd058adc 100644 --- a/instances/test_live_clone.py +++ b/instances/test_live_clone.py @@ -1,4 +1,4 @@ -"""Live checks for cloning (R-08). Runs only with TEST_LIBVIRT_HOST set.""" +"""Live checks for cloning. Runs only with TEST_LIBVIRT_HOST set.""" import os import unittest diff --git a/instances/test_live_create.py b/instances/test_live_create.py index 3cf50944..ae1167e0 100644 --- a/instances/test_live_create.py +++ b/instances/test_live_create.py @@ -1,4 +1,4 @@ -"""Live checks that a failed VM creation leaves no volumes behind (R-08). +"""Live checks that a failed VM creation leaves no volumes behind. Runs only with TEST_LIBVIRT_HOST set (see instances/livetest.py). """ diff --git a/instances/test_live_dataloss.py b/instances/test_live_dataloss.py index 3c03f0c1..f0ecf211 100644 --- a/instances/test_live_dataloss.py +++ b/instances/test_live_dataloss.py @@ -1,8 +1,8 @@ -"""Live reproductions of the Wave 1a data-loss findings. +"""Live tests for cases that lost disks or changed the wrong VM. -Each test asserts the safe behavior and is marked expectedFailure until -its finding is fixed; a fix turns it into an unexpected success, which -fails the run until the marker is removed. Runs only with +Each test asserts the safe behavior. Known unfixed cases are marked +expectedFailure; a fix turns them into unexpected successes, which fail +the run until the marker is removed. Runs only with TEST_LIBVIRT_HOST set (see instances/livetest.py). """ @@ -90,10 +90,10 @@ class LiveDataLossTestCase(TestCase): except libvirt.libvirtError: return False - # R-03: external snapshots + # External snapshots @unittest.expectedFailure - def test_r03_revert_external_snapshot_keeps_disk_added_later(self): + def test_revert_external_snapshot_keeps_disk_added_later(self): base = livetest.create_volume(self.conn, P + "r03-a") dom, inst = self.vm("r03-a", [base]) self.post("create_external_snapshot", inst, {"name": "snap"}) @@ -109,7 +109,7 @@ class LiveDataLossTestCase(TestCase): self.assertTrue(livetest.volume_exists(self.conn, later), "revert deleted a disk the snapshot never had") @unittest.expectedFailure - def test_r03_delete_older_external_snapshot_keeps_newer_snapshot_files(self): + def test_delete_older_external_snapshot_keeps_newer_snapshot_files(self): base = livetest.create_volume(self.conn, P + "r03-b") dom, inst = self.vm("r03-b", [base]) self.post("create_external_snapshot", inst, {"name": "older"}) @@ -122,7 +122,7 @@ class LiveDataLossTestCase(TestCase): self.assertTrue(livetest.volume_exists(self.conn, path), f"{path} was deleted") self.assertIn("s1.newer", dom.snapshotListNames(0)) - # R-13: internal snapshots of UEFI VMs + # Internal snapshots of UEFI VMs def _uefi_internal_snapshot(self, running): base = livetest.create_volume(self.conn, P + "r13") @@ -145,15 +145,15 @@ class LiveDataLossTestCase(TestCase): return etree.tostring(etree.fromstring(dom.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)).find("os")) - def test_r13_uefi_internal_snapshot_of_a_stopped_vm(self): + def test_uefi_internal_snapshot_of_a_stopped_vm(self): self._uefi_internal_snapshot(running=False) - def test_r13_uefi_internal_snapshot_of_a_running_vm(self): + def test_uefi_internal_snapshot_of_a_running_vm(self): self._uefi_internal_snapshot(running=True) - # R-14: destroy + # Destroy - def test_r14_destroy_keeps_a_volume_another_vm_uses(self): + def test_destroy_keeps_a_volume_another_vm_uses(self): shared = livetest.create_volume(self.conn, P + "r14-shared") _, inst = self.vm("r14-a", [shared]) self.vm("r14-b", [shared]) @@ -182,13 +182,13 @@ class LiveDataLossTestCase(TestCase): self.assertEqual(response.status_code, 302) self.assertTrue(livetest.volume_exists(self.conn, base), "deleted the backing file of another VM's disk") - def test_r14_destroy_keeps_the_backing_file_of_a_stopped_vm(self): + def test_destroy_keeps_the_backing_file_of_a_stopped_vm(self): self._destroy_base_of_another_vms_overlay(running=False) - def test_r14_destroy_keeps_the_backing_file_of_a_running_vm(self): + def test_destroy_keeps_the_backing_file_of_a_running_vm(self): self._destroy_base_of_another_vms_overlay(running=True) - def test_r14_destroy_with_managed_save_removes_the_vm(self): + def test_destroy_with_managed_save_removes_the_vm(self): base = livetest.create_volume(self.conn, P + "r14-save") dom, inst = self.vm("r14-save", [base]) dom.create() @@ -200,7 +200,7 @@ class LiveDataLossTestCase(TestCase): self.assertFalse(self.domain_exists(uuid), "VM is still defined") self.assertFalse(Instance.objects.filter(uuid=uuid).exists()) - def test_r14_destroy_of_a_paused_vm_removes_it(self): + def test_destroy_of_a_paused_vm_removes_it(self): base = livetest.create_volume(self.conn, P + "r14-paused") dom, inst = self.vm("r14-paused", [base]) dom.create() @@ -210,7 +210,7 @@ class LiveDataLossTestCase(TestCase): self.assertFalse(self.domain_exists(dom.UUIDString()), "paused VM is still running") - # S-02: delete a volume only after it is detached + # Delete a volume only after it is detached def _delete_attached_volume(self, pause): base = livetest.create_volume(self.conn, P + "s02") @@ -229,13 +229,13 @@ class LiveDataLossTestCase(TestCase): self.assertIn("vdb", self.disk_sources(dom)) self.assertTrue(livetest.volume_exists(self.conn, data), "volume deleted while the VM still uses it") - def test_s02_delete_volume_of_a_paused_vm(self): + def test_delete_volume_of_a_paused_vm(self): self._delete_attached_volume(pause=True) - def test_s02_delete_volume_of_a_running_vm_without_guest_ack(self): + def test_delete_volume_of_a_running_vm_without_guest_ack(self): self._delete_attached_volume(pause=False) - def test_s02_delete_volume_another_vm_uses_is_refused(self): + def test_delete_volume_another_vm_uses_is_refused(self): base = livetest.create_volume(self.conn, P + "s02-own") shared = livetest.create_volume(self.conn, P + "s02-shared") _, inst = self.vm("s02-a", [base, shared]) @@ -246,9 +246,9 @@ class LiveDataLossTestCase(TestCase): self.assertEqual(response.status_code, 302) self.assertTrue(livetest.volume_exists(self.conn, shared), "deleted another VM's disk") - # R-06: operations follow the VM's UUID, not its name + # Operations follow the VM's UUID, not its name - def test_r06_mutation_follows_uuid_after_names_are_swapped(self): + def test_mutation_follows_uuid_after_names_are_swapped(self): dom_a, inst_a = self.vm("r06-a", []) dom_b, _ = self.vm("r06-b", []) dom_a.rename(P + "r06-tmp", 0) @@ -260,7 +260,7 @@ class LiveDataLossTestCase(TestCase): self.assertIn("for-a", dom_a.XMLDesc(0)) self.assertNotIn("for-a", dom_b.XMLDesc(0)) - def test_r06_vm_replaced_under_the_same_name_is_not_touched(self): + def test_vm_replaced_under_the_same_name_is_not_touched(self): dom_old, inst = self.vm("r06-c", []) dom_old.undefine() dom_new = livetest.define_vm(self.conn, P + "r06-c", []) diff --git a/instances/test_live_iso.py b/instances/test_live_iso.py index 2a6f3f60..785bafa9 100644 --- a/instances/test_live_iso.py +++ b/instances/test_live_iso.py @@ -1,4 +1,4 @@ -"""Live checks for ISO mount/unmount (R-12). Runs only with TEST_LIBVIRT_HOST set.""" +"""Live checks for ISO mount/unmount. Runs only with TEST_LIBVIRT_HOST set.""" import os import unittest diff --git a/instances/test_live_xml.py b/instances/test_live_xml.py index 3d235452..c88e5276 100644 --- a/instances/test_live_xml.py +++ b/instances/test_live_xml.py @@ -1,4 +1,4 @@ -"""Live checks that persistent edits keep secrets and pending changes (R-01, R-02). +"""Live checks that persistent edits keep secrets and pending changes. Every edit that redefines the domain must start from the persistent definition with secrets (VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE). diff --git a/instances/test_root_pass.py b/instances/test_root_pass.py index 82ba6a83..f062ac9f 100644 --- a/instances/test_root_pass.py +++ b/instances/test_root_pass.py @@ -26,7 +26,7 @@ class SetRootPassTestCase(TestCase): @patch("socket.socket") @patch.object(Instance, "proxy") def test_set_root_pass_post(self, mock_proxy, mock_socket_cls): - # Renamed on the host: gstfsd must get the name of this UUID's domain (R-06) + # Renamed on the host: gstfsd must get the name of this UUID's domain mock_proxy.instance.name.return_value = "renamed-on-host" mock_proxy.get_status.return_value = 5 # status: running mock_sock = MagicMock() @@ -46,7 +46,7 @@ class SetRootPassTestCase(TestCase): data = json.loads(sent_bytes.decode()) self.assertEqual(data["action"], "password") self.assertEqual(data["vname"], "renamed-on-host") - # SHA-512 crypt with a random salt (ROADMAP S-08), not the old fixed one + # SHA-512 crypt with a random salt, not the old fixed one self.assertTrue(data["passwd"].startswith("$6$")) self.assertFalse(data["passwd"].startswith("$6$kgPoiREy$")) diff --git a/instances/test_security_mutations.py b/instances/test_security_mutations.py index 7196cafd..8420e288 100644 --- a/instances/test_security_mutations.py +++ b/instances/test_security_mutations.py @@ -299,7 +299,7 @@ class InstanceSecurityMutationsTestCase(TestCase): def test_disk_mutation_denied_with_is_change(self): # change_user has is_change=True, is_delete=False. Disk views are - # superuser-only (S-02/S-03/S-04), so is_change alone is not enough. + # superuser-only, so is_change alone is not enough. self.client.force_login(self.change_user) with patch("instances.models.wvmInstance"), patch("instances.views.wvmStorage") as mock_storage: res = self.client.post( diff --git a/instances/test_template_flag.py b/instances/test_template_flag.py index 9be99ddb..8d9b3e62 100644 --- a/instances/test_template_flag.py +++ b/instances/test_template_flag.py @@ -1,5 +1,5 @@ """ -ROADMAP S-22: only superusers and staff may mark or unmark a VM as a template. +Only superusers and staff may mark or unmark a VM as a template. The UI only disables the checkbox for other users, and a disabled checkbox is not submitted, so the server must not derive is_template from its absence for them. diff --git a/instances/test_xss.py b/instances/test_xss.py index 4e9d631d..962e0864 100644 --- a/instances/test_xss.py +++ b/instances/test_xss.py @@ -1,7 +1,7 @@ """ -Regression tests for ROADMAP Wave 0 item 3 (S-06, S-07): JSON endpoints must -not be served as text/html (reflected XSS), and templates must not build HTML -by concatenating server data that contains user-controlled names (stored XSS). +JSON endpoints must not be served as text/html (reflected XSS), and +templates must not build HTML by concatenating server data that contains +user-controlled names (stored XSS). """ import re from pathlib import Path diff --git a/instances/utils.py b/instances/utils.py index 7629158d..6224a307 100644 --- a/instances/utils.py +++ b/instances/utils.py @@ -20,7 +20,7 @@ def can_open_console(user, instance): The single rule for console access (noVNC page, novncd, the virt-viewer .vv file and the VDI URL): an active superuser or an active owner of the VM. The global view_instances permission is read-only and does not grant - an interactive console (ROADMAP S-09). + an interactive console. """ if not user.is_active: return False diff --git a/instances/views.py b/instances/views.py index 43da4f54..29662df6 100755 --- a/instances/views.py +++ b/instances/views.py @@ -1909,7 +1909,7 @@ def change_options(request, pk): userinstance = UserInstance(is_change=False) if request.user.is_superuser or userinstance.is_change: - # Only superusers and staff may (un)mark templates (ROADMAP S-22). The + # Only superusers and staff may (un)mark templates. The # checkbox is disabled for everyone else, and a disabled checkbox is # not submitted, so for them the flag must be left alone. if request.user.is_superuser or request.user.is_staff: @@ -2111,7 +2111,7 @@ def create_instance(request, compute_id, arch, machine): data = form.cleaned_data meta_prealloc = bool(data["meta_prealloc"]) - # Everything is checked before any storage is allocated (R-08). + # Everything is checked before any storage is allocated. if data["name"] in instances: raise util.OperationError(_("A virtual machine with this name already exists")) if Instance.objects.filter(name__exact=data["name"]): diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 6553a350..c1a10eac 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -51,7 +51,7 @@ from vrtManager.storage import wvmStorage, wvmStorages # Edits that redefine the domain start from this: the persistent definition, # with secrets. Live XML would drop pending changes, non-secure XML the VNC -# password (R-01, R-02). +# password. PERSISTENT_XML = VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE @@ -711,7 +711,7 @@ class wvmInstance(wvmConnect): """Insert path into, or with None eject, CD-ROM dev. The live and the persistent definition are updated separately from - their own device XML, so neither is rewritten from the other (R-12). + their own device XML, so neither is rewritten from the other. """ definitions = [("persistent", PERSISTENT_XML, VIR_DOMAIN_AFFECT_CONFIG)] if self.instance.isActive(): # running or paused @@ -1338,7 +1338,7 @@ class wvmInstance(wvmConnect): time.time(), ) # libvirt decides whether this firmware/NVRAM supports internal - # snapshots; the domain definition is never rewritten for it (R-13). + # snapshots; the domain definition is never rewritten for it. xml += self._XMLDesc(VIR_DOMAIN_XML_SECURE) xml += """0 """ @@ -1506,7 +1506,7 @@ class wvmInstance(wvmConnect): def clone_instance(self, clone_data): """Copy a shut-off VM. Inputs are checked before anything is allocated, - and on failure only the volumes this call created are removed (R-08).""" + and on failure only the volumes this call created are removed.""" if self.get_status() != 5: # A running guest keeps writing while its disks are copied. raise util.OperationError("Shut the VM down before cloning it") diff --git a/vrtManager/test_change_network.py b/vrtManager/test_change_network.py index b26fc356..025f48ca 100644 --- a/vrtManager/test_change_network.py +++ b/vrtManager/test_change_network.py @@ -41,7 +41,7 @@ class TestChangeNetwork(unittest.TestCase): self.assertEqual(second.find("source").attrib, {"bridge": "br0"}) self.assertEqual(second.find("model").get("type"), "e1000") self.assertEqual(second.find("filterref").get("filter"), "clean-traffic") - # F-06: QoS, link state and the PCI address survive + # QoS, link state and the PCI address survive self.assertEqual(second.find("bandwidth/outbound").get("average"), "1000") self.assertEqual(second.find("link").get("state"), "down") self.assertEqual(second.find("address").get("bus"), "0x02") diff --git a/vrtManager/test_connection.py b/vrtManager/test_connection.py index acfb1063..8dc82ae8 100644 --- a/vrtManager/test_connection.py +++ b/vrtManager/test_connection.py @@ -1,4 +1,4 @@ -"""R-09: reachability probe and connections that do not block each other.""" +"""Reachability probe and connections that do not block each other.""" import socket import threading diff --git a/vrtManager/test_iso_media.py b/vrtManager/test_iso_media.py index 9c15d1f6..f46d42ec 100644 --- a/vrtManager/test_iso_media.py +++ b/vrtManager/test_iso_media.py @@ -25,7 +25,7 @@ def vm(active): class IsoMediaTestCase(unittest.TestCase): - """R-12: media change goes through updateDeviceFlags for the right CD-ROM.""" + """Media change goes through updateDeviceFlags for the right CD-ROM.""" def updates(self, inst): return [ diff --git a/vrtManager/test_persistent_edits.py b/vrtManager/test_persistent_edits.py index 89af7769..33636a02 100644 --- a/vrtManager/test_persistent_edits.py +++ b/vrtManager/test_persistent_edits.py @@ -16,7 +16,7 @@ DOMAIN = """vm131072131072< class PersistentEditsTestCase(unittest.TestCase): - """R-01/R-02: edits read the persistent definition with secrets.""" + """Edits read the persistent definition with secrets.""" def test_edits_read_the_persistent_secure_definition(self): edits = { diff --git a/vrtManager/test_xml_safety.py b/vrtManager/test_xml_safety.py index 84679803..d96b41e5 100644 --- a/vrtManager/test_xml_safety.py +++ b/vrtManager/test_xml_safety.py @@ -170,7 +170,7 @@ class TestXmlSafety(unittest.TestCase): inst._defineXML.assert_not_called() def test_internal_snapshot_never_rewrites_a_pflash_loader(self): - # R-13: libvirt decides; the definition is not switched to rom. + # libvirt decides; the definition is not switched to rom. inst = wvmInstance.__new__(wvmInstance) inst.get_status = MagicMock(return_value=5) inst._XMLDesc = MagicMock( @@ -187,7 +187,7 @@ class TestXmlSafety(unittest.TestCase): class TestCloneRollback(unittest.TestCase): - """R-08: a failed clone removes only the volumes it created.""" + """A failed clone removes only the volumes it created.""" def test_copies_are_removed_when_the_definition_fails(self): import libvirt diff --git a/webvirtcloud/test_authorization_matrix.py b/webvirtcloud/test_authorization_matrix.py index 566b10ac..e746c677 100644 --- a/webvirtcloud/test_authorization_matrix.py +++ b/webvirtcloud/test_authorization_matrix.py @@ -1,5 +1,5 @@ """ -Authorization matrix (ROADMAP Wave 0 item 5, S-09/S-10). +Authorization matrix. Walks every named URL pattern and checks that an authenticated user without any relation to a VM or compute cannot reach it, unless the URL is in the @@ -32,7 +32,7 @@ ALLOWED_FOR_ANY_USER = { "index": "landing page", "instances:index": "lists only the user's own instances", "accounts:login": "login page", - "accounts:email_otp": "part of the login flow (S-12 tracks its own issues)", + "accounts:email_otp": "part of the login flow (its own issues are tracked separately)", "accounts:logout": "logout", "accounts:profile": "the user's own profile", "accounts:ssh_key_create": "the user's own SSH keys", @@ -40,31 +40,31 @@ ALLOWED_FOR_ANY_USER = { "rest_framework:login": "DRF browsable API login", "rest_framework:logout": "DRF browsable API logout", "console": "renders an error without a valid token; access is checked per VM", - "ds_openstack_index": "static cloud-init datasource index (F-14)", + "ds_openstack_index": "static cloud-init datasource index", # Meant for VMs: answers for the VM whose name matches the reverse DNS of - # the client IP. The design is broken and tracked as F-14. - "ds_openstack_metadata": "cloud-init datasource keyed by client IP (F-14)", - "ds_openstack_userdata": "cloud-init datasource keyed by client IP (F-14)", + # the client IP. The design is broken and needs a redesign. + "ds_openstack_metadata": "cloud-init datasource keyed by client IP", + "ds_openstack_userdata": "cloud-init datasource keyed by client IP", "instance-list": "API: filtered to the user's own instances", "compute-instance-list": "API: filtered to the user's own instances", "instance-flavor-list": "API: flavor catalogue", "instance-flavor-detail": "API: flavor catalogue", - "schema": "OpenAPI schema (SERVE_PERMISSIONS is S-21, Wave 3)", - "schema-json": "OpenAPI schema (SERVE_PERMISSIONS is S-21, Wave 3)", - "schema-redoc": "API docs (SERVE_PERMISSIONS is S-21, Wave 3)", - "schema-swagger-ui": "API docs (SERVE_PERMISSIONS is S-21, Wave 3)", + "schema": "OpenAPI schema (SERVE_PERMISSIONS not restricted yet)", + "schema-json": "OpenAPI schema (SERVE_PERMISSIONS not restricted yet)", + "schema-redoc": "API docs (SERVE_PERMISSIONS not restricted yet)", + "schema-swagger-ui": "API docs (SERVE_PERMISSIONS not restricted yet)", } # URL name -> why an anonymous visitor may reach it. Everything else must # redirect to the login page. ALLOWED_FOR_ANONYMOUS = { "accounts:login": "login page", - "accounts:email_otp": "part of the login flow (S-12 tracks its own issues)", + "accounts:email_otp": "part of the login flow (its own issues are tracked separately)", "rest_framework:login": "DRF browsable API login page", - "schema": "OpenAPI schema (SERVE_PERMISSIONS is S-21, Wave 3)", - "schema-json": "OpenAPI schema (SERVE_PERMISSIONS is S-21, Wave 3)", - "schema-redoc": "API docs (SERVE_PERMISSIONS is S-21, Wave 3)", - "schema-swagger-ui": "API docs (SERVE_PERMISSIONS is S-21, Wave 3)", + "schema": "OpenAPI schema (SERVE_PERMISSIONS not restricted yet)", + "schema-json": "OpenAPI schema (SERVE_PERMISSIONS not restricted yet)", + "schema-redoc": "API docs (SERVE_PERMISSIONS not restricted yet)", + "schema-swagger-ui": "API docs (SERVE_PERMISSIONS not restricted yet)", } # Endpoints that expose a VM's console (or its VNC password) and therefore