Compare commits

...

3 Commits

Author SHA1 Message Date
cda492a4be ... 2025-06-15 21:24:50 +02:00
0bae1ed774 ... 2025-06-15 20:55:06 +02:00
e701615e53 ... 2025-06-15 20:41:33 +02:00
2 changed files with 122 additions and 49 deletions

View File

@ -221,3 +221,11 @@ trap 'error "Script interrupted"' INT TERM
# Run main function # Run main function
main "$@" main "$@"
# Install OpenSSL development headers and pkg-config
sudo apt update
sudo apt install -y pkg-config libssl-dev
cd ~/code/git.threefold.info/herocode/sal
./build_herodo.sh

View File

@ -27,15 +27,15 @@ BRIDGE_IP="192.168.100.1/24"
NETWORK="192.168.100.0/24" NETWORK="192.168.100.0/24"
log() { log() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}" echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}" >&2
} }
warn() { warn() {
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}" echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}" >&2
} }
error() { error() {
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}" echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}" >&2
# If VM_NUMBER is set and we're in VM creation phase, clean up # If VM_NUMBER is set and we're in VM creation phase, clean up
if [ -n "$VM_NUMBER" ] && [ -n "$VM_PID" ]; then if [ -n "$VM_NUMBER" ] && [ -n "$VM_PID" ]; then
@ -46,7 +46,7 @@ error() {
} }
info() { info() {
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')] INFO: $1${NC}" echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')] INFO: $1${NC}" >&2
} }
# Test functions # Test functions
@ -119,7 +119,7 @@ generate_password_hash() {
wait_for_vm_boot() { wait_for_vm_boot() {
local vm_name="$1" local vm_name="$1"
local expected_ip="$2" local expected_ip="$2"
local max_wait=120 # 3 minutes local max_wait=180 # 3 minutes, increased from 120
local count=0 local count=0
log "Waiting for VM '$vm_name' to boot with static IP $expected_ip..." log "Waiting for VM '$vm_name' to boot with static IP $expected_ip..."
@ -131,7 +131,7 @@ wait_for_vm_boot() {
fi fi
# Try to ping the expected static IP # Try to ping the expected static IP
if ping -c 1 -W 2 "$expected_ip" >/dev/null 2>&1; then if ping -c 2 -W 3 "$expected_ip" >/dev/null 2>&1; then
log "VM is responding at static IP address: $expected_ip" log "VM is responding at static IP address: $expected_ip"
echo "$expected_ip" echo "$expected_ip"
return 0 return 0
@ -200,9 +200,10 @@ test_ssh_connection() {
while [ $attempt -le $max_attempts ]; do while [ $attempt -le $max_attempts ]; do
info "SSH attempt $attempt/$max_attempts" info "SSH attempt $attempt/$max_attempts"
# Test SSH connection with timeout # Test SSH connection with timeout, using key-based auth, with verbose output for diagnostics
if timeout 10 sshpass -p 'ubuntu' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 ubuntu@"$vm_ip" 'echo "SSH connection successful"' 2>/dev/null; then info "Attempting SSH with key: timeout 10 ssh -i \"$SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH\" -v -o StrictHostKeyChecking=no -o ConnectTimeout=5 ubuntu@\"$vm_ip\" 'echo \"SSH connection successful\"'" >&2
log "✓ SSH connection successful to ubuntu@$vm_ip" if timeout 10 ssh -i "$SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH" -v -o StrictHostKeyChecking=no -o ConnectTimeout=5 ubuntu@"$vm_ip" 'echo "SSH connection successful"'; then
log "✓ SSH connection successful to ubuntu@$vm_ip with key $SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH" >&2
return 0 return 0
fi fi
@ -253,8 +254,52 @@ fi
# Calculate static IP address based on VM number # Calculate static IP address based on VM number
VM_STATIC_IP="192.168.100.$VM_NUMBER" VM_STATIC_IP="192.168.100.$VM_NUMBER"
log "Starting VM: $VM_NAME (number $VM_NUMBER) with ${MEMORY_MB}MB RAM and $CPU_CORES CPU cores" log "Starting VM: $VM_NAME (number $VM_NUMBER) with ${MEMORY_MB}MB RAM and $CPU_CORES CPU cores" >&2
log "VM will be assigned static IP: $VM_STATIC_IP" log "VM will be assigned static IP: $VM_STATIC_IP" >&2
# SSH Key Configuration for Host Root to VM Ubuntu User
HOST_ROOT_SSH_DIR="/root/.ssh"
HOST_ROOT_SSH_PUB_KEY_PATH_ED25519="$HOST_ROOT_SSH_DIR/id_ed25519.pub"
HOST_ROOT_SSH_PRIV_KEY_PATH_ED25519="$HOST_ROOT_SSH_DIR/id_ed25519"
HOST_ROOT_SSH_PUB_KEY_PATH_RSA="$HOST_ROOT_SSH_DIR/id_rsa.pub"
HOST_ROOT_SSH_PRIV_KEY_PATH_RSA="$HOST_ROOT_SSH_DIR/id_rsa"
SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH=""
SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH=""
mkdir -p "$HOST_ROOT_SSH_DIR"
chmod 700 "$HOST_ROOT_SSH_DIR"
if [ -f "$HOST_ROOT_SSH_PUB_KEY_PATH_ED25519" ]; then
SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH="$HOST_ROOT_SSH_PUB_KEY_PATH_ED25519"
SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH="$HOST_ROOT_SSH_PRIV_KEY_PATH_ED25519"
log "Using existing ED25519 SSH key: $SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH" >&2
elif [ -f "$HOST_ROOT_SSH_PUB_KEY_PATH_RSA" ]; then
SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH="$HOST_ROOT_SSH_PUB_KEY_PATH_RSA"
SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH="$HOST_ROOT_SSH_PRIV_KEY_PATH_RSA"
log "Using existing RSA SSH key: $SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH" >&2
else
log "No existing SSH key found for root. Generating ED25519 key..." >&2
ssh-keygen -t ed25519 -N "" -f "$HOST_ROOT_SSH_PRIV_KEY_PATH_ED25519" -q
if [ $? -eq 0 ] && [ -f "$HOST_ROOT_SSH_PUB_KEY_PATH_ED25519" ]; then
SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH="$HOST_ROOT_SSH_PUB_KEY_PATH_ED25519"
SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH="$HOST_ROOT_SSH_PRIV_KEY_PATH_ED25519"
log "Generated ED25519 SSH key: $SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH" >&2
chmod 600 "$HOST_ROOT_SSH_PRIV_KEY_PATH_ED25519"
chmod 644 "$HOST_ROOT_SSH_PUB_KEY_PATH_ED25519"
else
error "Failed to generate ED25519 SSH key."
fi
fi
if [ -z "$SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH" ]; then
error "Could not find or generate an SSH public key for root user."
fi
HOST_ROOT_SSH_PUB_KEY_CONTENT=$(cat "$SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH")
if [ -z "$HOST_ROOT_SSH_PUB_KEY_CONTENT" ]; then
error "SSH public key content is empty at $SELECTED_HOST_ROOT_SSH_PUB_KEY_PATH"
fi
# Comprehensive prerequisite checks # Comprehensive prerequisite checks
log "Performing prerequisite checks..." log "Performing prerequisite checks..."
@ -448,9 +493,13 @@ fi
# Create cloud-init image for first boot # Create cloud-init image for first boot
log "Creating cloud-init configuration..." log "Creating cloud-init configuration..."
# Generate a random MAC address for the VM (used in cloud-init and hypervisor)
VM_MAC="52:54:00:$(printf '%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))"
log "Generated MAC address for VM: $VM_MAC"
# Generate proper password hash for 'ubuntu' # Generate proper password hash for 'ubuntu'
PASSWORD_HASH=$(generate_password_hash) # PASSWORD_HASH=$(generate_password_hash) # No longer needed for ubuntu user
test_step "Password hash generation" "[ -n '$PASSWORD_HASH' ]" # test_step "Password hash generation" "[ -n '$PASSWORD_HASH' ]"
cat > "/tmp/user-data" << EOF cat > "/tmp/user-data" << EOF
#cloud-config #cloud-config
@ -458,35 +507,43 @@ users:
- name: ubuntu - name: ubuntu
sudo: ALL=(ALL) NOPASSWD:ALL sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash shell: /bin/bash
lock_passwd: false # lock_passwd: false # Not needed with key auth
passwd: $PASSWORD_HASH # passwd: $PASSWORD_HASH # Using SSH key instead
groups: sudo groups: sudo
home: /home/ubuntu home: /home/ubuntu
ssh_authorized_keys:
- ${HOST_ROOT_SSH_PUB_KEY_CONTENT}
# Enable SSH with password authentication # ssh_pwauth: true # Disabling password auth for ubuntu user by not setting a password
ssh_pwauth: true disable_root: false # Keep root disabled for direct login, sudo is available
disable_root: false chpasswd: # This section might be irrelevant now for ubuntu user
chpasswd:
expire: false expire: false
# SSH configuration # SSH configuration
ssh_authorized_keys: [] # ssh_authorized_keys: [] # This was a global setting, moved to user-specific
# Network configuration with static IP # Network configuration with static IP
network:
config: disabled # This disables cloud-init's direct network config, relying on write_files + runcmd
write_files:
- path: /etc/netplan/50-cloud-init.yaml
content: |
network: network:
version: 2 version: 2
ethernets: ethernets:
ens3: ens3:
dhcp4: false dhcp4: false
addresses: addresses:
- $VM_STATIC_IP/24 - $VM_STATIC_IP/24 # Use variable for IP
routes: # gateway4: 192.168.100.1 # Deprecated
routes: # Use modern routes syntax
- to: default - to: default
via: 192.168.100.1 via: 192.168.100.1
nameservers: nameservers:
addresses: addresses:
- 8.8.8.8 - 8.8.8.8
- 8.8.4.4 - 1.1.1.1
# Package updates and installs # Package updates and installs
package_update: true package_update: true
@ -507,12 +564,16 @@ runcmd:
- systemctl start ssh - systemctl start ssh
- systemctl status ssh - systemctl status ssh
- netplan apply - netplan apply
- sleep 5 - chmod 0600 /etc/netplan/50-cloud-init.yaml || echo "Failed to chmod /etc/netplan/50-cloud-init.yaml"
- ip addr flush dev ens3 - sleep 2 # Allow netplan apply to settle
- ip addr add $VM_STATIC_IP/24 dev ens3 #- ip addr flush dev ens3
- ip route add default via 192.168.100.1 #- ip addr add $VM_STATIC_IP/24 dev ens3
#- ip route add default via 192.168.100.1
- ip addr show ens3 - ip addr show ens3
- ip route show - ip route show
- ping 192.168.100.2 -c 3
- echo "WERE THERE"
# Final message # Final message
final_message: "Cloud-init setup complete. VM is ready for SSH access!" final_message: "Cloud-init setup complete. VM is ready for SSH access!"
@ -653,9 +714,6 @@ VM_LOG_FILE="/tmp/cloud-hypervisor-vm$VM_NUMBER.log"
# Remove existing socket and log file if they exist # Remove existing socket and log file if they exist
rm -f "$VM_SOCKET" "$VM_LOG_FILE" rm -f "$VM_SOCKET" "$VM_LOG_FILE"
# Generate a random MAC address for the VM
VM_MAC="52:54:00:$(printf '%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))"
log "Generated MAC address for VM: $VM_MAC"
# Start Cloud Hypervisor in background with error handling # Start Cloud Hypervisor in background with error handling
log "Launching Cloud Hypervisor..." log "Launching Cloud Hypervisor..."
@ -778,15 +836,22 @@ fi
# Test SSH connectivity # Test SSH connectivity
if test_ssh_connection "$VM_IP"; then if test_ssh_connection "$VM_IP"; then
log "🎉 SUCCESS: VM $VM_NAME is fully operational!" log "🎉 SUCCESS: VM $VM_NAME is fully operational!" >&2
log "✓ VM is running with PID $VM_PID" log "✓ VM is running with PID $VM_PID" >&2
log "✓ VM has IP address: $VM_IP" log "✓ VM has IP address: $VM_IP" >&2
log "✓ SSH is working: ssh ubuntu@$VM_IP (password: ubuntu)" log "✓ SSH is working with key: ssh -i \"$SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH\" ubuntu@$VM_IP" >&2
log "✓ VM info saved to: $VM_INFO_FILE" log "✓ VM info saved to: $VM_INFO_FILE" >&2
echo ""
info "VM $VM_NAME is ready for use!" # Display relevant IP configuration lines from VM log
info "Connect via SSH: ssh ubuntu@$VM_IP" if [ -f "$VM_LOG_FILE" ]; then
info "Default password: ubuntu (please change after first login)" info "Relevant IP configuration from VM log ($VM_LOG_FILE):" >&2
grep -E "inet .*ens3|default via" "$VM_LOG_FILE" | tail -n 5 || true # Output of grep goes to stdout, which is fine here
fi
echo "" >&2 # Direct echo to stderr
info "VM $VM_NAME is ready for use!" >&2
info "Connect via SSH: ssh -i \"$SELECTED_HOST_ROOT_SSH_PRIV_KEY_PATH\" ubuntu@$VM_IP" >&2
# info "Default password: ubuntu (please change after first login)" # No longer relevant
info "To stop the VM: sudo $(dirname "$0")/ubuntu_vm_delete.sh $VM_NUMBER" info "To stop the VM: sudo $(dirname "$0")/ubuntu_vm_delete.sh $VM_NUMBER"
echo "" echo ""