1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-09 19:56:48 +00:00

fix(logs): failures name their job, VM and user; the new VM form shows a list it could not load

- A failed cancel hook logged "worker task cancel failed": it now names
  the job, its kind, resource and user, with the traceback for a fault
  of the panel.
- novncd logged "Console connection failed" without the VM or the user.
- django-axes wrote four INFO lines a login ("Reset 0 access
  attempts"...); logins are on the Logs page, so it logs warnings only.
- The new VM form's machine types and disk buses answered 200 with an
  empty object when libvirt failed, and nothing was logged: the list
  stayed empty, the form could not go on and said nothing. They answer
  400 with the error, as the pool's volume list does, the warning is
  logged with the compute, and the form's lists show an error they get
  with the page's messages.
This commit is contained in:
catborise 2026-11-06 23:14:08 +03:00
parent 432b1505b3
commit 6abea495f1
14 changed files with 155 additions and 40 deletions

View file

@ -25,6 +25,7 @@ from websockify import ProxyRequestHandler, WebSocketProxy # noqa: E402
from console.sshtunnels import open_tunnel, tunnel_target # noqa: E402
from console.tokens import ACCESS_CHECK, authorize, may_still_open, session_user_id # noqa: E402
from logs.audit import write # noqa: E402
from operations.utils import safe_text, traceback_of # noqa: E402
from vrtManager.connection import CONN_SOCKET, CONN_SSH, CONNECT_TIMEOUT # noqa: E402
from vrtManager.util import is_loopback # noqa: E402
from webvirtcloud.settings import WS_HOST, WS_PORT # noqa: E402
@ -120,7 +121,7 @@ class ConsoleClient:
logging.warning("Console connection without a token in its websocket URL")
return
user = None
instance = user = None
try:
instance, user = authorize(token, "vnc")
# a token read from a log or a URL is no use without its user's session
@ -133,7 +134,9 @@ class ConsoleClient:
write(user.username if user else "", "-", "", f"VNC console refused: {e}", False, address)
return
except Exception as e:
logging.warning("Console connection failed: %s", e)
# the VM and its user, as the refusal above; a fault of the panel with its traceback, without secrets
logging.warning("Console connection to VM %s for %s failed: %s%s", instance.name if instance else "-",
user.username if user else "-", safe_text(e), traceback_of(e))
return
logging.debug(
"Console of %s@%s (type %s): %s:%s, socket %s",

View file

@ -17,6 +17,7 @@ from django.core.signing import TimestampSigner
from django.conf import settings
from django.test import TestCase, override_settings
from instances.models import Instance
from libvirt import libvirtError
from console.tests.daemons import novncd_mod
ROOT = Path(__file__).resolve().parent.parent.parent
@ -63,6 +64,31 @@ class NovncdDaemonLogicTestCase(TestCase):
self.assertEqual(opts.host, "192.168.1.100")
self.assertEqual(opts.port, 7070)
@patch.object(novncd_mod, "get_connection_infos")
def test_a_console_that_cannot_be_reached_is_logged_with_its_vm_and_user(self, mock_get_info):
mock_get_info.side_effect = libvirtError("Domain not found")
self.authorize.return_value[0].name = "vm-alpha"
handler = self.ConsoleClient()
handler.path = "/novncd/?token=1-uuid"
with self.assertLogs(level="WARNING") as logs:
handler._new_client(socket_factory=MagicMock())
self.assertEqual(logs.output, ["WARNING:root:Console connection to VM vm-alpha for vnc-user failed: Domain not found"])
@patch.object(novncd_mod, "get_connection_infos")
def test_a_fault_of_the_panel_is_logged_with_its_traceback_without_secrets(self, mock_get_info):
try:
raise RuntimeError("password=review-dummy-secret")
except RuntimeError as cause:
mock_get_info.side_effect = OSError("console setup failed")
mock_get_info.side_effect.__cause__ = cause
handler = self.ConsoleClient()
handler.path = "/novncd/?token=1-uuid"
with self.assertLogs(level="WARNING") as logs:
handler._new_client(socket_factory=MagicMock())
self.assertIn("Traceback", logs.output[0])
self.assertIn("password=***", logs.output[0])
self.assertNotIn("review-dummy-secret", logs.output[0])
@patch.object(novncd_mod, "get_connection_infos")
def test_a_cookie_does_not_choose_the_console(self, mock_get_info):
# another tab's console in a cookie: the URL's own token is used