Установщик автоматически выбирает сборку под x86 Raspberry Orange Pi

Этот коммит содержится в:
Виктор
2026-05-06 21:55:26 +09:00
родитель 6207b8d2c3
Коммит 330208c1dd
+47 -7
Просмотреть файл
@@ -2,7 +2,7 @@
set -euo pipefail set -euo pipefail
# Virtuality Web Panel Installer # Virtuality Web Panel Installer
# Clean step-by-step installer with readable statuses, Linux-user auth and log file. # Auto-detects x86_64 / Raspberry Pi ARM64 / Orange Pi 5 ARM64 / generic ARM64 profile.
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WEB_DIR="${REPO_DIR}/web" WEB_DIR="${REPO_DIR}/web"
@@ -13,7 +13,9 @@ PORT="${VIRTUALITY_WEB_PORT:-8088}"
AUTH_USER="${VIRTUALITY_AUTH_USER:-${SUDO_USER:-viktor}}" AUTH_USER="${VIRTUALITY_AUTH_USER:-${SUDO_USER:-viktor}}"
LOG_DIR="/var/log/virtuality" LOG_DIR="/var/log/virtuality"
LOG_FILE="${LOG_DIR}/install_web_panel_$(date +%Y%m%d_%H%M%S).log" LOG_FILE="${LOG_DIR}/install_web_panel_$(date +%Y%m%d_%H%M%S).log"
TOTAL_STEPS=11 PROFILE_DIR="/var/lib/virtuality/config"
PROFILE_FILE="${PROFILE_DIR}/host_profile.json"
TOTAL_STEPS=12
CURRENT_STEP=0 CURRENT_STEP=0
ESC="\033" ESC="\033"
@@ -27,7 +29,7 @@ CYAN="${ESC}[36m"
BLUE="${ESC}[34m" BLUE="${ESC}[34m"
GRAY="${ESC}[90m" GRAY="${ESC}[90m"
mkdir -p "$LOG_DIR" mkdir -p "$LOG_DIR" "$PROFILE_DIR"
timestamp() { date '+%Y-%m-%d %H:%M:%S'; } timestamp() { date '+%Y-%m-%d %H:%M:%S'; }
line() { printf '%*s\n' 72 '' | tr ' ' '─'; } line() { printf '%*s\n' 72 '' | tr ' ' '─'; }
@@ -37,7 +39,7 @@ print_header() {
clear 2>/dev/null || true clear 2>/dev/null || true
echo -e "${CYAN}${BOLD}╭────────────────────────────────────────────────────────────╮${RESET}" echo -e "${CYAN}${BOLD}╭────────────────────────────────────────────────────────────╮${RESET}"
echo -e "${CYAN}${BOLD}${RESET} ${BOLD}Virtuality Web Panel Installer${RESET} ${CYAN}${BOLD}${RESET}" echo -e "${CYAN}${BOLD}${RESET} ${BOLD}Virtuality Web Panel Installer${RESET} ${CYAN}${BOLD}${RESET}"
echo -e "${CYAN}${BOLD}${RESET} Панель управления VM, сервисами, сетью и storage pools ${CYAN}${BOLD}${RESET}" echo -e "${CYAN}${BOLD}${RESET} Auto profile: x86 / VPS / Raspberry / Orange Pi 5 ${CYAN}${BOLD}${RESET}"
echo -e "${CYAN}${BOLD}╰────────────────────────────────────────────────────────────╯${RESET}" echo -e "${CYAN}${BOLD}╰────────────────────────────────────────────────────────────╯${RESET}"
echo echo
echo -e "${GRAY}Лог установки:${RESET} ${LOG_FILE}" echo -e "${GRAY}Лог установки:${RESET} ${LOG_FILE}"
@@ -70,6 +72,7 @@ run_logged() {
service_state() { systemctl is-active "$1" 2>/dev/null || echo "inactive"; } service_state() { systemctl is-active "$1" 2>/dev/null || echo "inactive"; }
require_root() { [[ "$EUID" -eq 0 ]] || fail "Запусти через sudo: sudo bash scripts/install_web_panel.sh"; } require_root() { [[ "$EUID" -eq 0 ]] || fail "Запусти через sudo: sudo bash scripts/install_web_panel.sh"; }
json_value() { python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get(sys.argv[2], ""))' "$PROFILE_FILE" "$1" 2>/dev/null || true; }
print_header print_header
@@ -83,6 +86,23 @@ ok "FastAPI entrypoint найден: web/app.py"
[[ -f "$WEB_DIR/requirements.txt" ]] || fail "Не найден web/requirements.txt" [[ -f "$WEB_DIR/requirements.txt" ]] || fail "Не найден web/requirements.txt"
ok "requirements.txt найден" ok "requirements.txt найден"
step "Автоматически определяем профиль сборки"
if [[ -x "${REPO_DIR}/scripts/detect_host_profile.sh" ]]; then
PROFILE="$(${REPO_DIR}/scripts/detect_host_profile.sh 2>>"$LOG_FILE" | tail -n1)"
else
bash "${REPO_DIR}/scripts/detect_host_profile.sh" >>"$LOG_FILE" 2>&1 || true
PROFILE="$(json_value profile)"
fi
[[ -n "$PROFILE" ]] || PROFILE="x86_64"
ARCH="$(json_value arch)"
MODEL="$(json_value model)"
LABEL="$(json_value label)"
PACKAGE_PROFILE="$(json_value package_profile)"
ok "Профиль: ${LABEL:-$PROFILE}"
ok "Архитектура: ${ARCH:-unknown}"
ok "Модель: ${MODEL:-unknown}"
ok "Конфиг профиля: $PROFILE_FILE"
step "Проверяем Linux-пользователя для входа" step "Проверяем Linux-пользователя для входа"
if id "$AUTH_USER" >/dev/null 2>&1; then if id "$AUTH_USER" >/dev/null 2>&1; then
ok "Пользователь найден: $AUTH_USER" ok "Пользователь найден: $AUTH_USER"
@@ -107,12 +127,30 @@ done
step "Обновляем apt cache" step "Обновляем apt cache"
run_logged "apt update выполнен" apt update run_logged "apt update выполнен" apt update
step "Устанавливаем системные зависимости" step "Устанавливаем системные зависимости под выбранную сборку"
run_logged "Пакеты Python/venv/pip/rsync/nftables установлены" apt install -y python3 python3-venv python3-pip rsync openssl nftables COMMON_PACKAGES=(python3 python3-venv python3-pip rsync openssl nftables)
X86_PACKAGES=(qemu-system-x86 virtinst libvirt-daemon-system libvirt-clients bridge-utils)
ARM_PACKAGES=(qemu-system-arm qemu-efi-aarch64 virtinst libvirt-daemon-system libvirt-clients bridge-utils cloud-image-utils)
PACKAGES=("${COMMON_PACKAGES[@]}")
case "$PACKAGE_PROFILE" in
raspberry|orangepi5|arm64)
PACKAGES+=("${ARM_PACKAGES[@]}")
;;
*)
PACKAGES+=("${X86_PACKAGES[@]}")
;;
esac
run_logged "Системные пакеты установлены для профиля ${PACKAGE_PROFILE:-x86}" apt install -y "${PACKAGES[@]}"
step "Копируем web-панель в /opt/virtuality" step "Копируем web-панель в /opt/virtuality"
run_logged "Создана директория /opt/virtuality" mkdir -p /opt/virtuality run_logged "Создана директория /opt/virtuality" mkdir -p /opt/virtuality
run_logged "Файлы панели синхронизированы в $APP_DIR" rsync -a --delete "$WEB_DIR/" "$APP_DIR/" run_logged "Файлы панели синхронизированы в $APP_DIR" rsync -a --delete "$WEB_DIR/" "$APP_DIR/"
run_logged "Конфиг профиля доступен web-панели" mkdir -p "$PROFILE_DIR"
if [[ -f "$PROFILE_FILE" ]]; then
ok "Профиль уже сохранён: $PROFILE_FILE"
else
warn "Профиль не найден после детекта, будет создан web-панелью при старте"
fi
step "Создаём конфиг авторизации" step "Создаём конфиг авторизации"
SESSION_SECRET="$(openssl rand -hex 32)" SESSION_SECRET="$(openssl rand -hex 32)"
@@ -192,11 +230,13 @@ echo -e "${GREEN}${BOLD}╰─────────────────
echo echo
echo -e "${BOLD}URL:${RESET} http://${SERVER_IP}:${PORT}" echo -e "${BOLD}URL:${RESET} http://${SERVER_IP}:${PORT}"
echo -e "${BOLD}Login:${RESET} ${AUTH_USER} / пароль Linux-пользователя" echo -e "${BOLD}Login:${RESET} ${AUTH_USER} / пароль Linux-пользователя"
echo -e "${BOLD}Profile:${RESET} ${LABEL:-$PROFILE}"
echo -e "${BOLD}Arch:${RESET} ${ARCH:-unknown}"
echo -e "${BOLD}Service:${RESET} virtuality-web.service" echo -e "${BOLD}Service:${RESET} virtuality-web.service"
echo -e "${BOLD}Status:${RESET} systemctl status virtuality-web --no-pager" echo -e "${BOLD}Status:${RESET} systemctl status virtuality-web --no-pager"
echo -e "${BOLD}Logs:${RESET} journalctl -u virtuality-web -f" echo -e "${BOLD}Logs:${RESET} journalctl -u virtuality-web -f"
echo -e "${BOLD}Install log:${RESET} ${LOG_FILE}" echo -e "${BOLD}Install log:${RESET} ${LOG_FILE}"
echo echo
line line
echo -e "${DIM}Следующий шаг: настройка сети /network и создание VM.${RESET}" echo -e "${DIM}Следующий шаг: /host для проверки профиля, /network для NAT, /vm/create для VM.${RESET}"
line line