summaryrefslogtreecommitdiff
path: root/build-vm-openstack
diff options
context:
space:
mode:
Diffstat (limited to 'build-vm-openstack')
-rw-r--r--build-vm-openstack282
1 files changed, 282 insertions, 0 deletions
diff --git a/build-vm-openstack b/build-vm-openstack
new file mode 100644
index 0000000..4bdb92f
--- /dev/null
+++ b/build-vm-openstack
@@ -0,0 +1,282 @@
+#!/bin/bash
+#
+# Openstack specific functions
+#
+################################################################
+#
+# Copyright (c) 2017 SUSE Linux Products GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or 3 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program (see the file COPYING); if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#
+################################################################
+
+
+OPENSTACK_BUILD_ID=
+
+OPENSTACK_VOLUME_GRUB=
+OPENSTACK_VOLUME_ROOT=
+OPENSTACK_VOLUME_SWAP=
+OPENSTACK_ROOT_ATTACH_INFO=
+OPENSTACK_SWAP_ATTACH_INFO=
+
+openstack_get_field() {
+ echo -n "$1"|perl -n -e "\$_ =~ /^\|\s+$2\s+\|\s+(\S*)\s+\|\$/ && print \$1"
+}
+
+openstack_get_disk_state() {
+ local OUT=$($CINDERCLIENT show "$1")
+ openstack_get_field "$OUT" status
+}
+
+openstack_cinder_volume2id() {
+ local OUT=$($CINDERCLIENT show "$1")
+ openstack_get_field "$OUT" id
+}
+
+# sets OPENSTACK_ATTACH_INFO
+cloud_volume_attach_openstack() {
+ local VM_SERVER="$1"
+ local VM_VOL_NAME="$2"
+ local VM_VOL_ID=$(openstack_cinder_volume2id $VM_VOL_NAME)
+
+ # Example output of "nova volume-attach
+ # +----------+--------------------------------------+
+ # | Property | Value |
+ # +----------+--------------------------------------+
+ # | device | /dev/vdb |
+ # | id | 793e9a04-7068-4cf1-86e7-26509f709b54 |
+ # | serverId | 175e470c-5869-4425-988a-6b334a2fa655 |
+ # | volumeId | 793e9a04-7068-4cf1-86e7-26509f709b54 |
+ # +----------+--------------------------------------+
+ local OUT=$($NOVACLIENT volume-attach "$VM_SERVER" "$VM_VOL_ID")
+ test $? -gt 0 && cleanup_and_exit 3 "ERROR: nova volume-attach failed. $?"
+
+ local device_path=`openstack_get_field "$OUT" device`
+ local serverId=`openstack_get_field "$OUT" serverId`
+ while true ; do
+ local state=`openstack_get_disk_state "$VM_VOL_NAME"`
+ test "$state" = "in-use" && break
+ test -z "$state" && cleanup_and_exit 3 "ERROR: unable to find state of volume $VM_VOL_NAME"
+ if test "$state" = available ; then
+ echo "WARNING: volume $VM_VOL_NAME got not attached, retrying" >&2
+ OUT=`$NOVACLIENT volume-attach "$VM_SERVER" "$VM_VOL_ID"`
+ test $? -gt 0 && cleanup_and_exit 3 "ERROR: nova attach failed. $?"
+ device_path=`openstack_get_field "$OUT" device`
+ fi
+ sleep 3
+ done
+ test "${device_path:0:5}" = "/dev/" || cleanup_and_exit 3 "device path not starting with /dev/: $device_path"
+
+ if ! test -e "$device_path" ; then
+ echo "waiting for $device_path to appear"
+ for i in 1 2 3 4 5 6 7 8 9 10 ; do
+ sleep 1
+ test -e "$device_path" && break
+ done
+ test -b "$device_path" || cleanup_and_exit 3 "$device_path did not appear"
+ fi
+
+ # return attach info. Example:
+ # 793e9a04-7068-4cf1-86e7-26509f709b54:175e470c-5869-4425-988a-6b334a2fa655:/dev/vdb
+ OPENSTACK_ATTACH_INFO="$VM_VOL_ID:$serverId:$device_path"
+}
+
+cloud_volume_detach_openstack() {
+ local VM_SERVER=${1:37:36}
+ local VM_VOL_ID=${1:0:36}
+
+ test -z "$VM_SERVER" -o -z "$VM_VOL_ID" && cleanup_and_exit 1 "cloud_volume_detach_openstack: bad attach info"
+
+ # needed at all?
+ $NOVACLIENT volume-detach "$VM_SERVER" "$VM_VOL_ID"
+
+ state=`openstack_get_disk_state $VM_VOL_ID`
+ while test "$state" = detaching ; do
+ sleep 1
+ state=`openstack_get_disk_state $VM_VOL_ID`
+ done
+
+ if test "$state" = "available" ; then
+ return 0
+ fi
+
+ if ! $NOVACLIENT volume-detach "$VM_SERVER" "$VM_VOL_ID" ; then
+ cleanup_and_exit 3 "ERROR: nova detach of $VM_VOL_ID failed."
+ fi
+ while test "$state" != "available" ; do
+ state=`openstack_get_disk_state $VM_VOL_ID`
+ sleep 3
+ done
+}
+
+vm_verify_options_openstack() {
+ OPENSTACK_VOLUME_ROOT="$VM_ROOT"
+ OPENSTACK_VOLUME_SWAP="$VM_SWAP"
+ VM_ROOT_TYPE=unattached
+ VM_SWAP_TYPE=unattached
+
+ # Checking for required tools (nova and cinder)
+ NOVACLIENT=`type -p nova`
+ if test -z "$NOVACLIENT" ; then
+ cleanup_and_exit 3 "ERROR: nova not installed. Please install nova and try again"
+ fi
+
+ CINDERCLIENT=`type -p cinder`
+ if test -z "$CINDERCLIENT" ; then
+ cleanup_and_exit 3 "ERROR: nova not installed. Please install cinder and try again"
+ fi
+
+ if test -n "$KILL" -o -n "$DO_WIPE" ; then
+ return
+ fi
+
+ # verify options
+ if test -z "$OS_AUTH_URL" ; then
+ cleanup_and_exit 3 "ERROR: No openstack environment set. This vm-type works only inside of an openstack VM."
+ fi
+ if test -z "$VM_KERNEL" ; then
+ cleanup_and_exit 3 "ERROR: No worker boot VM volume name specified."
+ fi
+ if test -z "$VM_ROOT" ; then
+ cleanup_and_exit 3 "ERROR: No worker root VM volume name specified."
+ fi
+ if test -z "$VM_SWAP" ; then
+ cleanup_and_exit 3 "ERROR: No worker swap VM volume name specified."
+ fi
+ if test -z "$VM_SERVER" ; then
+ cleanup_and_exit 3 "ERROR: No VM server node name specified (usually this instance)."
+ fi
+ if test -z "$VM_WORKER" ; then
+ cleanup_and_exit 3 "ERROR: No VM worker node name specified (the instance to be created)."
+ fi
+
+ if test -z "$VM_OPENSTACK_FLAVOR" ; then
+ cleanup_and_exit 3 "ERROR: No VM openstack flavor set (--openstack-flavor <FLAVOR-NAME|FLAVOR-ID>)."
+ fi
+
+ # set default values
+ VM_ROOTDEV="LABEL=obsrootfs"
+ VM_SWAPDEV="LABEL=obsswapfs"
+
+ # hack: mis-use kernel parameter
+ OPENSTACK_VOLUME_GRUB="$VM_KERNEL"
+ VM_KERNEL=
+}
+
+vm_attach_root_openstack() {
+ test -n "$OPENSTACK_ROOT_ATTACH_INFO" && cleanup_and_exit 1 "root is already attached"
+ local OPENSTACK_ATTACH_INFO
+ cloud_volume_attach_openstack "$VM_SERVER" "$OPENSTACK_VOLUME_ROOT"
+ OPENSTACK_ROOT_ATTACH_INFO=$OPENSTACK_ATTACH_INFO
+ VM_ROOT=${OPENSTACK_ATTACH_INFO:74}
+ VM_ROOT_TYPE=device
+}
+
+vm_attach_swap_openstack() {
+ test -n "$OPENSTACK_SWAP_ATTACH_INFO" && cleanup_and_exit 1 "root is already attached"
+ local OPENSTACK_ATTACH_INFO
+ cloud_volume_attach_openstack "$VM_SERVER" "$OPENSTACK_VOLUME_SWAP"
+ OPENSTACK_SWAP_ATTACH_INFO=$OPENSTACK_ATTACH_INFO
+ VM_SWAP=${OPENSTACK_ATTACH_INFO:74}
+ VM_SWAP_TYPE=device
+}
+
+vm_detach_root_openstack() {
+ test -z "$OPENSTACK_ROOT_ATTACH_INFO" && cleanup_and_exit 1 "root is not attached"
+ local OPENSTACK_ATTACH_INFO=$OPENSTACK_ROOT_ATTACH_INFO
+ OPENSTACK_ROOT_ATTACH_INFO=
+ cloud_volume_detach_openstack "$OPENSTACK_ATTACH_INFO" || cleanup_and_exit 3
+ VM_ROOT=$OPENSTACK_VOLUME_ROOT
+ VM_ROOT_TYPE=unattached
+}
+
+vm_detach_swap_openstack() {
+ test -z "$OPENSTACK_SWAP_ATTACH_INFO" && cleanup_and_exit 1 "swap is not attached"
+ local OPENSTACK_ATTACH_INFO=$OPENSTACK_SWAP_ATTACH_INFO
+ OPENSTACK_SWAP_ATTACH_INFO=
+ cloud_volume_detach_openstack "$OPENSTACK_ATTACH_INFO" || cleanup_and_exit 3
+ VM_SWAP=$OPENSTACK_VOLUME_SWAP
+ VM_SWAP_TYPE=unattached
+}
+
+vm_cleanup_openstack() {
+ test -n "$OPENSTACK_ROOT_ATTACH_INFO" && vm_detach_root_openstack
+ test -n "$OPENSTACK_SWAP_ATTACH_INFO" && vm_detach_swap_openstack
+}
+
+vm_fixup_openstack() {
+ # No way to handle this via init= parameter here....
+ echo "#!/bin/sh" > "$BUILD_ROOT/sbin/init"
+ echo 'echo "exec /.build/build \"$@\""' >> "$BUILD_ROOT/sbin/init"
+ echo 'exec /.build/build "$@"' >> "$BUILD_ROOT/sbin/init"
+ echo 'echo "Waiting for input"' >> "$BUILD_ROOT/sbin/init"
+ echo 'read' >> "$BUILD_ROOT/sbin/init"
+ chmod 0755 "$BUILD_ROOT/sbin/init"
+}
+
+vm_sysrq_openstack() {
+ :
+}
+
+vm_wipe_openstack() {
+ if test -n "$VM_WORKER" ; then
+ $NOVACLIENT delete $VM_WORKER
+ fi
+}
+
+vm_kill_openstack() {
+ if $NOVACLIENT show "$VM_WORKER" >/dev/null 2>&1 ; then
+ if ! $NOVACLIENT delete "$VM_WORKER" ; then
+ cleanup_and_exit 1 "could not kill openstack vm build $VM_WORKER"
+ fi
+ fi
+}
+
+openstack_wait_for_delete_instance() {
+ while test -n "$($NOVACLIENT list|grep $VM_WORKER)" ; do
+ sleep 1
+ done
+}
+
+vm_startup_openstack() {
+ local VM_VOL_ROOT_ID=`openstack_cinder_volume2id ${VM_ROOT}`
+ local VM_VOL_SWAP_ID=`openstack_cinder_volume2id ${VM_SWAP}`
+ local VM_VOL_BOOT_ID=`openstack_cinder_volume2id ${OPENSTACK_VOLUME_GRUB}`
+
+ local OUTPUT=`\
+ $NOVACLIENT boot \
+ --flavor $VM_OPENSTACK_FLAVOR \
+ --block-device source=volume,dest=volume,bootindex=0,id=${VM_VOL_BOOT_ID}\
+ --block-device source=volume,dest=volume,bootindex=1,id=${VM_VOL_ROOT_ID}\
+ --block-device source=volume,dest=volume,bootindex=2,id=${VM_VOL_SWAP_ID}\
+ --poll "$VM_WORKER" || cleanup_and_exit 3\
+ `
+ OPENSTACK_BUILD_ID=`openstack_get_field "$OUTPUT" id`
+
+ for try in 1 2 3 4 5 ; do
+ WS_URL=`$NOVACLIENT get-serial-console $VM_WORKER|grep serial |perl -p -e 's#.*(ws://.*) \|#$1#'`
+ test -n "$WS_URL" && break
+ sleep 1
+ done
+
+ if ! $BUILD_DIR/openstack-console "${WS_URL}" ; then
+ $NOVACLIENT delete $OPENSTACK_BUILD_ID
+ cleanup_and_exit 3
+ else
+ $NOVACLIENT delete $OPENSTACK_BUILD_ID
+ openstack_wait_for_delete_instance
+ fi
+}
+