From 11348b2c375cf94f43aee943b3b221f3ef8baa5c Mon Sep 17 00:00:00 2001 From: catborise Date: Mon, 26 Oct 2026 12:12:39 +0300 Subject: [PATCH] fix(instances): Guest Info says when the agent fails and keeps what it answered When the guest agent failed, the Guest Info section stayed empty with no word: the request's error answer was not handled. An agent without the time zone or host name command lost the OS details it had answered too. The section now shows the agent's error, and a missing command leaves out only its own details. --- instances/templates/instance.html | 20 +++++++++++--------- instances/templates/instances/info_tab.html | 1 + vrtManager/instance.py | 6 ++++-- vrtManager/tests/test_interface_addresses.py | 13 +++++++++++++ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/instances/templates/instance.html b/instances/templates/instance.html index 98fa3e07..55888d45 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -438,15 +438,17 @@ } function load_osinfo() { $.getJSON("{% url 'instances:osinfo' instance.id %}", function (data) { - $.each(data, function() { - $('#oshostname').text(data['host-name']); - $('#osname').text(data.id); - $('#osprettyname').text(data['pretty-name']); - $('#oskernelrelease').text(data['kernel-release']); - $('#oskernelversion').text(data['kernel-version']); - $('#osversion').text(data.version); - $('#ostimezone').text(data.zone + " / " + data.offset); - }) + $('#osinfo-error').addClass('d-none'); + $('#oshostname').text(data['host-name'] || ''); + $('#osname').text(data.id || ''); + $('#osprettyname').text(data['pretty-name'] || ''); + $('#oskernelrelease').text(data['kernel-release'] || ''); + $('#oskernelversion').text(data['kernel-version'] || ''); + $('#osversion').text(data.version || ''); + $('#ostimezone').text(data.zone ? data.zone + " / " + data.offset : ''); + }).fail(function (xhr) { + var error = xhr.responseJSON && xhr.responseJSON.error; + $('#osinfo-error').text(error || "{% trans 'The guest agent did not answer' %}").removeClass('d-none'); }); } diff --git a/instances/templates/instances/info_tab.html b/instances/templates/instances/info_tab.html index 24853cad..0779a916 100644 --- a/instances/templates/instances/info_tab.html +++ b/instances/templates/instances/info_tab.html @@ -1,6 +1,7 @@ {% load i18n %}
+
{% trans "Hostname" %}
diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 0c5f0b95..ee5767be 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -389,8 +389,10 @@ class wvmInstance(wvmConnect): def osinfo(self): info = agent_command(self.instance, "guest-get-osinfo") - info.update(agent_command(self.instance, "guest-get-timezone")) - info.update(agent_command(self.instance, "guest-get-host-name")) + # an agent without one of these commands still gives the rest + for command in ("guest-get-timezone", "guest-get-host-name"): + with contextlib.suppress(libvirtError): + info.update(agent_command(self.instance, command)) return info def start(self, flags=0): diff --git a/vrtManager/tests/test_interface_addresses.py b/vrtManager/tests/test_interface_addresses.py index ab234890..cb107650 100644 --- a/vrtManager/tests/test_interface_addresses.py +++ b/vrtManager/tests/test_interface_addresses.py @@ -71,6 +71,19 @@ class OsInfoTestCase(unittest.TestCase): self.assertEqual(inst.osinfo(), {"kernel-release": "6.12", "zone": "UTC", "host-name": "web"}) self.assertEqual({c.args[2] for c in agent.call_args_list}, {10}) + def test_a_command_the_agent_lacks_leaves_out_only_its_details(self): + inst = wvmInstance.__new__(wvmInstance) + inst.instance = MagicMock() + + def agent(dom, cmd, timeout, flags): + if json.loads(cmd)["execute"] == "guest-get-timezone": + raise libvirtError("The command guest-get-timezone has not been found") + return json.dumps({"return": {"guest-get-osinfo": {"id": "alma"}, "guest-get-host-name": {"host-name": "web"}}[ + json.loads(cmd)["execute"]]}) + + with patch.object(module, "qemuAgentCommand", side_effect=agent): + self.assertEqual(inst.osinfo(), {"id": "alma", "host-name": "web"}) + if __name__ == "__main__": unittest.main()