Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fc971e0a6 | ||
|
|
2ae9708c4e | ||
|
|
8a9b7568a7 | ||
|
|
f754331c3a | ||
|
|
e46734cd37 | ||
|
|
bc87579d77 | ||
|
|
e59d09a788 | ||
|
|
cee8d04e36 | ||
|
|
8ebc2b4753 | ||
|
|
795b0ebf39 | ||
|
|
43514fc949 | ||
|
|
c1c26aff56 |
No files matched your search
@@ -58,7 +58,6 @@ jobs:
|
|||||||
if [[ "${{ github.event_name }}" == "push" ]]; then
|
if [[ "${{ github.event_name }}" == "push" ]]; then
|
||||||
# Always recreate from main — avoids rebase conflicts after PR merge
|
# Always recreate from main — avoids rebase conflicts after PR merge
|
||||||
git checkout -b chore/version-bump origin/main
|
git checkout -b chore/version-bump origin/main
|
||||||
git push --force origin chore/version-bump
|
|
||||||
else
|
else
|
||||||
# Label change: check out the existing branch
|
# Label change: check out the existing branch
|
||||||
git fetch origin chore/version-bump
|
git fetch origin chore/version-bump
|
||||||
@@ -133,8 +132,8 @@ jobs:
|
|||||||
echo "$MAIN_CHANGELOG"
|
echo "$MAIN_CHANGELOG"
|
||||||
} > debian/changelog
|
} > debian/changelog
|
||||||
git add debian/changelog
|
git add debian/changelog
|
||||||
git diff --cached --quiet || git commit -m "chore: update changelog to v${NEW_VERSION}"
|
git commit -m "chore: update changelog to v${NEW_VERSION}"
|
||||||
git push --force-with-lease origin chore/version-bump
|
git push --force origin chore/version-bump
|
||||||
|
|
||||||
- name: Build PR body
|
- name: Build PR body
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -36,11 +36,20 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
needs: discover
|
needs: discover
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: debian:trixie
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
mod: ${{ fromJSON(needs.discover.outputs.mods) }}
|
mod: ${{ fromJSON(needs.discover.outputs.mods) }}
|
||||||
steps:
|
steps:
|
||||||
|
# ── Base tools (mirrors validate-mods.yml) ──────────────────────────────
|
||||||
|
- name: Install base tools
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates git sudo wget xz-utils dpkg nodejs perl
|
||||||
|
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
@@ -48,22 +57,32 @@ jobs:
|
|||||||
# ── Build (mirrors test-release.yml) ───────────────────────────────────
|
# ── Build (mirrors test-release.yml) ───────────────────────────────────
|
||||||
- name: Install build deps
|
- name: Install build deps
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -qq
|
apt-get update -qq
|
||||||
sudo apt-get install -y devscripts debhelper build-essential
|
apt-get install -y devscripts debhelper build-essential
|
||||||
|
|
||||||
|
- name: Compute build version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
BASE_VERSION=$(grep -m1 '(' debian/changelog | sed 's/.*(\(.*\)).*/\1/')
|
||||||
|
SHORT_SHA=$(git rev-parse --short HEAD)
|
||||||
|
BUILD_VERSION="${BASE_VERSION}+weekly.${SHORT_SHA}"
|
||||||
|
echo "build_version=$BUILD_VERSION" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Building version: $BUILD_VERSION"
|
||||||
|
|
||||||
- name: Inject version into Config.pm
|
- name: Inject version into Config.pm
|
||||||
run: |
|
run: |
|
||||||
VERSION=$(grep -m1 '(' debian/changelog | sed 's/.*(\(.*\)).*/\1/')
|
BUILD_VERSION="${{ steps.version.outputs.build_version }}"
|
||||||
SHORT_SHA=$(git rev-parse --short HEAD)
|
sed -i -E "s/^our \\\$VERSION\s*=.*/our \\\$VERSION = '${BUILD_VERSION}';/" \
|
||||||
export BUILD_VERSION="${VERSION}-test-${SHORT_SHA}"
|
src/modules/node_info/files/Config.pm
|
||||||
perl -i -pe 'BEGIN { $v = $ENV{BUILD_VERSION} }
|
|
||||||
s/(our \$VERSION\s*=\s*'"'"')[^'"'"']*'"'"';/$1'"'"'$v'"'"';/
|
- name: Set package version in changelog
|
||||||
' src/modules/node_info/files/Config.pm
|
run: |
|
||||||
|
BUILD_VERSION="${{ steps.version.outputs.build_version }}"
|
||||||
|
sed -i -E "0,/\(([^)]*)\)/s//(${BUILD_VERSION})/" debian/changelog
|
||||||
|
|
||||||
- name: Generate dynamic debian rules
|
- name: Generate dynamic debian rules
|
||||||
run: |
|
run: |
|
||||||
bash build/gen-rules.sh >> debian/rules
|
bash build/gen-rules.sh >> debian/rules
|
||||||
bash build/gen-rules.sh conffiles >> debian/pve-mod.conffiles
|
|
||||||
|
|
||||||
- name: Build package
|
- name: Build package
|
||||||
run: dpkg-buildpackage -us -uc -b
|
run: dpkg-buildpackage -us -uc -b
|
||||||
@@ -72,13 +91,26 @@ jobs:
|
|||||||
- name: Fetch upstream Proxmox files
|
- name: Fetch upstream Proxmox files
|
||||||
run: bash build/test/fetch-proxmox-files.sh
|
run: bash build/test/fetch-proxmox-files.sh
|
||||||
|
|
||||||
|
- name: Capture upstream package versions
|
||||||
|
id: pve_versions
|
||||||
|
run: |
|
||||||
|
PVE_MANAGER_VERSION=$(dpkg-query -W -f='${Version}' pve-manager 2>/dev/null || echo "unknown")
|
||||||
|
PWT_VERSION=$(dpkg-query -W -f='${Version}' proxmox-widget-toolkit 2>/dev/null || echo "unknown")
|
||||||
|
echo "pve_manager=${PVE_MANAGER_VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "proxmox_widget_toolkit=${PWT_VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "pve-manager: ${PVE_MANAGER_VERSION}"
|
||||||
|
echo "proxmox-widget-toolkit: ${PWT_VERSION}"
|
||||||
|
|
||||||
- name: Install built package
|
- name: Install built package
|
||||||
run: sudo apt-get install -y ../pve-mod_*.deb
|
run: apt-get install -y ../pve-mod_*.deb
|
||||||
|
|
||||||
- name: Test mod
|
- name: Test mod
|
||||||
run: |
|
run: |
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
sudo bash build/test/test-patches.sh "${{ matrix.mod }}" 2>&1 | tee test-output.log
|
bash build/test/test-patches.sh "${{ matrix.mod }}" 2>&1 | tee test-output.log
|
||||||
|
|
||||||
|
- name: Validate source syntax
|
||||||
|
run: bash build/test/test-syntax.sh "${{ matrix.mod }}"
|
||||||
|
|
||||||
- name: Report failure as issue
|
- name: Report failure as issue
|
||||||
if: failure()
|
if: failure()
|
||||||
@@ -90,6 +122,10 @@ jobs:
|
|||||||
{
|
{
|
||||||
echo "The weekly patch test failed for mod \`${MOD}\` against the latest Proxmox VE files."
|
echo "The weekly patch test failed for mod \`${MOD}\` against the latest Proxmox VE files."
|
||||||
echo ""
|
echo ""
|
||||||
|
echo "**Proxmox versions tested:**"
|
||||||
|
echo "- pve-manager: \`${{ steps.pve_versions.outputs.pve_manager }}\`"
|
||||||
|
echo "- proxmox-widget-toolkit: \`${{ steps.pve_versions.outputs.proxmox_widget_toolkit }}\`"
|
||||||
|
echo ""
|
||||||
echo "Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
echo "Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "<details><summary>Test log</summary>"
|
echo "<details><summary>Test log</summary>"
|
||||||
@@ -109,8 +145,9 @@ jobs:
|
|||||||
--jq ".[] | select(.title==\"$TITLE\") | .number" | head -n1)
|
--jq ".[] | select(.title==\"$TITLE\") | .number" | head -n1)
|
||||||
|
|
||||||
if [[ -n "$EXISTING" ]]; then
|
if [[ -n "$EXISTING" ]]; then
|
||||||
|
gh issue edit "$EXISTING" --body-file issue-body.md
|
||||||
gh issue comment "$EXISTING" --body-file issue-body.md
|
gh issue comment "$EXISTING" --body-file issue-body.md
|
||||||
echo "Commented on existing issue #$EXISTING"
|
echo "Updated and commented on existing issue #$EXISTING"
|
||||||
else
|
else
|
||||||
gh issue create --title "$TITLE" --label patch-break --body-file issue-body.md
|
gh issue create --title "$TITLE" --label patch-break --body-file issue-body.md
|
||||||
echo "Opened new issue for mod $MOD"
|
echo "Opened new issue for mod $MOD"
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ test_one_mod() {
|
|||||||
if [[ $ok -eq 0 ]]; then
|
if [[ $ok -eq 0 ]]; then
|
||||||
info "Reverting patches for '$mod'..."
|
info "Reverting patches for '$mod'..."
|
||||||
local revert_log
|
local revert_log
|
||||||
revert_log="$("$REVERT" 2>&1)"
|
revert_log="$("$REVERT" "$mod" 2>&1)"
|
||||||
echo "$revert_log"
|
echo "$revert_log"
|
||||||
if echo "$revert_log" | grep -qE "could not be reverted cleanly|reported an error"; then
|
if echo "$revert_log" | grep -qE "could not be reverted cleanly|reported an error"; then
|
||||||
warn "revert-patches.sh reported an unclean revert for mod '$mod'"
|
warn "revert-patches.sh reported an unclean revert for mod '$mod'"
|
||||||
|
|||||||
@@ -3,11 +3,80 @@ A small collection of scripts and mods for Proxmox Virtual Environment (PVE)
|
|||||||
|
|
||||||
If you find this helpful, a small donation is appreciated, [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=K8XPMSEBERH3W).
|
If you find this helpful, a small donation is appreciated, [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=K8XPMSEBERH3W).
|
||||||
|
|
||||||
## Node sensor readings view
|
| Version | Description | Status |
|
||||||
|
|---------|-------------|--------|
|
||||||
|
| **v2** (current) | Debian package (`pve-mod`) with interactive `pve-mod-configure` wizard | Recommended |
|
||||||
|
| v1 (legacy) | Standalone bash scripts, manual install | Archived — see [Legacy section](#legacy-v1-shell-scripts) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version 2 (beta) — Debian package
|
||||||
|
|
||||||
|
Compatibility: PVE 9.0+
|
||||||
|
|
||||||
|
TBD PICTURE
|
||||||
|
|
||||||
|
`pve-mod` is a Debian package that installs UI patches and an interactive configuration wizard.
|
||||||
|
|
||||||
|
### Mods
|
||||||
|
|
||||||
|
| Mod | Description | Dependencies |
|
||||||
|
|--------|-------------|--------------|
|
||||||
|
| [`node_info`](src/modules/node_info/readme.md) | Displays sensor readings in the node summary panel: CPU, NVMe/HDD/SSD temperatures (°C/°F), fan speeds, RAM temperatures, GPU stats (Intel/NVIDIA), UPS status, and system/motherboard info. <br> Can optionally run as background sensor daemon | - General sensors: `lm-sensors`<br>- HDD/SSD: Kernal module `drivetemp`<br>- UPS: `upsc`<br>- GPU: INTEL `intel-gpu-tools` and/or NVIDIA `nvidia-driver-* `
|
||||||
|
| [`nag_screen`](src/modules/nag_screen/readme.md) | Removes the subscription nag screen from the PVE web UI. | - |
|
||||||
|
|
||||||
|
### How it works
|
||||||
|
|
||||||
|
1. The `pve-mod` package installs the mods installation, patch files under `/usr/lib/pve-mod/`.
|
||||||
|
2. The mods main configuration file and mods can be found under `/etc/pve-mod/`.
|
||||||
|
2. Running `pve-mod-configure` prompts for which modules to enable and configuration of mods.
|
||||||
|
3. The wizard applies the selected patches to the PVE system files and restarts `pveproxy`.
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
Commands and mod configuration must be run as `root`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -sL https://raw.githubusercontent.com/Meliox/PVE-mods/refs/heads/main/install.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Install respective mod dependencies - see Mod table.
|
||||||
|
|
||||||
|
Run `pve-mod-configure` to install/uninstall and configure mods.
|
||||||
|
|
||||||
|
#### Manual configuration changes
|
||||||
|
Configuration files are located in `/etc/pve-mod/`. After any manual edits, restart `pveproxy` to apply the changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl restart pveproxy
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uninstall
|
||||||
|
|
||||||
|
Commands and mod configuration must be run as `root`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt-get remove pve-mod
|
||||||
|
```
|
||||||
|
And remove dependencies needed by respective mods.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
Multiple node support requires application to be installed on all nodes with identical configuration. (untested)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Legacy / v1 (shell scripts)
|
||||||
|
|
||||||
|
> **These scripts are archived.** For new installations, use the [v2 Debian package](#version-2--debian-package) above.
|
||||||
|
|
||||||
|
### Node sensor readings view
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
Compatibility:
|
Compatibility:
|
||||||
- 9.0-9.2. Newer versions may often work
|
- 9.0-9.2. Newer versions may often work
|
||||||
- Older version (7.x-8.x), use git version from Apr 6th 2025
|
- Older version (7.x-8.x), use git version from Apr 6th 2025
|
||||||

|
|
||||||
|
|
||||||
This bash script installs a modification to the Proxmox Virtual Environment (PVE) web user interface (UI) to display sensor readings in a flexible and readable manner.
|
This bash script installs a modification to the Proxmox Virtual Environment (PVE) web user interface (UI) to display sensor readings in a flexible and readable manner.
|
||||||
The following readings are possible:
|
The following readings are possible:
|
||||||
@@ -15,7 +84,7 @@ The following readings are possible:
|
|||||||
- UPS information via Network Monitoring Tool
|
- UPS information via Network Monitoring Tool
|
||||||
- Motherboard information or system information via dmidecode
|
- Motherboard information or system information via dmidecode
|
||||||
|
|
||||||
### How it works
|
#### How it works
|
||||||
The modification involves the following steps:
|
The modification involves the following steps:
|
||||||
1. Backup original files in the home directory/backup
|
1. Backup original files in the home directory/backup
|
||||||
- `/usr/share/pve-manager/js/pvemanagerlib.js`
|
- `/usr/share/pve-manager/js/pvemanagerlib.js`
|
||||||
@@ -38,7 +107,7 @@ Notes:
|
|||||||
- UPS support in multi-node setups require identical login credentials across nodes. This has not been fully tested.
|
- UPS support in multi-node setups require identical login credentials across nodes. This has not been fully tested.
|
||||||
- Proxmox upgrades may overwrite modified files; reinstallation of this mod could be required.
|
- Proxmox upgrades may overwrite modified files; reinstallation of this mod could be required.
|
||||||
|
|
||||||
### Install
|
#### Install
|
||||||
Instructions be performed as 'root', as normal users do not have access to the files.
|
Instructions be performed as 'root', as normal users do not have access to the files.
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -51,7 +120,7 @@ bash pve-mod-gui-sensors.sh install
|
|||||||
```
|
```
|
||||||
Additionally, adjustments are available in the first part of the script, where paths can be edited, cpucore offset and display information.
|
Additionally, adjustments are available in the first part of the script, where paths can be edited, cpucore offset and display information.
|
||||||
|
|
||||||
## Nag screen deactivation
|
### Nag screen deactivation
|
||||||
(Tested compatibility: 7.x - 8.3.5)
|
(Tested compatibility: 7.x - 8.3.5)
|
||||||
This bash script installs a modification to the Proxmox Virtual Environment (PVE) web user interface (UI) which deactivates the subscription nag screen.
|
This bash script installs a modification to the Proxmox Virtual Environment (PVE) web user interface (UI) which deactivates the subscription nag screen.
|
||||||
|
|
||||||
@@ -65,21 +134,21 @@ The script provides three options:
|
|||||||
| `install` | Installs the modification by applying the necessary changes. |
|
| `install` | Installs the modification by applying the necessary changes. |
|
||||||
| `uninstall` | Removes the modification by restoring the original files from backups. |
|
| `uninstall` | Removes the modification by restoring the original files from backups. |
|
||||||
|
|
||||||
### Install
|
#### Install
|
||||||
Instructions be performed as 'root', as normal users do not have access to the files.
|
Instructions be performed as 'root', as normal users do not have access to the files.
|
||||||
```
|
```
|
||||||
wget https://raw.githubusercontent.com/Meliox/PVE-mods/refs/heads/main/legacy-scripts/pve-mod-nag-screen.sh
|
wget https://raw.githubusercontent.com/Meliox/PVE-mods/refs/heads/main/legacy-scripts/pve-mod-nag-screen.sh
|
||||||
bash pve-mod-nag-screen.sh install
|
bash pve-mod-nag-screen.sh install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Script to update all containers
|
### Script to update all containers
|
||||||
(Tested compatibility: 7.x - 8.3.5)
|
(Tested compatibility: 7.x - 8.3.5)
|
||||||
|
|
||||||
This script updates all running Proxmox containers, skipping specified excluded containers, and generates a separate log file for each container.
|
This script updates all running Proxmox containers, skipping specified excluded containers, and generates a separate log file for each container.
|
||||||
The script first updates the Proxmox host system, then iterates through each container, updates the container, and reboots it if necessary.
|
The script first updates the Proxmox host system, then iterates through each container, updates the container, and reboots it if necessary.
|
||||||
Each container's log file is stored in $log_path and the main script log file is named container-upgrade-main.log.
|
Each container's log file is stored in $log_path and the main script log file is named container-upgrade-main.log.
|
||||||
|
|
||||||
### Install
|
#### Install
|
||||||
```
|
```
|
||||||
wget https://raw.githubusercontent.com/Meliox/PVE-mods/refs/heads/main/legacy-scripts/updateallcontainers.sh
|
wget https://raw.githubusercontent.com/Meliox/PVE-mods/refs/heads/main/legacy-scripts/updateallcontainers.sh
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ sub _get_temperature_sensors {
|
|||||||
hdd => $config{lm_sensors}{enable_hdd_temp} ? \1 : \0,
|
hdd => $config{lm_sensors}{enable_hdd_temp} ? \1 : \0,
|
||||||
other => $config{lm_sensors}{enable_other_temp} ? \1 : \0,
|
other => $config{lm_sensors}{enable_other_temp} ? \1 : \0,
|
||||||
temp_unit => $config{lm_sensors}{temp_unit},
|
temp_unit => $config{lm_sensors}{temp_unit},
|
||||||
|
cpu_temp_target => $config{lm_sensors}{cpu_temp_target},
|
||||||
data => { 'PVE MOD lm-sensors Enhanced' => $sensors_json },
|
data => { 'PVE MOD lm-sensors Enhanced' => $sensors_json },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,14 @@ sub notify_pve_mod_worker {
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
sub _worker_lock_file_exists {
|
sub _worker_lock_file_exists {
|
||||||
return -f $pve_mod_worker_lock;
|
return 0 unless -f $pve_mod_worker_lock;
|
||||||
|
my $pid = read_lock_pid($pve_mod_worker_lock);
|
||||||
|
if (defined $pid && $pid =~ /^(\d+)$/ && is_process_alive($1)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
debug(__LINE__, "Stale or zombie worker lock found, removing it");
|
||||||
|
unlink($pve_mod_worker_lock);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Forks the worker process and records its PID in the lock file.
|
# Forks the worker process and records its PID in the lock file.
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ sub _merge_graphics_files {
|
|||||||
Intel => {},
|
Intel => {},
|
||||||
NVIDIA => {},
|
NVIDIA => {},
|
||||||
AMD => {},
|
AMD => {},
|
||||||
|
temp_unit => $config{lm_sensors}{temp_unit},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,7 +135,7 @@ sub _load_graphics_data {
|
|||||||
\@filepaths,
|
\@filepaths,
|
||||||
$graphics_cache,
|
$graphics_cache,
|
||||||
\&_merge_graphics_files,
|
\&_merge_graphics_files,
|
||||||
{ Graphics => { Intel => {}, NVIDIA => {}, AMD => {} } }
|
{ Graphics => { Intel => {}, NVIDIA => {}, AMD => {}, temp_unit => $config{lm_sensors}{temp_unit} } }
|
||||||
);
|
);
|
||||||
|
|
||||||
my $intel_count = scalar(keys %{$data->{Graphics}{Intel} // {}});
|
my $intel_count = scalar(keys %{$data->{Graphics}{Intel} // {}});
|
||||||
|
|||||||
@@ -224,14 +224,13 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
objValue = {};
|
objValue = {};
|
||||||
}
|
}
|
||||||
// sensors configuration
|
// sensors configuration
|
||||||
const cpuTempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: objValue.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
|
const cpuTempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: value.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
|
||||||
|
|
||||||
const cpuKeysI = Object.keys(objValue).filter(item => String(item).startsWith('coretemp-isa-')).sort();
|
const cpuKeysI = Object.keys(objValue).filter(item => String(item).startsWith('coretemp-isa-')).sort();
|
||||||
const cpuKeysA = Object.keys(objValue).filter(item => String(item).startsWith('k10temp-pci-')).sort();
|
const cpuKeysA = Object.keys(objValue).filter(item => String(item).startsWith('k10temp-pci-')).sort();
|
||||||
const cpuKeysRpi = Object.keys(objValue).filter(item => String(item).startsWith('cpu_thermal-virtual-')).sort();
|
const cpuKeysRpi = Object.keys(objValue).filter(item => String(item).startsWith('cpu_thermal-virtual-')).sort();
|
||||||
const bINTEL = cpuKeysI.length > 0 ? true : false;
|
const bINTEL = cpuKeysI.length > 0 ? true : false;
|
||||||
const INTELPackagePrefix = 'Core' == 'Core' ? 'Core ' : 'Package id';
|
const INTELPackagePrefix = value.cpu_temp_target == 'Core' ? 'Core ' : 'Package id';
|
||||||
const INTELPackageCaption = 'Core' == 'Core' ? 'Core' : 'Package';
|
const INTELPackageCaption = value.cpu_temp_target == 'Core' ? 'Core' : 'Package';
|
||||||
let AMDPackagePrefix = 'Tccd';
|
let AMDPackagePrefix = 'Tccd';
|
||||||
let AMDPackageCaption = 'CCD';
|
let AMDPackageCaption = 'CCD';
|
||||||
|
|
||||||
@@ -392,9 +391,16 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
this.hide();
|
this.hide();
|
||||||
return '';
|
return '';
|
||||||
} else if (!gpuStats || !gpuStats.Graphics) {
|
} else if (!gpuStats || !gpuStats.Graphics) {
|
||||||
|
this.hide();
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create temperature helper for GPU temperature conversion
|
||||||
|
const gpuTempHelper = Ext.create('PVE.mod.TempHelper', {
|
||||||
|
srcUnit: PVE.mod.TempHelper.CELSIUS,
|
||||||
|
dstUnit: gpuStats.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS
|
||||||
|
});
|
||||||
|
|
||||||
let html = '<table style="width: 100%; border-collapse: collapse; table-layout: fixed;">';
|
let html = '<table style="width: 100%; border-collapse: collapse; table-layout: fixed;">';
|
||||||
|
|
||||||
// Intel GPUs - Secondary details
|
// Intel GPUs - Secondary details
|
||||||
@@ -445,6 +451,15 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
|
|
||||||
let details = [];
|
let details = [];
|
||||||
|
|
||||||
|
// GPU Utilization
|
||||||
|
if (stats.utilization && stats.utilization.gpu) {
|
||||||
|
const gpuUsage = parseInt(stats.utilization.gpu);
|
||||||
|
let gpuStyle = '';
|
||||||
|
if (gpuUsage >= 90) gpuStyle = 'color: #d9534f; font-weight: bold;';
|
||||||
|
else if (gpuUsage >= 70) gpuStyle = 'color: #f0ad4e; font-weight: bold;';
|
||||||
|
details.push(`<span style="${gpuStyle}">GPU: ${stats.utilization.gpu}%</span>`);
|
||||||
|
}
|
||||||
|
|
||||||
// Memory Utilization
|
// Memory Utilization
|
||||||
if (stats.utilization && stats.utilization.memory) {
|
if (stats.utilization && stats.utilization.memory) {
|
||||||
const memUsage = parseInt(stats.utilization.memory);
|
const memUsage = parseInt(stats.utilization.memory);
|
||||||
@@ -467,13 +482,18 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
|
|
||||||
// Temperature
|
// Temperature
|
||||||
if (stats.temperature) {
|
if (stats.temperature) {
|
||||||
|
const gpuTemp = gpuTempHelper.getTemp(parseFloat(stats.temperature.gpu));
|
||||||
|
const tempUnit = gpuTempHelper.getUnit();
|
||||||
|
// Convert thresholds to target unit for comparison
|
||||||
|
const tempHigh = gpuTempHelper.getTemp(80);
|
||||||
|
const tempWarn = gpuTempHelper.getTemp(70);
|
||||||
let tempStyle = '';
|
let tempStyle = '';
|
||||||
if (stats.temperature.gpu >= 80) {
|
if (gpuTemp >= tempHigh) {
|
||||||
tempStyle = 'color: red; font-weight: bold;';
|
tempStyle = 'color: red; font-weight: bold;';
|
||||||
} else if (stats.temperature.gpu >= 70) {
|
} else if (gpuTemp >= tempWarn) {
|
||||||
tempStyle = 'color: #FFC300; font-weight: bold;';
|
tempStyle = 'color: #FFC300; font-weight: bold;';
|
||||||
}
|
}
|
||||||
details.push(`Temp: <span style="${tempStyle}">${stats.temperature.gpu}${stats.temperature.unit}</span>`);
|
details.push(`Temp: <span style="${tempStyle}">${Ext.util.Format.number(gpuTemp, '0')}${tempUnit}</span>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Power
|
// Power
|
||||||
@@ -489,9 +509,12 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
html += '</table>';
|
html += '</table>';
|
||||||
return html.indexOf('<tr>') > 0
|
if (html.indexOf('<tr>') <= 0) {
|
||||||
? '<div style="padding-left: 20px; box-sizing: border-box;">' + html + '</div>'
|
this.hide();
|
||||||
: '';
|
return '';
|
||||||
|
}
|
||||||
|
this.show();
|
||||||
|
return '<div style="padding-left: 20px; box-sizing: border-box;">' + html + '</div>';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -520,7 +543,7 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
} catch(e) {
|
} catch(e) {
|
||||||
objValue = {};
|
objValue = {};
|
||||||
}
|
}
|
||||||
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: objValue.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
|
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: value.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
|
||||||
const drvKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }));
|
const drvKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }));
|
||||||
let drvData = [];
|
let drvData = [];
|
||||||
drvKeys.forEach((drvKey) => {
|
drvKeys.forEach((drvKey) => {
|
||||||
@@ -600,7 +623,7 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
} catch(e) {
|
} catch(e) {
|
||||||
objValue = {};
|
objValue = {};
|
||||||
}
|
}
|
||||||
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: objValue.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
|
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: value.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
|
||||||
const nvmeKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort();
|
const nvmeKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort();
|
||||||
let nvmeData = [];
|
let nvmeData = [];
|
||||||
nvmeKeys.forEach((nvmeKey, index) => {
|
nvmeKeys.forEach((nvmeKey, index) => {
|
||||||
@@ -688,7 +711,7 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
} catch(e) {
|
} catch(e) {
|
||||||
objValue = {};
|
objValue = {};
|
||||||
}
|
}
|
||||||
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: objValue.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
|
const tempHelper = Ext.create('PVE.mod.TempHelper', {srcUnit: PVE.mod.TempHelper.CELSIUS, dstUnit: value.temp_unit === 'F' ? PVE.mod.TempHelper.FAHRENHEIT : PVE.mod.TempHelper.CELSIUS});
|
||||||
|
|
||||||
// Keep only keys that do not belong to known categories
|
// Keep only keys that do not belong to known categories
|
||||||
const otherKeys = Object.keys(objValue).filter(key =>
|
const otherKeys = Object.keys(objValue).filter(key =>
|
||||||
@@ -846,6 +869,7 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
this.hide();
|
this.hide();
|
||||||
return '';
|
return '';
|
||||||
} else if (!gpuStats || !gpuStats.Graphics || !gpuStats.Graphics.NVIDIA) {
|
} else if (!gpuStats || !gpuStats.Graphics || !gpuStats.Graphics.NVIDIA) {
|
||||||
|
this.hide();
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -873,8 +897,10 @@ Ext.define('PVE.node.StatusView', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (rows.length === 0) {
|
if (rows.length === 0) {
|
||||||
|
this.hide();
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
this.show();
|
||||||
|
|
||||||
return '<div style="padding-left: 20px; box-sizing: border-box;"><table style="width: 100%; border-collapse: collapse; table-layout: fixed;">' + rows.join('') + '</table></div>';
|
return '<div style="padding-left: 20px; box-sizing: border-box;"><table style="width: 100%; border-collapse: collapse; table-layout: fixed;">' + rows.join('') + '</table></div>';
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -91,7 +91,15 @@ sub read_sysfs {
|
|||||||
|
|
||||||
sub is_process_alive {
|
sub is_process_alive {
|
||||||
my ($pid) = @_;
|
my ($pid) = @_;
|
||||||
return -d "/proc/$pid";
|
return 0 unless -d "/proc/$pid";
|
||||||
|
# A zombie still has /proc/<pid> but is dead - otherwise a stale
|
||||||
|
# worker lock is never cleaned up.
|
||||||
|
if (open my $fh, '<', "/proc/$pid/stat") {
|
||||||
|
my $line = <$fh>;
|
||||||
|
close $fh;
|
||||||
|
return 0 if defined $line && $line =~ /\)\s+Z\s/;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub read_lock_pid {
|
sub read_lock_pid {
|
||||||
|
|||||||
Reference in new issue
Block a user