mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-26 10:31:17 +00:00
Preflight disk space before Pulse updates
Some checks failed
Some checks failed
This commit is contained in:
parent
0b836aa3af
commit
4de1c3745a
3 changed files with 162 additions and 1 deletions
97
install.sh
97
install.sh
|
|
@ -31,6 +31,8 @@ CONTAINER_CREATED_FOR_CLEANUP=false
|
|||
BUILD_FROM_SOURCE_MARKER="$INSTALL_DIR/BUILD_FROM_SOURCE"
|
||||
DETECTED_CTID=""
|
||||
STOPPED_PULSE_SERVICE=""
|
||||
UPDATE_MIN_TEMP_FREE_BYTES=$((900 * 1024 * 1024))
|
||||
UPDATE_MIN_INSTALL_FREE_BYTES=$((256 * 1024 * 1024))
|
||||
|
||||
# Installer version - the major version this script is bundled with
|
||||
INSTALLER_MAJOR_VERSION=5
|
||||
|
|
@ -42,6 +44,97 @@ AUTO_NODE_REGISTER_ERROR=""
|
|||
DEBIAN_TEMPLATE_FALLBACK="debian-12-standard_12.12-1_amd64.tar.zst"
|
||||
DEBIAN_TEMPLATE=""
|
||||
|
||||
bytes_to_human() {
|
||||
local bytes="${1:-0}"
|
||||
|
||||
if [[ ! "$bytes" =~ ^[0-9]+$ ]]; then
|
||||
printf '%s\n' "$bytes"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local units=("B" "KB" "MB" "GB" "TB")
|
||||
local value="$bytes"
|
||||
local unit_index=0
|
||||
|
||||
while (( value >= 1024 && unit_index < ${#units[@]} - 1 )); do
|
||||
value=$((value / 1024))
|
||||
((unit_index += 1))
|
||||
done
|
||||
|
||||
printf '%s%s\n' "$value" "${units[$unit_index]}"
|
||||
}
|
||||
|
||||
get_available_bytes_for_path() {
|
||||
local path="$1"
|
||||
local available_kb=""
|
||||
|
||||
available_kb=$(df -Pk "$path" 2>/dev/null | awk 'NR==2 {print $4}')
|
||||
if [[ ! "$available_kb" =~ ^[0-9]+$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s\n' $((available_kb * 1024))
|
||||
}
|
||||
|
||||
get_filesystem_device_for_path() {
|
||||
local path="$1"
|
||||
local filesystem=""
|
||||
|
||||
filesystem=$(df -Pk "$path" 2>/dev/null | awk 'NR==2 {print $1}')
|
||||
if [[ -z "$filesystem" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$filesystem"
|
||||
}
|
||||
|
||||
ensure_update_disk_headroom() {
|
||||
local temp_path="${1:-/tmp}"
|
||||
local install_path="${2:-$INSTALL_DIR}"
|
||||
local temp_fs=""
|
||||
local install_fs=""
|
||||
local temp_free_bytes=""
|
||||
local install_free_bytes=""
|
||||
local combined_required_bytes=$((UPDATE_MIN_TEMP_FREE_BYTES + UPDATE_MIN_INSTALL_FREE_BYTES))
|
||||
|
||||
temp_fs=$(get_filesystem_device_for_path "$temp_path" 2>/dev/null || true)
|
||||
install_fs=$(get_filesystem_device_for_path "$install_path" 2>/dev/null || true)
|
||||
temp_free_bytes=$(get_available_bytes_for_path "$temp_path" 2>/dev/null || true)
|
||||
install_free_bytes=$(get_available_bytes_for_path "$install_path" 2>/dev/null || true)
|
||||
|
||||
if [[ -z "$temp_free_bytes" || -z "$install_free_bytes" ]]; then
|
||||
print_warn "Could not determine available disk space for the update preflight; continuing anyway"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "$temp_fs" && "$temp_fs" == "$install_fs" ]]; then
|
||||
if (( temp_free_bytes < combined_required_bytes )); then
|
||||
print_error "Not enough free disk space to stage the Pulse update"
|
||||
print_info "The same filesystem backs $temp_path and $install_path"
|
||||
print_info "Available: $(bytes_to_human "$temp_free_bytes"), required: $(bytes_to_human "$combined_required_bytes")"
|
||||
print_info "Free disk space and retry the update"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
if (( temp_free_bytes < UPDATE_MIN_TEMP_FREE_BYTES )); then
|
||||
print_error "Not enough free disk space in $temp_path to stage the Pulse update"
|
||||
print_info "Available: $(bytes_to_human "$temp_free_bytes"), required: $(bytes_to_human "$UPDATE_MIN_TEMP_FREE_BYTES")"
|
||||
print_info "Free disk space under $temp_path and retry the update"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if (( install_free_bytes < UPDATE_MIN_INSTALL_FREE_BYTES )); then
|
||||
print_error "Not enough free disk space in $install_path to apply the Pulse update"
|
||||
print_info "Available: $(bytes_to_human "$install_free_bytes"), required: $(bytes_to_human "$UPDATE_MIN_INSTALL_FREE_BYTES")"
|
||||
print_info "Free disk space under $install_path and retry the update"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
get_latest_release_from_redirect() {
|
||||
# Follow the GitHub "latest" redirect and extract the tag in a way that
|
||||
# tolerates intermediate redirects that omit /tag/ (issue #698).
|
||||
|
|
@ -2604,6 +2697,10 @@ download_pulse() {
|
|||
|
||||
rm -f "$BUILD_FROM_SOURCE_MARKER"
|
||||
|
||||
if ! ensure_update_disk_headroom "/tmp" "$INSTALL_DIR"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
EXISTING_SERVICE=$(detect_service_name)
|
||||
stop_pulse_service_for_update "$EXISTING_SERVICE" || true
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func (a *InstallShAdapter) PrepareUpdate(ctx context.Context, request UpdateRequ
|
|||
Prerequisites: []string{
|
||||
"Root access (sudo)",
|
||||
"Internet connection",
|
||||
"At least 100MB free disk space",
|
||||
"About 1.2GB free disk space for update staging",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,68 @@ test_infer_release_from_archive_name_supports_prerelease() {
|
|||
)
|
||||
}
|
||||
|
||||
test_ensure_update_disk_headroom_fails_when_tmp_and_install_share_full_filesystem() {
|
||||
(
|
||||
load_installer
|
||||
|
||||
UPDATE_MIN_TEMP_FREE_BYTES=$((100 * 1024))
|
||||
UPDATE_MIN_INSTALL_FREE_BYTES=$((80 * 1024))
|
||||
|
||||
print_error() { :; }
|
||||
print_info() { :; }
|
||||
print_warn() { :; }
|
||||
df() {
|
||||
if [[ "$1" == "-Pk" ]]; then
|
||||
case "$2" in
|
||||
/tmp|/opt/pulse)
|
||||
printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\n'
|
||||
printf '/dev/shared 1000 0 150 0%% /\n'
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
command df "$@"
|
||||
}
|
||||
|
||||
if ensure_update_disk_headroom /tmp /opt/pulse; then
|
||||
echo "ensure_update_disk_headroom unexpectedly passed on a shared full filesystem" >&2
|
||||
return 1
|
||||
fi
|
||||
)
|
||||
}
|
||||
|
||||
test_ensure_update_disk_headroom_accepts_separate_filesystems_with_sufficient_space() {
|
||||
(
|
||||
load_installer
|
||||
|
||||
UPDATE_MIN_TEMP_FREE_BYTES=$((100 * 1024))
|
||||
UPDATE_MIN_INSTALL_FREE_BYTES=$((80 * 1024))
|
||||
|
||||
print_error() { :; }
|
||||
print_info() { :; }
|
||||
print_warn() { :; }
|
||||
df() {
|
||||
if [[ "$1" == "-Pk" ]]; then
|
||||
case "$2" in
|
||||
/tmp)
|
||||
printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\n'
|
||||
printf '/dev/tmp 1000 0 120 0%% /tmp\n'
|
||||
return 0
|
||||
;;
|
||||
/opt/pulse)
|
||||
printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\n'
|
||||
printf '/dev/root 1000 0 90 0%% /\n'
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
command df "$@"
|
||||
}
|
||||
|
||||
ensure_update_disk_headroom /tmp /opt/pulse
|
||||
)
|
||||
}
|
||||
|
||||
test_download_pulse_installs_from_local_archive_without_network() {
|
||||
(
|
||||
load_installer
|
||||
|
|
@ -266,6 +328,8 @@ test_install_additional_agent_binaries_skips_network_when_local_extras_are_missi
|
|||
|
||||
main() {
|
||||
assert_success "infer_release_from_archive_name parses prerelease tarballs" test_infer_release_from_archive_name_supports_prerelease
|
||||
assert_success "update disk preflight fails on shared low-space filesystems" test_ensure_update_disk_headroom_fails_when_tmp_and_install_share_full_filesystem
|
||||
assert_success "update disk preflight passes on separate filesystems with enough headroom" test_ensure_update_disk_headroom_accepts_separate_filesystems_with_sufficient_space
|
||||
assert_success "download_pulse installs from local archive without network" test_download_pulse_installs_from_local_archive_without_network
|
||||
assert_success "prefetch helper writes archive path via output variable" test_prefetch_pulse_archive_for_container_sets_output_var
|
||||
assert_success "wrong-arch archives fail before replacing the installed binary" test_install_pulse_archive_rejects_mismatched_arch_without_replacing_existing_binary
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue