...
This commit is contained in:
parent
d336f36929
commit
3dbd0d0aea
61
tools/extract_kernel.sh
Executable file
61
tools/extract_kernel.sh
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Extract kernel and initrd from Ubuntu cloud image
|
||||||
|
# This script ensures kernel boot works automatically
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_SUBVOL="/var/lib/vms/base"
|
||||||
|
BASE_IMAGE_PATH="$BASE_SUBVOL/ubuntu-24.04-server-cloudimg-amd64.raw"
|
||||||
|
KERNEL_PATH="$BASE_SUBVOL/vmlinuz"
|
||||||
|
INITRD_PATH="$BASE_SUBVOL/initrd.img"
|
||||||
|
|
||||||
|
# Check if kernel and initrd already exist
|
||||||
|
if [ -f "$KERNEL_PATH" ] && [ -f "$INITRD_PATH" ]; then
|
||||||
|
log "Kernel and initrd already extracted"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if base image exists
|
||||||
|
if [ ! -f "$BASE_IMAGE_PATH" ]; then
|
||||||
|
error "Base image not found at $BASE_IMAGE_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Extracting kernel and initrd from base image..."
|
||||||
|
|
||||||
|
# Create temporary mount point
|
||||||
|
TEMP_MOUNT=$(mktemp -d)
|
||||||
|
trap "umount '$TEMP_MOUNT' 2>/dev/null || true; losetup -d /dev/loop1 2>/dev/null || true; rmdir '$TEMP_MOUNT'" EXIT
|
||||||
|
|
||||||
|
# Mount the image
|
||||||
|
losetup -P /dev/loop1 "$BASE_IMAGE_PATH"
|
||||||
|
|
||||||
|
# Mount the boot partition (partition 16 contains kernel/initrd)
|
||||||
|
mount /dev/loop1p16 "$TEMP_MOUNT"
|
||||||
|
|
||||||
|
# Copy kernel and initrd
|
||||||
|
if [ -f "$TEMP_MOUNT/vmlinuz-6.8.0-60-generic" ] && [ -f "$TEMP_MOUNT/initrd.img-6.8.0-60-generic" ]; then
|
||||||
|
cp "$TEMP_MOUNT/vmlinuz-6.8.0-60-generic" "$KERNEL_PATH"
|
||||||
|
cp "$TEMP_MOUNT/initrd.img-6.8.0-60-generic" "$INITRD_PATH"
|
||||||
|
log "✓ Kernel and initrd extracted successfully"
|
||||||
|
else
|
||||||
|
error "Kernel or initrd not found in boot partition"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup is handled by trap
|
||||||
|
log "Kernel extraction completed"
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Ubuntu VM Management Script
|
# Ubuntu VM Management Script
|
||||||
# Usage: ubuntu_vm_manage.sh <command> [vm_name]
|
# Usage: ubuntu_vm_manage.sh <command> [vm_number]
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
@ -36,65 +36,73 @@ info() {
|
|||||||
show_usage() {
|
show_usage() {
|
||||||
echo "Ubuntu VM Management Script"
|
echo "Ubuntu VM Management Script"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Usage: $0 <command> [vm_name]"
|
echo "Usage: $0 <command> [vm_number]"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Commands:"
|
echo "Commands:"
|
||||||
echo " list - List all VMs and their status"
|
echo " list - List all VMs and their status"
|
||||||
echo " status <vm_name> - Show detailed status of a specific VM"
|
echo " status <vm_number> - Show detailed status of a specific VM"
|
||||||
echo " console <vm_name> - Connect to VM console (serial)"
|
echo " console <vm_number> - Connect to VM console (serial)"
|
||||||
echo " ssh <vm_name> - SSH to VM (requires network setup)"
|
echo " ssh <vm_number> - SSH to VM (requires network setup)"
|
||||||
echo " stop <vm_name> - Stop a running VM"
|
echo " stop <vm_number> - Stop a running VM"
|
||||||
echo " start <vm_name> - Start a stopped VM"
|
echo " start <vm_number> - Start a stopped VM"
|
||||||
echo " delete <vm_name> - Delete a VM completely"
|
echo " delete <vm_number> - Delete a VM completely"
|
||||||
echo " ip <vm_name> - Show VM IP address"
|
echo " ip <vm_number> - Show VM IP address"
|
||||||
echo " logs <vm_name> - Show VM logs"
|
echo " logs <vm_number> - Show VM logs"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Examples:"
|
echo "Examples:"
|
||||||
echo " $0 list"
|
echo " $0 list"
|
||||||
echo " $0 status test-vm"
|
echo " $0 status 1"
|
||||||
echo " $0 console test-vm"
|
echo " $0 console 1"
|
||||||
echo " $0 ssh test-vm"
|
echo " $0 ssh 1"
|
||||||
}
|
}
|
||||||
|
|
||||||
list_vms() {
|
list_vms() {
|
||||||
log "Listing all VMs..."
|
log "Listing all VMs..."
|
||||||
echo ""
|
echo ""
|
||||||
printf "%-15s %-10s %-8s %-15s %-20s\n" "VM NAME" "STATUS" "PID" "MEMORY" "STARTED"
|
printf "%-8s %-15s %-15s %-10s %-8s %-15s %-20s\n" "VM #" "IP ADDRESS" "VM NAME" "STATUS" "PID" "MEMORY" "STARTED"
|
||||||
printf "%-15s %-10s %-8s %-15s %-20s\n" "-------" "------" "---" "------" "-------"
|
printf "%-8s %-15s %-15s %-10s %-8s %-15s %-20s\n" "----" "----------" "-------" "------" "---" "------" "-------"
|
||||||
|
|
||||||
if [ ! -d "$VMS_SUBVOL" ]; then
|
if [ ! -d "$VMS_SUBVOL" ]; then
|
||||||
warn "No VMs directory found at $VMS_SUBVOL"
|
warn "No VMs directory found at $VMS_SUBVOL"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for vm_dir in "$VMS_SUBVOL"/*; do
|
for vm_dir in "$VMS_SUBVOL"/vm*; do
|
||||||
if [ -d "$vm_dir" ]; then
|
if [ -d "$vm_dir" ]; then
|
||||||
vm_name=$(basename "$vm_dir")
|
vm_dirname=$(basename "$vm_dir")
|
||||||
vm_info_file="$vm_dir/vm-info.txt"
|
# Extract number from vm directory name (vm1, vm2, etc.)
|
||||||
|
vm_number=${vm_dirname#vm}
|
||||||
|
if [[ "$vm_number" =~ ^[0-9]+$ ]]; then
|
||||||
|
vm_ip="192.168.100.$vm_number"
|
||||||
|
vm_info_file="$vm_dir/vm-info.txt"
|
||||||
|
|
||||||
if [ -f "$vm_info_file" ]; then
|
if [ -f "$vm_info_file" ]; then
|
||||||
# Safely source the file with error handling
|
# Safely source the file with error handling
|
||||||
if source "$vm_info_file" 2>/dev/null; then
|
if source "$vm_info_file" 2>/dev/null; then
|
||||||
# Check if VM is running
|
# Check if VM is running
|
||||||
if [ -n "$VM_PID" ] && kill -0 "$VM_PID" 2>/dev/null; then
|
if [ -n "$VM_PID" ] && kill -0 "$VM_PID" 2>/dev/null; then
|
||||||
status="${GREEN}RUNNING${NC}"
|
status="${GREEN}RUNNING${NC}"
|
||||||
pid="$VM_PID"
|
pid="$VM_PID"
|
||||||
|
else
|
||||||
|
status="${RED}STOPPED${NC}"
|
||||||
|
pid="N/A"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle missing or malformed STARTED field
|
||||||
|
if [ -z "$STARTED" ]; then
|
||||||
|
STARTED="Unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use VM_NAME from config, fallback to vm number
|
||||||
|
display_name="${VM_NAME:-vm$vm_number}"
|
||||||
|
|
||||||
|
printf "%-8s %-15s %-15s %-18s %-8s %-15s %-20s\n" "$vm_number" "$vm_ip" "$display_name" "$(printf "%b" "$status")" "$pid" "${MEMORY_MB}MB" "$STARTED"
|
||||||
else
|
else
|
||||||
status="${RED}STOPPED${NC}"
|
printf "%-8s %-15s %-15s %-18s %-8s %-15s %-20s\n" "$vm_number" "$vm_ip" "vm$vm_number" "$(printf "%b" "${RED}ERROR${NC}")" "N/A" "N/A" "Config Error"
|
||||||
pid="N/A"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Handle missing or malformed STARTED field
|
|
||||||
if [ -z "$STARTED" ]; then
|
|
||||||
STARTED="Unknown"
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf "%-15s %-18s %-8s %-15s %-20s\n" "$vm_name" "$(printf "%b" "$status")" "$pid" "${MEMORY_MB}MB" "$STARTED"
|
|
||||||
else
|
else
|
||||||
printf "%-15s %-18s %-8s %-15s %-20s\n" "$vm_name" "$(printf "%b" "${RED}ERROR${NC}")" "N/A" "N/A" "Config Error"
|
printf "%-8s %-15s %-15s %-18s %-8s %-15s %-20s\n" "$vm_number" "$vm_ip" "vm$vm_number" "$(printf "%b" "${YELLOW}UNKNOWN${NC}")" "N/A" "N/A" "N/A"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
printf "%-15s %-18s %-8s %-15s %-20s\n" "$vm_name" "$(printf "%b" "${YELLOW}UNKNOWN${NC}")" "N/A" "N/A" "N/A"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@ -102,23 +110,30 @@ list_vms() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
show_vm_status() {
|
show_vm_status() {
|
||||||
local vm_name="$1"
|
local vm_number="$1"
|
||||||
local vm_dir="$VMS_SUBVOL/$vm_name"
|
local vm_dir="$VMS_SUBVOL/vm$vm_number"
|
||||||
local vm_info_file="$vm_dir/vm-info.txt"
|
local vm_info_file="$vm_dir/vm-info.txt"
|
||||||
|
|
||||||
|
# Validate VM number
|
||||||
|
if ! [[ "$vm_number" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "VM number must be a number"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! -d "$vm_dir" ]; then
|
if [ ! -d "$vm_dir" ]; then
|
||||||
error "VM '$vm_name' not found"
|
error "VM number '$vm_number' not found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$vm_info_file" ]; then
|
if [ ! -f "$vm_info_file" ]; then
|
||||||
error "VM info file not found for '$vm_name'"
|
error "VM info file not found for VM number '$vm_number'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source "$vm_info_file"
|
source "$vm_info_file"
|
||||||
|
|
||||||
log "VM Status for: $vm_name"
|
log "VM Status for VM number: $vm_number"
|
||||||
echo ""
|
echo ""
|
||||||
echo "VM Name: $VM_NAME"
|
echo "VM Number: $vm_number"
|
||||||
|
echo "VM Name: ${VM_NAME:-vm$vm_number}"
|
||||||
|
echo "Static IP: 192.168.100.$vm_number"
|
||||||
echo "Memory: ${MEMORY_MB}MB"
|
echo "Memory: ${MEMORY_MB}MB"
|
||||||
echo "CPU Cores: $CPU_CORES"
|
echo "CPU Cores: $CPU_CORES"
|
||||||
echo "Started: $STARTED"
|
echo "Started: $STARTED"
|
||||||
@ -152,21 +167,26 @@ show_vm_status() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect_console() {
|
connect_console() {
|
||||||
local vm_name="$1"
|
local vm_number="$1"
|
||||||
local vm_dir="$VMS_SUBVOL/$vm_name"
|
local vm_dir="$VMS_SUBVOL/vm$vm_number"
|
||||||
local vm_info_file="$vm_dir/vm-info.txt"
|
local vm_info_file="$vm_dir/vm-info.txt"
|
||||||
|
|
||||||
|
# Validate VM number
|
||||||
|
if ! [[ "$vm_number" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "VM number must be a number"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! -f "$vm_info_file" ]; then
|
if [ ! -f "$vm_info_file" ]; then
|
||||||
error "VM '$vm_name' not found"
|
error "VM number '$vm_number' not found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source "$vm_info_file"
|
source "$vm_info_file"
|
||||||
|
|
||||||
if [ -z "$VM_PID" ] || ! kill -0 "$VM_PID" 2>/dev/null; then
|
if [ -z "$VM_PID" ] || ! kill -0 "$VM_PID" 2>/dev/null; then
|
||||||
error "VM '$vm_name' is not running"
|
error "VM number '$vm_number' is not running"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "Connecting to console for VM '$vm_name'"
|
info "Connecting to console for VM number '$vm_number'"
|
||||||
info "Press Ctrl+A then X to exit console"
|
info "Press Ctrl+A then X to exit console"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
@ -186,39 +206,50 @@ connect_console() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssh_to_vm() {
|
ssh_to_vm() {
|
||||||
local vm_name="$1"
|
local vm_number="$1"
|
||||||
|
local vm_ip="192.168.100.$vm_number"
|
||||||
|
|
||||||
warn "SSH connection requires:"
|
# Validate VM number
|
||||||
warn "1. VM to be fully booted"
|
if ! [[ "$vm_number" =~ ^[0-9]+$ ]]; then
|
||||||
warn "2. Network bridge configured with IP"
|
error "VM number must be a number"
|
||||||
warn "3. VM to have received IP via DHCP"
|
fi
|
||||||
echo ""
|
|
||||||
info "To set up networking:"
|
info "Attempting SSH connection to VM number $vm_number at $vm_ip"
|
||||||
info "1. Configure bridge IP: ip addr add 192.168.100.1/24 dev br0"
|
|
||||||
info "2. Enable IP forwarding: echo 1 > /proc/sys/net/ipv4/ip_forward"
|
|
||||||
info "3. Set up NAT: iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -j MASQUERADE"
|
|
||||||
echo ""
|
|
||||||
info "Default login: ubuntu / ubuntu"
|
info "Default login: ubuntu / ubuntu"
|
||||||
info "SSH command: ssh ubuntu@<vm-ip>"
|
echo ""
|
||||||
|
|
||||||
|
# Try to SSH directly
|
||||||
|
if command -v sshpass &>/dev/null; then
|
||||||
|
info "Using sshpass for automatic login..."
|
||||||
|
sshpass -p 'ubuntu' ssh -o StrictHostKeyChecking=no ubuntu@"$vm_ip"
|
||||||
|
else
|
||||||
|
info "Manual SSH connection (enter password 'ubuntu'):"
|
||||||
|
ssh -o StrictHostKeyChecking=no ubuntu@"$vm_ip"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_vm() {
|
stop_vm() {
|
||||||
local vm_name="$1"
|
local vm_number="$1"
|
||||||
local vm_dir="$VMS_SUBVOL/$vm_name"
|
local vm_dir="$VMS_SUBVOL/vm$vm_number"
|
||||||
local vm_info_file="$vm_dir/vm-info.txt"
|
local vm_info_file="$vm_dir/vm-info.txt"
|
||||||
|
|
||||||
|
# Validate VM number
|
||||||
|
if ! [[ "$vm_number" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "VM number must be a number"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! -f "$vm_info_file" ]; then
|
if [ ! -f "$vm_info_file" ]; then
|
||||||
error "VM '$vm_name' not found"
|
error "VM number '$vm_number' not found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source "$vm_info_file"
|
source "$vm_info_file"
|
||||||
|
|
||||||
if [ -z "$VM_PID" ] || ! kill -0 "$VM_PID" 2>/dev/null; then
|
if [ -z "$VM_PID" ] || ! kill -0 "$VM_PID" 2>/dev/null; then
|
||||||
warn "VM '$vm_name' is not running"
|
warn "VM number '$vm_number' is not running"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Stopping VM '$vm_name' (PID: $VM_PID)..."
|
log "Stopping VM number '$vm_number' (PID: $VM_PID)..."
|
||||||
|
|
||||||
# Graceful shutdown first
|
# Graceful shutdown first
|
||||||
kill -TERM "$VM_PID" 2>/dev/null || true
|
kill -TERM "$VM_PID" 2>/dev/null || true
|
||||||
@ -242,15 +273,20 @@ stop_vm() {
|
|||||||
rm -f "$VM_SOCKET"
|
rm -f "$VM_SOCKET"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "VM '$vm_name' stopped"
|
log "VM number '$vm_number' stopped"
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_vm() {
|
delete_vm() {
|
||||||
local vm_name="$1"
|
local vm_number="$1"
|
||||||
local vm_dir="$VMS_SUBVOL/$vm_name"
|
local vm_dir="$VMS_SUBVOL/vm$vm_number"
|
||||||
|
|
||||||
|
# Validate VM number
|
||||||
|
if ! [[ "$vm_number" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "VM number must be a number"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! -d "$vm_dir" ]; then
|
if [ ! -d "$vm_dir" ]; then
|
||||||
error "VM '$vm_name' not found"
|
error "VM number '$vm_number' not found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Stop VM first if running
|
# Stop VM first if running
|
||||||
@ -258,45 +294,50 @@ delete_vm() {
|
|||||||
source "$vm_dir/vm-info.txt"
|
source "$vm_dir/vm-info.txt"
|
||||||
if [ -n "$VM_PID" ] && kill -0 "$VM_PID" 2>/dev/null; then
|
if [ -n "$VM_PID" ] && kill -0 "$VM_PID" 2>/dev/null; then
|
||||||
log "Stopping VM before deletion..."
|
log "Stopping VM before deletion..."
|
||||||
stop_vm "$vm_name"
|
stop_vm "$vm_number"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Confirm deletion
|
# Confirm deletion
|
||||||
echo -e "${RED}WARNING: This will permanently delete VM '$vm_name' and all its data!${NC}"
|
echo -e "${RED}WARNING: This will permanently delete VM number '$vm_number' and all its data!${NC}"
|
||||||
read -p "Are you sure? (yes/no): " confirm
|
read -p "Are you sure? (yes/no): " confirm
|
||||||
|
|
||||||
if [ "$confirm" = "yes" ]; then
|
if [ "$confirm" = "yes" ]; then
|
||||||
log "Deleting VM '$vm_name'..."
|
log "Deleting VM number '$vm_number'..."
|
||||||
btrfs subvolume delete "$vm_dir"
|
btrfs subvolume delete "$vm_dir"
|
||||||
log "VM '$vm_name' deleted successfully"
|
log "VM number '$vm_number' deleted successfully"
|
||||||
else
|
else
|
||||||
info "Deletion cancelled"
|
info "Deletion cancelled"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
start_vm() {
|
start_vm() {
|
||||||
local vm_name="$1"
|
local vm_number="$1"
|
||||||
local vm_dir="$VMS_SUBVOL/$vm_name"
|
local vm_dir="$VMS_SUBVOL/vm$vm_number"
|
||||||
local vm_info_file="$vm_dir/vm-info.txt"
|
local vm_info_file="$vm_dir/vm-info.txt"
|
||||||
|
|
||||||
|
# Validate VM number
|
||||||
|
if ! [[ "$vm_number" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "VM number must be a number"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! -d "$vm_dir" ]; then
|
if [ ! -d "$vm_dir" ]; then
|
||||||
error "VM '$vm_name' not found"
|
error "VM number '$vm_number' not found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$vm_info_file" ]; then
|
if [ ! -f "$vm_info_file" ]; then
|
||||||
error "VM info file not found for '$vm_name'"
|
error "VM info file not found for VM number '$vm_number'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source "$vm_info_file"
|
source "$vm_info_file"
|
||||||
|
|
||||||
# Check if VM is already running
|
# Check if VM is already running
|
||||||
if [ -n "$VM_PID" ] && kill -0 "$VM_PID" 2>/dev/null; then
|
if [ -n "$VM_PID" ] && kill -0 "$VM_PID" 2>/dev/null; then
|
||||||
warn "VM '$vm_name' is already running (PID: $VM_PID)"
|
warn "VM number '$vm_number' is already running (PID: $VM_PID)"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Starting VM '$vm_name'..."
|
log "Starting VM number '$vm_number'..."
|
||||||
|
|
||||||
# Create TAP interface
|
# Create TAP interface
|
||||||
if ! ip link show "$TAP_NAME" &>/dev/null; then
|
if ! ip link show "$TAP_NAME" &>/dev/null; then
|
||||||
@ -309,12 +350,17 @@ start_vm() {
|
|||||||
# Remove existing socket if it exists
|
# Remove existing socket if it exists
|
||||||
rm -f "$VM_SOCKET"
|
rm -f "$VM_SOCKET"
|
||||||
|
|
||||||
# Start Cloud Hypervisor in background
|
# Start Cloud Hypervisor in background with kernel boot
|
||||||
|
KERNEL_PATH="/var/lib/vms/base/vmlinuz"
|
||||||
|
INITRD_PATH="/var/lib/vms/base/initrd.img"
|
||||||
|
|
||||||
cloud-hypervisor \
|
cloud-hypervisor \
|
||||||
--api-socket "$VM_SOCKET" \
|
--api-socket "$VM_SOCKET" \
|
||||||
--memory "size=${MEMORY_MB}M" \
|
--memory "size=${MEMORY_MB}M" \
|
||||||
--cpus "boot=$CPU_CORES" \
|
--cpus "boot=$CPU_CORES" \
|
||||||
--kernel "/var/lib/vms/base/hypervisor-fw" \
|
--kernel "$KERNEL_PATH" \
|
||||||
|
--initramfs "$INITRD_PATH" \
|
||||||
|
--cmdline "root=LABEL=cloudimg-rootfs ro console=tty1 console=ttyS0" \
|
||||||
--disk "path=$VM_IMAGE_PATH" "path=$CLOUD_INIT_PATH,readonly=on" \
|
--disk "path=$VM_IMAGE_PATH" "path=$CLOUD_INIT_PATH,readonly=on" \
|
||||||
--net "tap=$TAP_NAME,mac=52:54:00:$(printf '%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))" \
|
--net "tap=$TAP_NAME,mac=52:54:00:$(printf '%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))" \
|
||||||
--serial tty \
|
--serial tty \
|
||||||
@ -326,10 +372,10 @@ start_vm() {
|
|||||||
# Update VM info file with new PID
|
# Update VM info file with new PID
|
||||||
sed -i "s/VM_PID=.*/VM_PID=$NEW_VM_PID/" "$vm_info_file"
|
sed -i "s/VM_PID=.*/VM_PID=$NEW_VM_PID/" "$vm_info_file"
|
||||||
|
|
||||||
log "VM '$vm_name' started with PID $NEW_VM_PID"
|
log "VM number '$vm_number' started with PID $NEW_VM_PID"
|
||||||
log "VM socket: $VM_SOCKET"
|
log "VM socket: $VM_SOCKET"
|
||||||
log "TAP interface: $TAP_NAME"
|
log "TAP interface: $TAP_NAME"
|
||||||
log "To connect to console: ./ubuntu_vm_manage.sh console $vm_name"
|
log "To connect to console: ./ubuntu_vm_manage.sh console $vm_number"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main script logic
|
# Main script logic
|
||||||
@ -339,50 +385,65 @@ if [ $# -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
COMMAND="$1"
|
COMMAND="$1"
|
||||||
VM_NAME="$2"
|
VM_NUMBER="$2"
|
||||||
|
|
||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
"list")
|
"list")
|
||||||
list_vms
|
list_vms
|
||||||
;;
|
;;
|
||||||
"status")
|
"status")
|
||||||
if [ -z "$VM_NAME" ]; then
|
if [ -z "$VM_NUMBER" ]; then
|
||||||
error "VM name required for status command"
|
error "VM number required for status command"
|
||||||
fi
|
fi
|
||||||
show_vm_status "$VM_NAME"
|
show_vm_status "$VM_NUMBER"
|
||||||
;;
|
;;
|
||||||
"console")
|
"console")
|
||||||
if [ -z "$VM_NAME" ]; then
|
if [ -z "$VM_NUMBER" ]; then
|
||||||
error "VM name required for console command"
|
error "VM number required for console command"
|
||||||
fi
|
fi
|
||||||
connect_console "$VM_NAME"
|
connect_console "$VM_NUMBER"
|
||||||
;;
|
;;
|
||||||
"ssh")
|
"ssh")
|
||||||
if [ -z "$VM_NAME" ]; then
|
if [ -z "$VM_NUMBER" ]; then
|
||||||
error "VM name required for ssh command"
|
error "VM number required for ssh command"
|
||||||
fi
|
fi
|
||||||
ssh_to_vm "$VM_NAME"
|
ssh_to_vm "$VM_NUMBER"
|
||||||
;;
|
;;
|
||||||
"stop")
|
"stop")
|
||||||
if [ -z "$VM_NAME" ]; then
|
if [ -z "$VM_NUMBER" ]; then
|
||||||
error "VM name required for stop command"
|
error "VM number required for stop command"
|
||||||
fi
|
fi
|
||||||
stop_vm "$VM_NAME"
|
stop_vm "$VM_NUMBER"
|
||||||
;;
|
;;
|
||||||
"start")
|
"start")
|
||||||
if [ -z "$VM_NAME" ]; then
|
if [ -z "$VM_NUMBER" ]; then
|
||||||
error "VM name required for start command"
|
error "VM number required for start command"
|
||||||
fi
|
fi
|
||||||
start_vm "$VM_NAME"
|
start_vm "$VM_NUMBER"
|
||||||
;;
|
;;
|
||||||
"delete")
|
"delete")
|
||||||
if [ -z "$VM_NAME" ]; then
|
if [ -z "$VM_NUMBER" ]; then
|
||||||
error "VM name required for delete command"
|
error "VM number required for delete command"
|
||||||
fi
|
fi
|
||||||
delete_vm "$VM_NAME"
|
delete_vm "$VM_NUMBER"
|
||||||
;;
|
;;
|
||||||
"ip"|"logs")
|
"ip")
|
||||||
warn "Command '$COMMAND' not yet implemented"
|
if [ -z "$VM_NUMBER" ]; then
|
||||||
|
error "VM number required for ip command"
|
||||||
|
fi
|
||||||
|
echo "VM $VM_NUMBER IP address: 192.168.100.$VM_NUMBER"
|
||||||
|
;;
|
||||||
|
"logs")
|
||||||
|
if [ -z "$VM_NUMBER" ]; then
|
||||||
|
error "VM number required for logs command"
|
||||||
|
fi
|
||||||
|
log_file="/tmp/cloud-hypervisor-vm$VM_NUMBER.log"
|
||||||
|
if [ -f "$log_file" ]; then
|
||||||
|
log "Showing logs for VM number $VM_NUMBER:"
|
||||||
|
tail -f "$log_file"
|
||||||
|
else
|
||||||
|
warn "Log file not found: $log_file"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error "Unknown command: $COMMAND"
|
error "Unknown command: $COMMAND"
|
||||||
|
@ -383,10 +383,36 @@ if [ ! -f "$FIRMWARE_PATH" ]; then
|
|||||||
chmod +x "$FIRMWARE_PATH"
|
chmod +x "$FIRMWARE_PATH"
|
||||||
test_step "Firmware executable check" "[ -x '$FIRMWARE_PATH' ]"
|
test_step "Firmware executable check" "[ -x '$FIRMWARE_PATH' ]"
|
||||||
log "✓ Firmware downloaded to $FIRMWARE_PATH"
|
log "✓ Firmware downloaded to $FIRMWARE_PATH"
|
||||||
else
|
else
|
||||||
log "✓ Firmware already exists at $FIRMWARE_PATH"
|
log "✓ Firmware already exists at $FIRMWARE_PATH"
|
||||||
test_file_exists "$FIRMWARE_PATH" "Firmware verification"
|
test_file_exists "$FIRMWARE_PATH" "Firmware verification"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Extract kernel and initrd from base image
|
||||||
|
log "Extracting kernel and initrd for kernel boot..."
|
||||||
|
EXTRACT_SCRIPT="$(dirname "$0")/extract_kernel.sh"
|
||||||
|
if [ -f "$EXTRACT_SCRIPT" ]; then
|
||||||
|
"$EXTRACT_SCRIPT"
|
||||||
|
else
|
||||||
|
warn "Kernel extraction script not found, attempting manual extraction..."
|
||||||
|
# Fallback manual extraction
|
||||||
|
KERNEL_PATH="$BASE_SUBVOL/vmlinuz"
|
||||||
|
INITRD_PATH="$BASE_SUBVOL/initrd.img"
|
||||||
|
if [ ! -f "$KERNEL_PATH" ] || [ ! -f "$INITRD_PATH" ]; then
|
||||||
|
log "Extracting kernel and initrd manually..."
|
||||||
|
TEMP_MOUNT=$(mktemp -d)
|
||||||
|
losetup -P /dev/loop1 "$BASE_IMAGE_PATH"
|
||||||
|
mount /dev/loop1p16 "$TEMP_MOUNT"
|
||||||
|
cp "$TEMP_MOUNT/vmlinuz-6.8.0-60-generic" "$KERNEL_PATH" 2>/dev/null || true
|
||||||
|
cp "$TEMP_MOUNT/initrd.img-6.8.0-60-generic" "$INITRD_PATH" 2>/dev/null || true
|
||||||
|
umount "$TEMP_MOUNT"
|
||||||
|
losetup -d /dev/loop1
|
||||||
|
rmdir "$TEMP_MOUNT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_file_exists "$BASE_SUBVOL/vmlinuz" "Kernel extraction"
|
||||||
|
test_file_exists "$BASE_SUBVOL/initrd.img" "Initrd extraction"
|
||||||
|
|
||||||
# Create VM subvolume by cloning from base
|
# Create VM subvolume by cloning from base
|
||||||
log "Setting up VM-specific storage..."
|
log "Setting up VM-specific storage..."
|
||||||
@ -625,14 +651,19 @@ log "Generated MAC address for VM: $VM_MAC"
|
|||||||
log "Launching Cloud Hypervisor..."
|
log "Launching Cloud Hypervisor..."
|
||||||
|
|
||||||
# Try to start Cloud Hypervisor and capture any error output
|
# Try to start Cloud Hypervisor and capture any error output
|
||||||
log "Starting Cloud Hypervisor with command:"
|
log "Starting Cloud Hypervisor with kernel boot:"
|
||||||
log "cloud-hypervisor --api-socket $VM_SOCKET --memory size=${MEMORY_MB}M --cpus boot=$CPU_CORES --firmware $FIRMWARE_PATH --disk path=$VM_IMAGE_PATH path=$CLOUD_INIT_PATH,readonly=on --net tap=$TAP_NAME,mac=$VM_MAC --serial file=$VM_LOG_FILE --console off --event-monitor path=${VM_LOG_FILE}.events"
|
log "cloud-hypervisor --memory size=${MEMORY_MB}M --cpus boot=$CPU_CORES --kernel $KERNEL_PATH --initramfs $INITRD_PATH --cmdline 'root=LABEL=cloudimg-rootfs ro console=tty1 console=ttyS0' --disk path=$VM_IMAGE_PATH path=$CLOUD_INIT_PATH,readonly=on --net tap=$TAP_NAME,mac=$VM_MAC --serial file=$VM_LOG_FILE --console off --event-monitor path=${VM_LOG_FILE}.events"
|
||||||
|
|
||||||
|
# Use kernel boot instead of firmware boot to properly pass root device
|
||||||
|
KERNEL_PATH="$BASE_SUBVOL/vmlinuz"
|
||||||
|
INITRD_PATH="$BASE_SUBVOL/initrd.img"
|
||||||
|
|
||||||
# Try with API socket first, fall back without it if needed
|
|
||||||
cloud-hypervisor \
|
cloud-hypervisor \
|
||||||
--memory "size=${MEMORY_MB}M" \
|
--memory "size=${MEMORY_MB}M" \
|
||||||
--cpus "boot=$CPU_CORES" \
|
--cpus "boot=$CPU_CORES" \
|
||||||
--firmware "$FIRMWARE_PATH" \
|
--kernel "$KERNEL_PATH" \
|
||||||
|
--initramfs "$INITRD_PATH" \
|
||||||
|
--cmdline "root=LABEL=cloudimg-rootfs ro console=tty1 console=ttyS0" \
|
||||||
--disk "path=$VM_IMAGE_PATH" "path=$CLOUD_INIT_PATH,readonly=on" \
|
--disk "path=$VM_IMAGE_PATH" "path=$CLOUD_INIT_PATH,readonly=on" \
|
||||||
--net "tap=$TAP_NAME,mac=$VM_MAC" \
|
--net "tap=$TAP_NAME,mac=$VM_MAC" \
|
||||||
--serial "file=$VM_LOG_FILE" \
|
--serial "file=$VM_LOG_FILE" \
|
||||||
|
Loading…
Reference in New Issue
Block a user