- Fixed sfdisk PATH issue in Containerfile.base (sfdisk is in /usr/sbin) - Updated Containerfile.minimal to use full path for grub-install - Enhanced test-bootc-deployment.sh to properly check utility locations - Added comprehensive section about related projects (apt-ostree, deb-bootupd, debian-bootc-corrected) - Updated validation script to handle Debian-specific utility locations - Improved error messages with specific solutions for PATH and utility issues This addresses the critical requirements from scope.md regarding disk utilities and PATH environment variables for bootc deployment.
342 lines
11 KiB
Bash
Executable file
342 lines
11 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Particle-OS Bootc Deployment Test Script
|
|
# Tests all critical requirements identified in scope.md
|
|
|
|
set -e
|
|
|
|
echo "🔍 Particle-OS Bootc Deployment Validation"
|
|
echo "=========================================="
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Function to print colored output
|
|
print_status() {
|
|
local status=$1
|
|
local message=$2
|
|
if [ "$status" = "PASS" ]; then
|
|
echo -e "${GREEN}✅ PASS${NC}: $message"
|
|
elif [ "$status" = "FAIL" ]; then
|
|
echo -e "${RED}❌ FAIL${NC}: $message"
|
|
else
|
|
echo -e "${YELLOW}⚠️ WARN${NC}: $message"
|
|
fi
|
|
}
|
|
|
|
# Function to check if command exists and is working
|
|
check_command() {
|
|
local cmd=$1
|
|
local description=$2
|
|
local required=$3
|
|
|
|
if command -v "$cmd" >/dev/null 2>&1; then
|
|
# Handle commands that don't support --version or -V
|
|
if [ "$cmd" = "mkfs.fat" ]; then
|
|
if "$cmd" --help >/dev/null 2>&1; then
|
|
print_status "PASS" "$description: $cmd is available and working"
|
|
return 0
|
|
else
|
|
print_status "FAIL" "$description: $cmd exists but not working properly"
|
|
return 1
|
|
fi
|
|
elif "$cmd" --version >/dev/null 2>&1 || "$cmd" -V >/dev/null 2>&1; then
|
|
print_status "PASS" "$description: $cmd is available and working"
|
|
return 0
|
|
else
|
|
print_status "FAIL" "$description: $cmd exists but not working properly"
|
|
return 1
|
|
fi
|
|
else
|
|
if [ "$required" = "true" ]; then
|
|
print_status "FAIL" "$description: $cmd is missing (REQUIRED)"
|
|
return 1
|
|
else
|
|
print_status "WARN" "$description: $cmd is missing (optional)"
|
|
return 0
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Function to check PATH environment
|
|
check_path() {
|
|
echo -e "\n🔍 Checking PATH environment..."
|
|
echo "Current PATH: $PATH"
|
|
|
|
# Check if critical directories are in PATH
|
|
if [[ ":$PATH:" == *":/usr/sbin:"* ]] && [[ ":$PATH:" == *":/sbin:"* ]]; then
|
|
print_status "PASS" "PATH includes /usr/sbin and /sbin"
|
|
else
|
|
print_status "FAIL" "PATH missing /usr/sbin or /sbin (CRITICAL for bootc)"
|
|
echo "Fixing PATH..."
|
|
export PATH="/usr/sbin:/sbin:$PATH"
|
|
echo "Updated PATH: $PATH"
|
|
fi
|
|
|
|
# Check if critical utilities are accessible via PATH
|
|
echo -e "\n🔍 Checking utility accessibility via PATH..."
|
|
if command -v sfdisk >/dev/null 2>&1; then
|
|
print_status "PASS" "sfdisk accessible via PATH"
|
|
else
|
|
print_status "FAIL" "sfdisk not accessible via PATH (should be in /usr/sbin)"
|
|
echo "Checking if sfdisk exists in /usr/sbin..."
|
|
if [ -x "/usr/sbin/sfdisk" ]; then
|
|
print_status "PASS" "sfdisk exists in /usr/sbin but not in PATH"
|
|
else
|
|
print_status "FAIL" "sfdisk missing from /usr/sbin"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Function to check disk utilities (CRITICAL from scope.md)
|
|
check_disk_utilities() {
|
|
echo -e "\n🔧 Checking disk utilities (CRITICAL for bootc deployment)..."
|
|
|
|
local all_passed=true
|
|
|
|
# Check required disk utilities with explicit path checking
|
|
echo -e "\n🔍 Checking disk utilities in their correct locations..."
|
|
|
|
# Check sfdisk (critical - should be in /usr/sbin)
|
|
if [ -x "/usr/sbin/sfdisk" ]; then
|
|
if /usr/sbin/sfdisk --version >/dev/null 2>&1; then
|
|
print_status "PASS" "sfdisk available in /usr/sbin and working"
|
|
else
|
|
print_status "FAIL" "sfdisk in /usr/sbin but not working properly"
|
|
all_passed=false
|
|
fi
|
|
else
|
|
print_status "FAIL" "sfdisk missing from /usr/sbin (CRITICAL)"
|
|
all_passed=false
|
|
fi
|
|
|
|
# Check other utilities
|
|
check_command "parted" "Alternative partitioning tool" "true" || all_passed=false
|
|
check_command "mkfs.ext4" "Ext4 filesystem creation" "true" || all_passed=false
|
|
check_command "mkfs.fat" "FAT filesystem creation" "true" || all_passed=false
|
|
|
|
# Check for GRUB installation (handle different names and locations)
|
|
if [ -x "/usr/sbin/grub-install" ]; then
|
|
if /usr/sbin/grub-install --version >/dev/null 2>&1; then
|
|
print_status "PASS" "grub-install available in /usr/sbin and working"
|
|
else
|
|
print_status "FAIL" "grub-install in /usr/sbin but not working properly"
|
|
all_passed=false
|
|
fi
|
|
elif [ -x "/usr/bin/grub-install" ]; then
|
|
if /usr/bin/grub-install --version >/dev/null 2>&1; then
|
|
print_status "PASS" "grub-install available in /usr/bin and working"
|
|
else
|
|
print_status "FAIL" "grub-install in /usr/bin but not working properly"
|
|
all_passed=false
|
|
fi
|
|
elif command -v "grub2-install" >/dev/null 2>&1; then
|
|
check_command "grub2-install" "GRUB2 bootloader installation" "true" || all_passed=false
|
|
else
|
|
print_status "FAIL" "GRUB bootloader installation: neither grub-install nor grub2-install found (REQUIRED)"
|
|
all_passed=false
|
|
fi
|
|
|
|
check_command "efibootmgr" "UEFI boot manager" "true" || all_passed=false
|
|
|
|
# Check additional utilities
|
|
check_command "fdisk" "Disk partitioning utility" "false"
|
|
check_command "gdisk" "GPT partitioning utility" "false"
|
|
|
|
if [ "$all_passed" = "false" ]; then
|
|
echo -e "\n${RED}❌ CRITICAL: Some required disk utilities are missing!${NC}"
|
|
echo "This will prevent bootc from deploying successfully."
|
|
echo ""
|
|
echo "Common solutions:"
|
|
echo "1. Install missing packages: apt install util-linux parted e2fsprogs dosfstools grub-efi-amd64 efibootmgr"
|
|
echo "2. Fix PATH: export PATH=\"/usr/sbin:/sbin:\$PATH\""
|
|
echo "3. Check utility locations: ls -la /usr/sbin/sfdisk /usr/sbin/grub-install"
|
|
return 1
|
|
fi
|
|
|
|
print_status "PASS" "All critical disk utilities are available"
|
|
return 0
|
|
}
|
|
|
|
# Function to check bootc functionality
|
|
check_bootc() {
|
|
echo -e "\n🚀 Checking bootc functionality..."
|
|
|
|
if command -v bootc >/dev/null 2>&1; then
|
|
local version=$(bootc --version 2>/dev/null || echo "unknown")
|
|
print_status "PASS" "bootc is available: $version"
|
|
|
|
# Test basic bootc commands
|
|
if bootc --help >/dev/null 2>&1; then
|
|
print_status "PASS" "bootc --help works correctly"
|
|
else
|
|
print_status "FAIL" "bootc --help failed"
|
|
return 1
|
|
fi
|
|
else
|
|
print_status "FAIL" "bootc is not available (CRITICAL)"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Function to check OSTree functionality
|
|
check_ostree() {
|
|
echo -e "\n🌳 Checking OSTree functionality..."
|
|
|
|
if command -v ostree >/dev/null 2>&1; then
|
|
local version=$(ostree --version 2>/dev/null || echo "unknown")
|
|
print_status "PASS" "ostree is available: $version"
|
|
|
|
# Test basic ostree commands
|
|
if ostree --help >/dev/null 2>&1; then
|
|
print_status "PASS" "ostree --help works correctly"
|
|
else
|
|
print_status "FAIL" "ostree --help failed"
|
|
return 1
|
|
fi
|
|
else
|
|
print_status "FAIL" "ostree is not available (CRITICAL)"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Function to check filesystem structure
|
|
check_filesystem_structure() {
|
|
echo -e "\n📁 Checking OSTree filesystem structure..."
|
|
|
|
local all_passed=true
|
|
|
|
# Check required directories
|
|
local required_dirs=(
|
|
"/ostree"
|
|
"/sysroot"
|
|
"/usr/lib/ostree-boot"
|
|
"/usr/lib/modules"
|
|
"/usr/lib/kernel"
|
|
"/etc/ostree"
|
|
"/var/lib/ostree"
|
|
"/var/home"
|
|
)
|
|
|
|
for dir in "${required_dirs[@]}"; do
|
|
if [ -d "$dir" ]; then
|
|
print_status "PASS" "Directory exists: $dir"
|
|
else
|
|
print_status "FAIL" "Directory missing: $dir"
|
|
all_passed=false
|
|
fi
|
|
done
|
|
|
|
# Check home symlink
|
|
if [ -L "/home" ] && [ "$(readlink /home)" = "../var/home" ]; then
|
|
print_status "PASS" "Home symlink correctly points to /var/home"
|
|
else
|
|
print_status "FAIL" "Home symlink incorrect or missing"
|
|
all_passed=false
|
|
fi
|
|
|
|
if [ "$all_passed" = "false" ]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Function to check container runtime
|
|
check_container_runtime() {
|
|
echo -e "\n🐳 Checking container runtime..."
|
|
|
|
if command -v podman >/dev/null 2>&1; then
|
|
local version=$(podman --version 2>/dev/null || echo "unknown")
|
|
print_status "PASS" "podman is available: $version"
|
|
|
|
# Test podman functionality
|
|
if podman --help >/dev/null 2>&1; then
|
|
print_status "PASS" "podman --help works correctly"
|
|
else
|
|
print_status "FAIL" "podman --help failed"
|
|
return 1
|
|
fi
|
|
else
|
|
print_status "FAIL" "podman is not available (CRITICAL)"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Function to run deployment test
|
|
test_deployment() {
|
|
echo -e "\n🧪 Testing bootc deployment capabilities..."
|
|
|
|
# Check if we're in a container
|
|
if [ -f /.dockerenv ] || grep -q docker /proc/1/cgroup 2>/dev/null; then
|
|
print_status "WARN" "Running in container - deployment test limited"
|
|
echo "Note: Full deployment test requires host system access"
|
|
return 0
|
|
fi
|
|
|
|
# Check if we have access to block devices
|
|
if [ -b /dev/sda ] || [ -b /dev/vda ]; then
|
|
print_status "PASS" "Block devices accessible for deployment testing"
|
|
else
|
|
print_status "WARN" "No block devices accessible for deployment testing"
|
|
fi
|
|
|
|
# Check if we have sufficient privileges
|
|
if [ "$(id -u)" -eq 0 ]; then
|
|
print_status "PASS" "Running with root privileges for deployment"
|
|
else
|
|
print_status "WARN" "Not running with root privileges - some tests may fail"
|
|
fi
|
|
}
|
|
|
|
# Main validation function
|
|
main() {
|
|
echo "Starting comprehensive validation..."
|
|
|
|
local exit_code=0
|
|
|
|
# Run all checks
|
|
check_path || exit_code=1
|
|
check_disk_utilities || exit_code=1
|
|
check_bootc || exit_code=1
|
|
check_ostree || exit_code=1
|
|
check_filesystem_structure || exit_code=1
|
|
check_container_runtime || exit_code=1
|
|
test_deployment || exit_code=1
|
|
|
|
# Summary
|
|
echo -e "\n📊 Validation Summary"
|
|
echo "===================="
|
|
|
|
if [ $exit_code -eq 0 ]; then
|
|
echo -e "${GREEN}🎉 All critical checks passed!${NC}"
|
|
echo "Your Particle-OS image is ready for bootc deployment."
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo "1. Test image in VM: just test-image"
|
|
echo "2. Validate boot process"
|
|
echo "3. Test OSTree functionality"
|
|
else
|
|
echo -e "${RED}❌ Some critical checks failed!${NC}"
|
|
echo "Please fix the issues above before attempting deployment."
|
|
echo ""
|
|
echo "Common solutions:"
|
|
echo "1. Install missing packages: apt install util-linux parted e2fsprogs dosfstools"
|
|
echo "2. Fix PATH: export PATH=\"/usr/sbin:/sbin:\$PATH\""
|
|
echo "3. Ensure all Containerfile requirements are met"
|
|
fi
|
|
|
|
return $exit_code
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|