mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-11 12:46:49 +00:00
feat(instances): a VM's stats in one grid, its logs a switch away
The Stats tab stacked one large card per chart, so a VM with a few devices made a long page, and its "Real Time" and "Logs" sub-tabs were shown to every user although only a superuser may read the logs. The owner chose the layout from rendered options: a state line, CPU and memory side by side, one chart per NIC and disk below, each with its latest reading next to its title, and a small Graphs/Logs switch for superusers. Codex reviewed the tab; this is fixed: - Memory is shown in MiB (it was labelled MB), and its axis grows to the RSS when the RSS passes the balloon size instead of clipping it. - The CPU reading says it is of the host's CPUs. - A NIC is titled by its MAC, not an invented "eth0", and its readings are matched to its chart by the MAC: they were matched by position, so removing a NIC while the page was open moved the next one's readings into its chart. - A VM that is not running says nothing is measured. - The logs load whenever the Logs view is shown, by keyboard too; an empty answer says "None" and a failed one says so, instead of an empty table. The tab shows the latest 50 rows, with a link to all of the VM's rows on the Logs page. - The VM's header shows memory in MiB; it said MB.
This commit is contained in:
parent
b72e9b1442
commit
5e93920d78
9 changed files with 193 additions and 110 deletions
|
|
@ -1378,7 +1378,7 @@ class wvmInstance(wvmConnect):
|
|||
and target.get("dev")
|
||||
):
|
||||
disks.append(target.get("dev")) # blockStats takes the target name
|
||||
# all NICs, in the order of the page's charts; one without a target is not measured
|
||||
# all NICs, known by their MAC; one without a target is not measured
|
||||
nics = []
|
||||
for nic in tree.findall("devices/interface"):
|
||||
mac, target = nic.find("mac"), nic.find("target")
|
||||
|
|
@ -1391,7 +1391,7 @@ class wvmInstance(wvmConnect):
|
|||
return {
|
||||
"cpu": 0,
|
||||
"disks": [{"dev": dev, "rd": 0, "wr": 0} for dev in disks],
|
||||
"nics": [{"dev": i, "rx": 0, "tx": 0} for i in range(len(nics))],
|
||||
"nics": [{"mac": mac, "rx": 0, "tx": 0} for mac, target in nics],
|
||||
}
|
||||
|
||||
key = [self.instance.ID(), self.host_info[2], disks, nics]
|
||||
|
|
@ -1418,8 +1418,8 @@ class wvmInstance(wvmConnect):
|
|||
for dev, old, new in zip(disks, before[1], after[1])
|
||||
],
|
||||
"nics": [
|
||||
{"dev": i, "rx": _rate(old[0], new[0], seconds, 8), "tx": _rate(old[1], new[1], seconds, 8)}
|
||||
for i, (old, new) in enumerate(zip(before[2], after[2]))
|
||||
{"mac": mac, "rx": _rate(old[0], new[0], seconds, 8), "tx": _rate(old[1], new[1], seconds, 8)}
|
||||
for (mac, target), old, new in zip(nics, before[2], after[2])
|
||||
],
|
||||
"window": seconds,
|
||||
}
|
||||
|
|
@ -1436,7 +1436,7 @@ class wvmInstance(wvmConnect):
|
|||
usage = rates(before, counters) or {
|
||||
"cpu": None,
|
||||
"disks": [{"dev": dev, "rd": None, "wr": None} for dev in disks],
|
||||
"nics": [{"dev": i, "rx": None, "tx": None} for i in range(len(nics))],
|
||||
"nics": [{"mac": mac, "rx": None, "tx": None} for mac, target in nics],
|
||||
"window": None,
|
||||
}
|
||||
usage["sample"] = {"key": key, "counters": counters}
|
||||
|
|
|
|||
|
|
@ -86,8 +86,8 @@ class UsageTestCase(unittest.TestCase):
|
|||
self.assertEqual(
|
||||
result["disks"], [{"dev": "vda", "rd": 1000, "wr": 3000}, {"dev": "vdb", "rd": 2000, "wr": 6000}]
|
||||
)
|
||||
# bits; the NIC without a target is not measured and keeps its place
|
||||
self.assertEqual(result["nics"], [{"dev": 0, "rx": None, "tx": None}, {"dev": 1, "rx": 800, "tx": 400}])
|
||||
# bits; the NIC without a target is not measured
|
||||
self.assertEqual(result["nics"], [{"mac": "52:54:00:00:00:01", "rx": None, "tx": None}, {"mac": "52:54:00:00:00:02", "rx": 800, "tx": 400}])
|
||||
self.assertEqual(result["sample"]["counters"][3], 101.0)
|
||||
|
||||
def test_since_the_previous_sample_without_waiting(self):
|
||||
|
|
@ -98,7 +98,7 @@ class UsageTestCase(unittest.TestCase):
|
|||
self.time.sleep.assert_not_called()
|
||||
self.assertEqual((result["cpu"], result["window"]), (12.5, 9.5))
|
||||
self.assertEqual(result["disks"][1], {"dev": "vdb", "rd": 2000, "wr": 6000}) # per second
|
||||
self.assertEqual(result["nics"][1], {"dev": 1, "rx": 800, "tx": 400})
|
||||
self.assertEqual(result["nics"][1], {"mac": "52:54:00:00:00:02", "rx": 800, "tx": 400})
|
||||
self.assertEqual(result["sample"]["counters"][3], 110.5)
|
||||
|
||||
def test_a_sample_of_another_run_host_or_devices_is_not_used(self):
|
||||
|
|
@ -169,7 +169,7 @@ class UsageTestCase(unittest.TestCase):
|
|||
{
|
||||
"cpu": 0,
|
||||
"disks": [{"dev": "vda", "rd": 0, "wr": 0}, {"dev": "vdb", "rd": 0, "wr": 0}],
|
||||
"nics": [{"dev": 0, "rx": 0, "tx": 0}, {"dev": 1, "rx": 0, "tx": 0}],
|
||||
"nics": [{"mac": "52:54:00:00:00:01", "rx": 0, "tx": 0}, {"mac": "52:54:00:00:00:02", "rx": 0, "tx": 0}],
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue