From 0d0c7c7578cb60fa2bc552d4752d37c642faee33 Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Thu, 3 Apr 2014 19:03:11 -0700 Subject: [PATCH 1/3] fix(qemu_template): Replace getopts with simple pattern matching. The use of getopts was leading to conflicts between this script's short options and qemu's long options. For example -serial was getting interpreted as -s -- erial which is not very helpful. --- build_library/qemu_template.sh | 40 ++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/build_library/qemu_template.sh b/build_library/qemu_template.sh index 7d5b352e36..c0f631cb6c 100755 --- a/build_library/qemu_template.sh +++ b/build_library/qemu_template.sh @@ -11,6 +11,7 @@ VM_CDROM= VM_NCPUS="`grep -c ^processor /proc/cpuinfo`" SSH_PORT=2222 SSH_KEYS="" +SAFE_ARGS=0 USAGE="Usage: $0 [-a authorized_keys] [--] [qemu options...] Options: -a FILE SSH public keys for login access. [~/.ssh/id_{dsa,rsa}.pub] @@ -29,24 +30,31 @@ Any arguments after -a and -p will be passed through to qemu, -- may be used as an explicit separator. See the qemu(1) man page for more details. " -safe_args=0 -script_args=1 -while getopts ":a:p:svh" OPTION -do - case $OPTION in - a) SSH_KEYS="$OPTARG" ;; - p) SSH_PORT="$OPTARG" ;; - s) safe_args=1 ;; - v) set -x ;; - h) echo "$USAGE"; exit ;; - ?) break ;; +while [ $# -ge 1 ]; do + case "$1" in + -a|-authorized-keys) + SSH_KEYS="$2" + shift 2 ;; + -p|-ssh-port) + SSH_PORT="$2" + shift 2 ;; + -s|-safe) + SAFE_ARGS=1 + shift ;; + -v|-verbose) + set -x + shift ;; + -h|-help|--help) + echo "$USAGE" + exit ;; + --) + shift + break ;; + *) + break ;; esac - script_args=$OPTIND done -shift $((script_args - 1)) -[ "$1" = "--" ] && shift - METADATA=$(mktemp -t -d coreos-meta-data.XXXXXXXXXX) if [ $? -ne 0 ] || [ ! -d "$METADATA" ]; then @@ -79,7 +87,7 @@ else fi # Start assembling our default command line arguments -if [ "${safe_args}" -eq 1 ]; then +if [ "${SAFE_ARGS}" -eq 1 ]; then disk_type="ide" else disk_type="virtio" From 150ab005e0332f3b7954559e408dccc63732e6c8 Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Thu, 3 Apr 2014 19:23:18 -0700 Subject: [PATCH 2/3] feat(qemu_template): Provide SSH keys via config drive Moving away from our old behavior of loading 'authorized_keys' on virtfs volumes. Still using virtfs to avoid depending on mkisofs or similar. --- build_library/qemu_template.sh | 65 +++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/build_library/qemu_template.sh b/build_library/qemu_template.sh index c0f631cb6c..ee8877896c 100755 --- a/build_library/qemu_template.sh +++ b/build_library/qemu_template.sh @@ -56,34 +56,49 @@ while [ $# -ge 1 ]; do done -METADATA=$(mktemp -t -d coreos-meta-data.XXXXXXXXXX) -if [ $? -ne 0 ] || [ ! -d "$METADATA" ]; then - echo "$0: mktemp -d failed!" >&2 - exit 1 -fi -trap "rm -rf '$METADATA'" EXIT - - -# Do our best to create an authorized_keys file -if [ -n "$SSH_KEYS" ]; then - if [ ! -f "$SSH_KEYS" ]; then - echo "$0: SSH keys file not found: $SSH_KEYS" >&2 - exit 1 - elif ! cp "$SSH_KEYS" "${METADATA}/authorized_keys"; then - echo "$0: Failed to copy SSH keys from $SSH_KEYS" >&2 - exit 1 - fi -else - # Nothing provided, try fetching from ssh-agent and the local fs +find_ssh_keys() { if [ -S "$SSH_AUTH_SOCK" ]; then - ssh-add -L >> "${METADATA}/authorized_keys" + ssh-add -L fi for default_key in ~/.ssh/id_*.pub; do if [ ! -f "$default_key" ]; then continue fi - cat "$default_key" >> "${METADATA}/authorized_keys" + cat "$default_key" done +} + +write_ssh_keys() { + echo "#cloud-config" + echo "ssh_authorized_keys:" + sed -e 's/^/ - /' +} + + +CONFIG_DRIVE=$(mktemp -t -d coreos-configdrive.XXXXXXXXXX) +if [ $? -ne 0 ] || [ ! -d "$CONFIG_DRIVE" ]; then + echo "$0: mktemp -d failed!" >&2 + exit 1 +fi +trap "rm -rf '$CONFIG_DRIVE'" EXIT +mkdir -p "${CONFIG_DRIVE}/openstack/latest" + + +if [ -n "$SSH_KEYS" ]; then + if [ ! -f "$SSH_KEYS" ]; then + echo "$0: SSH keys file not found: $SSH_KEYS" >&2 + exit 1 + fi + SSH_KEYS_TEXT=$(cat "$SSH_KEYS") + if [ $? -ne 0 ] || [ -z "$SSH_KEYS_TEXT" ]; then + echo "$0: Failed to read SSH keys from $SSH_KEYS" >&2 + exit 1 + fi + echo "$SSH_KEYS_TEXT" | write_ssh_keys > \ + "${CONFIG_DRIVE}/openstack/latest/user_data" +else + find_ssh_keys | write_ssh_keys > \ + "${CONFIG_DRIVE}/openstack/latest/user_data" fi # Start assembling our default command line arguments @@ -116,20 +131,20 @@ if [ -n "${VM_CDROM}" ]; then fi # Default to KVM, fall back on full emulation -# ${METADATA} will be mounted in CoreOS as /media/metadata +# ${CONFIG_DRIVE} will be mounted in CoreOS as /media/configdrive qemu-system-x86_64 \ -name "$VM_NAME" \ -m ${VM_MEMORY} \ -machine accel=kvm:tcg \ -net nic,vlan=0,model=virtio \ -net user,vlan=0,hostfwd=tcp::"${SSH_PORT}"-:22 \ - -fsdev local,id=metadata,security_model=none,readonly,path="${METADATA}" \ - -device virtio-9p-pci,fsdev=metadata,mount_tag=metadata \ + -fsdev local,id=conf,security_model=none,readonly,path="${CONFIG_DRIVE}" \ + -device virtio-9p-pci,fsdev=conf,mount_tag=config-2 \ "$@" RET=$? # Cleanup! -rm -rf "${METADATA}" +rm -rf "${CONFIG_DRIVE}" trap - EXIT exit ${RET} From 12c0008ad9d730856d72d3d5c7be6164773af8b6 Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Thu, 3 Apr 2014 21:06:22 -0700 Subject: [PATCH 3/3] feat(qemu_template): Add support for user-provided configs. A custom cloud config can be provided directly via -u or as an existing config drive image via -c. --- build_library/qemu_template.sh | 94 ++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/build_library/qemu_template.sh b/build_library/qemu_template.sh index ee8877896c..6f1108b33f 100755 --- a/build_library/qemu_template.sh +++ b/build_library/qemu_template.sh @@ -11,9 +11,13 @@ VM_CDROM= VM_NCPUS="`grep -c ^processor /proc/cpuinfo`" SSH_PORT=2222 SSH_KEYS="" +CONFIG_FILE="" +CONFIG_IMAGE="" SAFE_ARGS=0 USAGE="Usage: $0 [-a authorized_keys] [--] [qemu options...] Options: + -u FILE Cloudinit user-data as either a cloud config or script. + -c FILE Config drive as an iso or fat filesystem image. -a FILE SSH public keys for login access. [~/.ssh/id_{dsa,rsa}.pub] -p PORT The port on localhost to map to the VM's sshd. [2222] -s Safe settings: single simple cpu, ide disks. @@ -30,9 +34,25 @@ Any arguments after -a and -p will be passed through to qemu, -- may be used as an explicit separator. See the qemu(1) man page for more details. " +check_conflict() { + if [ -n "${CONFIG_FILE}${CONFIG_IMAGE}${SSH_KEYS}" ]; then + echo "The -u -c and -a options cannot be combined!" >&2 + exit 1 + fi +} + while [ $# -ge 1 ]; do case "$1" in + -u|-user-data) + check_conflict + CONFIG_FILE="$2" + shift 2 ;; + -c|-config-drive) + check_conflict + CONFIG_IMAGE="$2" + shift 2 ;; -a|-authorized-keys) + check_conflict SSH_KEYS="$2" shift 2 ;; -p|-ssh-port) @@ -75,30 +95,38 @@ write_ssh_keys() { } -CONFIG_DRIVE=$(mktemp -t -d coreos-configdrive.XXXXXXXXXX) -if [ $? -ne 0 ] || [ ! -d "$CONFIG_DRIVE" ]; then - echo "$0: mktemp -d failed!" >&2 - exit 1 -fi -trap "rm -rf '$CONFIG_DRIVE'" EXIT -mkdir -p "${CONFIG_DRIVE}/openstack/latest" - - -if [ -n "$SSH_KEYS" ]; then - if [ ! -f "$SSH_KEYS" ]; then - echo "$0: SSH keys file not found: $SSH_KEYS" >&2 +if [ -z "${CONFIG_IMAGE}" ]; then + CONFIG_DRIVE=$(mktemp -t -d coreos-configdrive.XXXXXXXXXX) + if [ $? -ne 0 ] || [ ! -d "$CONFIG_DRIVE" ]; then + echo "$0: mktemp -d failed!" >&2 exit 1 fi - SSH_KEYS_TEXT=$(cat "$SSH_KEYS") - if [ $? -ne 0 ] || [ -z "$SSH_KEYS_TEXT" ]; then - echo "$0: Failed to read SSH keys from $SSH_KEYS" >&2 - exit 1 + trap "rm -rf '$CONFIG_DRIVE'" EXIT + mkdir -p "${CONFIG_DRIVE}/openstack/latest" + + + if [ -n "$SSH_KEYS" ]; then + if [ ! -f "$SSH_KEYS" ]; then + echo "$0: SSH keys file not found: $SSH_KEYS" >&2 + exit 1 + fi + SSH_KEYS_TEXT=$(cat "$SSH_KEYS") + if [ $? -ne 0 ] || [ -z "$SSH_KEYS_TEXT" ]; then + echo "$0: Failed to read SSH keys from $SSH_KEYS" >&2 + exit 1 + fi + echo "$SSH_KEYS_TEXT" | write_ssh_keys > \ + "${CONFIG_DRIVE}/openstack/latest/user_data" + elif [ -n "${CONFIG_FILE}" ]; then + cp "${CONFIG_FILE}" "${CONFIG_DRIVE}/openstack/latest/user_data" + if [ $? -ne 0 ]; then + echo "$0: Failed to copy cloudinit file from $CONFIG_FILE" >&2 + exit 1 + fi + else + find_ssh_keys | write_ssh_keys > \ + "${CONFIG_DRIVE}/openstack/latest/user_data" fi - echo "$SSH_KEYS_TEXT" | write_ssh_keys > \ - "${CONFIG_DRIVE}/openstack/latest/user_data" -else - find_ssh_keys | write_ssh_keys > \ - "${CONFIG_DRIVE}/openstack/latest/user_data" fi # Start assembling our default command line arguments @@ -110,6 +138,17 @@ else set -- -cpu host -smp "${VM_NCPUS}" "$@" fi +# ${CONFIG_DRIVE} or ${CONFIG_IMAGE} will be mounted in CoreOS as /media/configdrive +if [ -n "${CONFIG_DRIVE}" ]; then + set -- \ + -fsdev local,id=conf,security_model=none,readonly,path="${CONFIG_DRIVE}" \ + -device virtio-9p-pci,fsdev=conf,mount_tag=config-2 "$@" +fi + +if [ -n "${CONFIG_IMAGE}" ]; then + set -- -drive if=${disk_type},file="${CONFIG_IMAGE}" "$@" +fi + if [ -n "${VM_IMAGE}" ]; then set -- -drive if=${disk_type},file="${SCRIPT_DIR}/${VM_IMAGE}" "$@" fi @@ -127,24 +166,15 @@ if [ -n "${VM_UUID}" ]; then fi if [ -n "${VM_CDROM}" ]; then - set -- -cdrom "$VM_CDROM" "$@" + set -- -cdrom "${SCRIPT_DIR}/${VM_CDROM}" "$@" fi # Default to KVM, fall back on full emulation -# ${CONFIG_DRIVE} will be mounted in CoreOS as /media/configdrive qemu-system-x86_64 \ -name "$VM_NAME" \ -m ${VM_MEMORY} \ -machine accel=kvm:tcg \ -net nic,vlan=0,model=virtio \ -net user,vlan=0,hostfwd=tcp::"${SSH_PORT}"-:22 \ - -fsdev local,id=conf,security_model=none,readonly,path="${CONFIG_DRIVE}" \ - -device virtio-9p-pci,fsdev=conf,mount_tag=config-2 \ "$@" -RET=$? - - -# Cleanup! -rm -rf "${CONFIG_DRIVE}" -trap - EXIT -exit ${RET} +exit $?