File build-vm-openstack of Package build
#
# 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....
rm -rf "$BUILD_ROOT/sbin/init"
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 ! python $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
}