diff --git a/examples/okd_pxe/src/main.rs b/examples/okd_pxe/src/main.rs index 9778e18..b026fbf 100644 --- a/examples/okd_pxe/src/main.rs +++ b/examples/okd_pxe/src/main.rs @@ -15,6 +15,10 @@ async fn main() { let topology = get_topology().await; let gateway_ip = topology.router.get_gateway(); + let kickstart_filename = "inventory.kickstart"; + let cluster_pubkey_filename = "cluster_ssh_key.pub"; + let harmony_inventory_agent = "harmony_inventory_agent"; + // TODO this should be a single IPXEScore instead of having the user do this step by step let scores: Vec>> = vec![ Box::new(DhcpScore { @@ -29,18 +33,162 @@ async fn main() { files_to_serve: Url::LocalFolder("./data/pxe/okd/tftpboot/".to_string()), }), Box::new(StaticFilesHttpScore { - folder_to_serve: None, - files: vec![FileContent { - path: FilePath::Relative("boot.ipxe".to_string()), - content: format!( - "#!ipxe + folder_to_serve: Some(Url::LocalFolder("./data/pxe/okd/http_files/".to_string())), + files: vec![ + FileContent { + path: FilePath::Relative("boot.ipxe".to_string()), + content: format!( + "#!ipxe set base-url http://{gateway_ip}:8080 set hostfile ${{base-url}}/byMAC/01-${{mac:hexhyp}}.ipxe chain ${{hostfile}} || chain ${{base-url}}/default.ipxe" - ), - }], + ), + }, + FileContent { + path: FilePath::Relative(kickstart_filename.to_string()), + content: format!( + r#"# ================================================================= +# Harmony Discovery Agent - Kickstart File (inventory.kickstart) +# ================================================================= +# +# This Kickstart file configures the CentOS Stream 9 live environment. +# It does NOT install to disk. It sets up SSH for remote access +# and downloads and runs the harmony-inventory-agent. +# + +# --- System Configuration +lang en_US.UTF-8 +keyboard --xlayouts='us' +timezone America/New_York --isUtc + +# --- Network Configuration +# Ensure the network is activated using DHCP. +network --bootproto=dhcp --device=link --activate + +# --- Security Configuration +# Disable the firewall for this isolated provisioning network. +firewall --disabled +# Disable SELinux for simplicity in the live environment. +selinux --disabled +# Disable password-based root login for security. +rootpw --lock + +# --- Service Configuration +# Ensure the SSH daemon is enabled. +services --enabled="sshd" + +# We are running a live environment, so no disk partitioning. +# The 'liveimg' command would be used here if booting from a squashfs, +# but since we are booting from kernel/initrd, we just use the %post. + +# Do not run the graphical initial setup wizard. +firstboot --disable + +# --- Post-Boot Scripting +# This section runs after the live environment has booted into RAM. +%post --log=/root/ks-post.log + +echo "Harmony Kickstart: Post-boot script started." + +# 1. Configure SSH Access +# Create the .ssh directory and set correct permissions. +echo " - Setting up SSH authorized_keys..." +mkdir -p /root/.ssh +chmod 700 /root/.ssh + +# Download the public key and place it in authorized_keys. +curl -sSL "http://{gateway_ip}:8080/{cluster_pubkey_filename}" -o /root/.ssh/authorized_keys +chmod 600 /root/.ssh/authorized_keys + +# SELinux context is handled by 'selinux --disabled' above, +# but if SELinux were enabled, this would be essential: +# restorecon -R /root/.ssh + +# 2. Download the Harmony Inventory Agent +echo " - Downloading harmony-inventory-agent..." +curl -sSL "http://{gateway_ip}:8080/{harmony_inventory_agent}" -o /usr/local/bin/harmony-inventory-agent +chmod +x /usr/local/bin/harmony-inventory-agent + +# 3. Create a systemd service to run the agent persistently +echo " - Creating systemd service for the agent..." +cat > /etc/systemd/system/harmony-agent.service << EOF +[Unit] +Description=Harmony Inventory Agent +After=network-online.target +Wants=network-online.target + +[Service] +ExecStart=/usr/local/bin/harmony-inventory-agent +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF + +# 4. Enable and start the service +echo " - Enabling and starting harmony-agent.service..." +systemctl daemon-reload +systemctl enable --now harmony-agent.service + +echo "Harmony Kickstart: Post-boot script finished. The inventory agent is running." + +curl localhost:8080/inventory | tee -a /tmp/harmony_inventory.json + +%end + +# Do not automatically reboot or poweroff. +# The machine should remain running for inventory scraping."# + ), + }, + FileContent { + path: FilePath::Relative("default.ipxe".to_string()), + content: format!( + r#"#!ipxe + +# ================================================================= +# Harmony Discovery Agent - Default Boot Script (default.ipxe) +# ================================================================= +# +# This script boots the CentOS Stream live environment for the +# purpose of hardware inventory. It loads the kernel and initramfs +# directly and passes a Kickstart URL for full automation. +# + +# --- Configuration +# Set the base URL for where the CentOS kernel/initrd are hosted. +set os_base_url http://{gateway_ip}:8080/os/centos-stream-9 +# Set the URL for the Kickstart file. +set ks_url http://{gateway_ip}:8080/{kickstart_filename} + +# --- Boot Process +echo "Harmony: Starting automated node discovery..." +echo "Fetching kernel from ${{os_base_url}}/vmlinuz..." +kernel ${{os_base_url}}/vmlinuz + +echo "Fetching initramfs from ${{os_base_url}}/initrd.img..." +initrd ${{os_base_url}}/initrd.img + +echo "Configuring kernel boot arguments..." +# Kernel Arguments Explained: +# - initrd=initrd.img: Specifies the initial ramdisk to use. +# - inst.stage2: Points to the OS source. For a live boot, the base URL is sufficient. +# - inst.ks: CRITICAL: Points to our Kickstart file for automation. +# - ip=dhcp: Ensures the live environment configures its network. +# - console=...: Provides boot output on both serial and graphical consoles for debugging. +imgargs vmlinuz initrd=initrd.img inst.stage2=${{os_base_url}} inst.ks=${{ks_url}} ip=dhcp console=ttyS0,115200 console=tty1 + +echo "Booting into CentOS Stream 9 live environment..." +boot || goto failed + +:failed +echo "Boot failed. Dropping to iPXE shell." +shell"# + ), + }, + ], }), ];