summaryrefslogtreecommitdiff
path: root/default/steps/bootstrap
diff options
context:
space:
mode:
Diffstat (limited to 'default/steps/bootstrap')
-rw-r--r--default/steps/bootstrap/debian/prepare_autoinstall.yaml11
-rw-r--r--default/steps/bootstrap/download_installer.yaml31
-rw-r--r--default/steps/bootstrap/prepare_appliance.yaml33
-rw-r--r--default/steps/bootstrap/prepare_disk.yaml10
-rw-r--r--default/steps/bootstrap/prepare_ssh_to_out_context.yaml23
-rw-r--r--default/steps/bootstrap/start_http_server.yaml19
-rw-r--r--default/steps/bootstrap/start_qemu.yaml227
7 files changed, 354 insertions, 0 deletions
diff --git a/default/steps/bootstrap/debian/prepare_autoinstall.yaml b/default/steps/bootstrap/debian/prepare_autoinstall.yaml
new file mode 100644
index 0000000..f737d20
--- /dev/null
+++ b/default/steps/bootstrap/debian/prepare_autoinstall.yaml
@@ -0,0 +1,11 @@
+- copy_autoinstall_script_to_http_directory:
+ - exec_local: mkdir -p $${http_directory}
+ - exec_local: cp $${base_preseed_path} $${http_directory}/preseed.cfg
+
+- customize_preseed:
+ - exec_local: sed -i -e 's|\(d-i passwd/root-password password \).*|\1$${root_password}|g' $${http_directory}/preseed.cfg
+ - exec_local: sed -i -e 's|\(d-i passwd/root-password-again password \).*|\1$${root_password}|g' $${http_directory}/preseed.cfg
+ - exec_local: sed -i -e 's|\(d-i mirror/http/hostname string \).*|\1$${deb_mirror_hostname}|g' $${http_directory}/preseed.cfg
+ - exec_local: sed -i -e 's|\(d-i mirror/http/directory string \).*|\1$${deb_mirror_directory}|g' $${http_directory}/preseed.cfg
+ - exec_local: sed -i -e 's|\(d-i apt-setup/security_host string \).*|\1$${deb_security_hostname}|g' $${http_directory}/preseed.cfg
+ - exec_local: sed -i -e 's|\(d-i apt-setup/security_path string \).*|\1$${deb_security_directory}|g' $${http_directory}/preseed.cfg
diff --git a/default/steps/bootstrap/download_installer.yaml b/default/steps/bootstrap/download_installer.yaml
new file mode 100644
index 0000000..f15f58c
--- /dev/null
+++ b/default/steps/bootstrap/download_installer.yaml
@@ -0,0 +1,31 @@
+- download_installer:
+ - test:
+ - exec_local: test -n "$${installer_iso_url}" -o -n "$${installer_iso_finder_helper}"
+ - group:
+ - test:
+ - exec_local: test -z "$${installer_iso_url}"
+ - exec_local: |
+ echo "Looking for the netinstall iso URL for $${installer_iso_finder_args}"
+ DOWNLOAD_SRC_URL=$(python2 $${installer_iso_finder_helper} $${installer_iso_finder_args})
+ - download_file_local:
+ - $${installer_iso_url}
+ - $${qemu_iso_path}
+ - exec_local: unset DOWNLOAD_SRC_URL
+ - group:
+ - test:
+ - exec_local: test -n "$${installer_kernel_url}"
+ - download_file_local:
+ - $${installer_kernel_url}
+ - $${qemu_kernel_path}
+ - test:
+ - exec_local: test -n "$${installer_initrd_url}"
+ - download_file_local:
+ - $${installer_initrd_url}
+ - $${qemu_initrd_path}
+
+- delete_installer:
+ - on_checkpoint: skip
+ - on_export_clean:
+ - exec_local: rm -f $${qemu_iso_path}
+ - exec_local: rm -f $${qemu_kernel_path}
+ - exec_local: rm -f $${qemu_initrd_path}
diff --git a/default/steps/bootstrap/prepare_appliance.yaml b/default/steps/bootstrap/prepare_appliance.yaml
new file mode 100644
index 0000000..4f597c4
--- /dev/null
+++ b/default/steps/bootstrap/prepare_appliance.yaml
@@ -0,0 +1,33 @@
+- insecure_ssh_key: $${kameleon_cwd}/insecure_ssh_key
+
+- generate_ssh_keys:
+ - check_cmd_local: ssh-keygen
+ - exec_local: echo -e 'y\n' | ssh-keygen -q -t rsa -b 4096 -f $${insecure_ssh_key} -N ''
+ - exec_local: cat $${insecure_ssh_key}
+
+- inject_ssh_private_key:
+ - check_cmd_local: virt-customize
+ - exec_local: |
+ virt-customize \
+ -a $${image_disk}.$${image_format} \
+ --run-command 'mkdir -p /root/.ssh' \
+ --upload $${insecure_ssh_key}.pub:/root/.ssh/.kameleon_authorized_keys \
+ --run-command 'touch /root/.ssh/authorized_keys' \
+ --run-command 'cp /root/.ssh/authorized_keys /root/.ssh/authorized_keys.bak' \
+ --run-command 'cat /root/.ssh/.kameleon_authorized_keys >> /root/.ssh/authorized_keys' \
+ --run-command 'chmod 700 /root/.ssh' \
+ --run-command 'chmod -R go-rw /root/.ssh' \
+ --run-command 'chown -R root:root /root/.ssh'
+ - on_export_init:
+ - exec_local: |
+ virt-customize \
+ -a $${image_disk}.$${image_format} \
+ --run-command 'mv /root/.ssh/authorized_keys.bak /root/.ssh/authorized_keys' \
+ --delete /root/.ssh/.kameleon_authorized_keys
+
+- add_insecure_key_to_ssh_config:
+ - on_checkpoint: redo
+ - exec_local: |
+ cat <<EOF >> $${ssh_config_file}
+ IdentityFile $${insecure_ssh_key}
+ EOF
diff --git a/default/steps/bootstrap/prepare_disk.yaml b/default/steps/bootstrap/prepare_disk.yaml
new file mode 100644
index 0000000..9c3dce4
--- /dev/null
+++ b/default/steps/bootstrap/prepare_disk.yaml
@@ -0,0 +1,10 @@
+- create_initial_image:
+ - check_cmd_local: qemu-img
+ - exec_local: |
+ rm -f $${image_disk}.$${image_format}
+ qemu-img create -f qcow2 $${image_disk}.$${image_format} $${qemu_image_size}
+
+- delete_initial_image:
+ - on_checkpoint: skip
+ - on_export_clean:
+ - exec_local: rm -f $${image_disk}.$${image_format}
diff --git a/default/steps/bootstrap/prepare_ssh_to_out_context.yaml b/default/steps/bootstrap/prepare_ssh_to_out_context.yaml
new file mode 100644
index 0000000..172f7a4
--- /dev/null
+++ b/default/steps/bootstrap/prepare_ssh_to_out_context.yaml
@@ -0,0 +1,23 @@
+- select_empty_port:
+ - on_checkpoint: redo
+ - exec_local: |
+ # Find empty SSH forwarding port
+ SSH_FWD_PORT=$(__find_free_port 50000 60000)
+ echo "SSH forwarding port: $SSH_FWD_PORT"
+- prepare_ssh_config:
+ - on_checkpoint: redo
+ - write_local:
+ - $${ssh_config_file}
+ - |
+ Host $${kameleon_recipe_name}
+ HostName 127.0.0.1
+ Port ${SSH_FWD_PORT}
+ User root
+ UserKnownHostsFile /dev/null
+ StrictHostKeyChecking no
+ PasswordAuthentication no
+ IdentitiesOnly yes
+ LogLevel FATAL
+ ForwardAgent yes
+ Compression yes
+ Protocol 2
diff --git a/default/steps/bootstrap/start_http_server.yaml b/default/steps/bootstrap/start_http_server.yaml
new file mode 100644
index 0000000..59184c3
--- /dev/null
+++ b/default/steps/bootstrap/start_http_server.yaml
@@ -0,0 +1,19 @@
+- http_script: $${kameleon_data_dir}/helpers/simple_http_server.py
+
+- run_http_server:
+ - exec_local: |
+ HTTP_PORT=$(__find_free_port 8000 8100)
+ echo "HTTP port: $HTTP_PORT"
+ export HTTP_PORT
+ - exec_local: python2 $${http_script} --root $${http_directory} --bind 0.0.0.0 --port $HTTP_PORT --daemon --pid $${http_pid}
+ - on_bootstrap_clean:
+ - exec_local: |
+ if [ -f $${http_pid} ]; then
+ HTTP_PID=$(cat $${http_pid})
+ if ps -p $HTTP_PID > /dev/null; then
+ echo "Killing HTTP server (pid: $HTTP_PID)..."
+ kill -9 "$HTTP_PID"
+ rm -f $${http_pid}
+ fi
+ rm -f $${http_pid}
+ fi
diff --git a/default/steps/bootstrap/start_qemu.yaml b/default/steps/bootstrap/start_qemu.yaml
new file mode 100644
index 0000000..4d47953
--- /dev/null
+++ b/default/steps/bootstrap/start_qemu.yaml
@@ -0,0 +1,227 @@
+# Require SSH_FWD_PORT bash environment variable to be set
+
+# This must be set if you want to boot an ISO image:
+- qemu_iso_path: ""
+- qemu_iso_boot: true
+# Else that can be set to boot from a kernel, initrd and cmdline:
+- qemu_kernel_path: ""
+- qemu_initrd_path: ""
+- qemu_append_cmdline: ""
+# Else boot from disk.
+
+- vm_expected_service: ssh
+- boot_timeout: 100
+- shutdown_timeout: 100
+- debug: false
+- telnet_port: ""
+- no_reboot: true
+- socat_monitor: socat - UNIX-CONNECT:$${qemu_monitor_socket}
+- qemu_sendkeys_script: $${kameleon_data_dir}/qemu-sendkeys.rb
+- qemu_sendkeys_commands:
+- vm_expected_service: ssh
+- vm_cleanup_section: setup
+- shutdown_vm_immediately: false
+- force_vm_shutdown: true
+- qemu_enable_kvm: true
+- qemu_cpus: 2
+- qemu_memory_size: 768
+- qemu_monitor_socket: $${kameleon_cwd}/qemu_monitor.socket
+- qemu_arch: $${arch}
+- qemu_image_size: 10G
+- qemu_pidfile: $${kameleon_cwd}/qemu.pid
+- qemu_uefi: false
+- qemu_uefi_code_path: /usr/share/AAVMF/AAVMF_CODE.fd
+- qemu_uefi_vars_path: /usr/share/AAVMF/AAVMF_VARS.fd
+- qemu_netdev_user_options:
+- disk_cache: unsafe
+
+- start_vm:
+ - on_checkpoint: redo
+ - check_cmd_local: qemu-system-$${qemu_arch}
+ - check_cmd_local: socat
+ - on_bootstrap_clean:
+ - test:
+ - exec_local: test "$${shutdown_vm_immediately}" == "false" -a "$${vm_cleanup_section}" == "bootstrap"
+ - group:
+ - exec_local: &1 |
+ if [ -f $${qemu_pidfile} ]; then
+ _QEMU_PID=$(< $${qemu_pidfile})
+ if ps -p $_QEMU_PID > /dev/null; then
+ if [ "$${force_vm_shutdown}" == "true" ]; then
+ if [ -S $${qemu_monitor_socket} ]; then
+ echo "Executing a graceful shutdown of the qemu VM via the monitor socket..."
+ NEXT_WAIT_TIME=0
+ echo system_powerdown | socat - UNIX-CONNECT:$${qemu_monitor_socket} || true
+ while ps -p $_QEMU_PID > /dev/null && [ $NEXT_WAIT_TIME -lt $${shutdown_timeout} ];
+ do
+ sleep 1
+ echo -en "\rWaiting for qemu virtual machine to shutdown...($(( $${shutdown_timeout} - 1 - NEXT_WAIT_TIME++ ))s)"
+ done
+ fi
+ else
+ echo "Waiting for the VM to shutdown"
+ echo "Run 'vncviewer :$VNC_PORT' to see what's happening in the VM"
+ while ps -p $_QEMU_PID > /dev/null;
+ do
+ sleep 2
+ done
+ fi
+ fi
+ fi
+ - exec_local: &2 |
+ if [ -f $${qemu_pidfile} ]; then
+ _QEMU_PID=$(< $${qemu_pidfile})
+ if ps -p $_QEMU_PID > /dev/null; then
+ if [ -S $${qemu_monitor_socket} ]; then
+ echo "The graceful shutdown of the qemu VM should have failed (monitor socket is there)..."
+ fi
+ echo "Killing qemu (pid: $_QEMU_PID)."
+ kill -9 "$_QEMU_PID"
+ fi
+ rm -f $${qemu_pidfile}
+ fi
+ rm -f $${qemu_monitor_socket}
+ - on_setup_clean:
+ - test:
+ - exec_local: test "$${shutdown_vm_immediately}" == "false" -a "$${vm_cleanup_section}" == "setup"
+ - group:
+ - exec_local: *1
+ - exec_local: *2
+ - on_export_clean:
+ - test:
+ - exec_local: test "$${shutdown_vm_immediately}" == "false" -a "$${vm_cleanup_section}" == "export"
+ - group:
+ - exec_local: *1
+ - exec_local: *2
+ - exec_local: |
+ if [ "$${shutdown_vm_immediately}" == "true" ]; then
+ echo "Qemu VM shutdown: immediately"
+ else
+ echo "Qemu VM shutdown: in $${vm_cleanup_section} section cleaning"
+ fi
+ - exec_local: |
+ if [ -r $${qemu_pidfile} ] && pgrep -F $${qemu_pidfile} > /dev/null; then
+ echo "Qemu pid file found, with process running: killing it !" 1>&2
+ pkill -F $${qemu_pidfile}
+ sleep 0.5
+ if pgrep -F $${qemu_pidfile} > /dev/null; then
+ echo "Failed to kill qemu process." 1>&2
+ exit 1
+ fi
+ fi
+ - exec_local: |
+ echo "Starting qemu..."
+ if [ "$${qemu_enable_kvm}" == "true" ] && (/usr/sbin/kvm-ok > /dev/null || egrep '(vmx|svm)' /proc/cpuinfo > /dev/null) ; then # print warning if /usr/sbin/kvm-ok is not installed
+ if [ "$${qemu_arch}" == "aarch64" ]; then
+ ENABLE_KVM="-enable-kvm -accel kvm -machine virt,gic-version=host,accel=kvm:tcg -cpu host"
+ #ENABLE_KVM="-global virtio-blk-pci.scsi=off -no-user-config -enable-fips -machine virt,gic-version=host,accel=kvm:tcg -cpu host -rtc driftfix=slew -object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0"
+ elif [ "$${qemu_arch}" == "ppc64" ]; then
+ ENABLE_KVM="-enable-kvm -accel kvm -machine pseries,accel=kvm:tcg -cpu host"
+ else #X86_64
+ ENABLE_KVM="-enable-kvm -cpu host"
+ fi
+ BOOT_TIMEOUT=$${boot_timeout}
+ else
+ echo "No KVM acceleration used"
+ BOOT_TIMEOUT=$(($${boot_timeout}*2))
+ fi
+ if [ -f "vm_state_to_load.txt" ]
+ then
+ SAVED_STATE="$(< vm_state_to_load.txt)"
+ LOADVM="-loadvm $SAVED_STATE"
+ rm -f vm_state_to_load.txt
+ fi
+ if [ "$${debug}" == "true" ]; then
+ VNC_OPT=""
+ else
+ # Find empty VNC port
+ VNC_PORT=$(( $(__find_free_port 5900 5910) - 5900 ))
+ echo "VNC port: $VNC_PORT"
+ VNC_OPT="-vnc :$VNC_PORT"
+ fi
+ if [ -n "$${telnet_port}" ]; then
+ SERIAL_TELNET="telnet:localhost:$${telnet_port},server"
+ fi
+ # Select disk
+ QEMU_DRIVES="-drive file=$${image_disk}.$${image_format},cache=$${disk_cache},media=disk,if=virtio,id=drive0"
+ QEMU_BOOT=
+ QEMU_APPEND_CMDLINE=
+ if [ "$${qemu_uefi}" == "true" ]; then
+ if [ ! -f $${kameleon_cwd}/qemu_uefi_vars.fd ]; then
+ cp $${qemu_uefi_vars_path} $${kameleon_cwd}/qemu_uefi_vars.fd
+ fi
+ QEMU_BOOT="-drive if=pflash,format=raw,readonly,file=$${qemu_uefi_code_path} -drive if=pflash,format=raw,file=$${kameleon_cwd}/qemu_uefi_vars.fd"
+ fi
+ if [ -n "$${qemu_iso_path}" ]; then
+ QEMU_DRIVES="-drive file=$${qemu_iso_path},readonly,media=cdrom $QEMU_DRIVES"
+ if [ "$${qemu_iso_boot}" == "true" ]; then
+ QEMU_BOOT="$QEMU_BOOT -boot order=d"
+ fi
+ elif [ -n "$${qemu_kernel_path}" ]; then
+ QEMU_BOOT="$QEMU_BOOT -kernel $${qemu_kernel_path}"
+ if [ -n "$${qemu_initrd_path}" ]; then
+ QEMU_BOOT="$QEMU_BOOT -initrd $${qemu_initrd_path}"
+ fi
+ if [ -n "$${qemu_append_cmdline}" ]; then
+ QEMU_APPEND_CMDLINE="$${qemu_append_cmdline}"
+ QEMU_APPEND_CMDLINE=${QEMU_APPEND_CMDLINE//%LOCAL_IP%/$${local_ip}}
+ QEMU_APPEND_CMDLINE=${QEMU_APPEND_CMDLINE//%HTTP_PORT%/$HTTP_PORT}
+ fi
+ fi
+ if [ -n "$${qemu_netdev_user_options}" ]; then
+ QEMU_NETDEV_USER_OPTIONS=",$${qemu_netdev_user_options}"
+ fi
+ if [ "$${no_reboot}" == "true" ]; then
+ NO_REBOOT="-no-reboot"
+ fi
+ if [ -n "${SSH_FWD_PORT}" ]; then
+ HOSTFWD=",hostfwd=tcp::${SSH_FWD_PORT}-:22"
+ fi
+ qemu-system-$${qemu_arch} $ENABLE_KVM -smp $${qemu_cpus} -m $${qemu_memory_size} -rtc base=localtime \
+ -net nic,model=virtio -net user${QEMU_NETDEV_USER_OPTIONS}${HOSTFWD} \
+ $QEMU_DRIVES \
+ -monitor unix:$${qemu_monitor_socket},server,nowait -pidfile $${qemu_pidfile} -daemonize \
+ $QEMU_BOOT ${QEMU_APPEND_CMDLINE:+-append "$QEMU_APPEND_CMDLINE"} $NO_REBOOT \
+ $VNC_OPT $SERIAL_TELNET\
+ $LOADVM
+ - exec_local: |
+ VM_AVAILABLE=0
+ if [ "$${vm_expected_service}" == "ssh" ]; then
+ TIMEOUT=$(( $(date +%s) + $BOOT_TIMEOUT ))
+ until timeout 5 ssh -q -F $${ssh_config_file} -o ConnectionAttempts=1 $${kameleon_recipe_name} -t true && VM_AVAILABLE=1 || [ $(date +%s) -gt $TIMEOUT ];
+ do
+ echo -en "\rWaiting for SSH to become available in VM for out_context...($(( TIMEOUT - $(date +%s) ))s)"
+ sleep 1
+ done
+ echo
+ else
+ TIMEOUT=$(( $(date +%s) + $BOOT_TIMEOUT ))
+ until timeout 1 [ $(date +%s) -gt $TIMEOUT ];
+ do
+ echo -en "\rWaiting for VM to become available : ($(( TIMEOUT - $(date +%s) ))s)"
+ sleep 1
+ done
+ echo
+ VM_AVAILABLE=1
+ fi
+ - rescue:
+ - exec_local: test $VM_AVAILABLE -eq 1
+ - breakpoint: |
+ Failed to get VM up and running (expected service: $${vm_expected_service}). Please verify the VM successfully booted with a vnc client.
+ - test:
+ - exec_local: test -e "$${qemu_sendkeys_commands}" -a -s "$${qemu_sendkeys_commands}"
+ - exec_local: |
+ echo "Sending keyboard commands to the VM: $${qemu_sendkeys_commands}"
+ echo "(Local httpd server url: http://$${local_ip}:$HTTP_PORT)"
+ ruby $${qemu_sendkeys_script} -d 0.05 "$(sed -e s/%LOCAL_IP%/$${local_ip}/g -e s/%HTTP_PORT%/$HTTP_PORT/g $${qemu_sendkeys_commands})" | $${socat_monitor} > /dev/null
+ - exec_local: echo "No keyboard commands to send"
+
+- shutdown_vm:
+ - on_checkpoint: redo
+ - on_clean:
+ - test:
+ - exec_local: test "$${shutdown_vm_immediately}" == "true"
+ - exec_local: *2
+ - test:
+ - exec_local: test "$${shutdown_vm_immediately}" == "true"
+ - exec_local: *1