File PersistenceOS.spec of Package PersistenceOS

#
# spec file for package PersistenceOS
#
# Copyright (c) 2024 PersistenceOS Team
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself.
#
# Please submit bugfixes or comments via https://github.com/PersistenceOS/PersistenceOS/issues
#

Name:           PersistenceOS
Version:        6.1.0
Release:        1
Summary:        PersistenceOS - Hypervisor and NAS operating system
License:        MIT
Group:          System/Base
URL:            https://persistenceos.org
Source0:        PersistenceOS-%{version}.tar.xz

# BuildRequires: Only packages needed to build the RPM (unpacking, copying)
BuildRequires:  coreutils
BuildRequires:  bash
BuildRequires:  tar
BuildRequires:  xz
BuildRequires:  findutils
# We don't need kiwi or python build tools here as we are just packaging files

# Requires: Packages needed for the *installed* system to function
Requires:       bash
Requires:       coreutils
Requires:       systemd
Requires:       util-linux
Requires:       grep
Requires:       sed
Requires:       gawk
Requires:       findutils
Requires:       procps
Requires:       shadow # For user management if scripts need it
Requires:       sudo # If any scripts use sudo
# Python & API Runtime
Requires:       python311-base
Requires:       python311-fastapi
Requires:       python311-uvicorn
Requires:       python311-psutil
Requires:       python311-pydantic
Requires:       python311-typing-extensions
Requires:       python311-websockets
Requires:       python311-aiofiles
Requires:       python311-python-multipart
Requires:       python311-starlette
Requires:       python311-httptools
Requires:       python311-ujson
# Virtualization Runtime
Requires:       libvirt-client
Requires:       libvirt-daemon
Requires:       qemu-kvm
Requires:       libvirt-daemon-qemu # Needed by libvirtd
Requires:       dnsmasq # Often used by libvirt default network
# Removed bridge-utils as iproute2 provides network bridging functionality
# Storage Runtime
Requires:       btrfsprogs
Requires:       xfsprogs
Requires:       lvm2
Requires:       snapper # If snapper features are used
Requires:       smartmontools # If health checks use it
Requires:       e2fsprogs # If ext4 needed
Requires:       cryptsetup # If encryption needed
Requires:       mdadm # If RAID needed
Requires:       parted # If scripts perform partitioning
# Networking Runtime
Requires:       NetworkManager
Requires:       iproute2
# Removed nftables as it's not used
Requires:       iputils
# Bootloader Runtime (Needed if scripts interact with it post-install)
Requires:       grub2
Requires:       efibootmgr
# Removed perl-Bootloader as it's not necessary with grub2
# Other Essential Runtime
Requires:       openssl
Requires:       polkit
Requires:       transactional-update # If scripts trigger updates
Requires:       zypper # If scripts manage packages
Requires:       podman # If container features are used
# Only include podman dependencies if actually using container features
# Requires:       slirp4netns # podman dependency
# Requires:       fuse-overlayfs # podman dependency
Requires:       ca-certificates # For HTTPS calls
Requires:       timezone # For time management
# Security Runtime
Requires:       firewalld
Requires:       policycoreutils
Requires:       selinux-policy
# System Runtime
Requires:       kiwi-systemdeps-core
Requires:       kiwi-systemdeps-iso-media
# Removed as redundant with MicroOS base patterns
# Requires:       systemd-default-settings-branding-SLE-Micro
Requires:       supportutils
Requires:       usbutils
Requires:       pciutils
Requires:       lm_sensors
Requires:       kbd
Requires:       rsync
Requires:       jq
# Removed fcgiwrap and spawn-fcgi as they're not used in the current web UI
# Only include these if specifically needed by your FastAPI application
Requires:       python311-sqlalchemy # For database access if needed
Requires:       python311-jinja2 # For templating if needed
Requires:       python311-passlib # For password hashing
Requires:       figlet # For ASCII art in welcome screen
# Web UI Frontend Dependencies
Requires:       nodejs-common # For Node.js ecosystem compatibility if needed

BuildRoot:      %{_tmppath}/%{name}-%{version}-build
BuildArch:      x86_64

%description
PersistenceOS is a specialized hypervisor and NAS operating system based on SUSE Micro Leap 6.1,
designed to provide robust virtualization capabilities with advanced storage management and
snapshot functionality. It leverages both btrfs (for system and snapshots) and XFS (for VM storage)
to provide the optimal balance of snapshot capabilities and performance.

%prep
%setup -q

%build
# Nothing to build

%install
mkdir -p %{buildroot}/usr/lib/persistence
mkdir -p %{buildroot}/usr/lib/persistence/scripts
mkdir -p %{buildroot}/usr/lib/persistence/services
mkdir -p %{buildroot}/usr/lib/persistence/bin
mkdir -p %{buildroot}/usr/lib/persistence/tools
mkdir -p %{buildroot}/usr/lib/persistence/web-ui
mkdir -p %{buildroot}/usr/lib/persistence/api
mkdir -p %{buildroot}/usr/lib/persistence/templates
mkdir -p %{buildroot}/usr/lib/persistence/templates/services
mkdir -p %{buildroot}/usr/lib/persistence/health
mkdir -p %{buildroot}/usr/lib/persistence/python
mkdir -p %{buildroot}/var/lib/persistence
mkdir -p %{buildroot}/var/log/persistence
mkdir -p %{buildroot}/var/lib/persistenceos
mkdir -p %{buildroot}/etc/systemd/system
mkdir -p %{buildroot}/etc/ssl/persistenceos

# Copy scripts
cp -r scripts/* %{buildroot}/usr/lib/persistence/scripts/

# Copy services
cp -r services/* %{buildroot}/usr/lib/persistence/services/

# Copy tools
cp -r tools/* %{buildroot}/usr/lib/persistence/tools/

# Copy web-ui
mkdir -p %{buildroot}/usr/lib/persistence/web-ui
mkdir -p %{buildroot}/usr/lib/persistence/web-ui/js
mkdir -p %{buildroot}/usr/lib/persistence/web-ui/css
mkdir -p %{buildroot}/usr/lib/persistence/web-ui/img

# Copy web-ui files if they exist
if [ -d "web-ui" ]; then
    cp -r web-ui/* %{buildroot}/usr/lib/persistence/web-ui/
fi

# Copy login.html if it exists
if [ -f "web-ui/login.html" ]; then
    cp web-ui/login.html %{buildroot}/usr/lib/persistence/web-ui/
fi

# Copy JavaScript files from current directory (OBS SOURCES) to web-ui/js
# These files are uploaded to OBS SOURCES and need to be included in the RPM
for js_file in "app.js" "auth.js" "vue.js" "login.js"; do
    if [ -f "$js_file" ]; then
        echo "Copying $js_file to web-ui/js/"
        cp "$js_file" %{buildroot}/usr/lib/persistence/web-ui/js/
        chmod 644 %{buildroot}/usr/lib/persistence/web-ui/js/$js_file
    else
        echo "Warning: $js_file not found in SOURCES directory"
    fi
done

# Make sure web-ui directory exists and has proper permissions
chmod 755 %{buildroot}/usr/lib/persistence/web-ui
chmod 755 %{buildroot}/usr/lib/persistence/web-ui/js
chmod 755 %{buildroot}/usr/lib/persistence/web-ui/css
chmod 755 %{buildroot}/usr/lib/persistence/web-ui/img

# Create minimal index.html if it doesn't exist
if [ ! -f "%{buildroot}/usr/lib/persistence/web-ui/index.html" ]; then
    mkdir -p %{buildroot}/usr/lib/persistence/web-ui
    cat > %{buildroot}/usr/lib/persistence/web-ui/index.html << EOF
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PersistenceOS</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f5f5f5;
        }
        .container {
            text-align: center;
            padding: 20px;
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            max-width: 600px;
        }
        h1 {
            color: #2c3e50;
        }
        .logo {
            font-size: 40px;
            font-weight: bold;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="logo">PersistenceOS</div>
        <h1>Welcome to PersistenceOS 6.1</h1>
        <p>Storage Management and Virtualization Platform</p>
        <p>The web interface is currently initializing. If this page persists, please check the system logs.</p>
    </div>
</body>
</html>
EOF
fi

# Copy python
cp -r python/* %{buildroot}/usr/lib/persistence/python/

# Copy service files to the standard location (hybrid approach - fallback in config.sh if this fails)
mkdir -p %{buildroot}/usr/lib/systemd/system/
if ls services/*.service >/dev/null 2>&1; then
    cp services/*.service %{buildroot}/usr/lib/systemd/system/ || echo "Warning: Failed to copy service files - config.sh will handle as fallback"
else
    echo "Warning: No service files found - config.sh will create them"
fi

# Copy preset file if it exists
mkdir -p %{buildroot}/usr/lib/systemd/system-preset/
if [ -f "services/90-persistenceos.preset" ]; then
    cp services/90-persistenceos.preset %{buildroot}/usr/lib/systemd/system-preset/ || echo "Warning: Failed to copy preset file"
fi

# Note: Welcome screen services (persistenceos-welcome.service and persistenceos-welcome.timer)
# are created and managed by persistenceos-core-services.service

# Create systemd drop-in directory (if needed in the future)
mkdir -p %{buildroot}/etc/systemd/system/graphical.target.d/
# Note: graphical.conf will be created if needed by core services

# Create SSL certificate directory
mkdir -p %{buildroot}/etc/ssl/persistenceos

# Create version file
cat > %{buildroot}/var/lib/persistenceos/version << EOF
PersistenceOS %{version}
Build date: $(date -u +"%Y-%m-%dT%H:%M:%SZ")
EOF

%files
%defattr(-,root,root)
%dir /usr/lib/persistence
%dir /usr/lib/persistence/scripts
%dir /usr/lib/persistence/services
%dir /usr/lib/persistence/bin
%dir /usr/lib/persistence/tools
%dir /usr/lib/persistence/web-ui
%dir /usr/lib/persistence/api
%dir /usr/lib/persistence/templates
%dir /usr/lib/persistence/templates/services
%dir /usr/lib/persistence/health
%dir /usr/lib/persistence/python
%dir /var/lib/persistence
%dir /var/log/persistence
%dir /var/lib/persistenceos
%dir /etc/ssl/persistenceos

/usr/lib/persistence/scripts/*
/usr/lib/persistence/services/*
/usr/lib/persistence/tools/*
/usr/lib/persistence/web-ui/*
/usr/lib/persistence/api/*
/usr/lib/persistence/python/*
/usr/lib/persistence/health/*
/usr/lib/systemd/system/*.service
/usr/lib/systemd/system-preset/*.preset
# Note: Timer files and graphical.conf are created dynamically by services

# Make diagnose-web.sh executable
%post
# Make scripts executable
find /usr/lib/persistence/scripts -type f -name "*.sh" -exec chmod 755 {} \;

# Create bin directory if it doesn't exist
mkdir -p "/usr/lib/persistence/bin"

# Copy config.sh to bin directory for easy access
if [ -f "/usr/lib/persistence/scripts/config.sh" ]; then
    cp "/usr/lib/persistence/scripts/config.sh" "/usr/lib/persistence/bin/config"
    chmod 755 "/usr/lib/persistence/bin/config"
    echo "Copied config.sh to bin directory as 'config'"
fi

# Create a link for "image" command that points to config.sh for backward compatibility
if [ -f "/usr/lib/persistence/scripts/config.sh" ]; then
    ln -sf "/usr/lib/persistence/scripts/config.sh" "/usr/lib/persistence/bin/image"
    chmod 755 "/usr/lib/persistence/bin/image"
    echo "Created symbolic link for image command pointing to config.sh"
fi

# Create backward compatibility directory for script/config.sh
mkdir -p "/usr/lib/persistence/script"
ln -sf "/usr/lib/persistence/scripts/config.sh" "/usr/lib/persistence/script/config.sh"

# Verify JavaScript files were installed correctly
echo "Verifying JavaScript file installation..."
js_dir="/usr/lib/persistence/web-ui/js"
mkdir -p "$js_dir"
for js_file in "app.js" "auth.js" "vue.js" "login.js"; do
    if [ -f "$js_dir/$js_file" ]; then
        file_size=$(stat -c%s "$js_dir/$js_file" 2>/dev/null || echo "unknown")
        echo "✅ $js_file installed: $file_size bytes"
    else
        echo "⚠️  $js_file not found - will be handled by config.sh during first boot"
    fi
done

# Ensure proper permissions for web-ui directory
chmod -R 755 "/usr/lib/persistence/web-ui"
find "/usr/lib/persistence/web-ui" -type f -exec chmod 644 {} \; 2>/dev/null || true

# Add welcome message hook to /etc/profile if not already there
if [ -f "/etc/profile" ]; then
    if ! grep -q "PersistenceOS welcome message" "/etc/profile" 2>/dev/null; then
        cat >> "/etc/profile" << 'EOF'

# Display PersistenceOS welcome message on login for interactive shells
if [[ $- == *i* ]]; then
    if [[ -f /usr/lib/persistence/bin/image ]]; then
        /usr/lib/persistence/bin/image --login
    elif [[ -f /usr/lib/persistence/scripts/config.sh ]]; then
        /usr/lib/persistence/scripts/config.sh --login
    fi
fi
EOF
        echo "Added welcome message hook to /etc/profile"
    fi
fi

# Ensure health checker directories exist
mkdir -p "/usr/libexec/health-checker"
mkdir -p "/etc/health-checker.d"
mkdir -p "/usr/lib/persistence/health"

# Create etc-overlayfs.sh hook if it doesn't exist
if [ ! -f "/usr/libexec/health-checker/etc-overlayfs.sh" ]; then
    cat > "/usr/libexec/health-checker/etc-overlayfs.sh" << 'EOF'
#!/bin/bash
check() {
    # Simple check that always succeeds for now
    # Will be expanded with actual overlayfs checks as needed
    return 0
}

if [ "$1" = "check" ]; then
    check
fi
exit 0
EOF
    chmod +x "/usr/libexec/health-checker/etc-overlayfs.sh"
    echo "Created etc-overlayfs.sh hook"
fi

# Create persistenceos health checker hook
if [ ! -f "/usr/libexec/health-checker/persistenceos.sh" ]; then
    cat > "/usr/libexec/health-checker/persistenceos.sh" << 'EOF'
#!/bin/bash
check() {
    # Check if core PersistenceOS directories exist
    [ -d "/usr/lib/persistence" ] || return 1
    [ -d "/var/lib/persistence" ] || return 1

    # Check if FastAPI web server is accessible via health endpoint
    if command -v curl >/dev/null 2>&1; then
        curl -f -s -m 2 http://localhost:8080/api/health >/dev/null || return 1
    fi

    # All checks passed
    return 0
}

if [ "$1" = "check" ]; then
    check
fi
exit 0
EOF
    chmod +x "/usr/libexec/health-checker/persistenceos.sh"
    echo "Created persistenceos.sh hook"
fi

# Create health checker configuration
if [ ! -f "/etc/health-checker.d/persistenceos.conf" ]; then
    cat > "/etc/health-checker.d/persistenceos.conf" << 'EOF'
# PersistenceOS Health Checker configuration
CHECK_INTERVAL=300
SNAPSHOT_CHECK=yes
OVERLAY_CHECK=yes
UPDATE_CHECK=yes
SERVICE_CHECK=yes
BTRFS_CHECK=yes
EOF
    chmod 644 "/etc/health-checker.d/persistenceos.conf"
    echo "Created health checker configuration"
fi

%license LICENSE
%doc README.md

%changelog
* Thu May 16 2024 PersistenceOS Team <team@persistence-os.org> - 6.1.0-1
- Fixed IP detection in welcome message
- Added diagnostic script for web server issues
- Added backward compatibility for script paths
- Ensured index.html fallback exists
openSUSE Build Service is sponsored by