From f5d204e5b273562a6eb4759d80492e816af71719 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Sun, 28 Sep 2025 09:54:41 +0100
Subject: [PATCH 01/63] Add power placeholder and Split physical CPUS
---
emhttp/plugins/dynamix/DashStats.page | 34 +++++++++++++---------
emhttp/plugins/dynamix/include/Helpers.php | 17 +++++++++++
2 files changed, 37 insertions(+), 14 deletions(-)
diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page
index b959f60bf..68ca33c79 100755
--- a/emhttp/plugins/dynamix/DashStats.page
+++ b/emhttp/plugins/dynamix/DashStats.page
@@ -94,7 +94,7 @@ foreach ($devs as $disk) {
}
$array_percent = number_format(100*$array_used/($array_size ?: 1),1,$dot,'');
-exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list|sort -nu', $cpus);
+$cpus=get_cpu_packages();
$wg_up = $wireguard ? exec("wg show interfaces") : '';
$wg_up = $wg_up ? explode(' ',$wg_up) : [];
$up = count($wg_up);
@@ -345,6 +345,9 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
|
+
+ _(Total Power)_: N/A
+
@@ -395,20 +398,23 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
|
- foreach ($cpus as $pair) {
- [$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair);
- echo "";
- if ($is_intel_cpu && count($core_types) > 0)
- $core_type = "({$core_types[$cpu1]})";
- else
- $core_type = "";
+ foreach ($cpus as $cpu_index=>$package) {
+ echo "| "._("Physical")." CPU $cpu_index "._("Power").": N/A |
";
+ foreach ($package as $pair) {
+ [$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair);
+ echo "";
+ if ($is_intel_cpu && count($core_types) > 0)
+ $core_type = "({$core_types[$cpu1]})";
+ else
+ $core_type = "";
- if ($cpu2)
- echo "| CPU $cpu1 $core_type - HT $cpu2 0% 0%
| ";
- else
- echo "CPU $cpu1 $core_type0%
| ";
- echo "
";
- }
+ if ($cpu2)
+ echo "CPU $cpu1 $core_type - HT $cpu2 0% 0%
| ";
+ else
+ echo "CPU $cpu1 $core_type0%
| ";
+ echo "";
+ }
+ }
?>
|
diff --git a/emhttp/plugins/dynamix/include/Helpers.php b/emhttp/plugins/dynamix/include/Helpers.php
index 5c3dfacc5..75b152448 100644
--- a/emhttp/plugins/dynamix/include/Helpers.php
+++ b/emhttp/plugins/dynamix/include/Helpers.php
@@ -857,4 +857,21 @@ HTML;
return $html;
}
+
+function get_cpu_packages(string $separator = ','): array {
+ $packages = [];
+ foreach (glob("/sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list") as $path) {
+ $pkg_id = (int)file_get_contents(dirname($path) . "/physical_package_id");
+ $siblings = str_replace(",", $separator, trim(file_get_contents($path)));
+ if (!in_array($siblings, $packages[$pkg_id] ?? [])) {
+ $packages[$pkg_id][] = $siblings;
+ }
+ }
+ foreach ($packages as &$list) {
+ $keys = array_map(fn($s) => (int)explode($separator, $s)[0], $list);
+ array_multisort($keys, SORT_ASC, SORT_NUMERIC, $list);
+ }
+ unset($list);
+ return $packages;
+}
?>
From e64211b8e5d083f99c0dbfae6ec8319b0c752e91 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Sun, 28 Sep 2025 10:11:26 +0100
Subject: [PATCH 02/63] Add icon to total power.
---
emhttp/plugins/dynamix/DashStats.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page
index 68ca33c79..f03d557a9 100755
--- a/emhttp/plugins/dynamix/DashStats.page
+++ b/emhttp/plugins/dynamix/DashStats.page
@@ -346,7 +346,7 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
|
- _(Total Power)_: N/A
+ _(Total Power)_: N/A
From e4ed5896f6e5fd3c7022f47c3ca0f91b1a6c0f27 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Sun, 28 Sep 2025 10:17:16 +0100
Subject: [PATCH 03/63] Fix placeholder index
---
emhttp/plugins/dynamix/DashStats.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page
index f03d557a9..42ccf33a8 100755
--- a/emhttp/plugins/dynamix/DashStats.page
+++ b/emhttp/plugins/dynamix/DashStats.page
@@ -399,7 +399,7 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
foreach ($cpus as $cpu_index=>$package) {
- echo " | "._("Physical")." CPU $cpu_index "._("Power").": N/A |
";
+ echo ""._("Physical")." CPU $cpu_index "._("Power").": N/A | ";
foreach ($package as $pair) {
[$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair);
echo "";
From b54bb1a16472b415ff49655d0cb6c9e151fe058f Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Thu, 16 Oct 2025 10:23:31 -0400
Subject: [PATCH 04/63] Refactor fixed listing height processing
---
.../dynamix.vm.manager/VMMachines.page | 59 +++++++++++--------
1 file changed, 33 insertions(+), 26 deletions(-)
diff --git a/emhttp/plugins/dynamix.vm.manager/VMMachines.page b/emhttp/plugins/dynamix.vm.manager/VMMachines.page
index b6da578d3..f39f20da4 100755
--- a/emhttp/plugins/dynamix.vm.manager/VMMachines.page
+++ b/emhttp/plugins/dynamix.vm.manager/VMMachines.page
@@ -3,6 +3,7 @@ Title="Virtual Machines"
Tag="columns"
Cond="is_file('/var/run/libvirt/libvirtd.pid')"
Markdown="false"
+Focus="tableHeaderResize"
---
- fillAvailableHeight({
- targetElementSelector: '.js-fill-available-height',
- elementSelectorsForHeight: [
- '.js-actions',
- '#kvm_table thead',
- ],
- elementSelectorsForSpacing: [
- '#kvm_table',
- ],
- manualSpacingOffset: 50, // without this, the main content will still be scrollable by like 20px
- });
- // Handle table header fixed positioning after resize
- function tableHeaderResize() {
- $('#kvm_table thead,#kvm_table tbody').removeClass('fixed');
- $('#kvm_table thead tr th').each(function(){$(this).width($(this).width());});
- $('#kvm_table tbody tr td').each(function(){$(this).width($(this).width());});
- $('#kvm_table thead,#kvm_table tbody').not('.child').addClass('fixed');
- }
tableHeaderResize();
+
+ // Handle table header resizing when window is resized with debouncing
+ var resizeTimeout;
$(window).bind('resize',function(){
- tableHeaderResize();
- });
- // Handle table header resizing when tab is clicked
- 2):?>
- $("#tab1").on('click',function(){
+ clearTimeout(resizeTimeout);
+ resizeTimeout = setTimeout(function(){
tableHeaderResize();
- });
-
-
+ }, 150);
+ });
+
});
}
+
+// Handle table header fixed positioning after resize
+// Only applicable to listing height: fixed
+// Function needs to exist in the global scope due to "Focus" attribute in the page
+function tableHeaderResize() {
+
+ fillAvailableHeight({
+ targetElementSelector: '.js-fill-available-height',
+ elementSelectorsForHeight: [
+ '.js-actions',
+ '#kvm_table thead',
+ ],
+ elementSelectorsForSpacing: [
+ '#kvm_table',
+ ],
+ manualSpacingOffset: 50, // without this, the main content will still be scrollable by like 20px
+ });
+ $('#kvm_table thead,#kvm_table tbody').removeClass('fixed');
+ $('#kvm_table thead tr th').each(function(){$(this).width($(this).width());});
+ $('#kvm_table tbody tr td').each(function(){$(this).width($(this).width());});
+ $('#kvm_table thead,#kvm_table tbody').not('.child').addClass('fixed');
+
+}
+
$(function() {
$color = strpos($msg, "rror:")!==false ? 'red-text':'green-text'?>
From 7e88002238d97e2d92d2f57686e8af117a62c7d7 Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Thu, 16 Oct 2025 11:07:43 -0400
Subject: [PATCH 05/63] Fix respawning of events
---
emhttp/plugins/dynamix.vm.manager/VMMachines.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix.vm.manager/VMMachines.page b/emhttp/plugins/dynamix.vm.manager/VMMachines.page
index f39f20da4..69e450aa7 100755
--- a/emhttp/plugins/dynamix.vm.manager/VMMachines.page
+++ b/emhttp/plugins/dynamix.vm.manager/VMMachines.page
@@ -467,7 +467,7 @@ function loadlist() {
// Handle table header resizing when window is resized with debouncing
var resizeTimeout;
- $(window).bind('resize',function(){
+ $(window).off('resize.vmTableResize').on('resize.vmTableResize',function(){
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function(){
tableHeaderResize();
From 2f66cd3d021f225767ed0bc62520b01a7f1b6ee8 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Tue, 21 Oct 2025 20:30:49 +0100
Subject: [PATCH 06/63] Changes for power and temp.
---
emhttp/plugins/dynamix/DashStats.page | 96 ++++++++++++++++++++++++++-
1 file changed, 93 insertions(+), 3 deletions(-)
diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page
index 42ccf33a8..09b63a7d2 100755
--- a/emhttp/plugins/dynamix/DashStats.page
+++ b/emhttp/plugins/dynamix/DashStats.page
@@ -346,11 +346,13 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
|
- _(Total Power)_: N/A
+ _(Total)_ _(Power)_: N/A
+
-
+ _(Temp)_:
+
_(Load)_:
0%
@@ -399,7 +401,11 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
foreach ($cpus as $cpu_index=>$package) {
- echo " | "._("Physical")." CPU $cpu_index "._("Power").": N/A |
";
+ if (count($cpus) > 1) {
+ echo ""._("Physical")." CPU $cpu_index "._("Power").": N/A ";
+ if (count($cpus)>1) echo _("Temp").": N/A";
+ echo " | ";
+ }
foreach ($package as $pair) {
[$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair);
echo "";
@@ -1696,6 +1702,36 @@ function addChartNet(rx, tx) {
txTimeSeries.append(now, Math.floor(tx / 1000));
}
+function updateCPUPower() {
+ if (!cpupower) return;
+
+ // Update total power
+ const totalEl = document.getElementById('cpu-total-power');
+ const totalPower = cpupower.totalPower ?? 0;
+ if (totalEl) {
+ totalEl.innerHTML = ` _(Total)_ _(Power)_: ${totalPower.toFixed(2)} W`;
+ }
+
+ // Update each core's span
+ const cpuspower = cpupower.power ?? [];
+ cpuspower.forEach((power, index) => {
+ const coreEl = document.getElementById(`cpu-power${index}`);
+ const coreTempEl = document.getElementById(`cpu-temp${index}`);
+ if (coreEl) {
+ coreEl.innerHTML = `${power.toFixed(2)} W`;
+ }
+ });
+
+ const cpustemps = cpupower.temp ?? [];
+ cpustemps.forEach((temp, index) => {
+ const coreTempEl = document.getElementById(`cpu-temp${index}`);
+ if (coreTempEl) {
+ coreTempEl.innerHTML = `${temp.toFixed(0)} C`;;
+ }
+ });
+
+}
+
// Cache for last values to avoid unnecessary DOM updates
var lastCpuValues = {
load: -1,
@@ -2771,6 +2807,60 @@ $(function() {
setTimeout(function() {
// Charts initialized
},500);
+
+
+
+ // Start GraphQL CPU power subscription with retry logic
+ let cpuInitPWRAttempts = 0, cpuPWRRetryMs = 100;
+ function initPwrCpuSubscription() {
+
+
+ if (window.gql && window.apolloClient) {
+ // Define the subscription query when GraphQL is available
+ // corepower has the temps currently.
+ CPU_POWER_SUBSCRIPTION = window.gql(`
+ subscription SystemMetricsCpuTelemetry {
+ systemMetricsCpuTelemetry {
+ totalPower,
+ power,
+ temp,
+ }
+ }
+ `);
+ cpuPowerSubscription = window.apolloClient.subscribe({
+ query: CPU_POWER_SUBSCRIPTION
+ }).subscribe({
+ next: (result) => {
+
+
+ if (result.data?.systemMetricsCpuTelemetry){
+ cpupower = result.data.systemMetricsCpuTelemetry;
+
+ updateCPUPower();
+ }
+ },
+ error: (err) => {
+ console.error('CPU power subscription error:', err);
+ // Try to resubscribe with capped backoff
+ if (cpuPowerSubscription) { try { cpuPowerSubscription.unsubscribe(); } catch(e){} }
+ setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 5000));
+ }
+ });
+ } else {
+ // Retry with capped backoff if GraphQL client not ready
+ cpuPWRInitAttempts++;
+ setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 2000));
+ }
+ }
+ initPwrCpuSubscription();
+ // Cleanup GraphQL subscription on page unload
+ $(window).on('beforeunload', function() {
+ if (cpuPowerSubscription) {
+ cpuPowerSubscription.unsubscribe();
+ }
+ });
+
+
// Cleanup GraphQL subscription on page unload
$(window).on('beforeunload', function() {
From e799c9144d925a3a0c139fec038f12f93a7f3185 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Wed, 22 Oct 2025 21:53:07 +0100
Subject: [PATCH 07/63] Layout change and fixes
---
emhttp/plugins/dynamix/DashStats.page | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page
index c4b08fbde..c2863c20e 100755
--- a/emhttp/plugins/dynamix/DashStats.page
+++ b/emhttp/plugins/dynamix/DashStats.page
@@ -95,6 +95,7 @@ foreach ($devs as $disk) {
$array_percent = number_format(100*$array_used/($array_size ?: 1),1,$dot,'');
$cpus=get_cpu_packages();
+$cpus[] = ["16,17"];
$wg_up = $wireguard ? exec("wg show interfaces") : '';
$wg_up = $wg_up ? explode(' ',$wg_up) : [];
$up = count($wg_up);
@@ -351,11 +352,11 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
|
- _(Total)_ _(Power)_: N/A
+ _(Total)_ _(Power)_: N/A
- _(Temp)_:
+ _(Temperature)_: N/A
@@ -403,12 +404,12 @@ switch ($themeHelper->getThemeName()) { // $themeHelper set in DefaultPageLayout
|
-
+
foreach ($cpus as $cpu_index=>$package) {
if (count($cpus) > 1) {
- echo "| "._("Physical")." CPU $cpu_index "._("Power").": N/A ";
- if (count($cpus)>1) echo _("Temp").": N/A";
+ echo " | "._("Physical")." CPU $cpu_index "._("Power").": N/A ";
+ if (count($cpus)>1) echo " "._("Temperature").": N/A";
echo " |
";
}
foreach ($package as $pair) {
@@ -1453,6 +1454,8 @@ var startup = true;
var stopgap = ' |
';
var recall = null;
var recover = null;
+var tempunit="=_var($display,'unit','C');?>";
+
// Helper function to calculate millisPerPixel based on container width
function getMillisPerPixel(timeInSeconds, containerId) {
@@ -1721,7 +1724,6 @@ function updateCPUPower() {
const cpuspower = cpupower.power ?? [];
cpuspower.forEach((power, index) => {
const coreEl = document.getElementById(`cpu-power${index}`);
- const coreTempEl = document.getElementById(`cpu-temp${index}`);
if (coreEl) {
coreEl.innerHTML = `${power.toFixed(2)} W`;
}
@@ -1731,7 +1733,11 @@ function updateCPUPower() {
cpustemps.forEach((temp, index) => {
const coreTempEl = document.getElementById(`cpu-temp${index}`);
if (coreTempEl) {
- coreTempEl.innerHTML = `${temp.toFixed(0)} C`;;
+ tempdisplay = temp.toFixed(0);
+ if (tempunit === "F") {
+ tempdisplay = ((temp.toFixed(0))* 9 / 5) + 32;
+ }
+ coreTempEl.innerHTML = Math.round(tempdisplay)+` °`+tempunit;;
}
});
@@ -2853,7 +2859,7 @@ $(function() {
});
} else {
// Retry with capped backoff if GraphQL client not ready
- cpuPWRInitAttempts++;
+ cpuPInitPWRAttempts++;
setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 2000));
}
}
From 5083f85d8a298ba71f1cf4ca9a5a6aef70f9102c Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Wed, 22 Oct 2025 22:00:41 +0100
Subject: [PATCH 08/63] Remove test code
---
emhttp/plugins/dynamix/DashStats.page | 2 --
emhttp/plugins/dynamix/include/cpulist.php | 22 ++++++++++++++++++++++
2 files changed, 22 insertions(+), 2 deletions(-)
create mode 100644 emhttp/plugins/dynamix/include/cpulist.php
diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page
index c2863c20e..1259ff11b 100755
--- a/emhttp/plugins/dynamix/DashStats.page
+++ b/emhttp/plugins/dynamix/DashStats.page
@@ -95,7 +95,6 @@ foreach ($devs as $disk) {
$array_percent = number_format(100*$array_used/($array_size ?: 1),1,$dot,'');
$cpus=get_cpu_packages();
-$cpus[] = ["16,17"];
$wg_up = $wireguard ? exec("wg show interfaces") : '';
$wg_up = $wg_up ? explode(' ',$wg_up) : [];
$up = count($wg_up);
@@ -1456,7 +1455,6 @@ var recall = null;
var recover = null;
var tempunit="=_var($display,'unit','C');?>";
-
// Helper function to calculate millisPerPixel based on container width
function getMillisPerPixel(timeInSeconds, containerId) {
var container = document.getElementById(containerId);
diff --git a/emhttp/plugins/dynamix/include/cpulist.php b/emhttp/plugins/dynamix/include/cpulist.php
new file mode 100644
index 000000000..8d1db3573
--- /dev/null
+++ b/emhttp/plugins/dynamix/include/cpulist.php
@@ -0,0 +1,22 @@
+ (int)explode($separator, $s)[0], $list);
+ array_multisort($keys, SORT_ASC, SORT_NUMERIC, $list);
+ }
+ unset($list);
+
+ return $packages;
+}
From 117a49491a2595f3f18267461baf18d9357df8b7 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Thu, 23 Oct 2025 12:09:13 +0100
Subject: [PATCH 09/63] Update DashStats.page
---
emhttp/plugins/dynamix/DashStats.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/DashStats.page b/emhttp/plugins/dynamix/DashStats.page
index 1259ff11b..60fbc8f96 100755
--- a/emhttp/plugins/dynamix/DashStats.page
+++ b/emhttp/plugins/dynamix/DashStats.page
@@ -2857,7 +2857,7 @@ $(function() {
});
} else {
// Retry with capped backoff if GraphQL client not ready
- cpuPInitPWRAttempts++;
+ cpuInitPWRAttempts++;
setTimeout(initPwrCpuSubscription, Math.min(cpuPWRRetryMs *= 2, 2000));
}
}
From 1ad896a5bed4433ccf238bb929d1b50a60ee330a Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Fri, 24 Oct 2025 10:29:45 +0100
Subject: [PATCH 10/63] Fix: Disk creation error for VM change
---
emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
index bde11c7c7..c9f721932 100644
--- a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
+++ b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
@@ -255,7 +255,7 @@ if (isset($_POST['updatevm'])) {
$xml = str_replace($olduuid,$newuuid,$xml);
} else {
// form view
- if ($error = create_vdisk($_POST) === false) {
+ if (($error = create_vdisk($_POST)) === false) {
$arrExistingConfig = custom::createArray('domain',$strXML);
$arrUpdatedConfig = custom::createArray('domain',$lv->config_to_xml($_POST));
if ($debug) {
From c3d88a7dd80d746c66e97e347c493ce4221da863 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Sun, 26 Oct 2025 17:10:27 +0000
Subject: [PATCH 11/63] Bug: Cdrom bus IDE for Q35 is invalid set to SATA
---
.../plugins/dynamix.vm.manager/templates/Custom.form.php | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
index bde11c7c7..6e08339a4 100644
--- a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
+++ b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
@@ -2484,6 +2484,13 @@ $(function() {
});
+ $("#vmform #domain_machine").change(function changeMachineEvent(){
+ // Cdrom Bus: select IDE for i440 and SATA for q35
+ if ($(this).val().indexOf('q35') != -1) {
+ $('#vmform .cdrom_bus').val('sata');
+ }
+ });
+
$("#vmform .domain_vcpu").change(function changeVCPUEvent(){
var $cores = $("#vmform .domain_vcpu:checked");
if ($cores.length < 1) {
From 5fb682c2253147c7c17b4e3b6d5190b938e92cec Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Tue, 28 Oct 2025 00:16:51 -0700
Subject: [PATCH 12/63] Fix: ZFS allocation profile always shows 1 vdev only
---
emhttp/plugins/dynamix/DeviceInfo.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/DeviceInfo.page b/emhttp/plugins/dynamix/DeviceInfo.page
index 88df03ea2..9cb8bc83a 100755
--- a/emhttp/plugins/dynamix/DeviceInfo.page
+++ b/emhttp/plugins/dynamix/DeviceInfo.page
@@ -346,7 +346,7 @@ function selectDiskFsWidthZFS(slots,init) {
}));
}
}
- selected_width = slots;
+ if (selected_width == 0) selected_width = width;
}
$('#diskFsWidth').val(selected_width);
}
From a593173c7d67245df65083c0536740b0123080ef Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Tue, 28 Oct 2025 00:18:59 -0700
Subject: [PATCH 13/63] fix: Docker NAT failure due to missing br_netfilter
---
etc/rc.d/rc.docker | 2 ++
1 file changed, 2 insertions(+)
diff --git a/etc/rc.d/rc.docker b/etc/rc.d/rc.docker
index d5ba3bf29..90cec4c68 100755
--- a/etc/rc.d/rc.docker
+++ b/etc/rc.d/rc.docker
@@ -243,6 +243,8 @@ container_add_route(){
docker_network_start(){
log "Starting network..."
+ # ensure br_netfilter modules is loaded, re: https://github.com/moby/moby/issues/48948
+ modprobe br_netfilter
# create list of possible custom networks
EXCLUDE=; INCLUDE=$(ls --indicator-style=none $SYSTEM | awk '/^br[0-9]+/' ORS=' ')
while IFS=$'\n' read -r NETWORK; do
From a7885eca09135d3e59d490dcdfe58d5c8543c21b Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Wed, 29 Oct 2025 01:35:23 -0700
Subject: [PATCH 14/63] Fix: ZFS allocation profile always shows 1 vdev only
---
emhttp/plugins/dynamix/DeviceInfo.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/DeviceInfo.page b/emhttp/plugins/dynamix/DeviceInfo.page
index 9cb8bc83a..35c2def45 100755
--- a/emhttp/plugins/dynamix/DeviceInfo.page
+++ b/emhttp/plugins/dynamix/DeviceInfo.page
@@ -344,9 +344,9 @@ function selectDiskFsWidthZFS(slots,init) {
value: width,
text: _(sprintf('%s '+label+' of %s devices',groups,width)),
}));
+ if (selected_width == 0) selected_width = width;
}
}
- if (selected_width == 0) selected_width = width;
}
$('#diskFsWidth').val(selected_width);
}
From 1018244c1f0d525b3a9229b7ea597d315cc77120 Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Wed, 29 Oct 2025 01:35:59 -0700
Subject: [PATCH 15/63] fix: mover run not logged when schedulled
---
sbin/mover | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/sbin/mover b/sbin/mover
index 62a2afb2c..7ddffb89e 100755
--- a/sbin/mover
+++ b/sbin/mover
@@ -36,13 +36,13 @@ move() {
start() {
if [ -f $PIDFILE ]; then
if ps h $(cat $PIDFILE) | grep mover ; then
- echo "mover: already running"
+ echo "mover: already running" >&2
exit 1
fi
fi
echo $$ >/var/run/mover.pid
- echo "mover: started"
+ echo "mover: started" >&2
shopt -s nullglob
@@ -108,7 +108,7 @@ start() {
done
rm -f $PIDFILE
- echo "mover: finished"
+ echo "mover: finished" >&2
}
empty() {
@@ -116,13 +116,13 @@ empty() {
if [ -f $PIDFILE ]; then
if ps h $(cat $PIDFILE) | grep mover ; then
- echo "mover: already running"
+ echo "mover: already running" >&2
exit 1
fi
fi
echo $$ >/var/run/mover.pid
- echo "mover: started"
+ echo "mover: started" >&2
shopt -s nullglob
@@ -145,7 +145,7 @@ empty() {
fi
rm -f $PIDFILE
- echo "mover: finished"
+ echo "mover: finished" >&2
}
killtree() {
From 160575b8a8815c8614e46e6f242ea050d02d0c6d Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Fri, 31 Oct 2025 08:32:51 +0000
Subject: [PATCH 16/63] Fix for systems not reporting correctly in DMI.
---
emhttp/plugins/dynamix/include/Helpers.php | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/emhttp/plugins/dynamix/include/Helpers.php b/emhttp/plugins/dynamix/include/Helpers.php
index 61a84cab9..e07536cbc 100644
--- a/emhttp/plugins/dynamix/include/Helpers.php
+++ b/emhttp/plugins/dynamix/include/Helpers.php
@@ -565,8 +565,7 @@ function dmidecode($key, $n, $all=true) {
}
function is_intel_cpu() {
- $cpu = dmidecode('Processor Information','4',0);
- $cpu_vendor = $cpu['Manufacturer'] ?? "";
+ $cpu_vendor = exec("grep -Pom1 '^model name\s+:\s*\K.+' /proc/cpuinfo") ?? "";
$is_intel_cpu = stripos($cpu_vendor, "intel") !== false ? true : false;
return $is_intel_cpu;
}
From 80173a4f87dcd99208b8ca389e888fb2b0058b20 Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Fri, 31 Oct 2025 12:01:22 +0000
Subject: [PATCH 17/63] Code rabbit suggestions
---
emhttp/plugins/dynamix/include/Helpers.php | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/emhttp/plugins/dynamix/include/Helpers.php b/emhttp/plugins/dynamix/include/Helpers.php
index e07536cbc..e0113c730 100644
--- a/emhttp/plugins/dynamix/include/Helpers.php
+++ b/emhttp/plugins/dynamix/include/Helpers.php
@@ -565,9 +565,8 @@ function dmidecode($key, $n, $all=true) {
}
function is_intel_cpu() {
- $cpu_vendor = exec("grep -Pom1 '^model name\s+:\s*\K.+' /proc/cpuinfo") ?? "";
- $is_intel_cpu = stripos($cpu_vendor, "intel") !== false ? true : false;
- return $is_intel_cpu;
+ $cpu_vendor_check = exec("grep -Pom1 '^model name\s+:\s*\K.+' /proc/cpuinfo") ?? "";
+ return stripos($cpu_vendor_check, "intel") !== false;
}
// Load saved PCI data
From 6a90e9d10c8a507bb9e1f7db313dae5b51ad08b1 Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Tue, 4 Nov 2025 15:58:24 -0800
Subject: [PATCH 18/63] fix: DeviceInfo: should not show 'Pool Device Status'
section if pool not Mounted
---
emhttp/plugins/dynamix/DeviceInfo.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/DeviceInfo.page b/emhttp/plugins/dynamix/DeviceInfo.page
index 35c2def45..e07dd554b 100755
--- a/emhttp/plugins/dynamix/DeviceInfo.page
+++ b/emhttp/plugins/dynamix/DeviceInfo.page
@@ -990,7 +990,7 @@ _(Critical disk utilization threshold)_ (%):
-
+
_(Pool Device Status)_
From 8e9b892145fed857cab70c272a07a66530d88b7b Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Tue, 4 Nov 2025 15:58:53 -0800
Subject: [PATCH 19/63] fix: rc.S.cont: restore /etc/machine-id from
/boot/config/machine-id file
---
etc/rc.d/rc.S.cont | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/etc/rc.d/rc.S.cont b/etc/rc.d/rc.S.cont
index f5a4f954f..2e00799cb 100755
--- a/etc/rc.d/rc.S.cont
+++ b/etc/rc.d/rc.S.cont
@@ -12,6 +12,14 @@
# run & log functions
. /etc/rc.d/rc.runlog
+# LimeTech - restore machine-id
+SRC="/boot/config/machine-id"
+DEST="/etc/machine-id"
+if [[ ! -f "$SRC" ]] || ! grep -Eq '^[0-9a-f]{32}$' "$SRC" ; then
+ /usr/bin/dbus-uuidgen --ensure="$SRC"
+fi
+/usr/bin/install -m 0644 "$SRC" "$DEST"
+
# LimeTech - bind selected devices to vfio-pci
/usr/local/sbin/vfio-pci 1>/var/log/vfio-pci 2>/var/log/vfio-pci-errors
From 5e91b061229fdff739fe58302345a5e719efa02e Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Tue, 4 Nov 2025 22:20:36 -0500
Subject: [PATCH 20/63] Feat: Better identify safemode
---
emhttp/plugins/dynamix/ArrayOperation.page | 29 +++++++++++++++++--
.../plugins/dynamix/styles/default-base.css | 4 +++
2 files changed, 31 insertions(+), 2 deletions(-)
mode change 100644 => 100755 emhttp/plugins/dynamix/ArrayOperation.page
diff --git a/emhttp/plugins/dynamix/ArrayOperation.page b/emhttp/plugins/dynamix/ArrayOperation.page
old mode 100644
new mode 100755
index 74381e295..9434adc99
--- a/emhttp/plugins/dynamix/ArrayOperation.page
+++ b/emhttp/plugins/dynamix/ArrayOperation.page
@@ -348,8 +348,33 @@ function shutdown_now(form, cmd) {
$(form).append('');
switch (cmd) {
- case 'reboot': var text = "_(This will reboot the system)_"; break;
- case 'shutdown': var text = "_(This will shutdown the system)_"; break;
+ case 'reboot':
+ if ($('input[name="safemode"]').prop('checked')) {
+
+ $nginx = parse_ini_file("/var/local/emhttp/nginx.ini");
+ $tailscaleUI = false;
+ foreach ($nginx as $key => $value) {
+ if (stripos($key, 'tailscale') !== false && $value == $_SERVER['HTTP_HOST']) {
+ $tailscaleUI = true;
+ break;
+ }
+ }
+ ?>
+ var text = "_(This will reboot the system in safe mode)_\n\n";
+ var text = text.concat("_(No plugins will be loaded in safe mode.)_");
+ if (is_file("/var/log/plugins/tailscale.plg") || is_file("/var/log/plugins/tailscale-preview.plg")): ?>
+ var text = text.concat(" _(If you use Tailscale to access the GUI or services of the server, this access will be lost.)_");
+ if ($tailscaleUI): ?>
+ var text = text.concat("\n\n_(You are currently accessing the GUI of the server via Tailscale.)_");
+ endif; ?>
+ endif; ?>
+ } else {
+ var text = "_(This will reboot the system)_";
+ }
+ break;
+ case 'shutdown':
+ var text = "_(This will shutdown the system)_";
+ break;
}
swal({
title:"_(Proceed)_?",
diff --git a/emhttp/plugins/dynamix/styles/default-base.css b/emhttp/plugins/dynamix/styles/default-base.css
index 164202fdc..19d6a6a7e 100755
--- a/emhttp/plugins/dynamix/styles/default-base.css
+++ b/emhttp/plugins/dynamix/styles/default-base.css
@@ -1902,6 +1902,10 @@ span#wlan0 {
position: relative;
}
+.font-bold {
+ font-weight: bold;
+}
+
.font-mono {
font-family: bitstream, monospace;
}
From 8f64bd76837f4bd7b29bf0c5e538995857e4fb12 Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Wed, 5 Nov 2025 00:55:55 -0500
Subject: [PATCH 21/63] Check for access via connect remote
---
emhttp/plugins/dynamix/ArrayOperation.page | 23 ++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/emhttp/plugins/dynamix/ArrayOperation.page b/emhttp/plugins/dynamix/ArrayOperation.page
index 9434adc99..7abc578ce 100755
--- a/emhttp/plugins/dynamix/ArrayOperation.page
+++ b/emhttp/plugins/dynamix/ArrayOperation.page
@@ -353,27 +353,34 @@ function shutdown_now(form, cmd) {
$nginx = parse_ini_file("/var/local/emhttp/nginx.ini");
$tailscaleUI = false;
+ $connectRemote = false;
foreach ($nginx as $key => $value) {
- if (stripos($key, 'tailscale') !== false && $value == $_SERVER['HTTP_HOST']) {
+ if (strpos($key, 'NGINX_TAILSCALE') !== false && $value == $_SERVER['HTTP_HOST']) {
$tailscaleUI = true;
break;
}
+ if (strpos($key, 'NGINX_WANFQDN') !== false && $value == $_SERVER['HTTP_HOST']) {
+ $connectRemote = true;
+ break;
+ }
}
?>
- var text = "_(This will reboot the system in safe mode)_\n\n";
- var text = text.concat("_(No plugins will be loaded in safe mode.)_");
- if (is_file("/var/log/plugins/tailscale.plg") || is_file("/var/log/plugins/tailscale-preview.plg")): ?>
- var text = text.concat(" _(If you use Tailscale to access the GUI or services of the server, this access will be lost.)_");
+ var text = "_(This will reboot the server in safe mode.)_\n\n" + "_(No plugins will be loaded in safe mode.)_";
+ if (is_file("/var/log/plugins/tailscale.plg") || is_file("/var/log/plugins/tailscale-preview.plg" || is_file("/var/log/plugins/dynamix.unraid.net.plg"))): ?>
+ text += " _(If you use Tailscale or Unraid Connect Remote Access to access the webGUI or services of the server, this access will be lost.)_";
if ($tailscaleUI): ?>
- var text = text.concat("\n\n_(You are currently accessing the GUI of the server via Tailscale.)_");
+ text += "\n\n_(You are currently accessing the webGUI of the server via Tailscale.)_";
+ endif; ?>
+ if ($connectRemote): ?>
+ text += "\n\n_(You are currently accessing the webGUI of the server via Unraid Connect Remote Access.)_";
endif; ?>
endif; ?>
} else {
- var text = "_(This will reboot the system)_";
+ var text = "_(This will reboot the server.)_";
}
break;
case 'shutdown':
- var text = "_(This will shutdown the system)_";
+ var text = "_(This will shutdown the server.)_";
break;
}
swal({
From c66eb75876a1a8584ec890275abd327e17397159 Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Wed, 5 Nov 2025 01:09:11 -0500
Subject: [PATCH 22/63] Remove duplicated class
---
emhttp/plugins/dynamix/ArrayOperation.page | 4 ++--
emhttp/plugins/dynamix/styles/default-base.css | 4 ----
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/emhttp/plugins/dynamix/ArrayOperation.page b/emhttp/plugins/dynamix/ArrayOperation.page
index 7abc578ce..672f6edf2 100755
--- a/emhttp/plugins/dynamix/ArrayOperation.page
+++ b/emhttp/plugins/dynamix/ArrayOperation.page
@@ -369,10 +369,10 @@ function shutdown_now(form, cmd) {
if (is_file("/var/log/plugins/tailscale.plg") || is_file("/var/log/plugins/tailscale-preview.plg" || is_file("/var/log/plugins/dynamix.unraid.net.plg"))): ?>
text += " _(If you use Tailscale or Unraid Connect Remote Access to access the webGUI or services of the server, this access will be lost.)_";
if ($tailscaleUI): ?>
- text += "\n\n_(You are currently accessing the webGUI of the server via Tailscale.)_";
+ text += "\n\n_(You are currently accessing the webGUI of the server via Tailscale.)_";
endif; ?>
if ($connectRemote): ?>
- text += "\n\n_(You are currently accessing the webGUI of the server via Unraid Connect Remote Access.)_";
+ text += "\n\n_(You are currently accessing the webGUI of the server via Unraid Connect Remote Access.)_";
endif; ?>
endif; ?>
} else {
diff --git a/emhttp/plugins/dynamix/styles/default-base.css b/emhttp/plugins/dynamix/styles/default-base.css
index 19d6a6a7e..164202fdc 100755
--- a/emhttp/plugins/dynamix/styles/default-base.css
+++ b/emhttp/plugins/dynamix/styles/default-base.css
@@ -1902,10 +1902,6 @@ span#wlan0 {
position: relative;
}
-.font-bold {
- font-weight: bold;
-}
-
.font-mono {
font-family: bitstream, monospace;
}
From f988d26b419d1354f6e05e4b47597cc086713fb9 Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Wed, 5 Nov 2025 01:12:54 -0500
Subject: [PATCH 23/63] Update emhttp/plugins/dynamix/ArrayOperation.page
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
emhttp/plugins/dynamix/ArrayOperation.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/ArrayOperation.page b/emhttp/plugins/dynamix/ArrayOperation.page
index 672f6edf2..2dd90660a 100755
--- a/emhttp/plugins/dynamix/ArrayOperation.page
+++ b/emhttp/plugins/dynamix/ArrayOperation.page
@@ -366,7 +366,7 @@ function shutdown_now(form, cmd) {
}
?>
var text = "_(This will reboot the server in safe mode.)_\n\n" + "_(No plugins will be loaded in safe mode.)_";
- if (is_file("/var/log/plugins/tailscale.plg") || is_file("/var/log/plugins/tailscale-preview.plg" || is_file("/var/log/plugins/dynamix.unraid.net.plg"))): ?>
+ if (is_file("/var/log/plugins/tailscale.plg") || is_file("/var/log/plugins/tailscale-preview.plg") || is_file("/var/log/plugins/dynamix.unraid.net.plg")): ?>
text += " _(If you use Tailscale or Unraid Connect Remote Access to access the webGUI or services of the server, this access will be lost.)_";
if ($tailscaleUI): ?>
text += "\n\n_(You are currently accessing the webGUI of the server via Tailscale.)_";
From 6e3c618cfe67ed23b56914ffc2a21e8f0e21380d Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Wed, 5 Nov 2025 01:14:23 -0500
Subject: [PATCH 24/63] Update emhttp/plugins/dynamix/ArrayOperation.page
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
emhttp/plugins/dynamix/ArrayOperation.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/ArrayOperation.page b/emhttp/plugins/dynamix/ArrayOperation.page
index 2dd90660a..4f452b11f 100755
--- a/emhttp/plugins/dynamix/ArrayOperation.page
+++ b/emhttp/plugins/dynamix/ArrayOperation.page
@@ -351,7 +351,7 @@ function shutdown_now(form, cmd) {
case 'reboot':
if ($('input[name="safemode"]').prop('checked')) {
- $nginx = parse_ini_file("/var/local/emhttp/nginx.ini");
+ $nginx = @parse_ini_file("/var/local/emhttp/nginx.ini") ?: [];
$tailscaleUI = false;
$connectRemote = false;
foreach ($nginx as $key => $value) {
From a3679c55734b66fdf037aa5c3778204763580153 Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Thu, 6 Nov 2025 13:55:47 -0500
Subject: [PATCH 25/63] Fix/Feat: Re-add Join as notification agent
---
emhttp/plugins/dynamix/agents/Join.xml | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 emhttp/plugins/dynamix/agents/Join.xml
diff --git a/emhttp/plugins/dynamix/agents/Join.xml b/emhttp/plugins/dynamix/agents/Join.xml
new file mode 100644
index 000000000..19872f120
--- /dev/null
+++ b/emhttp/plugins/dynamix/agents/Join.xml
@@ -0,0 +1,25 @@
+
+ Join
+
+ API_KEY
+ TITLE
+ MESSAGE
+
+
+
From 0b7c2caf75ee6970884a2977b0a588997cf487ea Mon Sep 17 00:00:00 2001
From: ljm42
Date: Thu, 6 Nov 2025 12:43:55 -0700
Subject: [PATCH 26/63] Fix: remove special chars from notify subject
---
emhttp/plugins/dynamix/scripts/notify | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/emhttp/plugins/dynamix/scripts/notify b/emhttp/plugins/dynamix/scripts/notify
index 8a5adc246..3725fde2f 100755
--- a/emhttp/plugins/dynamix/scripts/notify
+++ b/emhttp/plugins/dynamix/scripts/notify
@@ -222,8 +222,8 @@ case 'add':
$archive = "{$archive}/".safe_filename("{$event}-{$ticket}.notify");
if (file_exists($archive)) break;
$entity = $overrule===false ? $notify[$importance] : $overrule;
- if (!$mailtest) file_put_contents($archive,"timestamp=$timestamp\nevent=$event\nsubject=$subject\ndescription=$description\nimportance=$importance\n".($message ? "message=".str_replace('\n','
',$message)."\n" : ""));
- if (($entity & 1)==1 && !$mailtest && !$noBrowser) file_put_contents($unread,"timestamp=$timestamp\nevent=$event\nsubject=$subject\ndescription=$description\nimportance=$importance\nlink=$link\n");
+ if (!$mailtest) file_put_contents($archive,"timestamp=$timestamp\nevent=$event\nsubject=".clean_subject($subject)."\ndescription=$description\nimportance=$importance\n".($message ? "message=".str_replace('\n','
',$message)."\n" : ""));
+ if (($entity & 1)==1 && !$mailtest && !$noBrowser) file_put_contents($unread,"timestamp=$timestamp\nevent=$event\nsubject=".clean_subject($subject)."\ndescription=$description\nimportance=$importance\nlink=$link\n");
if (($entity & 2)==2 || $mailtest) generate_email($event, clean_subject($subject), str_replace('
','. ',$description), $importance, $message, $recipients, $fqdnlink);
if (($entity & 4)==4 && !$mailtest) { if (is_array($agents)) {foreach ($agents as $agent) {exec("TIMESTAMP='$timestamp' EVENT=".escapeshellarg($event)." SUBJECT=".escapeshellarg(clean_subject($subject))." DESCRIPTION=".escapeshellarg($description)." IMPORTANCE=".escapeshellarg($importance)." CONTENT=".escapeshellarg($message)." LINK=".escapeshellarg($fqdnlink)." bash ".$agent);};}};
break;
From 8aa50db48dd99a5e923e493c9433389468752afc Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Thu, 6 Nov 2025 17:08:33 -0500
Subject: [PATCH 27/63] Fix: Agents dropdowns not working in tabbed mode
---
emhttp/plugins/dynamix/NotificationAgents.page | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/emhttp/plugins/dynamix/NotificationAgents.page b/emhttp/plugins/dynamix/NotificationAgents.page
index af6d65bf3..ffaf3da02 100644
--- a/emhttp/plugins/dynamix/NotificationAgents.page
+++ b/emhttp/plugins/dynamix/NotificationAgents.page
@@ -1,6 +1,7 @@
Menu="Notifications:3"
Title="Notification Agents"
Tag="rss-square"
+Focus="initDropdown"
---
-
-$('#tab3').bind({click:function(){initDropdown();}});
-$(function(){if ($('#tab3').is(':checked')) initDropdown();});
-
+
$(function(){initDropdown();});
-
if (!String.prototype.format) {
String.prototype.format = function() {
From d8acaad47fe51c6cd0ef5e9651948c20a63d1e60 Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Fri, 7 Nov 2025 01:29:43 -0500
Subject: [PATCH 28/63] Tweaks
---
emhttp/plugins/dynamix/NotificationAgents.page | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/NotificationAgents.page b/emhttp/plugins/dynamix/NotificationAgents.page
index ffaf3da02..28e178f66 100644
--- a/emhttp/plugins/dynamix/NotificationAgents.page
+++ b/emhttp/plugins/dynamix/NotificationAgents.page
@@ -4,7 +4,7 @@ Tag="rss-square"
Focus="initDropdown"
---
+ if (!$tabbed): ?>
$(function(){initDropdown();});
+ endif; ?>
if (!String.prototype.format) {
String.prototype.format = function() {
From bff2cc691c2afc91ea9b7ff1664326470d1ab01f Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Fri, 7 Nov 2025 01:45:34 -0500
Subject: [PATCH 29/63] Fix when reloading page with focus on agent
---
emhttp/plugins/dynamix/NotificationAgents.page | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/emhttp/plugins/dynamix/NotificationAgents.page b/emhttp/plugins/dynamix/NotificationAgents.page
index 28e178f66..b6ecebc35 100644
--- a/emhttp/plugins/dynamix/NotificationAgents.page
+++ b/emhttp/plugins/dynamix/NotificationAgents.page
@@ -25,6 +25,10 @@ var openPage = true;
if (!$tabbed): ?>
$(function(){initDropdown();});
+ else: ?>
+$(function(){
+ if ( $('#tab3').attr('checked') ) initDropdown();
+});
endif; ?>
if (!String.prototype.format) {
From 1312098d7b840cd788b8464adefb136d69608519 Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Fri, 7 Nov 2025 00:53:40 -0800
Subject: [PATCH 30/63] fix: remove '-e' test option from 'mover' script
---
sbin/mover | 74 +++++-------------------------------------------------
1 file changed, 6 insertions(+), 68 deletions(-)
diff --git a/sbin/mover b/sbin/mover
index 7ddffb89e..25107d999 100755
--- a/sbin/mover
+++ b/sbin/mover
@@ -28,9 +28,9 @@ CFGPATH="/boot/config/shares"
DEBUGGING=""
move() {
- find "$1" -depth 2>/dev/null | /usr/libexec/unraid/move $2 $DEBUGGING
+ find "$1" -depth 2>/dev/null | /usr/libexec/unraid/move $DEBUGGING
# second pass to clean up leftover empty directories
- find "$1" -depth -type d 2>/dev/null | /usr/libexec/unraid/move $2 $DEBUGGING
+ find "$1" -depth -type d 2>/dev/null | /usr/libexec/unraid/move $DEBUGGING
}
start() {
@@ -92,7 +92,7 @@ start() {
for SHAREPATH in /mnt/$DISK/* ; do
SHARE=$(basename "$SHAREPATH")
if [[ -d "$SHAREPATH" && -f "$CFGPATH/$SHARE.cfg" ]]; then
- move "$SHAREPATH" "-e"
+ move "$SHAREPATH"
fi
done
@@ -111,43 +111,6 @@ start() {
echo "mover: finished" >&2
}
-empty() {
- DISK="$1"
-
- if [ -f $PIDFILE ]; then
- if ps h $(cat $PIDFILE) | grep mover ; then
- echo "mover: already running" >&2
- exit 1
- fi
- fi
-
- echo $$ >/var/run/mover.pid
- echo "mover: started" >&2
-
- shopt -s nullglob
-
- # we can only empty share directories
- for SHAREPATH in /mnt/$DISK/* ; do
- SHARE=$(basename "$SHAREPATH")
- if [[ -d "$SHAREPATH" && -f "$CFGPATH/$SHARE.cfg" ]]; then
- move "$SHAREPATH" "-e"
- fi
- done
-
- # output list of files which could not be moved
- # use 'find' in case huge number of files left in /mnt/$DISK
- count=$(find /mnt/$DISK -mindepth 1 | wc -l)
- if [ "$count" -gt 0 ]; then
- find /mnt/$DISK -mindepth 1 -depth -printf 'move: %p Not moved\n' | head -n 100
- if [ "$count" -gt 100 ]; then
- echo "[output truncated to first 100 entries]"
- fi
- fi
-
- rm -f $PIDFILE
- echo "mover: finished" >&2
-}
-
killtree() {
local pid=$1 child
@@ -170,43 +133,18 @@ stop() {
# display usage and then exit
usage() {
- echo "Usage: $0 start [-e ]"
- echo " $0 stop|status"
- echo " must match pattern 'disk[0-9]*' and /mnt/ must be a mountpoint"
+ echo "Usage: $0 start|stop|status"
exit 1
}
-# validate disk name
-validate_disk() {
- if [[ ! "$1" =~ ^disk[0-9]+$ ]]; then
- echo "Error: must match pattern 'disk[0-9]+$'"
- usage
- fi
- if ! mountpoint --nofollow /mnt/$1 > /dev/null 2>&1; then
- echo "Error: nothing mounted at /mnt/$1"
- usage
- fi
-}
-
-if [ "$#" -lt 1 ]; then
+if [ "$#" -ne 1 ]; then
usage
exit 1
fi
case $1 in
start)
- if [ -z "$2" ]; then
- start
- elif [ "$2" == "-e" ]; then
- if [ -z "$3" ]; then
- usage
- else
- validate_disk "$3"
- empty "$3"
- fi
- else
- usage
- fi
+ start
;;
stop)
stop
From e4979bae63630e86a95aac02f95d535920d55ffc Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Sat, 8 Nov 2025 01:59:24 -0500
Subject: [PATCH 31/63] Fix Search & language sizing on sidebar theme
---
emhttp/plugins/dynamix.gui.search/sheets/gui_search.css | 1 +
emhttp/plugins/dynamix/styles/default-base.css | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
mode change 100644 => 100755 emhttp/plugins/dynamix.gui.search/sheets/gui_search.css
diff --git a/emhttp/plugins/dynamix.gui.search/sheets/gui_search.css b/emhttp/plugins/dynamix.gui.search/sheets/gui_search.css
old mode 100644
new mode 100755
index aaef0d82e..8788ebed8
--- a/emhttp/plugins/dynamix.gui.search/sheets/gui_search.css
+++ b/emhttp/plugins/dynamix.gui.search/sheets/gui_search.css
@@ -58,6 +58,7 @@
#guiSearchBoxSpan {
margin: 0;
padding: 0;
+ height: 18px !important;
}
#guiSearchBox {
position: relative;
diff --git a/emhttp/plugins/dynamix/styles/default-base.css b/emhttp/plugins/dynamix/styles/default-base.css
index 164202fdc..9bfce5361 100755
--- a/emhttp/plugins/dynamix/styles/default-base.css
+++ b/emhttp/plugins/dynamix/styles/default-base.css
@@ -2563,7 +2563,7 @@ div#title.ud {
padding: 0;
}
- .LanguageButton {
+ .Theme--nav-top .LanguageButton {
font-size: 12px !important;
} /* Fix Switch Language Being Cut-Off */
From c450daee2e69affb55cd96737a81732d01a91090 Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Sat, 8 Nov 2025 03:12:48 -0500
Subject: [PATCH 32/63] Feat: Add port checking for VNC and sane defaults
---
.../templates/Custom.form.php | 20 +++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
mode change 100644 => 100755 emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
diff --git a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
old mode 100644
new mode 100755
index 5f668838c..ddb47ab81
--- a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
+++ b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php
@@ -103,8 +103,8 @@ $arrConfigDefaults = [
'autoport' => 'yes',
'model' => 'qxl',
'keymap' => 'none',
- 'port' => -1 ,
- 'wsport' => -1,
+ 'port' => 5900,
+ 'wsport' => 5901,
'copypaste' => 'no',
'render' => 'auto',
'DisplayOptions' => ""
@@ -1325,9 +1325,9 @@ foreach ($arrConfig['shares'] as $i => $arrShare) {
?>
_(VM Console Port)_:
-
+
_(VM Console WS Port)_:
-
+
|
@@ -2088,6 +2088,18 @@ foreach ($arrConfig['evdev'] as $i => $arrEvdev) {
var storageType = "=get_storage_fstype($arrConfig['template']['storage']);?>";
var storageLoc = "=$arrConfig['template']['storage']?>";
+function checkVNCPorts() {
+ const port = $("#port").val();
+ const wsport = $("#wsport").val();
+ if (port < 5900 || port > 65535 || wsport < 5900 || wsport > 65535 || port == wsport) {
+ swal({
+ title: "_(Invalid Port)_",
+ text: "_(VNC/SPICE ports must be between 5900 and 65535, and cannot be equal to each other)_",
+ type: "error",
+ confirmButtonText: "_(Ok)_"
+ });
+ }
+}
function updateMAC(index, port) {
var wlan0 = '=$mac?>'; // mac address of wlan0
var mac = $('input[name="nic['+index+'][mac]"');
From 89afd5a8b20764470b1e1eeb890c36f195435f5f Mon Sep 17 00:00:00 2001
From: Pujit Mehrotra
Date: Sat, 8 Nov 2025 12:20:51 -0500
Subject: [PATCH 33/63] fix: quote ini string values produced by `notify`
script
this improves compatibility with other ini parsers, making it easier for
the api to parse notification data correctly.
---
emhttp/plugins/dynamix/scripts/notify | 61 +++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 4 deletions(-)
diff --git a/emhttp/plugins/dynamix/scripts/notify b/emhttp/plugins/dynamix/scripts/notify
index 3725fde2f..04372c5c1 100755
--- a/emhttp/plugins/dynamix/scripts/notify
+++ b/emhttp/plugins/dynamix/scripts/notify
@@ -104,6 +104,37 @@ function clean_subject($subject) {
return $subject;
}
+/**
+ * Wrap string values in double quotes for INI compatibility and escape quotes/backslashes.
+ * Numeric types remain unquoted so they can be parsed as-is.
+ */
+function ini_encode_value($value) {
+ if (is_int($value) || is_float($value)) return $value;
+ if (is_bool($value)) return $value ? 'true' : 'false';
+ $value = (string)$value;
+ return '"'.strtr($value, ["\\"=>"\\\\", '"' => '\\"']).'"';
+}
+
+function build_ini_string(array $data) {
+ $lines = [];
+ foreach ($data as $key => $value) {
+ $lines[] = "{$key}=".ini_encode_value($value);
+ }
+ return implode("\n", $lines)."\n";
+}
+
+/**
+ * Trims and unescapes strings (eg quotes, backslashes) if necessary.
+ */
+function ini_decode_value($value) {
+ $value = trim($value);
+ $length = strlen($value);
+ if ($length >= 2 && $value[0] === '"' && $value[$length-1] === '"') {
+ return stripcslashes(substr($value, 1, -1));
+ }
+ return $value;
+}
+
// start
if ($argc == 1) exit(usage());
@@ -222,8 +253,27 @@ case 'add':
$archive = "{$archive}/".safe_filename("{$event}-{$ticket}.notify");
if (file_exists($archive)) break;
$entity = $overrule===false ? $notify[$importance] : $overrule;
- if (!$mailtest) file_put_contents($archive,"timestamp=$timestamp\nevent=$event\nsubject=".clean_subject($subject)."\ndescription=$description\nimportance=$importance\n".($message ? "message=".str_replace('\n','
',$message)."\n" : ""));
- if (($entity & 1)==1 && !$mailtest && !$noBrowser) file_put_contents($unread,"timestamp=$timestamp\nevent=$event\nsubject=".clean_subject($subject)."\ndescription=$description\nimportance=$importance\nlink=$link\n");
+ $cleanSubject = clean_subject($subject);
+ $archiveData = [
+ 'timestamp' => $timestamp,
+ 'event' => $event,
+ 'subject' => $cleanSubject,
+ 'description' => $description,
+ 'importance' => $importance,
+ ];
+ if ($message) $archiveData['message'] = str_replace('\n','
',$message);
+ if (!$mailtest) file_put_contents($archive, build_ini_string($archiveData));
+ if (($entity & 1)==1 && !$mailtest && !$noBrowser) {
+ $unreadData = [
+ 'timestamp' => $timestamp,
+ 'event' => $event,
+ 'subject' => $cleanSubject,
+ 'description' => $description,
+ 'importance' => $importance,
+ 'link' => $link,
+ ];
+ file_put_contents($unread, build_ini_string($unreadData));
+ }
if (($entity & 2)==2 || $mailtest) generate_email($event, clean_subject($subject), str_replace('
','. ',$description), $importance, $message, $recipients, $fqdnlink);
if (($entity & 4)==4 && !$mailtest) { if (is_array($agents)) {foreach ($agents as $agent) {exec("TIMESTAMP='$timestamp' EVENT=".escapeshellarg($event)." SUBJECT=".escapeshellarg(clean_subject($subject))." DESCRIPTION=".escapeshellarg($description)." IMPORTANCE=".escapeshellarg($importance)." CONTENT=".escapeshellarg($message)." LINK=".escapeshellarg($fqdnlink)." bash ".$agent);};}};
break;
@@ -241,9 +291,12 @@ case 'get':
$output[$i]['show'] = (fileperms($file) & 0x0FFF)==0400 ? 0 : 1;
foreach ($fields as $field) {
if (!$field) continue;
- [$key,$val] = array_pad(explode('=', $field),2,'');
+ # limit the explode('=', …) used during reads to two pieces so values containing = remain intact
+ [$key,$val] = array_pad(explode('=', $field, 2),2,'');
if ($time) {$val = date($notify['date'].' '.$notify['time'], $val); $time = false;}
- $output[$i][trim($key)] = trim($val);
+ # unescape the value before emitting JSON, so the browser UI
+ # and any scripts calling `notify get` still see plain strings
+ $output[$i][trim($key)] = ini_decode_value($val);
}
$i++;
}
From 49ff54cb0a9447180a94868445d1ce896c74b4e6 Mon Sep 17 00:00:00 2001
From: Pujit Mehrotra
Date: Sat, 8 Nov 2025 12:50:39 -0500
Subject: [PATCH 34/63] fix: use `stripslashes` instead of `stripcslashes` in
`notify` script
---
emhttp/plugins/dynamix/scripts/notify | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/scripts/notify b/emhttp/plugins/dynamix/scripts/notify
index 04372c5c1..a912aefde 100755
--- a/emhttp/plugins/dynamix/scripts/notify
+++ b/emhttp/plugins/dynamix/scripts/notify
@@ -130,7 +130,7 @@ function ini_decode_value($value) {
$value = trim($value);
$length = strlen($value);
if ($length >= 2 && $value[0] === '"' && $value[$length-1] === '"') {
- return stripcslashes(substr($value, 1, -1));
+ return stripslashes(substr($value, 1, -1));
}
return $value;
}
From 4d404b7cf1babd3b0642e6454cbec179853ad1f1 Mon Sep 17 00:00:00 2001
From: Pujit Mehrotra
Date: Sat, 8 Nov 2025 12:52:36 -0500
Subject: [PATCH 35/63] fix: redundant `clean_subject` calls
---
emhttp/plugins/dynamix/scripts/notify | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/emhttp/plugins/dynamix/scripts/notify b/emhttp/plugins/dynamix/scripts/notify
index a912aefde..1c4db802b 100755
--- a/emhttp/plugins/dynamix/scripts/notify
+++ b/emhttp/plugins/dynamix/scripts/notify
@@ -274,8 +274,8 @@ case 'add':
];
file_put_contents($unread, build_ini_string($unreadData));
}
- if (($entity & 2)==2 || $mailtest) generate_email($event, clean_subject($subject), str_replace('
','. ',$description), $importance, $message, $recipients, $fqdnlink);
- if (($entity & 4)==4 && !$mailtest) { if (is_array($agents)) {foreach ($agents as $agent) {exec("TIMESTAMP='$timestamp' EVENT=".escapeshellarg($event)." SUBJECT=".escapeshellarg(clean_subject($subject))." DESCRIPTION=".escapeshellarg($description)." IMPORTANCE=".escapeshellarg($importance)." CONTENT=".escapeshellarg($message)." LINK=".escapeshellarg($fqdnlink)." bash ".$agent);};}};
+ if (($entity & 2)==2 || $mailtest) generate_email($event, $cleanSubject, str_replace('
','. ',$description), $importance, $message, $recipients, $fqdnlink);
+ if (($entity & 4)==4 && !$mailtest) { if (is_array($agents)) {foreach ($agents as $agent) {exec("TIMESTAMP='$timestamp' EVENT=".escapeshellarg($event)." SUBJECT=".escapeshellarg($cleanSubject)." DESCRIPTION=".escapeshellarg($description)." IMPORTANCE=".escapeshellarg($importance)." CONTENT=".escapeshellarg($message)." LINK=".escapeshellarg($fqdnlink)." bash ".$agent);};}};
break;
case 'get':
From 1859921036240e5835cc746a164aa8797434174a Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Sun, 9 Nov 2025 13:52:27 -0500
Subject: [PATCH 36/63] Fix: GUI Search wouldn't update when plugin uninstalled
---
.../dynamix.plugin.manager/post-hooks/post_plugin_checks | 2 ++
1 file changed, 2 insertions(+)
diff --git a/emhttp/plugins/dynamix.plugin.manager/post-hooks/post_plugin_checks b/emhttp/plugins/dynamix.plugin.manager/post-hooks/post_plugin_checks
index f84d646d6..8f10eaf56 100755
--- a/emhttp/plugins/dynamix.plugin.manager/post-hooks/post_plugin_checks
+++ b/emhttp/plugins/dynamix.plugin.manager/post-hooks/post_plugin_checks
@@ -67,6 +67,8 @@ case 'language':
// nothing defined
break;
}
+// unset GUI search cache
+@unlink("/tmp/gui.search/searchResults.json");
// unset pending status
if ($method != 'check') @unlink("$pending/$name");
From 40b62796df59080ba29192b6482c5df81297523a Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Wed, 12 Nov 2025 17:42:18 -0500
Subject: [PATCH 37/63] Fix: Array usage bar sidenav theme
---
emhttp/plugins/dynamix/include/DefaultPageLayout/Header.php | 4 +++-
.../dynamix/include/DefaultPageLayout/Navigation/Main.php | 6 ++++--
emhttp/plugins/dynamix/styles/default-base.css | 6 ++++--
3 files changed, 11 insertions(+), 5 deletions(-)
mode change 100644 => 100755 emhttp/plugins/dynamix/include/DefaultPageLayout/Header.php
mode change 100644 => 100755 emhttp/plugins/dynamix/include/DefaultPageLayout/Navigation/Main.php
diff --git a/emhttp/plugins/dynamix/include/DefaultPageLayout/Header.php b/emhttp/plugins/dynamix/include/DefaultPageLayout/Header.php
old mode 100644
new mode 100755
index ea6e88031..579dd637d
--- a/emhttp/plugins/dynamix/include/DefaultPageLayout/Header.php
+++ b/emhttp/plugins/dynamix/include/DefaultPageLayout/Header.php
@@ -1,5 +1,7 @@
diff --git a/emhttp/plugins/dynamix/include/DefaultPageLayout/Navigation/Main.php b/emhttp/plugins/dynamix/include/DefaultPageLayout/Navigation/Main.php
old mode 100644
new mode 100755
index 3d4b5a0e0..40bd5e99d
--- a/emhttp/plugins/dynamix/include/DefaultPageLayout/Navigation/Main.php
+++ b/emhttp/plugins/dynamix/include/DefaultPageLayout/Navigation/Main.php
@@ -37,10 +37,12 @@
endif; ?>
- if ($display['usage']): ?>
+ if ($display['usage'] && ! $themeHelper->isSidebarTheme()): ?>
my_usage(); ?>
endif; ?>
-
+ if ($display['usage'] && $themeHelper->isSidebarTheme()): ?>
+
+ endif; ?>
foreach ($buttonPages as $button): ?>
if (empty($button['Link'])): ?>
$icon = $button['Icon']; ?>
diff --git a/emhttp/plugins/dynamix/styles/default-base.css b/emhttp/plugins/dynamix/styles/default-base.css
index 9bfce5361..b0d13e033 100755
--- a/emhttp/plugins/dynamix/styles/default-base.css
+++ b/emhttp/plugins/dynamix/styles/default-base.css
@@ -2594,8 +2594,10 @@ div#title.ud {
}
.usage-bar {
- position: relative;
- width: 6.4rem;
+ POSITION: absolute;
+ bottom: .5rem;
+ left: 50%;
+ width: 14rem;
margin: 0;
padding: 0;
}
From 911d9da630a1b59b8ea67c28f8cb5c95c57887af Mon Sep 17 00:00:00 2001
From: Squidly271
Date: Wed, 12 Nov 2025 17:44:28 -0500
Subject: [PATCH 38/63] Update default-base.css
---
emhttp/plugins/dynamix/styles/default-base.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/styles/default-base.css b/emhttp/plugins/dynamix/styles/default-base.css
index b0d13e033..cde054164 100755
--- a/emhttp/plugins/dynamix/styles/default-base.css
+++ b/emhttp/plugins/dynamix/styles/default-base.css
@@ -2594,7 +2594,7 @@ div#title.ud {
}
.usage-bar {
- POSITION: absolute;
+ position: absolute;
bottom: .5rem;
left: 50%;
width: 14rem;
From 515cded921977034ee98e64a101e1465b6917d03 Mon Sep 17 00:00:00 2001
From: Eli Bosley
Date: Fri, 14 Nov 2025 12:17:25 -0500
Subject: [PATCH 39/63] Update Crowdin configuration file
---
crowdin.yml | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 crowdin.yml
diff --git a/crowdin.yml b/crowdin.yml
new file mode 100644
index 000000000..d7faad685
--- /dev/null
+++ b/crowdin.yml
@@ -0,0 +1,2 @@
+bundles:
+ - 1
From 993a5f42a50e74f09fdef807bbb8ea3e5dc17a4b Mon Sep 17 00:00:00 2001
From: Eli Bosley
Date: Fri, 14 Nov 2025 12:18:17 -0500
Subject: [PATCH 40/63] Delete crowdin.yml
---
crowdin.yml | 2 --
1 file changed, 2 deletions(-)
delete mode 100644 crowdin.yml
diff --git a/crowdin.yml b/crowdin.yml
deleted file mode 100644
index d7faad685..000000000
--- a/crowdin.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-bundles:
- - 1
From 972e1be6fc827beda94397c8f065b5592b91d179 Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Fri, 14 Nov 2025 11:42:13 -0800
Subject: [PATCH 41/63] Fix: NFS security, "write settings to" does not work
for security modes Public and Secure
---
emhttp/plugins/dynamix/SecurityNFS.page | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/emhttp/plugins/dynamix/SecurityNFS.page b/emhttp/plugins/dynamix/SecurityNFS.page
index da4a9cf20..ce7d4f478 100755
--- a/emhttp/plugins/dynamix/SecurityNFS.page
+++ b/emhttp/plugins/dynamix/SecurityNFS.page
@@ -214,7 +214,7 @@ function writeNFS(data, n, i) {
var data = [];
/* Get the setting from the share config. */
- var hostList = $('textarea[name="shareHostListNFS"]').val().trim();
+ var hostList = $('textarea[name="shareHostListNFS"]').val()?.trim() || "";
/* Replace all new lines in data.hostList with spaces. */
var formattedHostList = = json_encode($sec_nfs[$name]['hostList']); ?>.replace(/\n/g, ' ');
From 77ea548bebfc393c78b45de4d61badc445b01e77 Mon Sep 17 00:00:00 2001
From: Tom Mortensen
Date: Fri, 14 Nov 2025 13:22:46 -0800
Subject: [PATCH 42/63] Fix: add Disable option to mover schedule
---
emhttp/plugins/dynamix/MoverSettings.page | 48 ++++++++++++++---------
1 file changed, 29 insertions(+), 19 deletions(-)
diff --git a/emhttp/plugins/dynamix/MoverSettings.page b/emhttp/plugins/dynamix/MoverSettings.page
index 4ca5a060e..e6576111a 100755
--- a/emhttp/plugins/dynamix/MoverSettings.page
+++ b/emhttp/plugins/dynamix/MoverSettings.page
@@ -15,6 +15,8 @@ Tag="calendar-check-o"
*/
?>
+$mode = ['Disabled','Hourly','Daily','Weekly','Monthly'];
+$days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
$setup = true;
if (!$pool_devices) {
echo ""._('No Cache device present')."!
";
@@ -23,11 +25,13 @@ if (!$pool_devices) {
echo ""._('User shares not enabled')."!
";
$setup = false;
}
-$cron = explode(' ',$var['shareMoverSchedule']);
-$move = $cron[2]!='*' ? 3 : ($cron[4]!='*' ? 2 : (substr($cron[1],0,1)!='*' ? 1 : 0));
-$mode = ['Hourly','Daily','Weekly','Monthly'];
-$days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
-
+if (empty($var['shareMoverSchedule'])) {
+ $cron = explode(' ', "* * * * *");
+ $move = 0;
+} else {
+ $cron = explode(' ', $var['shareMoverSchedule']);
+ $move = $cron[2]!='*' ? 4 : ($cron[4]!='*' ? 3 : (substr($cron[1],0,1)!='*' ? 2 : 1));
+}
$showMoverButton = $setup && $pool_devices;
$moverRunning = file_exists('/var/run/mover.pid');
?>
@@ -37,27 +41,33 @@ $(function() {
presetMover(document.mover_schedule);
});
endif; ?>
+function presetMover(form) {
+ var mode = form.shareMoverSchedule.value;
+ form.min.disabled = mode==0;
+ form.day.disabled = mode==0 || mode!=3;
+ form.dotm.disabled = mode==0 || mode!=4;
+ form.hour1.disabled = mode==0;
+ form.hour2.disabled = mode==0;
+ form.day.value = form.day.disabled ? '*' : (form.day.value=='*' ? 0 : form.day.value);
+ form.dotm.value = form.dotm.disabled ? '*' : (form.dotm.value=='*' ? 1 : form.dotm.value);
+ if (mode==1) {$('#H1').hide(); $('#H2').show();} else {$('#H2').hide(); $('#H1').show();}
+}
// Fool Unraid by simulating the original input field
function prepareMover(form) {
var mode = form.shareMoverSchedule.value;
- var min = mode!=0 ? form.min.value : 0;
- var hour = mode!=0 ? form.hour1.value : form.hour2.value;
- form.shareMoverSchedule.options[mode].value = min+' '+hour+' '+form.dotm.value+' * '+form.day.value;
+ if (mode == 0)
+ form.shareMoverSchedule.options[mode].value = '';
+ else {
+ var hour = mode!=1 ? form.hour1.value : form.hour2.value;
+ var min = mode!=1 ? form.min.value : 0;
+ form.shareMoverSchedule.options[mode].value = min+' '+hour+' '+form.dotm.value+' * '+form.day.value;
+ }
form.min.disabled = true;
form.hour1.disabled = true;
form.hour2.disabled = true;
form.dotm.disabled = true;
form.day.disabled = true;
}
-function presetMover(form) {
- var mode = form.shareMoverSchedule.value;
- form.min.disabled = false;
- form.day.disabled = mode!=2;
- form.dotm.disabled = mode!=3;
- form.day.value = form.day.disabled ? '*' : (form.day.value=='*' ? 0 : form.day.value);
- form.dotm.value = form.dotm.disabled ? '*' : (form.dotm.value=='*' ? 1 : form.dotm.value);
- if (mode==0) {$('#H1').hide(); $('#H2').show();} else {$('#H2').hide(); $('#H1').show();}
-}