From ac495c31dc94dc6763af187a18becb6c309028a0 Mon Sep 17 00:00:00 2001 From: Francesco Picone Date: Tue, 3 Mar 2026 13:47:34 +0100 Subject: [PATCH] ++ primo caricamento --- .env | 8 ++ bootstrap-garage-layout.sh | 148 +++++++++++++++++++++++++++++++++++++ docker-compose.yml | 32 ++++++++ garage/garage.toml | 20 +++++ start-garage.sh | 12 +++ 5 files changed, 220 insertions(+) create mode 100644 .env create mode 100644 bootstrap-garage-layout.sh create mode 100644 docker-compose.yml create mode 100644 garage/garage.toml create mode 100644 start-garage.sh diff --git a/.env b/.env new file mode 100644 index 0000000..5192024 --- /dev/null +++ b/.env @@ -0,0 +1,8 @@ +RESTART=always +GARAGE_CONTAINER_NAME=garage +GARAGE_CORE_IMAGE_VERSION=v2.0.0 +GARAGE_WEB_IMAGE_VERSION=latest +GARAGE_WEB_UI_PORT=3909 +GARAGE_DATA_PATH=nas_qwince +GARAGE_CONFIG_PATH=GARAGE +GARAGE_ADMIN_TOKEN=34fKJkkjjsaLjikjldjlkjlkjlkj diff --git a/bootstrap-garage-layout.sh b/bootstrap-garage-layout.sh new file mode 100644 index 0000000..40d670c --- /dev/null +++ b/bootstrap-garage-layout.sh @@ -0,0 +1,148 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$PROJECT_DIR" + +COMPOSE="docker compose" +SERVICE="garage" +GARAGE_BIN="/garage" +GARAGE_CMD="$COMPOSE exec -T $SERVICE $GARAGE_BIN" + +ZONE="${GARAGE_LAYOUT_ZONE:-dc1}" +FORCE_CAPACITY_UPDATE=false + +for arg in "$@"; do + case "$arg" in + --force-capacity-update) + FORCE_CAPACITY_UPDATE=true + ;; + -h|--help) + echo "Uso: $0 [--force-capacity-update]" + echo + echo " --force-capacity-update Riapplica layout se la capacità rilevata differisce da quella attuale del nodo" + exit 0 + ;; + *) + echo "Errore: opzione non riconosciuta: $arg" >&2 + echo "Usa --help per vedere le opzioni disponibili." >&2 + exit 1 + ;; + esac +done + +get_env_value() { + local key="$1" + local env_file="$PROJECT_DIR/.env" + + if [[ -n "${!key:-}" ]]; then + printf '%s' "${!key}" + return 0 + fi + + if [[ -f "$env_file" ]]; then + awk -F= -v k="$key" '$1==k {print $2; exit}' "$env_file" + return 0 + fi + + return 1 +} + +detect_capacity_gb() { + local data_path="$1" + local normalized_path="$data_path" + + if [[ "$data_path" != /* ]]; then + normalized_path="$PROJECT_DIR/$data_path" + fi + + if [[ ! -d "$normalized_path" ]]; then + return 1 + fi + + local size_gb + size_gb="$(df -BG --output=size "$normalized_path" 2>/dev/null | awk 'NR==2 {gsub(/G/,"",$1); print $1}')" + if [[ "$size_gb" =~ ^[0-9]+$ ]] && [[ "$size_gb" -gt 0 ]]; then + printf '%sG' "$size_gb" + return 0 + fi + + local used_gb + used_gb="$(du -sBG "$normalized_path" 2>/dev/null | awk '{gsub(/G/,"",$1); print $1}')" + if [[ "$used_gb" =~ ^[0-9]+$ ]] && [[ "$used_gb" -gt 0 ]]; then + printf '%sG' "$used_gb" + return 0 + fi + + return 1 +} + +if [[ -n "${GARAGE_LAYOUT_CAPACITY:-}" ]]; then + CAPACITY="$GARAGE_LAYOUT_CAPACITY" +else + DATA_PATH="$(get_env_value "GARAGE_DATA_PATH")" + if CAPACITY="$(detect_capacity_gb "$DATA_PATH")"; then + echo "Capacità auto-rilevata da GARAGE_DATA_PATH ($DATA_PATH): $CAPACITY" + else + CAPACITY="100G" + echo "Avviso: capacità non rilevabile da GARAGE_DATA_PATH (${DATA_PATH:-unset}), uso fallback $CAPACITY" >&2 + fi +fi + +if ! command -v docker >/dev/null 2>&1; then + echo "Errore: docker non trovato nel PATH." >&2 + exit 1 +fi + +if ! $COMPOSE ps --status running "$SERVICE" >/dev/null 2>&1; then + echo "Errore: il servizio '$SERVICE' non risulta avviato. Esegui: docker compose up -d" >&2 + exit 1 +fi + +LAYOUT_OUTPUT="$($GARAGE_CMD layout show)" +LAYOUT_VERSION="$(printf '%s\n' "$LAYOUT_OUTPUT" | sed -n 's/^Current cluster layout version: \([0-9][0-9]*\)$/\1/p')" +LAYOUT_VERSION="${LAYOUT_VERSION:-0}" + +STATUS_OUTPUT="$($GARAGE_CMD status)" + +NODE_ID="$(printf '%s\n' "$STATUS_OUTPUT" | awk ' + /==== HEALTHY NODES ====/ {in_table=1; next} + in_table && /^ID[[:space:]]+/ {next} + in_table && /^[0-9a-f]{8,}/ {print $1; exit} +')" + +if [[ -z "$NODE_ID" ]]; then + echo "Errore: nessun nodo healthy trovato su cui applicare il layout." >&2 + exit 1 +fi + +CURRENT_CAPACITY_GB="$(printf '%s\n' "$STATUS_OUTPUT" | awk -v id="$NODE_ID" '$1==id {for (i=1;i<=NF;i++) if ($i ~ /^[0-9.]+$/) {print int($i); exit}}')" +TARGET_CAPACITY_GB="$(printf '%s\n' "$CAPACITY" | sed -n 's/^\([0-9][0-9]*\)G$/\1/p')" + +NEEDS_LAYOUT_APPLY=false +if printf '%s\n' "$STATUS_OUTPUT" | grep -q 'NO ROLE ASSIGNED' || [[ "$LAYOUT_VERSION" -eq 0 ]]; then + NEEDS_LAYOUT_APPLY=true +elif [[ "$FORCE_CAPACITY_UPDATE" == true ]] && [[ -n "$CURRENT_CAPACITY_GB" ]] && [[ -n "$TARGET_CAPACITY_GB" ]] && [[ "$CURRENT_CAPACITY_GB" -ne "$TARGET_CAPACITY_GB" ]]; then + NEEDS_LAYOUT_APPLY=true +fi + +if [[ "$NEEDS_LAYOUT_APPLY" == true ]]; then + NEXT_VERSION=$((LAYOUT_VERSION + 1)) + + if [[ "$FORCE_CAPACITY_UPDATE" == true ]] && [[ "$LAYOUT_VERSION" -gt 0 ]]; then + echo "Aggiornamento capacità forzato richiesto (attuale=${CURRENT_CAPACITY_GB:-unknown}G, target=$CAPACITY)." + else + echo "Layout non pronto (version=$LAYOUT_VERSION)." + fi + echo "Applico ruolo al nodo $NODE_ID (zone=$ZONE, capacity=$CAPACITY)..." + + $GARAGE_CMD layout assign -z "$ZONE" -c "$CAPACITY" "$NODE_ID" >/dev/null + $GARAGE_CMD layout apply --version "$NEXT_VERSION" >/dev/null + + echo "Layout applicato (version=$NEXT_VERSION)." +else + echo "Layout già pronto (version=$LAYOUT_VERSION), nessuna modifica necessaria." +fi + +echo +$GARAGE_CMD status diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8af4f78 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +services: + garage: + image: dxflrs/garage:${GARAGE_CORE_IMAGE_VERSION} + container_name: ${GARAGE_CONTAINER_NAME} + restart: ${RESTART} + volumes: + # Garage configuration and metadata + - ./${GARAGE_CONFIG_PATH}/garage.toml:/etc/garage.toml + - ./${GARAGE_CONFIG_PATH}/meta:/var/lib/garage/meta + # Map the data directory to a local path for persistence + - ./${GARAGE_DATA_PATH}:/var/lib/garage/data + ports: + - "3900:3900" + - "3901:3901" + - "3902:3902" + - "3903:3903" + + webui: + image: khairul169/garage-webui:${GARAGE_WEB_IMAGE_VERSION} + container_name: ${GARAGE_CONTAINER_NAME}-webui + restart: ${RESTART} + depends_on: + - ${GARAGE_CONTAINER_NAME} + volumes: + # Mount the same configuration file for the web UI to read settings + - ./${GARAGE_CONFIG_PATH}/garage.toml:/etc/garage.toml:ro + ports: + - "${GARAGE_WEB_UI_PORT}:3909" + environment: + API_BASE_URL: "http://${GARAGE_CONTAINER_NAME}:3903" + API_ADMIN_KEY: "${GARAGE_ADMIN_TOKEN}" + S3_ENDPOINT_URL: "http://${GARAGE_CONTAINER_NAME}:3900" diff --git a/garage/garage.toml b/garage/garage.toml new file mode 100644 index 0000000..119bcaf --- /dev/null +++ b/garage/garage.toml @@ -0,0 +1,20 @@ +metadata_dir = "/var/lib/garage/meta" +data_dir = "/var/lib/garage/data" + +replication_factor = 1 + +rpc_secret = "5f45f0a031cbb7cbae9d0ecaebccc85589cb51a223f15589390745c4b0f8833b" +rpc_bind_addr = "0.0.0.0:3901" +rpc_public_addr = "127.0.0.1:3901" + +[s3_api] +api_bind_addr = "0.0.0.0:3900" +s3_region = "garage" + +[s3_web] +bind_addr = "0.0.0.0:3902" +root_domain = "localhost" + +[admin] +api_bind_addr = "0.0.0.0:3903" +admin_token = "34fKJkkjjsaLjikjldjlkjlkjlkj" diff --git a/start-garage.sh b/start-garage.sh new file mode 100644 index 0000000..a5dca48 --- /dev/null +++ b/start-garage.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")" + +echo "[1/2] Avvio stack Docker Compose..." +docker compose up -d + +echo "[2/2] Bootstrap layout Garage..." +./bootstrap-garage-layout.sh + +echo "OK: Garage avviato e layout verificato." \ No newline at end of file