mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2025-12-15 19:53:31 +01:00
Compare commits
46 Commits
2025-01-28
...
2025-01-30
| Author | SHA1 | Date | |
|---|---|---|---|
| 2e2db6603e | |||
| 72335f2c4e | |||
| a359ffc211 | |||
| cd4bcefa58 | |||
| a0eb173824 | |||
| 3d42ecb152 | |||
| 0642c7e2c8 | |||
| af04e933e3 | |||
| 0dfc513a27 | |||
| 26433efcd8 | |||
| 343de50ef8 | |||
| a38e9070ef | |||
| e2b548a7c3 | |||
| 737b18dea5 | |||
| 6b777a03c0 | |||
| d9b4778360 | |||
| 7299b77359 | |||
| d3882b6818 | |||
| 2ef0cd0f89 | |||
| f2eb24d527 | |||
| f520607d85 | |||
| 1270d87bf8 | |||
| 7f2481ea12 | |||
| 05f114ed64 | |||
| 6924a6fea4 | |||
| bb553ae48c | |||
| cbb18668dd | |||
| c7418171b4 | |||
| ed2ead9ef2 | |||
| e51c121af2 | |||
| 8c4e97d6cb | |||
| 1093fef23c | |||
| 6fa540f0da | |||
| ca7fb9b929 | |||
| 139f84a934 | |||
| 8bc50f4d71 | |||
| 3fa4cf6e07 | |||
| 63e3619b68 | |||
| 054b569e33 | |||
| cd740e52f4 | |||
| 37c7205978 | |||
| eb9633215c | |||
| 85a6819760 | |||
| 20d6162ac1 | |||
| 0dff2b3363 | |||
| c799e67ea5 |
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@ -1 +1,2 @@
|
||||
ko_fi: community_scripts
|
||||
github: community_scripts
|
||||
|
||||
44
CHANGELOG.md
44
CHANGELOG.md
@ -17,6 +17,50 @@ All LXC instances created using this repository come pre-installed with Midnight
|
||||
Do not break established syntax in this file, as it is automatically updated by a Github Workflow
|
||||
|
||||
|
||||
## 2025-01-30
|
||||
|
||||
### Changed
|
||||
|
||||
### ✨ New Scripts
|
||||
|
||||
- New Script: IT-Tools [@nicedevil007](https://github.com/nicedevil007) ([#1862](https://github.com/community-scripts/ProxmoxVE/pull/1862))
|
||||
- New Script: Mattermost [@Dracentis](https://github.com/Dracentis) ([#1856](https://github.com/community-scripts/ProxmoxVE/pull/1856))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- Optimize PVE Manager Version-Check [@MickLesk](https://github.com/MickLesk) ([#1866](https://github.com/community-scripts/ProxmoxVE/pull/1866))
|
||||
|
||||
### 🌐 Website
|
||||
|
||||
- [API] Update build.func to set the status message correct [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1878](https://github.com/community-scripts/ProxmoxVE/pull/1878))
|
||||
- [Website] Update /data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1876](https://github.com/community-scripts/ProxmoxVE/pull/1876))
|
||||
- Fix IT-Tools Website Entry (Default | Alpine) [@MickLesk](https://github.com/MickLesk) ([#1869](https://github.com/community-scripts/ProxmoxVE/pull/1869))
|
||||
- fix: remove rounded styles from command primitive [@steveiliop56](https://github.com/steveiliop56) ([#1840](https://github.com/community-scripts/ProxmoxVE/pull/1840))
|
||||
|
||||
### 🧰 Maintenance
|
||||
|
||||
- [API] Update build.func: add function to see if a script failed or not [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1874](https://github.com/community-scripts/ProxmoxVE/pull/1874))
|
||||
|
||||
## 2025-01-29
|
||||
|
||||
### Changed
|
||||
|
||||
### ✨ New Scripts
|
||||
|
||||
- New Script: Prometheus Proxmox VE Exporter [@andygrunwald](https://github.com/andygrunwald) ([#1805](https://github.com/community-scripts/ProxmoxVE/pull/1805))
|
||||
- New Script: Clean Orphaned LVM [@MickLesk](https://github.com/MickLesk) ([#1838](https://github.com/community-scripts/ProxmoxVE/pull/1838))
|
||||
|
||||
### 🌐 Website
|
||||
|
||||
- Patch http Url to https in build.func and /data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1849](https://github.com/community-scripts/ProxmoxVE/pull/1849))
|
||||
- [Frontend] Add /data to show API results [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1841](https://github.com/community-scripts/ProxmoxVE/pull/1841))
|
||||
- Update clean-orphaned-lvm.json [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1843](https://github.com/community-scripts/ProxmoxVE/pull/1843))
|
||||
|
||||
### 🧰 Maintenance
|
||||
|
||||
- Update build.func [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1851](https://github.com/community-scripts/ProxmoxVE/pull/1851))
|
||||
- [Diagnostic] Introduced optional lxc install diagnostics via API call [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1801](https://github.com/community-scripts/ProxmoxVE/pull/1801))
|
||||
|
||||
## 2025-01-28
|
||||
|
||||
### Changed
|
||||
|
||||
62
ct/alpine-it-tools.sh
Normal file
62
ct/alpine-it-tools.sh
Normal file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: nicedevil007 (NiceDevil)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
|
||||
# App Default Values
|
||||
APP="Alpine-IT-Tools"
|
||||
var_tags="alpine;development"
|
||||
var_cpu="1"
|
||||
var_ram="256"
|
||||
var_disk="0.2"
|
||||
var_os="alpine"
|
||||
var_version="3.21"
|
||||
var_unprivileged="1"
|
||||
|
||||
# App Output & Base Settings
|
||||
header_info "$APP"
|
||||
base_settings
|
||||
|
||||
# Core
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
if [[ ! -d /usr/share/nginx/html ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
RELEASE=$(curl -s https://api.github.com/repos/CorentinTh/it-tools/releases/latest | grep '"tag_name":' | cut -d '"' -f4)
|
||||
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
|
||||
DOWNLOAD_URL="https://github.com/CorentinTh/it-tools/releases/download/${RELEASE}/it-tools-${RELEASE#v}.zip"
|
||||
msg_info "Updating ${APP} LXC"
|
||||
curl -fsSL -o it-tools.zip "$DOWNLOAD_URL"
|
||||
mkdir -p /usr/share/nginx/html
|
||||
rm -rf /usr/share/nginx/html/*
|
||||
unzip -q it-tools.zip -d /tmp/it-tools
|
||||
cp -r /tmp/it-tools/dist/* /usr/share/nginx/html
|
||||
rm -rf /tmp/it-tools
|
||||
rm -f it-tools.zip
|
||||
msg_ok "Updated Successfully"
|
||||
else
|
||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||
fi
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed Successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
||||
6
ct/headers/alpine-it-tools
Normal file
6
ct/headers/alpine-it-tools
Normal file
@ -0,0 +1,6 @@
|
||||
___ __ _ __________ ______ __
|
||||
/ | / /___ (_)___ ___ / _/_ __/ /_ __/___ ____ / /____
|
||||
/ /| | / / __ \/ / __ \/ _ \______ / / / /_____/ / / __ \/ __ \/ / ___/
|
||||
/ ___ |/ / /_/ / / / / / __/_____// / / /_____/ / / /_/ / /_/ / (__ )
|
||||
/_/ |_/_/ .___/_/_/ /_/\___/ /___/ /_/ /_/ \____/\____/_/____/
|
||||
/_/
|
||||
6
ct/headers/mattermost
Normal file
6
ct/headers/mattermost
Normal file
@ -0,0 +1,6 @@
|
||||
__ ___ __ __ __
|
||||
/ |/ /___ _/ /_/ /____ _________ ___ ____ _____/ /_
|
||||
/ /|_/ / __ `/ __/ __/ _ \/ ___/ __ `__ \/ __ \/ ___/ __/
|
||||
/ / / / /_/ / /_/ /_/ __/ / / / / / / / /_/ (__ ) /_
|
||||
/_/ /_/\__,_/\__/\__/\___/_/ /_/ /_/ /_/\____/____/\__/
|
||||
|
||||
12
ct/headers/prometheus-pve-exporter
Normal file
12
ct/headers/prometheus-pve-exporter
Normal file
@ -0,0 +1,12 @@
|
||||
____ __ __ ____
|
||||
/ __ \_________ ____ ___ ___ / /_/ /_ ___ __ _______ / __ \
|
||||
/ /_/ / ___/ __ \/ __ `__ \/ _ \/ __/ __ \/ _ \/ / / / ___/_____/ /_/ /
|
||||
/ ____/ / / /_/ / / / / / / __/ /_/ / / / __/ /_/ (__ )_____/ ____/
|
||||
/_/ /_/ \____/_/ /_/ /_/\___/\__/_/ /_/\___/\__,_/____/ /_/
|
||||
|
||||
_ ________ ______ __
|
||||
| | / / ____/ / ____/ ______ ____ _____/ /____ _____
|
||||
| | / / __/______/ __/ | |/_/ __ \/ __ \/ ___/ __/ _ \/ ___/
|
||||
| |/ / /__/_____/ /____> </ /_/ / /_/ / / / /_/ __/ /
|
||||
|___/_____/ /_____/_/|_/ .___/\____/_/ \__/\___/_/
|
||||
/_/
|
||||
49
ct/mattermost.sh
Normal file
49
ct/mattermost.sh
Normal file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: Kaedon Cleland-Host (dracentis)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://mattermost.com/
|
||||
|
||||
# App Default Values
|
||||
APP="Mattermost"
|
||||
var_tags="collaboration"
|
||||
var_cpu="1"
|
||||
var_ram="2048"
|
||||
var_disk="8"
|
||||
var_os="ubuntu"
|
||||
var_version="24.04"
|
||||
var_unprivileged="1"
|
||||
|
||||
# App Output & Base Settings
|
||||
header_info "$APP"
|
||||
base_settings
|
||||
|
||||
# Core
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -f /etc/apt/sources.list.d/mattermost.list ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
msg_info "Updating ${APP} LXC"
|
||||
apt-get update &>/dev/null
|
||||
apt-get -y upgrade &>/dev/null
|
||||
msg_ok "Updated Successfully"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed Successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8065${CL}"
|
||||
57
ct/prometheus-pve-exporter.sh
Normal file
57
ct/prometheus-pve-exporter.sh
Normal file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: Andy Grunwald (andygrunwald)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/prometheus-pve/prometheus-pve-exporter
|
||||
|
||||
# App Default Values
|
||||
APP="Prometheus-PVE-Exporter"
|
||||
var_tags="monitoring"
|
||||
var_cpu="1"
|
||||
var_ram="1024"
|
||||
var_disk="2"
|
||||
var_os="debian"
|
||||
var_version="12"
|
||||
var_unprivileged="1"
|
||||
|
||||
# App Output & Base Settings
|
||||
header_info "$APP"
|
||||
base_settings
|
||||
|
||||
# Core
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -f /etc/systemd/system/prometheus-pve-exporter.service ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
msg_info "Stopping ${APP}"
|
||||
systemctl stop prometheus-pve-exporter
|
||||
msg_ok "Stopped ${APP}"
|
||||
|
||||
msg_info "Updating ${APP}"
|
||||
pip install prometheus-pve-exporter --upgrade --root-user-action=ignore &>/dev/null
|
||||
msg_ok "Updated ${APP}"
|
||||
|
||||
msg_info "Starting ${APP}"
|
||||
systemctl start prometheus-pve-exporter
|
||||
msg_ok "Started ${APP}"
|
||||
msg_ok "Updated Successfully"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed Successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9221${CL}"
|
||||
99
frontend/package-lock.json
generated
99
frontend/package-lock.json
generated
@ -23,6 +23,8 @@
|
||||
"@radix-ui/react-tabs": "^1.1.0",
|
||||
"@radix-ui/react-tooltip": "^1.1.2",
|
||||
"@vercel/analytics": "^1.2.2",
|
||||
"chart.js": "^4.4.1",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
@ -37,7 +39,9 @@
|
||||
"pocketbase": "^0.21.4",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"react": "19.0.0-rc-02c0e824-20241028",
|
||||
"react-chartjs-2": "^5.3.0",
|
||||
"react-code-blocks": "^0.1.6",
|
||||
"react-datepicker": "^7.6.0",
|
||||
"react-day-picker": "8.10.1",
|
||||
"react-dom": "19.0.0-rc-02c0e824-20241028",
|
||||
"react-icons": "^5.1.0",
|
||||
@ -1083,9 +1087,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/utils": {
|
||||
"version": "0.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
|
||||
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
|
||||
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
@ -1572,6 +1576,12 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@kurkle/color": {
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
|
||||
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "15.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.3.tgz",
|
||||
@ -3194,7 +3204,7 @@
|
||||
"version": "19.0.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/types-react/-/types-react-19.0.0-rc.1.tgz",
|
||||
"integrity": "sha512-RshndUfqTW6K3STLPis8BtAYCGOkMbtvYsi90gmVNDZBXUyUc5juf2PE9LfS/JmOlUIRO8cWTS/1MTnmhjDqyQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
@ -3204,7 +3214,7 @@
|
||||
"version": "19.0.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/types-react-dom/-/types-react-dom-19.0.0-rc.1.tgz",
|
||||
"integrity": "sha512-VSLZJl8VXCD0fAWp7DUTFUDCcZ8DVXOQmjhJMD03odgeFmu14ZQJHCXeETm3BEAhJqfgJaFkLnGkQv88sRx0fQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
@ -4152,6 +4162,27 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/chart.js": {
|
||||
"version": "4.4.7",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz",
|
||||
"integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@kurkle/color": "^0.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"pnpm": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chartjs-plugin-datalabels": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz",
|
||||
"integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"chart.js": ">=3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/check-error": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
|
||||
@ -7774,6 +7805,7 @@
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
|
||||
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
@ -7999,6 +8031,16 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-chartjs-2": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz",
|
||||
"integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"chart.js": "^4.1.1",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-code-blocks": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/react-code-blocks/-/react-code-blocks-0.1.6.tgz",
|
||||
@ -8017,6 +8059,46 @@
|
||||
"react": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/react-datepicker": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.6.0.tgz",
|
||||
"integrity": "sha512-9cQH6Z/qa4LrGhzdc3XoHbhrxNcMi9MKjZmYgF/1MNNaJwvdSjv3Xd+jjvrEEbKEf71ZgCA3n7fQbdwd70qCRw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "^0.27.0",
|
||||
"clsx": "^2.1.1",
|
||||
"date-fns": "^3.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc",
|
||||
"react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/react-datepicker/node_modules/@floating-ui/react": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.3.tgz",
|
||||
"integrity": "sha512-CLHnes3ixIFFKVQDdICjel8muhFLOBdQH7fgtHNPY8UbCNqbeKZ262G7K66lGQOUQWWnYocf7ZbUsLJgGfsLHg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom": "^2.1.2",
|
||||
"@floating-ui/utils": "^0.2.9",
|
||||
"tabbable": "^6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=17.0.0",
|
||||
"react-dom": ">=17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-datepicker/node_modules/date-fns": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
|
||||
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/react-day-picker": {
|
||||
"version": "8.10.1",
|
||||
"resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
|
||||
@ -9055,6 +9137,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tabbable": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
|
||||
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",
|
||||
@ -9420,6 +9508,7 @@
|
||||
"version": "5.6.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
|
||||
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
"@radix-ui/react-tabs": "^1.1.0",
|
||||
"@radix-ui/react-tooltip": "^1.1.2",
|
||||
"@vercel/analytics": "^1.2.2",
|
||||
"chart.js": "^4.4.1",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
@ -48,7 +50,9 @@
|
||||
"pocketbase": "^0.21.4",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"react": "19.0.0-rc-02c0e824-20241028",
|
||||
"react-chartjs-2": "^5.3.0",
|
||||
"react-code-blocks": "^0.1.6",
|
||||
"react-datepicker": "^7.6.0",
|
||||
"react-day-picker": "8.10.1",
|
||||
"react-dom": "19.0.0-rc-02c0e824-20241028",
|
||||
"react-icons": "^5.1.0",
|
||||
@ -63,20 +67,20 @@
|
||||
"@testing-library/dom": "^10.4.0",
|
||||
"@testing-library/react": "^16.0.1",
|
||||
"@types/node": "^22",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.8.1",
|
||||
"@typescript-eslint/parser": "^8.8.1",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"eslint-config-next": "15.0.2",
|
||||
"eslint": "^9.13.0",
|
||||
"eslint-config-next": "15.0.2",
|
||||
"jsdom": "^25.0.1",
|
||||
"postcss": "^8",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"tailwindcss": "^3.4.9",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tailwindcss-animated": "^1.1.2",
|
||||
"tailwindcss": "^3.4.9",
|
||||
"typescript": "^5",
|
||||
"vite-tsconfig-paths": "^5.1.3",
|
||||
"vitest": "^2.1.6"
|
||||
|
||||
248
frontend/src/app/data/page.tsx
Normal file
248
frontend/src/app/data/page.tsx
Normal file
@ -0,0 +1,248 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import DatePicker from 'react-datepicker';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import { string } from "zod";
|
||||
import ApplicationChart from "../../components/ApplicationChart";
|
||||
|
||||
interface DataModel {
|
||||
id: number;
|
||||
ct_type: number;
|
||||
disk_size: number;
|
||||
core_count: number;
|
||||
ram_size: number;
|
||||
verbose: string;
|
||||
os_type: string;
|
||||
os_version: string;
|
||||
hn: string;
|
||||
disableip6: string;
|
||||
ssh: string;
|
||||
tags: string;
|
||||
nsapp: string;
|
||||
created_at: string;
|
||||
method: string;
|
||||
pve_version: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
|
||||
const DataFetcher: React.FC = () => {
|
||||
const [data, setData] = useState<DataModel[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [startDate, setStartDate] = useState<Date | null>(null);
|
||||
const [endDate, setEndDate] = useState<Date | null>(null);
|
||||
const [sortConfig, setSortConfig] = useState<{ key: keyof DataModel | null, direction: 'ascending' | 'descending' }>({ key: 'id', direction: 'descending' });
|
||||
const [itemsPerPage, setItemsPerPage] = useState(5);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [showChart, setShowChart] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await fetch("https://api.htl-braunau.at/data/json");
|
||||
if (!response.ok) throw new Error("Failed to fetch data: ${response.statusText}");
|
||||
const result: DataModel[] = await response.json();
|
||||
setData(result);
|
||||
} catch (err) {
|
||||
setError((err as Error).message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
|
||||
const filteredData = data.filter(item => {
|
||||
const matchesSearchQuery = Object.values(item).some(value =>
|
||||
value.toString().toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
const itemDate = new Date(item.created_at);
|
||||
const matchesDateRange = (!startDate || itemDate >= startDate) && (!endDate || itemDate <= endDate);
|
||||
return matchesSearchQuery && matchesDateRange;
|
||||
});
|
||||
|
||||
const sortedData = React.useMemo(() => {
|
||||
let sortableData = [...filteredData];
|
||||
if (sortConfig.key !== null) {
|
||||
sortableData.sort((a, b) => {
|
||||
if (sortConfig.key !== null && a[sortConfig.key] < b[sortConfig.key]) {
|
||||
return sortConfig.direction === 'ascending' ? -1 : 1;
|
||||
}
|
||||
if (sortConfig.key !== null && a[sortConfig.key] > b[sortConfig.key]) {
|
||||
return sortConfig.direction === 'ascending' ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
return sortableData;
|
||||
}, [filteredData, sortConfig]);
|
||||
|
||||
const requestSort = (key: keyof DataModel | null) => {
|
||||
let direction: 'ascending' | 'descending' = 'ascending';
|
||||
if (sortConfig.key === key && sortConfig.direction === 'ascending') {
|
||||
direction = 'descending';
|
||||
} else if (sortConfig.key === key && sortConfig.direction === 'descending') {
|
||||
direction = 'ascending';
|
||||
} else {
|
||||
direction = 'descending';
|
||||
}
|
||||
setSortConfig({ key, direction });
|
||||
};
|
||||
|
||||
interface SortConfig {
|
||||
key: keyof DataModel | null;
|
||||
direction: 'ascending' | 'descending';
|
||||
}
|
||||
|
||||
const formatDate = (dateString: string): string => {
|
||||
const date = new Date(dateString);
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
const timezoneOffset = dateString.slice(-6);
|
||||
return `${day}.${month}.${year} ${hours}:${minutes} ${timezoneOffset} GMT`;
|
||||
};
|
||||
|
||||
const handleItemsPerPageChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
setItemsPerPage(Number(event.target.value));
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const paginatedData = sortedData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
|
||||
|
||||
if (loading) return <p>Loading...</p>;
|
||||
if (error) return <p>Error: {error}</p>;
|
||||
|
||||
|
||||
return (
|
||||
<div className="p-6 mt-20">
|
||||
<h1 className="text-2xl font-bold mb-4 text-center">Created LXCs</h1>
|
||||
<div className="mb-4 flex space-x-4">
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
value={searchQuery}
|
||||
onChange={e => setSearchQuery(e.target.value)}
|
||||
className="p-2 border"
|
||||
/>
|
||||
<label className="text-sm text-gray-600 mt-1 block">Search by keyword</label>
|
||||
</div>
|
||||
<div>
|
||||
<DatePicker
|
||||
selected={startDate}
|
||||
onChange={date => setStartDate(date)}
|
||||
selectsStart
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
placeholderText="Start date"
|
||||
className="p-2 border"
|
||||
/>
|
||||
<label className="text-sm text-gray-600 mt-1 block">Set a start date</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<DatePicker
|
||||
selected={endDate}
|
||||
onChange={date => setEndDate(date)}
|
||||
selectsEnd
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
placeholderText="End date"
|
||||
className="p-2 border"
|
||||
/>
|
||||
<label className="text-sm text-gray-600 mt-1 block">Set a end date</label>
|
||||
</div>
|
||||
</div>
|
||||
<ApplicationChart data={filteredData} />
|
||||
<div className="mb-4 flex justify-between items-center">
|
||||
<p className="text-lg font-bold">{filteredData.length} results found</p>
|
||||
<select value={itemsPerPage} onChange={handleItemsPerPageChange} className="p-2 border">
|
||||
<option value={25}>25</option>
|
||||
<option value={50}>50</option>
|
||||
<option value={100}>100</option>
|
||||
<option value={200}>200</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="overflow-x-auto">
|
||||
<div className="overflow-y-auto lg:overflow-y-visible">
|
||||
<table className="min-w-full table-auto border-collapse">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('status')}>Status</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('nsapp')}>Application</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('os_type')}>OS</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('os_version')}>OS Version</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('disk_size')}>Disk Size</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('core_count')}>Core Count</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('ram_size')}>RAM Size</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('hn')}>Hostname</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('ssh')}>SSH</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('verbose')}>Verb</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('tags')}>Tags</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('method')}>Method</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('pve_version')}>PVE Version</th>
|
||||
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('created_at')}>Created At</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{paginatedData.map((item, index) => (
|
||||
<tr key={index}>
|
||||
<td className="px-4 py-2 border-b">
|
||||
{item.status === "done" ? (
|
||||
"✔️"
|
||||
) : item.status === "failed" ? (
|
||||
"❌"
|
||||
) : item.status === "installing" ? (
|
||||
"🔄"
|
||||
) : (
|
||||
item.status
|
||||
)}
|
||||
</td>
|
||||
<td className="px-4 py-2 border-b">{item.nsapp}</td>
|
||||
<td className="px-4 py-2 border-b">{item.os_type}</td>
|
||||
<td className="px-4 py-2 border-b">{item.os_version}</td>
|
||||
<td className="px-4 py-2 border-b">{item.disk_size}</td>
|
||||
<td className="px-4 py-2 border-b">{item.core_count}</td>
|
||||
<td className="px-4 py-2 border-b">{item.ram_size}</td>
|
||||
<td className="px-4 py-2 border-b">{item.hn}</td>
|
||||
<td className="px-4 py-2 border-b">{item.ssh}</td>
|
||||
<td className="px-4 py-2 border-b">{item.verbose}</td>
|
||||
<td className="px-4 py-2 border-b">{item.tags.replace(/;/g, ' ')}</td>
|
||||
<td className="px-4 py-2 border-b">{item.method}</td>
|
||||
<td className="px-4 py-2 border-b">{item.pve_version}</td>
|
||||
<td className="px-4 py-2 border-b">{formatDate(item.created_at)}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 flex justify-between items-center">
|
||||
<button
|
||||
onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
|
||||
disabled={currentPage === 1}
|
||||
className="p-2 border"
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
<span>Page {currentPage}</span>
|
||||
<button
|
||||
onClick={() => setCurrentPage(prev => (prev * itemsPerPage < sortedData.length ? prev + 1 : prev))}
|
||||
disabled={currentPage * itemsPerPage >= sortedData.length}
|
||||
className="p-2 border"
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default DataFetcher;
|
||||
132
frontend/src/components/ApplicationChart.tsx
Normal file
132
frontend/src/components/ApplicationChart.tsx
Normal file
@ -0,0 +1,132 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { Pie } from "react-chartjs-2";
|
||||
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
|
||||
import ChartDataLabels from "chartjs-plugin-datalabels";
|
||||
import Modal from "@/components/Modal";
|
||||
|
||||
ChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);
|
||||
|
||||
interface ApplicationChartProps {
|
||||
data: { nsapp: string }[];
|
||||
}
|
||||
|
||||
const ApplicationChart: React.FC<ApplicationChartProps> = ({ data }) => {
|
||||
const [isChartOpen, setIsChartOpen] = useState(false);
|
||||
const [isTableOpen, setIsTableOpen] = useState(false);
|
||||
const [chartStartIndex, setChartStartIndex] = useState(0);
|
||||
const [tableLimit, setTableLimit] = useState(20);
|
||||
|
||||
const appCounts: Record<string, number> = {};
|
||||
data.forEach((item) => {
|
||||
appCounts[item.nsapp] = (appCounts[item.nsapp] || 0) + 1;
|
||||
});
|
||||
|
||||
const sortedApps = Object.entries(appCounts).sort(([, a], [, b]) => b - a);
|
||||
const chartApps = sortedApps.slice(chartStartIndex, chartStartIndex + 20);
|
||||
|
||||
const chartData = {
|
||||
labels: chartApps.map(([name]) => name),
|
||||
datasets: [
|
||||
{
|
||||
label: "Applications",
|
||||
data: chartApps.map(([, count]) => count),
|
||||
backgroundColor: [
|
||||
"#ff6384",
|
||||
"#36a2eb",
|
||||
"#ffce56",
|
||||
"#4bc0c0",
|
||||
"#9966ff",
|
||||
"#ff9f40",
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mt-6 text-center">
|
||||
<button
|
||||
onClick={() => setIsChartOpen(true)}
|
||||
className="m-2 p-2 bg-blue-500 text-white rounded"
|
||||
>
|
||||
📊 Open Chart
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsTableOpen(true)}
|
||||
className="m-2 p-2 bg-green-500 text-white rounded"
|
||||
>
|
||||
📋 Open Table
|
||||
</button>
|
||||
|
||||
<Modal isOpen={isChartOpen} onClose={() => setIsChartOpen(false)}>
|
||||
<h2 className="text-xl font-bold text-black dark:text-white mb-4">Top Applications (Chart)</h2>
|
||||
<div className="w-3/4 mx-auto">
|
||||
<Pie
|
||||
data={chartData}
|
||||
options={{
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
datalabels: {
|
||||
color: "white",
|
||||
font: { weight: "bold" },
|
||||
formatter: (value, context) =>
|
||||
context.chart.data.labels?.[context.dataIndex] || "",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-center space-x-4 mt-4">
|
||||
<button
|
||||
onClick={() => setChartStartIndex(Math.max(0, chartStartIndex - 20))}
|
||||
disabled={chartStartIndex === 0}
|
||||
className="p-2 border rounded bg-blue-500 text-white"
|
||||
>
|
||||
◀ Last 20
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setChartStartIndex(chartStartIndex + 20)}
|
||||
disabled={chartStartIndex + 20 >= sortedApps.length}
|
||||
className="p-2 border rounded bg-blue-500 text-white"
|
||||
>
|
||||
Next 20 ▶
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal isOpen={isTableOpen} onClose={() => setIsTableOpen(false)}>
|
||||
<h2 className="text-xl font-bold text-black dark:text-white mb-4">Application Count Table</h2>
|
||||
<table className="w-full border-collapse border border-gray-600 dark:border-gray-500">
|
||||
<thead>
|
||||
<tr className="bg-gray-800 text-white">
|
||||
<th className="p-2 border">Application</th>
|
||||
<th className="p-2 border">Count</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sortedApps.slice(0, tableLimit).map(([name, count]) => (
|
||||
<tr key={name} className="hover:bg-gray-200 dark:hover:bg-gray-700 text-black dark:text-white">
|
||||
<td className="p-2 border">{name}</td>
|
||||
<td className="p-2 border">{count}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{tableLimit < sortedApps.length && (
|
||||
<div className="text-center mt-4">
|
||||
<button
|
||||
onClick={() => setTableLimit(tableLimit + 20)}
|
||||
className="p-2 bg-green-500 text-white rounded"
|
||||
>
|
||||
Load More
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApplicationChart;
|
||||
29
frontend/src/components/Modal.tsx
Normal file
29
frontend/src/components/Modal.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
interface ModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const Modal: React.FC<ModalProps> = ({ isOpen, onClose, children }) => {
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50">
|
||||
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg shadow-lg w-11/12 max-w-4xl relative max-h-[90vh] overflow-y-auto">
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="absolute top-2 right-2 bg-red-500 text-white p-1 rounded"
|
||||
>
|
||||
✖
|
||||
</button>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Modal;
|
||||
@ -15,7 +15,7 @@ const Command = React.forwardRef<
|
||||
<CommandPrimitive
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
||||
"flex h-full w-full flex-col overflow-hidden bg-popover text-popover-foreground",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
56
install/alpine-it-tools-install.sh
Normal file
56
install/alpine-it-tools-install.sh
Normal file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: nicedevil007 (NiceDevil)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
|
||||
source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apk add \
|
||||
curl \
|
||||
mc \
|
||||
nginx \
|
||||
unzip
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Installing IT-Tools"
|
||||
RELEASE=$(curl -s https://api.github.com/repos/CorentinTh/it-tools/releases/latest | grep '"tag_name":' | cut -d '"' -f4)
|
||||
DOWNLOAD_URL="https://github.com/CorentinTh/it-tools/releases/download/${RELEASE}/it-tools-${RELEASE#v}.zip"
|
||||
|
||||
curl -fsSL -o it-tools.zip "$DOWNLOAD_URL"
|
||||
mkdir -p /usr/share/nginx/html
|
||||
unzip -q it-tools.zip -d /tmp/it-tools
|
||||
cp -r /tmp/it-tools/dist/* /usr/share/nginx/html
|
||||
cat <<'EOF' > /etc/nginx/http.d/default.conf
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
$STD rc-update add nginx default
|
||||
$STD rc-service nginx start
|
||||
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
|
||||
msg_ok "Installed IT-Tools"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
|
||||
msg_info "Cleaning up"
|
||||
rm -rf /tmp/it-tools
|
||||
rm -f it-tools.zip
|
||||
$STD apk cache clean
|
||||
msg_ok "Cleaned"
|
||||
60
install/mattermost-install.sh
Normal file
60
install/mattermost-install.sh
Normal file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: Kaedon Cleland-Host (dracentis)
|
||||
# License: MIT
|
||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt-get install -y \
|
||||
curl \
|
||||
sudo \
|
||||
mc \
|
||||
gpg \
|
||||
postgresql
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Setting up PostgreSQL"
|
||||
DB_NAME=mattermost
|
||||
DB_USER=mmuser
|
||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
|
||||
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;"
|
||||
$STD sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASS';"
|
||||
$STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME to $DB_USER;"
|
||||
$STD sudo -u postgres psql -c "ALTER DATABASE $DB_NAME OWNER TO $DB_USER;"
|
||||
$STD sudo -u postgres psql -c "GRANT USAGE, CREATE ON SCHEMA PUBLIC TO $DB_USER;"
|
||||
{
|
||||
echo "Mattermost Credentials"
|
||||
echo "Database User: $DB_USER"
|
||||
echo "Database Password: $DB_PASS"
|
||||
echo "Database Name: $DB_NAME"
|
||||
} >> ~/mattermost.creds
|
||||
msg_ok "Set up PostgreSQL"
|
||||
|
||||
msg_info "Installing Mattermost"
|
||||
IPADDRESS=$(hostname -I | awk '{print $1}')
|
||||
curl -sL -o /usr/share/keyrings/mattermost-archive-keyring.gpg https://deb.packages.mattermost.com/pubkey.gpg
|
||||
sh -c 'curl -sL https://deb.packages.mattermost.com/repo-setup.sh | sudo bash -s mattermost' >/dev/null
|
||||
$STD apt-get update
|
||||
$STD apt-get install -y mattermost
|
||||
$STD install -C -m 600 -o mattermost -g mattermost /opt/mattermost/config/config.defaults.json /opt/mattermost/config/config.json
|
||||
sed -i -e "/DataSource/c\ \"DataSource\": \"postgres://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME?sslmode=disable&connect_timeout=10\"," \
|
||||
-e "/SiteURL/c\ \"SiteURL\": \"http://$IPADDRESS:8065\"," /opt/mattermost/config/config.json
|
||||
systemctl enable -q --now mattermost.service
|
||||
msg_ok "Installed Mattermost"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
|
||||
msg_info "Cleaning up"
|
||||
$STD apt-get -y autoremove
|
||||
$STD apt-get -y autoclean
|
||||
msg_ok "Cleaned"
|
||||
70
install/prometheus-pve-exporter-install.sh
Normal file
70
install/prometheus-pve-exporter-install.sh
Normal file
@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: Andy Grunwald (andygrunwald)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/prometheus-pve/prometheus-pve-exporter
|
||||
|
||||
source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt-get install -y \
|
||||
curl \
|
||||
sudo \
|
||||
mc
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Setup Python3"
|
||||
$STD apt-get install -y \
|
||||
python3 \
|
||||
python3-pip
|
||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||
msg_ok "Setup Python3"
|
||||
|
||||
msg_info "Installing Prometheus Proxmox VE Exporter"
|
||||
python3 -m pip install --quiet --root-user-action=ignore prometheus-pve-exporter
|
||||
mkdir -p /opt/prometheus-pve-exporter
|
||||
cat <<EOF > /opt/prometheus-pve-exporter/pve.yml
|
||||
default:
|
||||
user: prometheus@pve
|
||||
password: sEcr3T!
|
||||
verify_ssl: false
|
||||
EOF
|
||||
msg_ok "Installed Prometheus Proxmox VE Exporter"
|
||||
|
||||
msg_info "Creating Service"
|
||||
cat <<EOF >/etc/systemd/system/prometheus-pve-exporter.service
|
||||
[Unit]
|
||||
Description=Prometheus Proxmox VE Exporter
|
||||
Documentation=https://github.com/znerol/prometheus-pve-exporter
|
||||
After=syslog.target network.target
|
||||
|
||||
[Service]
|
||||
User=root
|
||||
Restart=always
|
||||
Type=simple
|
||||
ExecStart=pve_exporter \
|
||||
--config.file=/opt/prometheus-pve-exporter/pve.yml \
|
||||
--web.listen-address=0.0.0.0:9221
|
||||
ExecReload=/bin/kill -HUP \$MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl enable -q --now prometheus-pve-exporter
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
|
||||
msg_info "Cleaning up"
|
||||
$STD apt-get -y autoremove
|
||||
$STD apt-get -y autoclean
|
||||
msg_ok "Cleaned"
|
||||
34
json/alpine-it-tools.json
Normal file
34
json/alpine-it-tools.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "Alpine-IT-Tools",
|
||||
"slug": "alpine-it-tools",
|
||||
"categories": [
|
||||
20
|
||||
],
|
||||
"date_created": "2025-01-30",
|
||||
"type": "ct",
|
||||
"updateable": true,
|
||||
"privileged": false,
|
||||
"interface_port": 80,
|
||||
"documentation": null,
|
||||
"website": "https://it-tools.tech/",
|
||||
"logo": "https://raw.githubusercontent.com/CorentinTh/it-tools/08d977b8cdb7ffb76adfa18ba6eb4b73795ec814/public/safari-pinned-tab.svg",
|
||||
"description": "IT-Tools is a web-based suite of utilities designed to streamline and simplify various IT tasks, providing tools for developers and system administrators to manage their workflows efficiently.",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "ct/alpine-it-tools.sh",
|
||||
"resources": {
|
||||
"cpu": 1,
|
||||
"ram": 256,
|
||||
"hdd": 0.2,
|
||||
"os": "alpine",
|
||||
"version": "3.21"
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_credentials": {
|
||||
"username": null,
|
||||
"password": null
|
||||
},
|
||||
"notes": []
|
||||
}
|
||||
39
json/clean-orphaned-lvm.json
Normal file
39
json/clean-orphaned-lvm.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "Proxmox Clean Orphaned LVM",
|
||||
"slug": "clean-orphaned-lvm",
|
||||
"categories": [
|
||||
1
|
||||
],
|
||||
"date_created": "2025-01-29",
|
||||
"type": "misc",
|
||||
"updateable": false,
|
||||
"privileged": false,
|
||||
"interface_port": null,
|
||||
"documentation": null,
|
||||
"website": null,
|
||||
"logo": "https://raw.githubusercontent.com/home-assistant/brands/master/core_integrations/proxmoxve/icon.png",
|
||||
"description": "This script helps Proxmox users identify and remove orphaned LVM volumes that are no longer associated with any VM or LXC container. It scans all LVM volumes, detects unused ones, and provides an interactive prompt to delete them safely. System-critical volumes like root, swap, and data are excluded to prevent accidental deletion.",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "misc/clean-orphaned-lvm.sh",
|
||||
"resources": {
|
||||
"cpu": null,
|
||||
"ram": null,
|
||||
"hdd": null,
|
||||
"os": null,
|
||||
"version": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_credentials": {
|
||||
"username": null,
|
||||
"password": null
|
||||
},
|
||||
"notes": [
|
||||
{
|
||||
"text": "Execute within the Proxmox shell",
|
||||
"type": "info"
|
||||
}
|
||||
]
|
||||
}
|
||||
34
json/mattermost.json
Normal file
34
json/mattermost.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "Mattermost",
|
||||
"slug": "mattermost",
|
||||
"categories": [
|
||||
25
|
||||
],
|
||||
"date_created": "2025-01-30",
|
||||
"type": "ct",
|
||||
"updateable": false,
|
||||
"privileged": false,
|
||||
"interface_port": 8065,
|
||||
"documentation": null,
|
||||
"website": "https://mattermost.com/",
|
||||
"logo": "https://avatars.githubusercontent.com/u/9828093?s=200&v=4",
|
||||
"description": "Mattermost is an open source platform for secure collaboration across the entire software development lifecycle. It's written in Go and React and runs as a single Linux binary with MySQL or PostgreSQL. It has a slimilar interface and features to Slack or Discord.",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "ct/mattermost.sh",
|
||||
"resources": {
|
||||
"cpu": 1,
|
||||
"ram": 2048,
|
||||
"hdd": 8,
|
||||
"os": "ubuntu",
|
||||
"version": "24.04"
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_credentials": {
|
||||
"username": null,
|
||||
"password": null
|
||||
},
|
||||
"notes": []
|
||||
}
|
||||
40
json/prometheus-pve-exporter.json
Normal file
40
json/prometheus-pve-exporter.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "Prometheus Proxmox VE Exporter",
|
||||
"slug": "prometheus-proxmox-ve-exporter",
|
||||
"categories": [
|
||||
1,
|
||||
9
|
||||
],
|
||||
"date_created": "2025-01-28",
|
||||
"type": "ct",
|
||||
"updateable": true,
|
||||
"privileged": false,
|
||||
"interface_port": 9221,
|
||||
"documentation": "https://github.com/prometheus-pve/prometheus-pve-exporter",
|
||||
"website": "https://github.com/prometheus-pve/prometheus-pve-exporter",
|
||||
"logo": "https://raw.githubusercontent.com/home-assistant/brands/master/core_integrations/proxmoxve/icon.png",
|
||||
"description": "An exporter that exposes information gathered from Proxmox VE node for use by the Prometheus monitoring system.",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "ct/prometheus-pve-exporter.sh",
|
||||
"resources": {
|
||||
"cpu": 1,
|
||||
"ram": 1024,
|
||||
"hdd": 2,
|
||||
"os": "debian",
|
||||
"version": "12"
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_credentials": {
|
||||
"username": null,
|
||||
"password": null
|
||||
},
|
||||
"notes": [
|
||||
{
|
||||
"text": "Please adjust the Proxmox credentials in the configuration file: /opt/prometheus-pve-exporter/pve.yml",
|
||||
"type": "info"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -102,7 +102,7 @@ while true; do
|
||||
esac
|
||||
done
|
||||
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[0-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[0-3](\.[0-9]+)*"; then
|
||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||
msg_error "⚠️ Requires Proxmox Virtual Environment Version 8.0 or later."
|
||||
msg_error "Exiting..."
|
||||
|
||||
332
misc/build.func
332
misc/build.func
@ -1,6 +1,7 @@
|
||||
# Copyright (c) 2021-2025 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# Co-Author: MickLesk
|
||||
# Co-Author: michelroegl-brunner
|
||||
# License: MIT
|
||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
@ -8,7 +9,10 @@ variables() {
|
||||
NSAPP=$(echo ${APP,,} | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces.
|
||||
var_install="${NSAPP}-install" # sets the var_install variable by appending "-install" to the value of NSAPP.
|
||||
INTEGER='^[0-9]+([.][0-9]+)?$' # it defines the INTEGER regular expression pattern.
|
||||
PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase
|
||||
PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase
|
||||
DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call.
|
||||
METHOD="default" # sets the METHOD variable to "default", used for the API call.
|
||||
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUDI variable.
|
||||
}
|
||||
|
||||
# This function sets various color variables using ANSI escape codes for formatting text in the terminal.
|
||||
@ -69,6 +73,7 @@ error_handler() {
|
||||
local exit_code="$?"
|
||||
local line_number="$1"
|
||||
local command="$2"
|
||||
post_update_to_api "failed"
|
||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||
echo -e "\n$error_message\n"
|
||||
}
|
||||
@ -137,16 +142,16 @@ root_check() {
|
||||
|
||||
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
|
||||
pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
sleep 2
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# When a node is running tens of containers, it's possible to exceed the kernel's cryptographic key storage allocations.
|
||||
# When a node is running tens of containers, it's possible to exceed the kernel's cryptographic key storage allocations.
|
||||
# These are tuneable, so verify if the currently deployment is approaching the limits, advise the user on how to tune the limits, and exit the script.
|
||||
# https://cleveruptime.com/docs/files/proc-key-users | https://docs.kernel.org/security/keys/core.html
|
||||
maxkeys_check() {
|
||||
@ -222,11 +227,11 @@ get_current_ip() {
|
||||
# Function to update the IP address in the MOTD file
|
||||
update_motd_ip() {
|
||||
MOTD_FILE="/etc/motd"
|
||||
|
||||
|
||||
if [ -f "$MOTD_FILE" ]; then
|
||||
# Remove existing IP Address lines to prevent duplication
|
||||
sed -i '/IP Address:/d' "$MOTD_FILE"
|
||||
|
||||
|
||||
IP=$(get_current_ip)
|
||||
# Add the new IP address
|
||||
echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >> "$MOTD_FILE"
|
||||
@ -359,34 +364,34 @@ exit_script() {
|
||||
advanced_settings() {
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Here is an instructional tip:" "To make a selection, use the Spacebar." 8 58
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Default distribution for $APP" "Default is: ${var_os} ${var_version} \n \nIf the default Linux distribution is not adhered to, script support will be discontinued. \n" 10 58
|
||||
if [ "$var_os" != "alpine" ]; then
|
||||
if [ "$var_os" != "alpine" ]; then
|
||||
var_default_os="${var_os}"
|
||||
var_os=""
|
||||
while [ -z "$var_os" ]; do
|
||||
if [ "$var_default_os" == "debian" ]; then
|
||||
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
|
||||
"debian" "" ON \
|
||||
"ubuntu" "" OFF \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$var_os" ]; then
|
||||
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
if [ "$var_default_os" == "debian" ]; then
|
||||
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
|
||||
"debian" "" ON \
|
||||
"ubuntu" "" OFF \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$var_os" ]; then
|
||||
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
if [ "$var_default_os" == "ubuntu" ]; then
|
||||
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
|
||||
"debian" "" OFF \
|
||||
"ubuntu" "" ON \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$var_os" ]; then
|
||||
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
if [ "$var_default_os" == "ubuntu" ]; then
|
||||
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
|
||||
"debian" "" OFF \
|
||||
"ubuntu" "" ON \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$var_os" ]; then
|
||||
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
@ -394,7 +399,7 @@ advanced_settings() {
|
||||
var_default_version="${var_version}"
|
||||
var_version=""
|
||||
while [ -z "$var_version" ]; do
|
||||
if [ "$var_default_version" == "11" ]; then
|
||||
if [ "$var_default_version" == "11" ]; then
|
||||
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DEBIAN VERSION" --radiolist "Choose Version" 10 58 2 \
|
||||
"11" "Bullseye" ON \
|
||||
"12" "Bookworm" OFF \
|
||||
@ -425,13 +430,13 @@ advanced_settings() {
|
||||
var_default_version="${var_version}"
|
||||
var_version=""
|
||||
while [ -z "$var_version" ]; do
|
||||
if [ "$var_default_version" == "20.04" ]; then
|
||||
if [ "$var_default_version" == "20.04" ]; then
|
||||
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
|
||||
"20.04" "Focal" ON \
|
||||
"22.04" "Jammy" OFF \
|
||||
"24.04" "Noble" OFF \
|
||||
"24.10" "Oracular" OFF \
|
||||
3>&1 1>&2 2>&3); then
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$var_version" ]; then
|
||||
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
|
||||
fi
|
||||
@ -444,7 +449,7 @@ advanced_settings() {
|
||||
"22.04" "Jammy" ON \
|
||||
"24.04" "Noble" OFF \
|
||||
"24.10" "Oracular" OFF \
|
||||
3>&1 1>&2 2>&3); then
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$var_version" ]; then
|
||||
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
|
||||
fi
|
||||
@ -452,25 +457,25 @@ advanced_settings() {
|
||||
exit_script
|
||||
fi
|
||||
elif [ "$var_default_version" == "24.04" ]; then
|
||||
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
|
||||
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
|
||||
"20.04" "Focal" OFF \
|
||||
"22.04" "Jammy" OFF \
|
||||
"24.04" "Noble" ON \
|
||||
"24.10" "Oracular" OFF \
|
||||
3>&1 1>&2 2>&3); then
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$var_version" ]; then
|
||||
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
|
||||
"20.04" "Focal" OFF \
|
||||
"22.04" "Jammy" OFF \
|
||||
"24.04" "Noble" OFF \
|
||||
"24.10" "Oracular" ON \
|
||||
3>&1 1>&2 2>&3); then
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$var_version" ]; then
|
||||
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
|
||||
fi
|
||||
@ -485,7 +490,7 @@ advanced_settings() {
|
||||
CT_DEFAULT_TYPE="${CT_TYPE}"
|
||||
CT_TYPE=""
|
||||
while [ -z "$CT_TYPE" ]; do
|
||||
if [ "$CT_DEFAULT_TYPE" == "1" ]; then
|
||||
if [ "$CT_DEFAULT_TYPE" == "1" ]; then
|
||||
if CT_TYPE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \
|
||||
"1" "Unprivileged" ON \
|
||||
"0" "Privileged" OFF \
|
||||
@ -550,7 +555,6 @@ advanced_settings() {
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
if CT_ID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Container ID" 8 58 $NEXTID --title "CONTAINER ID" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$CT_ID" ]; then
|
||||
CT_ID="$NEXTID"
|
||||
@ -741,14 +745,14 @@ advanced_settings() {
|
||||
|
||||
if ADV_TAGS=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Custom Tags?[If you remove all, there will be no tags!]" 8 58 ${TAGS} --title "Advanced Tags" 3>&1 1>&2 2>&3); then
|
||||
if [ -n "${ADV_TAGS}" ]; then
|
||||
ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]')
|
||||
TAGS="${ADV_TAGS}"
|
||||
ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]')
|
||||
TAGS="${ADV_TAGS}"
|
||||
else
|
||||
TAGS=";"
|
||||
fi
|
||||
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
|
||||
else
|
||||
exit_script
|
||||
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
|
||||
if [[ "$PW" == -password* ]]; then
|
||||
@ -771,7 +775,7 @@ advanced_settings() {
|
||||
fi
|
||||
else
|
||||
SSH_AUTHORIZED_KEY=""
|
||||
fi
|
||||
fi
|
||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
|
||||
VERB="yes"
|
||||
else
|
||||
@ -789,6 +793,144 @@ advanced_settings() {
|
||||
fi
|
||||
}
|
||||
|
||||
post_to_api() {
|
||||
local API_URL="http://api.community-scripts.org/upload"
|
||||
local pve_version="not found"
|
||||
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
|
||||
|
||||
JSON_PAYLOAD=$(cat <<EOF
|
||||
{
|
||||
"ct_type": $CT_TYPE,
|
||||
"disk_size": $DISK_SIZE,
|
||||
"core_count": $CORE_COUNT,
|
||||
"ram_size": $RAM_SIZE,
|
||||
"verbose": "$VERBOSE",
|
||||
"os_type": "$var_os",
|
||||
"os_version": "$var_version",
|
||||
"hn": "$HN",
|
||||
"disableip6": "$DISABLEIP6",
|
||||
"ssh": "$SSH",
|
||||
"tags": "$TAGS",
|
||||
"nsapp": "$NSAPP",
|
||||
"method": "$METHOD",
|
||||
"pve_version": "$pve_version",
|
||||
"status": "installing",
|
||||
"random_id": "$RANDOM_UUID"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
RESPONSE=$(curl -s -o response.txt -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$JSON_PAYLOAD")
|
||||
|
||||
if [ "$RESPONSE" -ne 201 ] && [ "$RESPONSE" -ne 302 ]; then
|
||||
msg_error "API request failed with HTTP code $RESPONSE"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
POST_UPDATE_DONE=false
|
||||
|
||||
post_update_to_api() {
|
||||
if [ "$POST_UPDATE_DONE" = true ]; then
|
||||
return 0
|
||||
fi
|
||||
local API_URL="http://api.community-scripts.org/upload/updatestatus"
|
||||
local status="${1:-}"
|
||||
JSON_PAYLOAD=$(cat <<EOF
|
||||
{
|
||||
"status": "$status",
|
||||
"random_id": "$RANDOM_UUID"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
RESPONSE=$(curl -s -o response.txt -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$JSON_PAYLOAD")
|
||||
|
||||
if [ "$RESPONSE" -ne 201 ] && [ "$RESPONSE" -ne 302 ]; then
|
||||
msg_error "API UPDATE request failed with HTTP code $RESPONSE"
|
||||
fi
|
||||
|
||||
POST_UPDATE_DONE=true
|
||||
}
|
||||
|
||||
diagnostics_check(){
|
||||
if ! [ -d "/usr/local/community-scripts" ]; then
|
||||
mkdir -p /usr/local/community-scripts
|
||||
fi
|
||||
|
||||
if ! [ -f "/usr/local/community-scripts/diagnostics" ]; then
|
||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS" --yesno "Send Diagnostics of LXC Installation?\n\n(This only transmits data without user data, just RAM, CPU, LXC name, ...)" 10 58); then
|
||||
cat <<EOF>/usr/local/community-scripts/diagnostics
|
||||
DIAGNOSTICS=yes
|
||||
|
||||
#This file is used to store the diagnostics settings for the Community-Scripts API.
|
||||
#https://github.com/community-scripts/ProxmoxVE/discussions/1836
|
||||
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
|
||||
#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
|
||||
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||
#This will disable the diagnostics feature.
|
||||
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||
#This will enable the diagnostics feature.
|
||||
#The following information will be sent:
|
||||
#"ct_type"
|
||||
#"disk_size"
|
||||
#"core_count"
|
||||
#"ram_size"
|
||||
#"verbose"
|
||||
#"os_type"
|
||||
#"os_version"
|
||||
#"hn"
|
||||
#"disableip6"
|
||||
#"ssh"
|
||||
#"tags"
|
||||
#"nsapp"
|
||||
#"method"
|
||||
#"pve_version"
|
||||
#If you have any concerns, please review the source code at /misc/build.func
|
||||
EOF
|
||||
DIAGNOSTICS="yes"
|
||||
else
|
||||
cat <<EOF >/usr/local/community-scripts/diagnostics
|
||||
DIAGNOSTICS=no
|
||||
|
||||
#This file is used to store the diagnostics settings for the Community-Scripts API.
|
||||
#https://github.com/community-scripts/ProxmoxVE/discussions/1836
|
||||
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
|
||||
#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
|
||||
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||
#This will disable the diagnostics feature.
|
||||
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
|
||||
#This will enable the diagnostics feature.
|
||||
#The following information will be sent:
|
||||
#"ct_type"
|
||||
#"disk_size"
|
||||
#"core_count"
|
||||
#"ram_size"
|
||||
#"verbose"
|
||||
#"os_type"
|
||||
#"os_version"
|
||||
#"hn"
|
||||
#"disableip6"
|
||||
#"ssh"
|
||||
#"tags"
|
||||
#"nsapp"
|
||||
#"method"
|
||||
#"pve_version"
|
||||
#If you have any concerns, please review the source code at /misc/build.func
|
||||
EOF
|
||||
DIAGNOSTICS="no"
|
||||
fi
|
||||
else
|
||||
DIAGNOSTICS=$(awk -F '=' '/^DIAGNOSTICS/ {print $2}' /usr/local/community-scripts/diagnostics)
|
||||
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
install_script() {
|
||||
pve_check
|
||||
shell_check
|
||||
@ -796,6 +938,7 @@ install_script() {
|
||||
arch_check
|
||||
ssh_check
|
||||
maxkeys_check
|
||||
diagnostics_check
|
||||
|
||||
if systemctl is-active -q ping-instances.service; then
|
||||
systemctl -q stop ping-instances.service
|
||||
@ -804,12 +947,14 @@ install_script() {
|
||||
timezone=$(cat /etc/timezone)
|
||||
header_info
|
||||
while true; do
|
||||
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --menu "Choose an option:" \
|
||||
12 50 4 \
|
||||
12 50 5 \
|
||||
"1" "Default Settings" \
|
||||
"2" "Default Settings (with verbose)" \
|
||||
"3" "Advanced Settings" \
|
||||
"4" "Exit" --nocancel --default-item "1" 3>&1 1>&2 2>&3)
|
||||
"4" "Diagnostic Settings" \
|
||||
"5" "Exit" --nocancel --default-item "1" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${CROSS}${RD} Menu canceled. Exiting.${CL}"
|
||||
@ -817,35 +962,55 @@ install_script() {
|
||||
fi
|
||||
|
||||
case $CHOICE in
|
||||
1)
|
||||
header_info
|
||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}"
|
||||
VERB="no"
|
||||
base_settings "$VERB"
|
||||
echo_default
|
||||
break
|
||||
;;
|
||||
2)
|
||||
header_info
|
||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${SEARCH}Verbose)${CL}"
|
||||
VERB="yes"
|
||||
base_settings "$VERB"
|
||||
echo_default
|
||||
break
|
||||
;;
|
||||
3)
|
||||
header_info
|
||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}"
|
||||
advanced_settings
|
||||
break
|
||||
;;
|
||||
4)
|
||||
echo -e "${CROSS}${RD}Exiting.${CL}"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo -e "${CROSS}${RD}Invalid option, please try again.${CL}"
|
||||
1)
|
||||
header_info
|
||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}"
|
||||
VERB="no"
|
||||
METHOD="default"
|
||||
base_settings "$VERB"
|
||||
echo_default
|
||||
break
|
||||
;;
|
||||
2)
|
||||
header_info
|
||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${SEARCH}Verbose)${CL}"
|
||||
VERB="yes"
|
||||
METHOD="default"
|
||||
base_settings "$VERB"
|
||||
echo_default
|
||||
break
|
||||
;;
|
||||
3)
|
||||
header_info
|
||||
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}"
|
||||
METHOD="advanced"
|
||||
advanced_settings
|
||||
break
|
||||
;;
|
||||
4)
|
||||
if [[ $DIAGNOSTICS == "yes" ]]; then
|
||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \
|
||||
--yes-button "No" --no-button "Back" ; then
|
||||
DIAGNOSTICS="no"
|
||||
sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=no/' /usr/local/community-scripts/diagnostics
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58
|
||||
fi
|
||||
else
|
||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \
|
||||
--yes-button "Yes" --no-button "Back" ; then
|
||||
DIAGNOSTICS="yes"
|
||||
sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=yes/' /usr/local/community-scripts/diagnostics
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
5)
|
||||
echo -e "${CROSS}${RD}Exiting.${CL}"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo -e "${CROSS}${RD}Invalid option, please try again.${CL}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
@ -911,7 +1076,7 @@ start() {
|
||||
|
||||
# This function collects user settings and integrates all the collected information.
|
||||
build_container() {
|
||||
# if [ "$VERB" == "yes" ]; then set -x; fi
|
||||
# if [ "$VERB" == "yes" ]; then set -x; fi
|
||||
|
||||
if [ "$CT_TYPE" == "1" ]; then
|
||||
FEATURES="keyctl=1,nesting=1"
|
||||
@ -919,6 +1084,9 @@ build_container() {
|
||||
FEATURES="nesting=1"
|
||||
fi
|
||||
|
||||
if [[ $DIAGNOSTICS == "yes" ]]; then
|
||||
post_to_api
|
||||
fi
|
||||
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
pushd $TEMP_DIR >/dev/null
|
||||
@ -1012,7 +1180,7 @@ EOF
|
||||
msg_ok "Started LXC Container"
|
||||
if [ "$var_os" == "alpine" ]; then
|
||||
sleep 3
|
||||
pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
|
||||
pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
|
||||
http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
|
||||
http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
|
||||
EOF'
|
||||
@ -1027,7 +1195,8 @@ description() {
|
||||
IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
|
||||
|
||||
# Generate LXC Description
|
||||
DESCRIPTION=$(cat <<EOF
|
||||
DESCRIPTION=$(
|
||||
cat <<EOF
|
||||
<div align='center'>
|
||||
<a href='https://Helper-Scripts.com' target='_blank' rel='noopener noreferrer'>
|
||||
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
|
||||
@ -1055,7 +1224,7 @@ description() {
|
||||
</span>
|
||||
</div>
|
||||
EOF
|
||||
)
|
||||
)
|
||||
|
||||
# Set Description in LXC
|
||||
pct set "$CTID" -description "$DESCRIPTION"
|
||||
@ -1063,4 +1232,13 @@ EOF
|
||||
if [[ -f /etc/systemd/system/ping-instances.service ]]; then
|
||||
systemctl start ping-instances.service
|
||||
fi
|
||||
|
||||
if [[ $DIAGNOSTICS == "yes" ]]; then
|
||||
post_update_to_api
|
||||
fi
|
||||
}
|
||||
|
||||
trap 'post_update_to_api "done"' EXIT
|
||||
trap 'post_update_to_api "failed"' SIGINT
|
||||
trap 'post_update_to_api "failed"' SIGTERM
|
||||
|
||||
|
||||
83
misc/clean-orphaned-lvm.sh
Normal file
83
misc/clean-orphaned-lvm.sh
Normal file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
____ ________ ____ __ __ __ _ ____ ___
|
||||
/ __ \_________ _ ______ ___ ____ _ __ / ____/ /__ ____ _____ / __ \_________ / /_ ____ _____ ___ ____/ / / /| | / / |/ /____
|
||||
/ /_/ / ___/ __ \| |/_/ __ `__ \/ __ \| |/_/ / / / / _ \/ __ `/ __ \ / / / / ___/ __ \/ __ \/ __ `/ __ \/ _ \/ __ / / / | | / / /|_/ / ___/
|
||||
/ ____/ / / /_/ /> </ / / / / / /_/ /> < / /___/ / __/ /_/ / / / / / /_/ / / / /_/ / / / / /_/ / / / / __/ /_/ / / /__| |/ / / / (__ )
|
||||
/_/ /_/ \____/_/|_/_/ /_/ /_/\____/_/|_| \____/_/\___/\__,_/_/ /_/ \____/_/ / .___/_/ /_/\__,_/_/ /_/\___/\__,_/ /_____/___/_/ /_/____/
|
||||
/_/
|
||||
EOF
|
||||
}
|
||||
|
||||
# Function to check for orphaned LVM volumes
|
||||
function find_orphaned_lvm {
|
||||
echo -e "\n🔍 Scanning for orphaned LVM volumes...\n"
|
||||
|
||||
orphaned_volumes=()
|
||||
while read -r lv vg size; do
|
||||
container_id=$(echo "$lv" | grep -oE "[0-9]+" | head -1)
|
||||
|
||||
# Exclude system-critical LVs
|
||||
if [[ "$lv" == "data" || "$lv" == "root" || "$lv" == "swap" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if the ID exists as a VM or LXC container
|
||||
if [ -f "/etc/pve/lxc/${container_id}.conf" ] || [ -f "/etc/pve/qemu-server/${container_id}.conf" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
orphaned_volumes+=("$lv" "$vg" "$size")
|
||||
done < <(lvs --noheadings -o lv_name,vg_name,lv_size --separator ' ' | awk '{print $1, $2, $3}')
|
||||
|
||||
if [ ${#orphaned_volumes[@]} -eq 0 ]; then
|
||||
echo -e "✅ No orphaned LVM volumes found.\n"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Display orphaned volumes
|
||||
echo -e "❗ The following orphaned LVM volumes were found:\n"
|
||||
printf "%-25s %-10s %-10s\n" "LV Name" "VG" "Size"
|
||||
printf "%-25s %-10s %-10s\n" "-------------------------" "----------" "----------"
|
||||
|
||||
for ((i = 0; i < ${#orphaned_volumes[@]}; i+=3)); do
|
||||
printf "%-25s %-10s %-10s\n" "${orphaned_volumes[i]}" "${orphaned_volumes[i+1]}" "${orphaned_volumes[i+2]}"
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Function to delete selected volumes
|
||||
function delete_orphaned_lvm {
|
||||
for ((i = 0; i < ${#orphaned_volumes[@]}; i+=3)); do
|
||||
lv="${orphaned_volumes[i]}"
|
||||
vg="${orphaned_volumes[i+1]}"
|
||||
size="${orphaned_volumes[i+2]}"
|
||||
|
||||
read -p "❓ Do you want to delete $lv (VG: $vg, Size: $size)? [y/N]: " confirm
|
||||
if [[ "$confirm" =~ ^[Yy]$ ]]; then
|
||||
echo -e "🗑️ Deleting $lv from $vg..."
|
||||
lvremove -f "$vg/$lv"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "✅ Successfully deleted $lv.\n"
|
||||
else
|
||||
echo -e "❌ Failed to delete $lv.\n"
|
||||
fi
|
||||
else
|
||||
echo -e "⚠️ Skipping $lv.\n"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Run script
|
||||
header_info
|
||||
find_orphaned_lvm
|
||||
delete_orphaned_lvm
|
||||
|
||||
echo -e "✅ Cleanup process completed!\n"
|
||||
@ -231,7 +231,7 @@ while true; do
|
||||
esac
|
||||
done
|
||||
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[0-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[0-3](\.[0-9]+)*"; then
|
||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.0 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -111,7 +111,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -111,7 +111,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -91,7 +91,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -115,7 +115,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -62,7 +62,7 @@ function cleanup() {
|
||||
}
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
pushd $TEMP_DIR >/dev/null
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -91,7 +91,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -157,7 +157,7 @@ function msg_error() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -91,7 +91,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -111,7 +111,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -112,7 +112,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
@ -111,7 +111,7 @@ function check_root() {
|
||||
}
|
||||
|
||||
function pve_check() {
|
||||
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
|
||||
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
|
||||
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
|
||||
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
|
||||
echo -e "Exiting..."
|
||||
|
||||
Reference in New Issue
Block a user