From 49eb6bcf114b78f9e12d81420ef441fe16441b32 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Thu, 18 Dec 2025 21:09:26 -0300 Subject: [PATCH] feat: add fallback images for LXC container creation and install-dependencies.sh - Try ubuntu:24.04, ubuntu:22.04, images:debian/12, images:debian/11 in order - Clean up failed container attempts before trying next image - Add install-dependencies.sh script for runtime library installation - Fixes 404 error when LXD image server has outdated cached images --- scripts/install-dependencies.sh | 168 +++++++++++++++++++++++++++++ src/core/package_manager/facade.rs | 53 ++++++--- 2 files changed, 209 insertions(+), 12 deletions(-) create mode 100755 scripts/install-dependencies.sh diff --git a/scripts/install-dependencies.sh b/scripts/install-dependencies.sh new file mode 100755 index 00000000..670fd5f9 --- /dev/null +++ b/scripts/install-dependencies.sh @@ -0,0 +1,168 @@ +#!/bin/bash +# +# install-dependencies.sh +# Installs all runtime dependencies required to run the botserver binary +# +# Usage: sudo ./install-dependencies.sh +# +# This script must be run on the HOST system (not inside a container) +# before running botserver for the first time. +# + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} botserver Dependency Installer${NC}" +echo -e "${GREEN}========================================${NC}" +echo "" + +# Check if running as root +if [ "$EUID" -ne 0 ]; then + echo -e "${RED}Error: This script must be run as root (use sudo)${NC}" + exit 1 +fi + +# Detect OS +if [ -f /etc/os-release ]; then + . /etc/os-release + OS=$ID + VERSION=$VERSION_ID +else + echo -e "${RED}Error: Cannot detect operating system${NC}" + exit 1 +fi + +echo -e "${YELLOW}Detected OS: $OS $VERSION${NC}" +echo "" + +install_debian_ubuntu() { + echo -e "${GREEN}Installing dependencies for Debian/Ubuntu...${NC}" + + apt-get update + + # Runtime libraries for botserver binary + apt-get install -y \ + libpq5 \ + libssl3 \ + liblzma5 \ + zlib1g \ + ca-certificates \ + curl \ + wget + + # LXC/LXD for container management (optional but recommended) + echo "" + echo -e "${YELLOW}Installing LXD for container support...${NC}" + apt-get install -y snapd || true + snap install lxd || apt-get install -y lxd || true + + # Initialize LXD if not already done + if command -v lxd &> /dev/null; then + if ! lxc list &> /dev/null 2>&1; then + echo -e "${YELLOW}Initializing LXD...${NC}" + lxd init --auto || true + fi + fi + + echo -e "${GREEN}Debian/Ubuntu dependencies installed successfully!${NC}" +} + +install_fedora_rhel() { + echo -e "${GREEN}Installing dependencies for Fedora/RHEL...${NC}" + + dnf install -y \ + libpq \ + openssl-libs \ + xz-libs \ + zlib \ + ca-certificates \ + curl \ + wget + + # LXC for container management + dnf install -y lxc lxc-templates || true + + echo -e "${GREEN}Fedora/RHEL dependencies installed successfully!${NC}" +} + +install_arch() { + echo -e "${GREEN}Installing dependencies for Arch Linux...${NC}" + + pacman -Sy --noconfirm \ + postgresql-libs \ + openssl \ + xz \ + zlib \ + ca-certificates \ + curl \ + wget \ + lxc + + echo -e "${GREEN}Arch Linux dependencies installed successfully!${NC}" +} + +install_alpine() { + echo -e "${GREEN}Installing dependencies for Alpine Linux...${NC}" + + apk add --no-cache \ + libpq \ + openssl \ + xz-libs \ + zlib \ + ca-certificates \ + curl \ + wget \ + lxc + + echo -e "${GREEN}Alpine Linux dependencies installed successfully!${NC}" +} + +# Install based on detected OS +case $OS in + ubuntu|debian|linuxmint|pop) + install_debian_ubuntu + ;; + fedora|rhel|centos|rocky|almalinux) + install_fedora_rhel + ;; + arch|manjaro) + install_arch + ;; + alpine) + install_alpine + ;; + *) + echo -e "${RED}Unsupported operating system: $OS${NC}" + echo "" + echo "Please manually install the following libraries:" + echo " - libpq (PostgreSQL client library)" + echo " - libssl (OpenSSL)" + echo " - liblzma (XZ compression)" + echo " - zlib (compression)" + echo " - LXC/LXD (for container support)" + exit 1 + ;; +esac + +echo "" +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} Dependencies installed successfully!${NC}" +echo -e "${GREEN}========================================${NC}" +echo "" +echo "You can now run botserver:" +echo "" +echo " ./botserver" +echo "" +echo "Or install components in containers:" +echo "" +echo " ./botserver install vault --container --tenant mycompany" +echo " ./botserver install vector_db --container --tenant mycompany" +echo "" +echo -e "${YELLOW}Note: Container commands must be run from the HOST system.${NC}" +echo "" diff --git a/src/core/package_manager/facade.rs b/src/core/package_manager/facade.rs index c5849967..8fb91f96 100644 --- a/src/core/package_manager/facade.rs +++ b/src/core/package_manager/facade.rs @@ -123,19 +123,48 @@ impl PackageManager { } pub fn install_container(&self, component: &ComponentConfig) -> Result<()> { let container_name = format!("{}-{}", self.tenant, component.name); - let output = Command::new("lxc") - .args(&[ - "launch", - "images:debian/12", - &container_name, - "-c", - "security.privileged=true", - ]) - .output()?; - if !output.status.success() { + + // Try multiple image sources in case one is unavailable + let images = [ + "ubuntu:24.04", + "ubuntu:22.04", + "images:debian/12", + "images:debian/11", + ]; + + let mut last_error = String::new(); + let mut success = false; + + for image in &images { + info!("Attempting to create container with image: {}", image); + let output = Command::new("lxc") + .args(&[ + "launch", + image, + &container_name, + "-c", + "security.privileged=true", + ]) + .output()?; + + if output.status.success() { + info!("Successfully created container with image: {}", image); + success = true; + break; + } else { + last_error = String::from_utf8_lossy(&output.stderr).to_string(); + warn!("Failed to create container with {}: {}", image, last_error); + // Clean up any partial container before trying next image + let _ = Command::new("lxc") + .args(&["delete", &container_name, "--force"]) + .output(); + } + } + + if !success { return Err(anyhow::anyhow!( - "LXC container creation failed: {}", - String::from_utf8_lossy(&output.stderr) + "LXC container creation failed with all images. Last error: {}", + last_error )); } std::thread::sleep(std::time::Duration::from_secs(15));