From 68a4819dd4094fa676c323b9a05438c8b8da09ae Mon Sep 17 00:00:00 2001 From: Dariusz Krol Date: Mon, 1 Oct 2018 15:57:26 +0200 Subject: Add image setup to trove devstack plugin Main goal is to have a working vm image registered in trove after devstack installation. It is a first step towards trovestack-redesign as described in https://etherpad.openstack.org/p/trovestack-redesign It is enabled by default during devstack installation with trove enabled plugin, but it can be skipped by setting DISABLE_TROVE_IMAGE_SETUP=TRUE Implementation details: * export environmental variables for diskimage-builder * build an image with disk-image-create script * register the newly created image in trove * add tripleo-elements information to default settings Change-Id: I6e57890c5b6fb65e9b8c63363f92e5a7c70e523e Signed-off-by: Dariusz Krol --- devstack/plugin.sh | 123 +++++++++++++++++++++ devstack/settings | 4 + integration/scripts/trovestack | 37 ++++--- integration/scripts/trovestack.rc | 2 +- trove/guestagent/datastore/mysql_common/service.py | 4 +- trove/tests/api/replication.py | 2 +- 6 files changed, 152 insertions(+), 20 deletions(-) diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 7649c522..15d76b78 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -291,6 +291,9 @@ function configure_trove { # install_trove() - Collect source and prepare function install_trove { + echo "Changing stack user sudoers" + echo "stack ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/60_stack_sh_allow_all + setup_develop $TROVE_DIR if [[ "${TROVE_USE_MOD_WSGI}" == "TRUE" ]]; then @@ -353,6 +356,12 @@ function init_trove { --os-password ${ADMIN_PASSWORD} \ --os-project-name ${ALT_TENANT_NAME} + # build and upload sample Trove mysql instance if not set otherwise + if [[ ${TROVE_DISABLE_IMAGE_SETUP} != "TRUE" ]]; then + echo "Setup datastore image" + _setup_minimal_image + fi + # If no guest image is specified, skip remaining setup [ -z "$TROVE_GUEST_IMAGE_URL" ] && return 0 @@ -559,6 +568,120 @@ function configure_tempest_for_trove { fi } +# _setup_minimal_image() - build and register in Trove a vm image with mysql +# - datastore can be set via env variables +function _setup_minimal_image { + ##### Prerequisites: + ##### - SSH KEYS has to be created on controller + ##### - trove will access controller ip to get trove source code by using HOST_SCP_USERNAME and an ssh key + ##### - we assume tripleo elements and all other elements have been downloaded + + echo "Exporting image-related environmental variables" + PRIMARY_IP=$(ip route get 8.8.8.8 | head -1 | cut -d' ' -f8) + export CONTROLLER_IP=${CONTROLLER_IP:-$PRIMARY_IP} + export HOST_USERNAME=${HOST_USERNAME:-'stack'} + export HOST_SCP_USERNAME=${HOST_SCP_USERNAME:-'stack'} + export GUEST_USERNAME=${GUEST_USERNAME:-'ubuntu'} + export PATH_TROVE=${PATH_TROVE:-'/opt/stack/trove'} + export ESCAPED_PATH_TROVE=$(echo $PATH_TROVE | sed 's/\//\\\//g') + export TROVESTACK_SCRIPTS=${TROVESTACK_SCRIPTS:-'/opt/stack/trove/integration/scripts'} + export SERVICE_TYPE=${SERVICE_TYPE:-'mysql'} + export SSH_DIR=${SSH_DIR:-'/opt/stack/.ssh'} + export GUEST_LOGDIR=${GUEST_LOGDIR:-'/var/log/trove/'} + export ESCAPED_GUEST_LOGDIR=$(echo $GUEST_LOGDIR | sed 's/\//\\\//g') + export DIB_CLOUD_INIT_DATASOURCES="ConfigDrive" + export DISTRO="ubuntu" + export VM=${VM:-'/opt/stack/images/ubuntu_mysql/ubuntu_mysql'} + + if [ -d "$TROVESTACK_SCRIPTS/files/elements" ]; then + export ELEMENTS_PATH=$TROVESTACK_SCRIPTS/files/elements + else + export ELEMENTS_PATH=. + fi + + if [ ! -z "$PATH_DISKIMAGEBUILDER" ]; then + export ELEMENTS_PATH+=:$PATH_DISKIMAGEBUILDER/elements + elif [ -d "/usr/local/lib/python2.7/dist-packages/diskimage_builder" ]; then + PATH_DISKIMG="/usr/local/lib/python2.7/dist-packages/diskimage_builder" + export ELEMENTS_PATH+=:$PATH_DISKIMG/elements + fi + + if [ ! -z "$PATH_TRIPLEO_ELEMENTS" ]; then + export ELEMENTS_PATH+=:$PATH_TRIPLEO_ELEMENTS/elements + else + git_clone $TRIPLEO_IMAGES_REPO $TRIPLEO_IMAGES_DIR $TRIPLEO_IMAGES_BRANCH + setup_develop $TRIPLEO_IMAGES_DIR + + export ELEMENTS_PATH+=:$TRIPLEO_IMAGES_DIR/elements + fi + + export DIB_APT_CONF_DIR=/etc/apt/apt.conf.d + export DIB_CLOUD_INIT_ETC_HOSTS=true + export QEMU_IMG_OPTIONS="--qemu-img-options compat=1.1" + export RELEASE=${RELEASE:-'xenial'} + export DIB_RELEASE=${RELEASE:-'xenial'} + + export TROVE_GUESTAGENT_CONF=${TROVE_GUESTAGENT_CONF:-'/etc/trove/trove-guestagent.conf'} + + mkdir -p ${SSH_DIR} + /usr/bin/ssh-keygen -f ${SSH_DIR}/id_rsa -q -N "" + cat ${SSH_DIR}/id_rsa.pub >> ${SSH_DIR}/authorized_keys + chmod 600 ${SSH_DIR}/authorized_keys + + echo "Run disk image create to actually create a new image" + disk-image-create -a amd64 -o "${VM}" -x ${QEMU_IMG_OPTIONS} ${DISTRO} \ + vm cloud-init-datasources ${DISTRO}-guest ${DISTRO}-${RELEASE}-guest \ + ${DISTRO}-${SERVICE_TYPE} ${DISTRO}-${RELEASE}-${SERVICE_TYPE} + + QCOW_IMAGE="$VM.qcow2" + + if [ ! -f $QCOW_IMAGE ]; then + echo "Image file was not found at $QCOW_IMAGE. Probably it was not created." + return 1 + fi + + DATASTORE=$SERVICE_TYPE + DATASTORE_VERSION=${DATASTORE_VERSION:-'5.7'} + ACTIVE=1 + INACTIVE=0 + + echo "Add image to glance" + GLANCE_OUT=$(openstack --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \ + image create $DISTRO-${DATASTORE}-${DATASTORE_VERSION} \ + --public --disk-format qcow2 --container-format bare --file $QCOW_IMAGE) + glance_image_id=$(echo "$GLANCE_OUT" | grep '| id ' | awk '{print $4}') + + echo "Create datastore specific entry in Trove AFAIK one per datastore, do not need when changing image" + $TROVE_MANAGE datastore_update $DATASTORE "" + + echo "Connect datastore entry to glance image" + $TROVE_MANAGE datastore_version_update $DATASTORE $DATASTORE_VERSION $DATASTORE $glance_image_id "" $ACTIVE + + echo "Set default datastore version" + $TROVE_MANAGE datastore_update $DATASTORE $DATASTORE_VERSION + + # just for tests + $TROVE_MANAGE datastore_version_update "$DATASTORE" "inactive_version" "manager1" $glance_image_id "" $INACTIVE + $TROVE_MANAGE datastore_update Test_Datastore_1 "" + + echo "Add validation rules if available" + if [ -f "$PATH_TROVE"/trove/templates/$DATASTORE/validation-rules.json ]; then + $TROVE_MANAGE db_load_datastore_config_parameters "$DATASTORE" "$DATASTORE_VERSION" \ + "$PATH_TROVE"/trove/templates/$DATASTORE/validation-rules.json + fi + + echo "Generate cloudinit" + CLOUDINIT_PATH=/etc/trove/cloudinit/mysql.cloudinit + + if [ ! -f $CLOUDINIT_PATH ]; then + sudo mkdir -p $(dirname $CLOUDINIT_PATH) + + sudo echo "#!/usr/bin/env bash" | sudo tee $CLOUDINIT_PATH + PUBKEY=`cat ${SSH_DIR}/id_rsa.pub` + sudo echo "echo '${PUBKEY}' > /home/${GUEST_USERNAME}/.ssh/authorized_keys" | sudo tee --append $CLOUDINIT_PATH + fi +} + # Dispatcher for trove plugin if is_service_enabled trove; then if [[ "$1" == "stack" && "$2" == "install" ]]; then diff --git a/devstack/settings b/devstack/settings index 0985982f..096be6c9 100644 --- a/devstack/settings +++ b/devstack/settings @@ -14,6 +14,10 @@ TROVE_DASHBOARD_DIR=${TROVE_DASHBOARD_DIR:-${DEST}/trove-dashboard} TROVE_DASHBOARD_REPO=${TROVE_DASHBOARD_REPO:-${GIT_BASE}/openstack/trove-dashboard.git} TROVE_DASHBOARD_BRANCH=${TROVE_DASHBOARD_BRANCH:-master} +TRIPLEO_IMAGES_DIR=${TRIPLEO_IMAGES_DIR:-${DEST}/tripleo-image-elements} +TRIPLEO_IMAGES_REPO=${TRIPLEO_IMAGES_REPO:-${GIT_BASE}/openstack/tripleo-image-elements.git} +TRIPLEO_IMAGES_BRANCH=${TRIPLEO_IMAGES_BRANCH:-master} + # Set up configuration directory and files TROVE_CONF_DIR=${TROVE_CONF_DIR:-/etc/trove} TROVE_CONF=${TROVE_CONF:-${TROVE_CONF_DIR}/trove.conf} diff --git a/integration/scripts/trovestack b/integration/scripts/trovestack index a060e997..a1ceafc7 100755 --- a/integration/scripts/trovestack +++ b/integration/scripts/trovestack @@ -852,26 +852,21 @@ function cmd_build_and_upload_image() { exit 1 fi - local IMAGE_URL="" - # Use /tmp as file_cache - FILES=/tmp - if [[ -n $IMAGE_DOWNLOAD_URL ]]; then - exclaim "Downloading and using cached image" - IMAGE_URL=$IMAGE_DOWNLOAD_URL - else - exclaim "Trying to build image" + + GLANCE_IMAGEID=$(openstack $CLOUD_ADMIN_ARG image list | grep "$DATASTORE_TYPE" | get_field 1) + echo "IMAGEID: $GLANCE_IMAGEID" + if [[ -z $GLANCE_IMAGEID ]]; then build_guest_image "${DATASTORE_TYPE}" QCOW_IMAGE=`find $VM_PATH -name '*.qcow2'` IMAGE_URL="file://$QCOW_IMAGE" - fi + GLANCE_IMAGEID=`get_glance_id upload_image $IMAGE_URL` + [[ -z "$GLANCE_IMAGEID" ]] && echo "Glance upload failed!" && exit 1 + echo "IMAGE ID: $GLANCE_IMAGEID" - GLANCE_IMAGEIDS=$(openstack $CLOUD_ADMIN_ARG image list | grep $(basename $IMAGE_URL .qcow2) | get_field 1) - if [[ -n $GLANCE_IMAGEIDS ]]; then - openstack $CLOUD_ADMIN_ARG image delete $GLANCE_IMAGEIDS + if [[ -f /etc/trove/cloudinit/mysql.cloudinit ]]; then + sudo cp /etc/trove/cloudinit/mysql.cloudinit /etc/trove/cloudinit/${DATASTORE_TYPE}.cloudinit + fi fi - GLANCE_IMAGEID=`get_glance_id upload_image $IMAGE_URL` - [[ -z "$GLANCE_IMAGEID" ]] && echo "Glance upload failed!" && exit 1 - echo "IMAGE ID: $GLANCE_IMAGEID" exclaim "Updating Datastores" cmd_set_datastore "${GLANCE_IMAGEID}" "${DATASTORE_TYPE}" "${RESTART_TROVE}" @@ -1341,7 +1336,17 @@ function cmd_gate_tests() { TROVESTACK_DUMP_ENV=true # Devstack vm-gate runs as a non-ubuntu user, but needs to connect to the guest image as ubuntu - echo "User=ubuntu" >> $HOME/.ssh/config + export TROVE_TEST_SSH_USER='ubuntu' + export TROVE_TEST_SSH_KEY_FILE=$HOME/.ssh/id_rsa + + CLOUDINIT_PATH=/etc/trove/cloudinit/mysql.cloudinit + PUBKEY=`cat ${HOME}/.ssh/id_rsa.pub` + + sudo echo "#!/bin/sh" | sudo tee $CLOUDINIT_PATH + sudo echo "" | sudo tee -a $CLOUDINIT_PATH + sudo echo "echo '${PUBKEY}' > /home/ubuntu/.ssh/authorized_keys" | sudo tee -a $CLOUDINIT_PATH + sudo echo "chmod 700 /home/ubuntu/.ssh" | sudo tee -a $CLOUDINIT_PATH + sudo echo "chmod 600 /home/ubuntu/.ssh/authorized_keys" | sudo tee -a $CLOUDINIT_PATH # Fix iptables rules that prevent amqp connections from the devstack box to the guests sudo iptables -D openstack-INPUT -j REJECT --reject-with icmp-host-prohibited || true diff --git a/integration/scripts/trovestack.rc b/integration/scripts/trovestack.rc index a32aed54..921e6b26 100644 --- a/integration/scripts/trovestack.rc +++ b/integration/scripts/trovestack.rc @@ -102,6 +102,6 @@ SWIFT_DISK_IMAGE=${SWIFT_DATA_DIR}/drives/images/swift.img #export TROVE_MAX_VOLUMES_PER_TENANT=40 #export TROVE_AGENT_CALL_LOW_TIMEOUT=15 #export TROVE_AGENT_CALL_HIGH_TIMEOUT=300 -#export TROVE_RESIZE_TIME_OUT=900 +#export TROVE_RESIZE_TIME_OUT=3600 #export TROVE_USAGE_TIMEOUT=1500 #export TROVE_STATE_CHANGE_WAIT_TIME=180 diff --git a/trove/guestagent/datastore/mysql_common/service.py b/trove/guestagent/datastore/mysql_common/service.py index 28931b03..51976646 100644 --- a/trove/guestagent/datastore/mysql_common/service.py +++ b/trove/guestagent/datastore/mysql_common/service.py @@ -934,7 +934,7 @@ class BaseMySqlApp(object): LOG.info("Starting slave replication.") with self.local_sql_client(self.get_engine()) as client: client.execute('START SLAVE') - self._wait_for_slave_status("ON", client, 60) + self._wait_for_slave_status("ON", client, 180) def stop_slave(self, for_failover): replication_user = None @@ -944,7 +944,7 @@ class BaseMySqlApp(object): replication_user = result.first()['Master_User'] client.execute('STOP SLAVE') client.execute('RESET SLAVE ALL') - self._wait_for_slave_status("OFF", client, 30) + self._wait_for_slave_status("OFF", client, 180) if not for_failover: client.execute('DROP USER ' + replication_user) return { diff --git a/trove/tests/api/replication.py b/trove/tests/api/replication.py index 57b0662c..effbba5c 100644 --- a/trove/tests/api/replication.py +++ b/trove/tests/api/replication.py @@ -177,7 +177,7 @@ class VerifySlave(object): return find_database @test - @time_out(5 * 60) + @time_out(20 * 60) def test_correctly_started_replication(self): poll_until(slave_is_running()) -- cgit v1.2.1