diff --git a/.github/workflows/verify-split-files.yml b/.github/workflows/verify-split-files.yml index 7b5f10a..644866f 100644 --- a/.github/workflows/verify-split-files.yml +++ b/.github/workflows/verify-split-files.yml @@ -36,6 +36,8 @@ on: - "tests/exit-code-hints.sh" - "tests/forge-release-json.sh" - "tests/install-cleanup.sh" + - "tests/incus-target.sh" + - "tests/incus-storage-space.sh" - "tests/release-stamp-pending.sh" - ".github/workflows/verify-split-files.yml" push: @@ -64,6 +66,8 @@ on: - "tests/exit-code-hints.sh" - "tests/forge-release-json.sh" - "tests/install-cleanup.sh" + - "tests/incus-target.sh" + - "tests/incus-storage-space.sh" - "tests/release-stamp-pending.sh" - ".github/workflows/verify-split-files.yml" workflow_dispatch: @@ -128,6 +132,11 @@ jobs: - name: Install cleanup and uv trap tests run: bash tests/install-cleanup.sh + - name: Incus target tests + run: bash tests/incus-target.sh + + - name: Incus storage space tests + run: bash tests/incus-storage-space.sh - name: Release stamp pending marker tests run: bash tests/release-stamp-pending.sh diff --git a/core/core.func b/core/core.func index 2b92e09..3a05c29 100644 --- a/core/core.func +++ b/core/core.func @@ -368,6 +368,18 @@ default_vars() { # - If VERBOSE=no: STD="silent" (suppress output via silent() wrapper) # - If DEV_MODE_TRACE=true: Enables bash tracing (set -x) # ------------------------------------------------------------------------------ +# Debian-style architecture of the machine that will run the container: the +# Incus server when driving a remote, otherwise this host. Needs no dpkg. +_cs_host_arch() { + local a="${INCUS_SERVER_ARCH:-}" + [[ -n "$a" ]] || a="$(dpkg --print-architecture 2>/dev/null || uname -m)" + case "$a" in + x86_64) a="amd64" ;; + aarch64) a="arm64" ;; + esac + printf '%s' "$a" +} + set_std_mode() { # Verbose shows the output live and still keeps it in the log; silent() reads VERBOSE. STD="silent" @@ -736,7 +748,7 @@ pmxcfs_check() { # ------------------------------------------------------------------------------ arch_check() { local arch - arch="$(dpkg --print-architecture 2>/dev/null || uname -m)" + arch="$(_cs_host_arch)" case "$arch" in x86_64) arch="amd64" ;; aarch64) arch="arm64" ;; @@ -2642,7 +2654,7 @@ ensure_whiptail() { # - Shows a short warning when running scripts on ARM64 systems # ------------------------------------------------------------------------------ arm64_notice() { - [[ "$(dpkg --print-architecture)" == "arm64" ]] || return 0 + [[ "$(_cs_host_arch)" == "arm64" ]] || return 0 whiptail --backtitle "Proxmox VE Helper Scripts" \ --title "ARM64 SUPPORT" \ @@ -2675,7 +2687,7 @@ on_hup_keepalive() { arch_resolve() { local amd64_val="${1:-amd64}" local arm64_val="${2:-arm64}" - local arch="${PCT_ARCH:-$(dpkg --print-architecture 2>/dev/null || uname -m)}" + local arch="${PCT_ARCH:-$(_cs_host_arch)}" case "$arch" in amd64 | x86_64) echo "$amd64_val" ;; arm64 | aarch64) echo "$arm64_val" ;; diff --git a/docs/backends.md b/docs/backends.md index ca47423..79ccbbe 100644 --- a/docs/backends.md +++ b/docs/backends.md @@ -71,6 +71,23 @@ from `/etc/localtime`, or from `Etc/UTC`. [`core/core.func`](../core/core.func) renders "Incus Version 6.x" on an Incus host and "PVE Version …" on Proxmox VE, from the same `PVEVERSION` value. +### Driving a remote server + +The `incus` client always talks to a remote; `local:` is only the default. +Every call in this backend uses bare names, so switching the default remote +points the whole flow at another server: + + incus remote add incusos https://:8443 --token + incus remote switch incusos + bash -c "$(curl -fsSL .../ct/.sh)" + +The machine running the script needs bash, curl, newt (for whiptail) and the +client; a BusyBox userland such as Alpine is fine. The backend +takes the server's architecture from `incus info` and names the target when +it is not `local`. This is the way in for IncusOS, which has no shell of its +own. Pool free space comes from `incus storage info`; the local `df` fallback +is skipped for a remote. + ## VM scripts on the two backends `ct/` scripts are shared; `vm/` scripts are not, and the reason is worth diff --git a/host/preflight.func b/host/preflight.func index 28a8c22..3c9aca3 100644 --- a/host/preflight.func +++ b/host/preflight.func @@ -81,6 +81,13 @@ preflight_warn() { # - https://docs.kernel.org/security/keys/core.html # ------------------------------------------------------------------------------ preflight_maxkeys() { + # The limits are the server's; a client driving a remote Incus cannot read them. + if ! command -v pveversion >/dev/null 2>&1 && command -v incus >/dev/null 2>&1 && + [[ "$(LC_ALL=C incus remote get-default 2>/dev/null || echo local)" != "local" ]]; then + preflight_pass "Kernel key limits left to the remote Incus server" + return 0 + fi + local per_user_maxkeys per_user_maxbytes per_user_maxkeys=$(cat /proc/sys/kernel/keys/maxkeys 2>/dev/null || echo 0) per_user_maxbytes=$(cat /proc/sys/kernel/keys/maxbytes 2>/dev/null || echo 0) @@ -395,7 +402,7 @@ preflight_container_id() { # ------------------------------------------------------------------------------ preflight_template_connectivity() { # ARM64 uses custom template sources (GitHub/jenkins), not the pveam catalog - if [[ "$(dpkg --print-architecture)" == "arm64" ]]; then + if [[ "$(_cs_host_arch)" == "arm64" ]]; then preflight_pass "Template connectivity check skipped (ARM64 uses custom template source)" return 0 fi @@ -435,7 +442,7 @@ preflight_template_connectivity() { # ------------------------------------------------------------------------------ preflight_template_available() { # ARM64 uses custom template sources (GitHub/jenkins), not the pveam catalog - if [[ "$(dpkg --print-architecture)" == "arm64" ]]; then + if [[ "$(_cs_host_arch)" == "arm64" ]]; then preflight_pass "Template check skipped (ARM64 uses custom template source)" return 0 fi diff --git a/incus/backend.func b/incus/backend.func index 896344d..1471fa0 100644 --- a/incus/backend.func +++ b/incus/backend.func @@ -158,25 +158,23 @@ _incus_resolve_launch_image() { } _incus_parse_size_to_bytes() { - # Accepts raw bytes or human values like 589.51GiB / 211MiB / 1.5TB - local raw="${1:-}" val unit + # Integer arithmetic only: BusyBox awk truncates printf "%d" to 32 bit. + local raw="${1:-}" int frac unit mult scale=1 i raw="${raw// /}" - [[ -z "$raw" ]] && return 1 - if [[ "$raw" =~ ^[0-9]+$ ]]; then - echo "$raw" - return 0 - fi - val=$(echo "$raw" | sed -E 's/[^0-9.].*$//') - unit=$(echo "$raw" | sed -E 's/^[0-9.]+//' | tr '[:lower:]' '[:upper:]') - [[ -z "$val" ]] && return 1 + [[ "$raw" =~ ^([0-9]+)(\.([0-9]+))?([A-Za-z]*)$ ]] || return 1 + int="${BASH_REMATCH[1]}" + frac="${BASH_REMATCH[3]}" + unit="${BASH_REMATCH[4]^^}" case "$unit" in - B | "") echo "$(awk -v v="$val" 'BEGIN{printf "%d", v}')" ;; - KB | KIB | K) echo "$(awk -v v="$val" 'BEGIN{printf "%d", v*1024}')" ;; - MB | MIB | M) echo "$(awk -v v="$val" 'BEGIN{printf "%d", v*1024*1024}')" ;; - GB | GIB | G) echo "$(awk -v v="$val" 'BEGIN{printf "%d", v*1024*1024*1024}')" ;; - TB | TIB | T) echo "$(awk -v v="$val" 'BEGIN{printf "%d", v*1024*1024*1024*1024}')" ;; + B | "") mult=1 ;; + KB | KIB | K) mult=1024 ;; + MB | MIB | M) mult=$((1024 * 1024)) ;; + GB | GIB | G) mult=$((1024 * 1024 * 1024)) ;; + TB | TIB | T) mult=$((1024 * 1024 * 1024 * 1024)) ;; *) return 1 ;; esac + for ((i = 0; i < ${#frac}; i++)); do scale=$((scale * 10)); done + echo $((10#$int * mult + 10#${frac:-0} * mult / scale)) } incus_storage_pool_free_gb() { @@ -187,18 +185,25 @@ incus_storage_pool_free_gb() { # LC_ALL=C: incus translates this output. A German host reports "Gesamter # Speicherplatz" and "Speicherplatz in Benutzung", so the awk below matched # nothing and a 357GB pool looked unmeasurable. + # Incus reports total and used only; with --bytes they are plain integers, so + # the subtraction stays in bash and never goes through awk floats (BusyBox awk + # truncates those to 32 bit). info=$(LC_ALL=C incus storage info --bytes "$pool" 2>/dev/null || true) - free_raw=$(echo "$info" | awk -F': *' '/space free:/ {print $2; exit}') - if [[ -n "$free_raw" ]]; then - free_bytes="$(_incus_parse_size_to_bytes "$free_raw" 2>/dev/null || true)" + free_raw=$(echo "$info" | awk -F': *' '/space free:/ {gsub(/"/, "", $2); print $2; exit}') + total_raw=$(echo "$info" | awk -F': *' '/total space:/ {gsub(/"/, "", $2); print $2; exit}') + used_raw=$(echo "$info" | awk -F': *' '/space used:/ {gsub(/"/, "", $2); print $2; exit}') + if [[ "$free_raw" =~ ^[0-9]+$ ]]; then + free_bytes="$free_raw" + elif [[ "$total_raw" =~ ^[0-9]+$ && "$used_raw" =~ ^[0-9]+$ && "$total_raw" -ge "$used_raw" ]]; then + free_bytes=$((total_raw - used_raw)) fi # Older/human output often has only "space used" + "total space" (no free line). if [[ -z "${free_bytes:-}" ]]; then info=$(LC_ALL=C incus storage info "$pool" 2>/dev/null || true) - free_raw=$(echo "$info" | awk -F': *' '/space free:/ {print $2; exit}') - total_raw=$(echo "$info" | awk -F': *' '/total space:/ {print $2; exit}') - used_raw=$(echo "$info" | awk -F': *' '/space used:/ {print $2; exit}') + free_raw=$(echo "$info" | awk -F': *' '/space free:/ {gsub(/"/, "", $2); print $2; exit}') + total_raw=$(echo "$info" | awk -F': *' '/total space:/ {gsub(/"/, "", $2); print $2; exit}') + used_raw=$(echo "$info" | awk -F': *' '/space used:/ {gsub(/"/, "", $2); print $2; exit}') if [[ -n "$free_raw" ]]; then free_bytes="$(_incus_parse_size_to_bytes "$free_raw" 2>/dev/null || true)" elif [[ -n "$total_raw" && -n "$used_raw" ]]; then @@ -215,7 +220,7 @@ incus_storage_pool_free_gb() { if [[ -z "${free_bytes:-}" ]]; then local src src="$(LC_ALL=C incus storage get "$pool" source 2>/dev/null || true)" - if [[ -n "$src" && -d "$src" ]]; then + if [[ "${INCUS_REMOTE:-local}" == "local" && -n "$src" && -d "$src" ]]; then free_bytes="$(df -PB1 "$src" 2>/dev/null | awk 'NR==2 {print $4}')" fi fi @@ -471,8 +476,9 @@ incus_create_lxc_container() { # plus a rollback to reach the state it would have had anyway. Privileged # only, and only when the host default is actually below what we want. local optional_sysctl_pending=0 + # The sysctl probe reads this machine; against a remote, just try the setting. if [[ "${CT_TYPE:-1}" == "0" ]] && - (($(cat /proc/sys/kernel/keys/maxkeys 2>/dev/null || echo 2000) < 2000)); then + { [[ "${INCUS_REMOTE:-local}" != "local" ]] || (($(cat /proc/sys/kernel/keys/maxkeys 2>/dev/null || echo 2000) < 2000)); }; then if incus config set "${CT_NAME}" linux.sysctl.kernel.keys.maxkeys=2000 >>"$LOGFILE" 2>&1; then optional_sysctl_pending=1 fi @@ -974,7 +980,7 @@ incus_set_root_password() { incus_customize_container() { msg_info "Customizing LXC Container" - ARCH="$(dpkg --print-architecture 2>/dev/null || uname -m)" + ARCH="$(_cs_host_arch)" if [[ "${var_os:-debian}" == "alpine" ]]; then sleep 2 @@ -1093,7 +1099,7 @@ INNEREOF" >>"${LOGFILE:-$INCUS_BUILD_LOG}" 2>&1 || { msg_error "Failed to push f incus exec "${CT_NAME}" -- bash -c "${_run_env} ${_install_script} touch /root/.install-${SESSION_ID}.done" 2>&1 | - tee >(sed -u 's/.*\r//' >>"${LOGFILE:-$INCUS_BUILD_LOG}") + tee >(sed 's/.*\r//' >>"${LOGFILE:-$INCUS_BUILD_LOG}") # PIPESTATUS, not $?: the line above turns pipefail off, so $? is tee's # status - always 0. Every non-zero exit from the container was discarded # here, which is why a half-finished install reported success. diff --git a/incus/build.func b/incus/build.func index c8fa33d..30e93f8 100644 --- a/incus/build.func +++ b/incus/build.func @@ -93,7 +93,9 @@ incus_variables() { else PVEVERSION="Incus" fi - KERNEL_VERSION=$(uname -r) + # The summary names the machine that runs the container, which may be a remote. + declare -f incus_target >/dev/null 2>&1 && command -v incus >/dev/null 2>&1 && incus_target + KERNEL_VERSION="${INCUS_SERVER_KERNEL:-$(uname -r)}" if [[ -n "${var_cpu:-}" && "${var_cpu}" =~ ^[0-9]+$ ]]; then export APP_DEFAULT_CPU="${var_cpu}"; fi if [[ -n "${var_ram:-}" && "${var_ram}" =~ ^[0-9]+$ ]]; then export APP_DEFAULT_RAM="${var_ram}"; fi if [[ -n "${var_disk:-}" && "${var_disk}" =~ ^[0-9]+$ ]]; then export APP_DEFAULT_DISK="${var_disk}"; fi diff --git a/incus/core.func b/incus/core.func index da0a6d2..9997431 100644 --- a/incus/core.func +++ b/incus/core.func @@ -233,6 +233,23 @@ incus_root_check() { # - Checks incus daemon is running # - Exits with error message if Incus is not available # ------------------------------------------------------------------------------ +# The client's default remote is where every bare name in this backend goes; +# IncusOS has no shell, so a switched remote is the only way to drive it. +incus_target() { + INCUS_REMOTE="$(LC_ALL=C incus remote get-default 2>/dev/null || echo local)" + local info + info="$(LC_ALL=C incus info 2>/dev/null)" + # kernel_architecture is a scalar; the architectures list indents by version. + INCUS_SERVER_ARCH="$(awk '$1 == "kernel_architecture:" {print $2; exit}' <<<"$info")" + [[ -n "$INCUS_SERVER_ARCH" ]] || INCUS_SERVER_ARCH="$(awk '$1 == "architectures:" {a=1; next} a && $1 == "-" {print $2; exit}' <<<"$info")" + case "$INCUS_SERVER_ARCH" in + x86_64) INCUS_SERVER_ARCH="amd64" ;; + aarch64) INCUS_SERVER_ARCH="arm64" ;; + esac + INCUS_SERVER_KERNEL="$(awk '$1 == "kernel_version:" {print $2; exit}' <<<"$info")" + export INCUS_REMOTE INCUS_SERVER_ARCH INCUS_SERVER_KERNEL +} + incus_check() { if ! command -v incus &>/dev/null; then incus_msg_error "Incus is not installed on this system." @@ -281,6 +298,11 @@ incus_check() { incus_msg_error "Create one with: incus storage create default dir" exit 1 fi + + incus_target + if [[ "$INCUS_REMOTE" != "local" ]]; then + incus_msg_custom "ℹ️" "${YW:-}" "Target: Incus remote '${INCUS_REMOTE}' (${INCUS_SERVER_ARCH:-unknown architecture})" + fi } # ============================================================================== diff --git a/tests/incus-storage-space.sh b/tests/incus-storage-space.sh new file mode 100644 index 0000000..44a7494 --- /dev/null +++ b/tests/incus-storage-space.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -uo pipefail + +CORE_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" +eval "$(awk '/^(_incus_parse_size_to_bytes|incus_storage_pool_free_gb)[(][)] [{]/,/^}/' "$CORE_DIR/incus/backend.func")" + +passed=0 failed=0 +export INCUS_REMOTE=incusos +# A ZFS pool as Incus reports it: total and used only, integers with --bytes. +incus() { + case "$*" in + "storage info --bytes local") + # yaml.Dump quotes strings that look like numbers; that is what the client prints. + [[ "${MOCK_BYTES:-yes}" == "yes" ]] && printf 'info:\n driver: zfs\n name: local\n space used: "238747648"\n total space: "88900000000"\nused by: {}\n' + ;; + "storage info local") + printf 'info:\n driver: zfs\n name: local\n space used: 227.68MiB\n total space: 82.80GiB\nused by: {}\n' + ;; + "storage get local source") echo "/var/lib/incus/storage-pools/local" ;; + esac +} + +expect() { + if [[ "$2" == "$3" ]]; then + echo "PASS $1" + passed=$((passed + 1)) + else + echo "FAIL $1: expected <$2>, got <$3>" >&2 + failed=$((failed + 1)) + fi +} + +expect "free space comes from the byte counts" 82 "$(incus_storage_pool_free_gb local)" +expect "without --bytes the human sizes still work" 82 "$(MOCK_BYTES=no incus_storage_pool_free_gb local)" +expect "GiB parses" 88905823027 "$(_incus_parse_size_to_bytes 82.80GiB)" +expect "MiB parses" 238739783 "$(_incus_parse_size_to_bytes 227.68MiB)" +expect "a plain number is bytes" 4096 "$(_incus_parse_size_to_bytes 4096)" +expect "a fraction below one works" 536870912 "$(_incus_parse_size_to_bytes 0.5GiB)" +expect "a leading zero in the fraction is decimal" 1101004 "$(_incus_parse_size_to_bytes 1.05MiB)" +expect "TiB stays within 64 bit" 1649267441664 "$(_incus_parse_size_to_bytes 1.5TiB)" +expect "nonsense is rejected" 1 "$(_incus_parse_size_to_bytes bogus >/dev/null 2>&1; echo $?)" + +printf '%s passed, %s failed\n' "$passed" "$failed" +((failed == 0)) diff --git a/tests/incus-target.sh b/tests/incus-target.sh new file mode 100644 index 0000000..614a9b4 --- /dev/null +++ b/tests/incus-target.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -uo pipefail + +CORE_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" +eval "$(awk '/^incus_target[(][)] [{]/,/^}/' "$CORE_DIR/incus/core.func")" +eval "$(awk '/^_cs_host_arch[(][)] [{]/,/^}/' "$CORE_DIR/core/core.func")" + +TEST_DIR="$(mktemp -d)" +trap 'rm -rf -- "$TEST_DIR"' EXIT +LOG="$TEST_DIR/log" +passed=0 failed=0 + +incus_msg_custom() { echo "$3" >>"$LOG"; } +# The client answers for its default remote; `incus info` is the server's YAML. +incus() { + case "$1 ${2:-}" in + "remote get-default") echo "${MOCK_REMOTE:-local}" ;; + "info ") + # Newer servers indent the list by four; kernel_architecture is the scalar we prefer. + if [[ -n "${MOCK_KERNEL_ARCH:-}" ]]; then + printf 'config: {}\nenvironment:\n addresses: []\n architectures:\n - %s\n - i686\n kernel_architecture: %s\n kernel_version: 6.12.0-incusos\n server_name: box\n' "${MOCK_ARCH:-x86_64}" "$MOCK_KERNEL_ARCH" + else + printf 'config: {}\nenvironment:\n addresses: []\n architectures:\n - %s\n - i686\n kernel_version: 6.12.0-incusos\n server_name: box\n' "${MOCK_ARCH:-x86_64}" + fi + ;; + esac +} + +expect() { + if [[ "$2" == "$3" ]]; then + echo "PASS $1" + passed=$((passed + 1)) + else + echo "FAIL $1: expected <$2>, got <$3>" >&2 + failed=$((failed + 1)) + fi +} + +: >"$LOG" +MOCK_REMOTE=incusos MOCK_ARCH=aarch64 incus_target +expect "the default remote is the target" incusos "$INCUS_REMOTE" +expect "the server architecture is read, in Debian naming" arm64 "$INCUS_SERVER_ARCH" +expect "the server kernel is read" 6.12.0-incusos "$INCUS_SERVER_KERNEL" +expect "incus_target itself prints nothing" "" "$(cat "$LOG")" + +: >"$LOG" +MOCK_REMOTE=local MOCK_ARCH=x86_64 incus_target +expect "local stays local" local "$INCUS_REMOTE" +expect "x86_64 becomes amd64" amd64 "$INCUS_SERVER_ARCH" +expect "_cs_host_arch follows the server" arm64 "$(INCUS_SERVER_ARCH=aarch64 _cs_host_arch)" +expect "_cs_host_arch maps this machine without dpkg" amd64 "$(INCUS_SERVER_ARCH="" _cs_host_arch)" + +MOCK_REMOTE=lab MOCK_ARCH=riscv64 incus_target +expect "an unmapped architecture is passed through" riscv64 "$INCUS_SERVER_ARCH" + +MOCK_REMOTE=incus-001 MOCK_ARCH=i686 MOCK_KERNEL_ARCH=x86_64 incus_target +expect "kernel_architecture wins over the list" amd64 "$INCUS_SERVER_ARCH" + +printf '%s passed, %s failed\n' "$passed" "$failed" +((failed == 0)) diff --git a/ui/API.txt b/ui/API.txt index 795bb83..eb7aaf1 100644 --- a/ui/API.txt +++ b/ui/API.txt @@ -4,6 +4,7 @@ _container_write_failure _cs_clear _cs_conffile_list _cs_engine_ref_line +_cs_host_arch _cs_host_version_line _cs_live_base _cs_os_family diff --git a/ui/build-ui.func b/ui/build-ui.func index 017147c..4134b88 100644 --- a/ui/build-ui.func +++ b/ui/build-ui.func @@ -178,6 +178,12 @@ run_preflight() { # - Exits with dedicated error codes when limits cannot be read or are exceeded # ------------------------------------------------------------------------------ maxkeys_check() { + # The limits are the server's; a client driving a remote Incus cannot read them. + if ! command -v pveversion >/dev/null 2>&1 && command -v incus >/dev/null 2>&1 && + [[ "$(LC_ALL=C incus remote get-default 2>/dev/null || echo local)" != "local" ]]; then + return 0 + fi + local per_user_maxkeys per_user_maxbytes used_lxc_keys used_lxc_bytes local threshold_keys threshold_bytes new_limit_keys new_limit_bytes local failure=0 diff --git a/ui/defaults.func b/ui/defaults.func index 7039615..c5a6b63 100644 --- a/ui/defaults.func +++ b/ui/defaults.func @@ -92,7 +92,7 @@ _list_os_versions() { # Templates are per-architecture. Without this the catalog offers amd64 # images on an arm64 host, which fail only after the download. local arch - arch="$(dpkg --print-architecture 2>/dev/null || echo amd64)" + arch="$(_cs_host_arch)" _pveam_available | grep -E "_${arch}\.(tar\.zst|tar\.xz|tar\.gz)([[:space:]]|$)" | awk '{print $2}' | @@ -109,7 +109,7 @@ _list_templates() { local search="${1:-}" pattern="${2:-}" [[ -n "$search" ]] || return 0 local arch - arch="$(dpkg --print-architecture 2>/dev/null || echo amd64)" + arch="$(_cs_host_arch)" _pveam_available | grep -E "_${arch}\.(tar\.zst|tar\.xz|tar\.gz)([[:space:]]|$)" | awk '{print $2}' | @@ -128,7 +128,7 @@ resolve_os_version() { [[ -n "$ostype" && -n "$want" ]] || return 0 # ARM64 pulls from linuxcontainers.org, the pveam catalog says nothing there - [[ "$(dpkg --print-architecture 2>/dev/null)" == "arm64" ]] && return 0 + [[ "$(_cs_host_arch)" == "arm64" ]] && return 0 local -a versions=() mapfile -t versions < <(_list_os_versions "$ostype") diff --git a/ui/menu.func b/ui/menu.func index b2eb5c3..3bb32e4 100644 --- a/ui/menu.func +++ b/ui/menu.func @@ -141,7 +141,7 @@ echo_default() { echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}" echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" - if [[ "$(dpkg --print-architecture)" == "arm64" ]]; then + if [[ "$(_cs_host_arch)" == "arm64" ]]; then echo -e "${INFO}${BOLD}${DGN}Architecture: ${BGN}arm64${CL}" fi if [[ -n "${var_gpu:-}" && "${var_gpu}" == "yes" ]]; then @@ -209,7 +209,7 @@ install_script() { storage_content_check diagnostics_check - if systemctl is-active -q ping-instances.service; then + if command -v systemctl >/dev/null 2>&1 && systemctl is-active -q ping-instances.service; then systemctl -q stop ping-instances.service fi