From bb6598d2f9973440018b257f6402c0ad0db60f16 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Fri, 9 Feb 2024 07:09:47 +0000
Subject: [PATCH 1/6] Add initial functions to collect VM usage data
---
.../dynamix.vm.manager/include/libvirt.php | 9 ++-
.../include/libvirt_helpers.php | 77 +++++++++++++++++++
2 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/emhttp/plugins/dynamix.vm.manager/include/libvirt.php b/emhttp/plugins/dynamix.vm.manager/include/libvirt.php
index 3436482b9..b5566a6b7 100644
--- a/emhttp/plugins/dynamix.vm.manager/include/libvirt.php
+++ b/emhttp/plugins/dynamix.vm.manager/include/libvirt.php
@@ -1694,8 +1694,8 @@
else {
$doms = libvirt_list_domains($this->conn);
foreach ($doms as $dom) {
- $tmp = $this->domain_get_name($dom);
- $ret[$tmp] = libvirt_domain_get_info($dom);
+ $tmp = $this->get_domain_object($dom);
+ $ret[$dom] = libvirt_domain_get_info($tmp);
}
}
@@ -1771,6 +1771,11 @@
return ($tmp) ? $tmp : $this->_set_last_error();
}
+ function domain_get_all_domain_stats() {
+ $tmp = libvirt_connect_get_all_domain_stats($this->conn);
+ return ($tmp) ? $tmp : $this->_set_last_error();
+ }
+
function domain_start($dom) {
$dom=$this->get_domain_object($dom);
if ($dom) {
diff --git a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
index b8b66d638..79de185b5 100644
--- a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
+++ b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
@@ -2528,4 +2528,81 @@ function addtemplatexml($post) {
return $reply;
}
+function get_vm_usage_stats($collectcpustats = true,$collectdiskstats = true,$collectnicstats = true, $collectmemstats = true) {
+ global $lv, $vmusagestats;
+
+ $hostcpus = $lv->host_get_node_info();
+ $timestamp = time();
+ $allstats=$lv->domain_get_all_domain_stats();
+
+ foreach ($allstats as $vm => $data) {
+ $state = $data["state.state"];
+ # CPU Metrics
+ $cpuTime = 0;
+ $cpuHostPercent = 0;
+ $cpuGuestPercent = 0;
+ $cpuTimeAbs = $data["cpu.time"];
+ if ($state == 1 && $collectcpustats == true) {
+ $guestcpus = $data["vcpu.current"];
+ $cpuTime = $cpuTimeAbs - $vmusagestats[$vm]["cpuTimeAbs"];
+ $pcentbase = ((($cpuTime) * 100.0) / ((($timestamp) - $vmusagestats[$vm]["timestamp"] ) * 1000.0 * 1000.0 * 1000.0));
+ $cpuHostPercent = round($pcentbase / $hostcpus['cpus'],1);
+ $cpuGuestPercent = round($pcentbase / $guestcpus, 1) ;
+ $cpuHostPercent = max(0.0, min(100.0, $cpuHostPercent));
+ $cpuGuestPercent = max(0.0, min(100.0, $cpuGuestPercent));
+ }
+
+ # Memory Metrics
+ if ($state == 1 && $collectmemstats) {
+ $currentmem = $data["balloon.current"];
+ $unusedmem = $data["balloon.unused"];
+ $meminuse = $currentmem - $unusedmem;
+ } else $currentmem = $meminuse = 0;
+
+ # Disk
+ if ($state == 1 && $collectdiskstats) {
+ $disknum = $data["block.count"];
+ $rd=$wr=$i=0;
+ for ($i = 0; $i < $disknum; $i++) {
+ if ($data["block.$i.name"] == "hda" || $data["block.$i.name"] == "hdb") continue;
+ $rd += $data["block.$i.rd.bytes"] ;
+ $wr += $data["block.$i.wr.bytes"] ;
+ }
+ $rdrate = ($rd - $vmusagestats[$vm]['rdp'])/1024;
+ $wrrate = ($wr - $vmusagestats[$vm]['wrp'])/1024;
+ } else $rdrate=$wrrate=0;
+
+ # Net
+ if ($state == 1 && $collectnicstats) {
+ $nicnum = $data["net.count"];
+ $rx=$tx=$i=0;
+ for ($i = 0; $i < $nicnum; $i++) {
+ $rx += $data["net.$i.rx.bytes"] ;
+ $tx += $data["net.$i.tx.bytes"] ;
+ }
+ $rxrate = round(($rx - $vmusagestats[$vm]['rxp'])/1024,0);
+ $txrate = round(($tx - $vmusagestats[$vm]['txp'])/1024,0);
+ } else $rxrate=$txrate=0;
+
+ $vmusagestats[$vm] = [
+ "cpuTime" => $cpuTime,
+ "cpuTimeAbs" => $cpuTimeAbs,
+ "cpuhost" => $cpuHostPercent,
+ "cpuguest" => $cpuGuestPercent,
+ "timestamp" => $timestamp,
+ "mem" => $meminuse,
+ "maxmem" => $currentmem,
+ "rxrate" => $rxrate,
+ "rxp" => $rx,
+ "txrate" => $txrate,
+ "txp" => $tx,
+ "rdp" => $rd,
+ "rdrate" => $rdrate,
+ "wrp" => $wr,
+ "wrrate" => $wrrate,
+ "state" => $state,
+ ];
+ }
+}
+
?>
From 71f655cd05506d3f53d26222fe0b5a8b6161bc46 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Sun, 11 Feb 2024 15:22:22 +0000
Subject: [PATCH 2/6] Add Stats page
---
.../dynamix.vm.manager/VMUsageStats.page | 41 ++++++++
.../include/libvirt_helpers.php | 8 +-
.../plugins/dynamix.vm.manager/nchan/vm_usage | 94 +++++++++++++++++++
3 files changed, 139 insertions(+), 4 deletions(-)
create mode 100644 emhttp/plugins/dynamix.vm.manager/VMUsageStats.page
create mode 100644 emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
diff --git a/emhttp/plugins/dynamix.vm.manager/VMUsageStats.page b/emhttp/plugins/dynamix.vm.manager/VMUsageStats.page
new file mode 100644
index 000000000..4a75e8180
--- /dev/null
+++ b/emhttp/plugins/dynamix.vm.manager/VMUsageStats.page
@@ -0,0 +1,41 @@
+Menu="VMs:0"
+Title="VM Usage Statisics"
+Cond="exec(\"grep -o '^SERVICE=.enable' /boot/config/domain.cfg 2>/dev/null\")"
+Nchan="vm_usage:stop"
+---
+
+
+$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
+?>
+
+ _(Name)_ _(Guest CPU)_ _(Host CPU)_ _(Memory)_ _(Disk IO)_ _(Network IO)_
+
+
+
+
+
\ No newline at end of file
diff --git a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
index 79de185b5..c870c97ba 100644
--- a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
+++ b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
@@ -2568,8 +2568,8 @@ function get_vm_usage_stats($collectcpustats = true,$collectdiskstats = true,$co
$rd += $data["block.$i.rd.bytes"] ;
$wr += $data["block.$i.wr.bytes"] ;
}
- $rdrate = ($rd - $vmusagestats[$vm]['rdp'])/1024;
- $wrrate = ($wr - $vmusagestats[$vm]['wrp'])/1024;
+ $rdrate = ($rd - $vmusagestats[$vm]['rdp']);
+ $wrrate = ($wr - $vmusagestats[$vm]['wrp']);
} else $rdrate=$wrrate=0;
# Net
@@ -2580,8 +2580,8 @@ function get_vm_usage_stats($collectcpustats = true,$collectdiskstats = true,$co
$rx += $data["net.$i.rx.bytes"] ;
$tx += $data["net.$i.tx.bytes"] ;
}
- $rxrate = round(($rx - $vmusagestats[$vm]['rxp'])/1024,0);
- $txrate = round(($tx - $vmusagestats[$vm]['txp'])/1024,0);
+ $rxrate = round(($rx - $vmusagestats[$vm]['rxp']),0);
+ $txrate = round(($tx - $vmusagestats[$vm]['txp']),0);
} else $rxrate=$txrate=0;
$vmusagestats[$vm] = [
diff --git a/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage b/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
new file mode 100644
index 000000000..cf700aae4
--- /dev/null
+++ b/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
@@ -0,0 +1,94 @@
+#!/usr/bin/php -q
+
+
+$docroot = '/usr/local/emhttp';
+$varroot = '/var/local/emhttp';
+$md5_old = -1;
+
+require_once "$docroot/webGui/include/Helpers.php";
+require_once "$docroot/webGui/include/publish.php";
+require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
+global $vmusagestats;
+extract(parse_plugin_cfg('dynamix',true));
+get_vm_usage_stats();
+sleep(1);
+
+
+// add translations
+$_SERVER['REQUEST_URI'] = 'dashboard';
+$login_locale = _var($display,'locale');
+require_once "$docroot/webGui/include/Translations.php";
+
+// remember current language
+$locale_init = $locale;
+
+function update_translation($locale) {
+ global $docroot,$language;
+ $language = [];
+ if ($locale) {
+ $text = "$docroot/languages/$locale/translations.txt";
+ if (file_exists($text)) {
+ $store = "$docroot/languages/$locale/translations.dot";
+ if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
+ $language = unserialize(file_get_contents($store));
+ }
+ $text = "$docroot/languages/$locale/dashboard.txt";
+ if (file_exists($text)) {
+ $store = "$docroot/languages/$locale/dashboard.dot";
+ if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
+ $language = array_merge($language,unserialize(file_get_contents($store)));
+ }
+ }
+}
+
+while (true) {
+
+ extract(parse_plugin_cfg('dynamix',true));
+ if (_var($display,'locale') != $locale_init) {
+ $locale_init = _var($display,'locale');
+ update_translation($locale_init);
+ }
+
+ get_vm_usage_stats();
+ $echo = [];
+ $echo = [];
+ $ts = $time1 - $time0;
+ $echodata = "";
+ $running = 0;
+ foreach ($vmusagestats as $vm => $vmdata) {
+
+ if ($vmdata['state'] == 1) {
+ $running++;
+ $echodata .= "$vm " ;
+ #".$vmdata['cpuguest']."% ".$vmdata['cpuhost']."% ";
+ $echodata .= " ".$vmdata['cpuguest']."%
";
+ $echodata .= "".$vmdata['cpuhost']."%
";
+ $echodata .= my_scale($vmdata['mem'],$unit)."$unit / ".my_scale($vmdata['maxmem'],$unit)."$unit ";
+ $echodata .= _("Read").": ".my_scale($vmdata['rxrate'],$unit)."$unit/s "._("Write").": ".my_scale($vmdata['txrate'],$unit)."$unit/s ";
+ $echodata .= _("RX").": ".my_scale($vmdata['rdrate'],$unit)."$unit/s "._("TX").": ".my_scale($vmdata['wrrate'],$unit)."$unit/s ";
+ }
+ $echo = $echodata ;
+ }
+ if ($running < 1) $echo = ""._("No VMs Running")." ";
+
+ $echo = json_encode($echo);
+ $md5_new = md5($echo,true);
+ if ($md5_new !== $md5_old) {
+ $md5_old = publish('vm_usage',$echo)!==false ? $md5_new : -1;
+ $time0 = $time1;
+ }
+
+ sleep(3);
+}
+?>
From 954969c2e483faa54c44ec810710d39ad7c33c1b Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Sun, 11 Feb 2024 15:25:18 +0000
Subject: [PATCH 3/6] Make script executable
---
emhttp/plugins/dynamix.vm.manager/nchan/vm_usage | 0
1 file changed, 0 insertions(+), 0 deletions(-)
mode change 100644 => 100755 emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
diff --git a/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage b/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
old mode 100644
new mode 100755
From eef77dc64de8d2fc39fc5e1f13113d8b4059cb20 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Sun, 11 Feb 2024 18:34:13 +0000
Subject: [PATCH 4/6] Fix graphs
---
emhttp/plugins/dynamix.vm.manager/nchan/vm_usage | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage b/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
index cf700aae4..f72b094d6 100755
--- a/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
+++ b/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
@@ -71,12 +71,11 @@ while (true) {
if ($vmdata['state'] == 1) {
$running++;
$echodata .= "$vm " ;
- #".$vmdata['cpuguest']."% ".$vmdata['cpuhost']."% ";
- $echodata .= " ".$vmdata['cpuguest']."%
";
- $echodata .= "".$vmdata['cpuhost']."%
";
+ $echodata .= " ".$vmdata['cpuguest']."%
";
+ $echodata .= "".$vmdata['cpuhost']."%
";
$echodata .= my_scale($vmdata['mem'],$unit)."$unit / ".my_scale($vmdata['maxmem'],$unit)."$unit ";
- $echodata .= _("Read").": ".my_scale($vmdata['rxrate'],$unit)."$unit/s "._("Write").": ".my_scale($vmdata['txrate'],$unit)."$unit/s ";
- $echodata .= _("RX").": ".my_scale($vmdata['rdrate'],$unit)."$unit/s "._("TX").": ".my_scale($vmdata['wrrate'],$unit)."$unit/s ";
+ $echodata .= _("Read").": ".my_scale($vmdata['rdrate'],$unit)."$unit/s "._("Write").": ".my_scale($vmdata['wrrate'],$unit)."$unit/s";
+ $echodata .= _("RX").": ".my_scale($vmdata['rxrate'],$unit)."$unit/s "._("TX").": ".my_scale($vmdata['txrate'],$unit)."$unit/s ";
}
$echo = $echodata ;
}
From 034b41726e32e15d581aaf1b07e7549e751eb40f Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Sun, 11 Feb 2024 18:42:11 +0000
Subject: [PATCH 5/6] Update vm_usage
---
emhttp/plugins/dynamix.vm.manager/nchan/vm_usage | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage b/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
index f72b094d6..031ac219e 100755
--- a/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
+++ b/emhttp/plugins/dynamix.vm.manager/nchan/vm_usage
@@ -79,7 +79,7 @@ while (true) {
}
$echo = $echodata ;
}
- if ($running < 1) $echo = ""._("No VMs Running")." ";
+ if ($running < 1) $echo = ""._('No VMs running')." ";
$echo = json_encode($echo);
$md5_new = md5($echo,true);
From 9f3047d2ff8283f04e034f8ea60516ae54ddf4ca Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Mon, 12 Feb 2024 22:04:37 +0000
Subject: [PATCH 6/6] Add options to settings to disable/enable + refresh rate
---
emhttp/languages/en_US/helptext.txt | 8 ++++++++
emhttp/plugins/dynamix.vm.manager/VMSettings.page | 13 +++++++++++++
emhttp/plugins/dynamix.vm.manager/VMUsageStats.page | 2 +-
emhttp/plugins/dynamix.vm.manager/nchan/vm_usage | 6 +++++-
4 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/emhttp/languages/en_US/helptext.txt b/emhttp/languages/en_US/helptext.txt
index 1de7bb595..0604c2d21 100644
--- a/emhttp/languages/en_US/helptext.txt
+++ b/emhttp/languages/en_US/helptext.txt
@@ -1675,6 +1675,14 @@ For setting the console options to show on context menus. Web will show only inb
Virtual Manager Remote Viewer will only show the Remote Viewer option. Both will show both Web and Remote Viewer.
:end
+:vms_usage_help:
+Show metrics for CPU both guest and host percentage, memory, disk io and network io.
+:end
+
+:vms_usage_timer_help:
+Setting in seconds for metrics refresh time.
+:end
+
:vms_acs_override_help:
*PCIe ACS override* allows various hardware components to expose themselves as isolated devices.
Typically it is sufficient to isolate *Downstream* ports.
diff --git a/emhttp/plugins/dynamix.vm.manager/VMSettings.page b/emhttp/plugins/dynamix.vm.manager/VMSettings.page
index 68246e5df..ea87c12a5 100644
--- a/emhttp/plugins/dynamix.vm.manager/VMSettings.page
+++ b/emhttp/plugins/dynamix.vm.manager/VMSettings.page
@@ -183,6 +183,19 @@ _(Console Options)_:
:vms_console_help:
+_(Show VM Usage)_:
+:
+ =mk_option($domain_cfg['USAGE'], 'N', _('Disabled'))?>
+ =mk_option($domain_cfg['USAGE'], 'Y', _('Enabled'))?>
+
+
+:vms_usage_help:
+
+_(VM Usage refresh timer(seconds))_:
+:
+
+:vms_usage_timer_help:
+
_(PCIe ACS override)_:
: >
= mk_option($pcie_acs_override, '', _('Disabled'))?>
diff --git a/emhttp/plugins/dynamix.vm.manager/VMUsageStats.page b/emhttp/plugins/dynamix.vm.manager/VMUsageStats.page
index 4a75e8180..b87c75e57 100644
--- a/emhttp/plugins/dynamix.vm.manager/VMUsageStats.page
+++ b/emhttp/plugins/dynamix.vm.manager/VMUsageStats.page
@@ -1,7 +1,7 @@
Menu="VMs:0"
Title="VM Usage Statisics"
-Cond="exec(\"grep -o '^SERVICE=.enable' /boot/config/domain.cfg 2>/dev/null\")"
Nchan="vm_usage:stop"
+Cond="exec(\"grep -o '^USAGE=.Y' /boot/config/domain.cfg 2>/dev/null\") && is_file('/var/run/libvirt/libvirtd.pid')"
---