host-install v1.4.0: appliance CPU/RAM cap passthrough (--cores/--memory)
Optional --cores N / --memory M (MiB) passed through to the agent's --selftest=provision as -cores/-memory ONLY when set (0/unset = golden default; avoids unknown-flag death on an agent < v0.52.0). Pre-flight soft WARN when a cap exceeds host nproc/MemTotal. Validated dry-run on felhom-pve. bash -n + shellcheck clean. Deploy dependency: hub artifact manifest must serve agent >= v0.52.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,26 @@
|
|||||||
# Felhom scripts — Changelog
|
# Felhom scripts — Changelog
|
||||||
|
|
||||||
|
## felhom-host-install.sh v1.4.0 — appliance CPU/RAM cap passthrough (`--cores` / `--memory`) (2026-07-01)
|
||||||
|
|
||||||
|
Colleague-safety batch #3 (host-install half; the mechanism is agent v0.52.0). Lets an operator cap the
|
||||||
|
provisioned guest so a trial appliance on a SHARED production Proxmox doesn't pressure the colleague's
|
||||||
|
existing guests.
|
||||||
|
|
||||||
|
- **`--cores N` / `--memory M` (MiB)** — optional; passed through to the agent's `--selftest=provision`
|
||||||
|
as `-cores`/`-memory`. `0`/unset = keep the golden's baked sizes (unchanged behaviour). New vars
|
||||||
|
`CPU_CORES`/`MEM_MIB`; `usage()` header gains an "Appliance cap (optional)" group.
|
||||||
|
- **Conditional passthrough** — `step_provision` builds a `cap_args` array and appends the flags to BOTH
|
||||||
|
the dry-run log and the real agent call **only when set**. An agent < v0.52.0 would reject an unknown
|
||||||
|
flag, so the flags are never sent unless the operator opts in (see the deploy dependency below).
|
||||||
|
- **Pre-flight sanity WARN (soft, provision only)** — if `--cores` > host `nproc` or `--memory` > host
|
||||||
|
`MemTotal`, `log_warn` "the cap won't protect other guests"; never `die` (the operator may know better).
|
||||||
|
- **Deploy dependency:** a fresh install using `--cores`/`--memory` needs the hub artifact manifest to
|
||||||
|
serve **agent ≥ v0.52.0**.
|
||||||
|
- **Validated dry-run on felhom-pve:** `--cores 2 --memory 4096 --dry-run` → provision command shows
|
||||||
|
`-cores 2 -memory 4096`; without the flags → neither present; `--cores 64 --memory 65536` → both WARN
|
||||||
|
lines (host 4 cores / ~15771 MiB). `bash -n` + `shellcheck` clean (0 new warnings; the 2 pre-existing
|
||||||
|
SC2015 in `step_verify` unchanged).
|
||||||
|
|
||||||
## felhom-host-install.sh v1.3.0 — `--uninstall` (clean revert) + pre-flight guards (2026-07-01)
|
## felhom-host-install.sh v1.3.0 — `--uninstall` (clean revert) + pre-flight guards (2026-07-01)
|
||||||
|
|
||||||
Colleague-safety batch #1+#2. Adds a first-class, guarded **`--uninstall`** teardown so an operator can
|
Colleague-safety batch #1+#2. Adds a first-class, guarded **`--uninstall`** teardown so an operator can
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# felhom-host-install.sh v1.3.0
|
# felhom-host-install.sh v1.4.0
|
||||||
# Day-0 host-bootstrap for a Felhom Proxmox host (operator-deploy model).
|
# Day-0 host-bootstrap for a Felhom Proxmox host (operator-deploy model).
|
||||||
#
|
#
|
||||||
# Run by the operator on a FRESHLY-PVE-INSTALLED box (after a manual PVE install
|
# Run by the operator on a FRESHLY-PVE-INSTALLED box (after a manual PVE install
|
||||||
@@ -45,6 +45,11 @@
|
|||||||
# --rootfs-grow N grow OS rootfs by N GiB (default: auto-compute)
|
# --rootfs-grow N grow OS rootfs by N GiB (default: auto-compute)
|
||||||
# --datavol-grow N grow Docker-data vol by N GiB (default: auto-compute)
|
# --datavol-grow N grow Docker-data vol by N GiB (default: auto-compute)
|
||||||
# --sysdata-grow N grow user-data vol by N GiB (default: auto-compute)
|
# --sysdata-grow N grow user-data vol by N GiB (default: auto-compute)
|
||||||
|
#
|
||||||
|
# Appliance cap (optional — protect a SHARED host's other guests; needs agent >= v0.52.0):
|
||||||
|
# --cores N cap the guest to N CPU cores (0/unset = golden default)
|
||||||
|
# --memory M cap the guest RAM to M MiB (0/unset = golden default)
|
||||||
|
#
|
||||||
# --passphrase-file PATH read the retrieval passphrase from a 0600 file
|
# --passphrase-file PATH read the retrieval passphrase from a 0600 file
|
||||||
# (default: secure no-echo prompt)
|
# (default: secure no-echo prompt)
|
||||||
# --preserve-from PATH merge non-Day-0 sections (privileged/storage/backup/
|
# --preserve-from PATH merge non-Day-0 sections (privileged/storage/backup/
|
||||||
@@ -85,7 +90,7 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_VERSION="1.3.0"
|
SCRIPT_VERSION="1.4.0"
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Logging (mirrors felhom-controller/scripts/docker-setup.sh)
|
# Logging (mirrors felhom-controller/scripts/docker-setup.sh)
|
||||||
@@ -118,6 +123,8 @@ BRIDGE_ADDR=""
|
|||||||
ROOTFS_GROW=""
|
ROOTFS_GROW=""
|
||||||
DATAVOL_GROW=""
|
DATAVOL_GROW=""
|
||||||
SYSDATA_GROW=""
|
SYSDATA_GROW=""
|
||||||
|
CPU_CORES="" # --cores: optional appliance CPU-core cap (empty/unset = golden default)
|
||||||
|
MEM_MIB="" # --memory: optional appliance RAM cap in MiB (empty/unset = golden default)
|
||||||
PASSPHRASE_FILE=""
|
PASSPHRASE_FILE=""
|
||||||
PRESERVE_FROM=""
|
PRESERVE_FROM=""
|
||||||
PRESERVE_STATE_FROM="" # dir holding a prior local-api.{crt,key} + local-tokens.log to carry over (keeps the pin stable across a reinstall)
|
PRESERVE_STATE_FROM="" # dir holding a prior local-api.{crt,key} + local-tokens.log to carry over (keeps the pin stable across a reinstall)
|
||||||
@@ -166,7 +173,7 @@ ART_GOLDEN_SHA=""
|
|||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Helpers
|
# Helpers
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
usage() { sed -n '2,75p' "$0" | sed 's/^# \{0,1\}//'; exit 0; }
|
usage() { sed -n '2,80p' "$0" | sed 's/^# \{0,1\}//'; exit 0; }
|
||||||
|
|
||||||
run() { # simple (no pipes/redirects) mutating command
|
run() { # simple (no pipes/redirects) mutating command
|
||||||
if $DRY_RUN; then log_dry "$*"; else "$@"; fi
|
if $DRY_RUN; then log_dry "$*"; else "$@"; fi
|
||||||
@@ -478,6 +485,8 @@ while [[ $# -gt 0 ]]; do
|
|||||||
--rootfs-grow) ROOTFS_GROW="$2"; shift 2 ;;
|
--rootfs-grow) ROOTFS_GROW="$2"; shift 2 ;;
|
||||||
--datavol-grow) DATAVOL_GROW="$2"; shift 2 ;;
|
--datavol-grow) DATAVOL_GROW="$2"; shift 2 ;;
|
||||||
--sysdata-grow) SYSDATA_GROW="$2"; shift 2 ;;
|
--sysdata-grow) SYSDATA_GROW="$2"; shift 2 ;;
|
||||||
|
--cores) CPU_CORES="$2"; shift 2 ;;
|
||||||
|
--memory) MEM_MIB="$2"; shift 2 ;;
|
||||||
--passphrase-file) PASSPHRASE_FILE="$2"; shift 2 ;;
|
--passphrase-file) PASSPHRASE_FILE="$2"; shift 2 ;;
|
||||||
--preserve-from) PRESERVE_FROM="$2"; shift 2 ;;
|
--preserve-from) PRESERVE_FROM="$2"; shift 2 ;;
|
||||||
--preserve-state-from) PRESERVE_STATE_FROM="$2"; shift 2 ;;
|
--preserve-state-from) PRESERVE_STATE_FROM="$2"; shift 2 ;;
|
||||||
@@ -621,6 +630,23 @@ step_preflight() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Appliance-cap sanity (soft): a cap that EXCEEDS host resources won't protect other guests. WARN,
|
||||||
|
# never die — the operator may know better (e.g. capping below a future hardware upgrade).
|
||||||
|
if ! $SKIP_PROVISION; then
|
||||||
|
if [[ -n "$CPU_CORES" ]]; then
|
||||||
|
local host_cores; host_cores=$(nproc 2>/dev/null || echo 0)
|
||||||
|
if [[ "${host_cores:-0}" -gt 0 && "$CPU_CORES" -gt "$host_cores" ]]; then
|
||||||
|
log_warn " requested cap (${CPU_CORES} cores) exceeds host cores (${host_cores}); the cap won't protect other guests."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -n "$MEM_MIB" ]]; then
|
||||||
|
local host_mem_mib; host_mem_mib=$(awk '/^MemTotal:/{print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 0)
|
||||||
|
if [[ "${host_mem_mib:-0}" -gt 0 && "$MEM_MIB" -gt "$host_mem_mib" ]]; then
|
||||||
|
log_warn " requested cap (${MEM_MIB} MiB) exceeds host RAM (~${host_mem_mib} MiB); the cap won't protect other guests."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# archive-storage-exists guard (provision only — the golden lives there + the restore reads it).
|
# archive-storage-exists guard (provision only — the golden lives there + the restore reads it).
|
||||||
if ! $SKIP_PROVISION; then
|
if ! $SKIP_PROVISION; then
|
||||||
if pvesm status --storage "$ARCHIVE_STORAGE" >/dev/null 2>&1; then
|
if pvesm status --storage "$ARCHIVE_STORAGE" >/dev/null 2>&1; then
|
||||||
@@ -1100,15 +1126,21 @@ step_provision() {
|
|||||||
log_step "8/8 provision guest $VMID"
|
log_step "8/8 provision guest $VMID"
|
||||||
# NOTE: -hub-password is passed on argv (the agent's only input for it) — briefly
|
# NOTE: -hub-password is passed on argv (the agent's only input for it) — briefly
|
||||||
# visible in ps. Tracked as an Observation (candidate: env/stdin in the agent).
|
# visible in ps. Tracked as an Observation (candidate: env/stdin in the agent).
|
||||||
|
# Optional operator CPU/RAM cap — passed to the agent ONLY when set (an agent < v0.52.0 would
|
||||||
|
# reject the unknown flag and die; opt-in means no one hits that until they intentionally cap).
|
||||||
|
local -a cap_args=()
|
||||||
|
[[ -n "$CPU_CORES" ]] && cap_args+=(-cores "$CPU_CORES")
|
||||||
|
[[ -n "$MEM_MIB" ]] && cap_args+=(-memory "$MEM_MIB")
|
||||||
if $DRY_RUN; then
|
if $DRY_RUN; then
|
||||||
log_dry "felhom-agent --config $AGENT_CONFIG --selftest=provision -archive $GOLDEN_VOLID -vmid $VMID -customer-id $CUSTOMER_ID -hub-password <pass> -rootfs-grow $ROOTFS_GROW -datavol-grow $DATAVOL_GROW -sysdata-grow $SYSDATA_GROW"
|
log_dry "felhom-agent --config $AGENT_CONFIG --selftest=provision -archive $GOLDEN_VOLID -vmid $VMID -customer-id $CUSTOMER_ID -hub-password <pass> -rootfs-grow $ROOTFS_GROW -datavol-grow $DATAVOL_GROW -sysdata-grow $SYSDATA_GROW ${cap_args[*]}"
|
||||||
log_dry "record provisioned_vmid=$VMID in $STATE_FILE (for a later automatic --uninstall)"
|
log_dry "record provisioned_vmid=$VMID in $STATE_FILE (for a later automatic --uninstall)"
|
||||||
_state_mark provision; return 0
|
_state_mark provision; return 0
|
||||||
fi
|
fi
|
||||||
if ! felhom-agent --config "$AGENT_CONFIG" --selftest=provision \
|
if ! felhom-agent --config "$AGENT_CONFIG" --selftest=provision \
|
||||||
-archive "$GOLDEN_VOLID" -vmid "$VMID" \
|
-archive "$GOLDEN_VOLID" -vmid "$VMID" \
|
||||||
-customer-id "$CUSTOMER_ID" -hub-password "$PASSPHRASE" \
|
-customer-id "$CUSTOMER_ID" -hub-password "$PASSPHRASE" \
|
||||||
-rootfs-grow "$ROOTFS_GROW" -datavol-grow "$DATAVOL_GROW" -sysdata-grow "$SYSDATA_GROW"; then
|
-rootfs-grow "$ROOTFS_GROW" -datavol-grow "$DATAVOL_GROW" -sysdata-grow "$SYSDATA_GROW" \
|
||||||
|
"${cap_args[@]}"; then
|
||||||
die "provision FAILED — see the agent error above. Fix and re-run with --resume."
|
die "provision FAILED — see the agent error above. Fix and re-run with --resume."
|
||||||
fi
|
fi
|
||||||
log_success " provision completed"
|
log_success " provision completed"
|
||||||
|
|||||||
Reference in New Issue
Block a user