#!/bin/bash # # Test osbuild-composer 'upload to vmware' functionality. To do so, create and # push a blueprint with composer cli. Then, create an instance in vSphere # from the uploaded image. Finally, verify that the instance is running and # cloud init ran. # set -euo pipefail source /usr/libexec/osbuild-composer-test/set-env-variables.sh source /usr/libexec/tests/osbuild-composer/shared_lib.sh IMAGE_TYPE="$1" if ! nvrGreaterOrEqual "osbuild-composer" "84" && [ "$IMAGE_TYPE" == "ova" ]; then greenprint "Skipping ova test on older osbuild-composer" exit 0 fi # Provision the software under test. /usr/libexec/osbuild-composer-test/provision.sh none GOVC_CMD=/tmp/govc # Note: in GitLab CI the GOVMOMI_ variables are defined one-by-one # instead of sourcing them from a file! VCENTER_CREDS="${VCENTER_CREDS:-}" if [ -n "$VCENTER_CREDS" ]; then # shellcheck source=/dev/null source "$VCENTER_CREDS" fi # We need govc to talk to vSphere if ! hash govc; then greenprint "Installing govc" pushd /tmp curl -Ls --retry 5 --output govc.gz \ https://github.com/vmware/govmomi/releases/download/v0.24.0/govc_linux_amd64.gz gunzip -f govc.gz chmod +x /tmp/govc $GOVC_CMD version popd fi # Generate a string, which can be used as a predictable resource name, # which helps identify issues and link lefotever resources to PRs CI="${CI:-false}" if [[ "$CI" == true ]]; then TEST_ID="$DISTRO_CODE-$ARCH-$CI_COMMIT_BRANCH-$CI_JOB_ID" else TEST_ID=$(uuidgen); fi IMAGE_KEY=osbuild-composer-vmware-test-${TEST_ID} ARTIFACTS="${ARTIFACTS:-/tmp/artifacts}" # Set up temporary files TEMPDIR=$(mktemp -d) VMWARE_CONFIG=${TEMPDIR}/vmware.toml BLUEPRINT_FILE=${TEMPDIR}/blueprint.toml COMPOSE_START=${TEMPDIR}/compose-start-${IMAGE_KEY}.json COMPOSE_INFO=${TEMPDIR}/compose-info-${IMAGE_KEY}.json SSH_DATA_DIR=$(/usr/libexec/osbuild-composer-test/gen-ssh.sh) SSH_KEY=${SSH_DATA_DIR}/id_rsa SSH_KEY_PUB=$(cat "$SSH_KEY".pub) # destroy VMs function cleanup() { set +eu greenprint "๐Ÿงผ Cleaning up" # kill dangling journalctl processes to prevent GitLab CI from hanging sudo pkill journalctl || echo "Nothing killed" $GOVC_CMD vm.destroy -u "${VC8_GOVMOMI_USERNAME}":"${VC8_GOVMOMI_PASSWORD}"@"${VC8_GOVMOMI_URL}" -k=true "${IMAGE_KEY}" set -eu } trap cleanup EXIT # Check that the system started and is running correctly running_test_check () { STATUS=$(sudo ssh -i "${SSH_KEY}" redhat@"${1}" 'systemctl --wait is-system-running') if [[ $STATUS == running || $STATUS == degraded ]]; then echo 0 else echo 1 fi } # Get the compose log. get_compose_log () { COMPOSE_ID=$1 LOG_FILE=${ARTIFACTS}/osbuild-${ID}-${VERSION_ID}-vmware.log # Download the logs. sudo composer-cli compose log "$COMPOSE_ID" | tee "$LOG_FILE" > /dev/null } # Get the compose metadata. get_compose_metadata () { COMPOSE_ID=$1 METADATA_FILE=${ARTIFACTS}/osbuild-${ID}-${VERSION_ID}-vmware.json # Download the metadata. sudo composer-cli compose metadata "$COMPOSE_ID" > /dev/null # Find the tarball and extract it. TARBALL=$(basename "$(find . -maxdepth 1 -type f -name "*-metadata.tar")") sudo tar -xf "$TARBALL" sudo rm -f "$TARBALL" # Move the JSON file into place. sudo cat "${COMPOSE_ID}".json | jq -M '.' | tee "$METADATA_FILE" > /dev/null } # Write an VMWare TOML file tee "$VMWARE_CONFIG" > /dev/null << EOF provider = "vmware" [settings] host = "${VC8_GOVMOMI_URL}" username = "${VC8_GOVMOMI_USERNAME}" password = "${VC8_GOVMOMI_PASSWORD}" cluster = "${VC8_GOVMOMI_CLUSTER}" dataStore = "${VC8_GOVMOMI_DATASTORE}" dataCenter = "${VC8_GOVMOMI_DATACENTER}" folder = "${VC8_GOVMOMI_FOLDER}" EOF # Write a basic blueprint for our image. tee "$BLUEPRINT_FILE" > /dev/null << EOF name = "bash" description = "A base system with bash" version = "0.0.1" [[packages]] name = "bash" # Related RHBZ#2065734 [[packages]] name = "ipa-client" version = "*" [customizations.services] enabled = ["sshd"] [[customizations.user]] name = "redhat" key = "${SSH_KEY_PUB}" EOF # Prepare the blueprint for the compose. greenprint "๐Ÿ“‹ Preparing blueprint" sudo composer-cli blueprints push "$BLUEPRINT_FILE" sudo composer-cli blueprints depsolve bash # Get worker unit file so we can watch the journal. WORKER_UNIT=$(sudo systemctl list-units | grep -o -E "osbuild.*worker.*\.service") sudo journalctl -af -n 1 -u "${WORKER_UNIT}" & WORKER_JOURNAL_PID=$! # Start the compose and upload to VMWare. greenprint "๐Ÿš€ Starting compose" sudo composer-cli --json compose start bash "$IMAGE_TYPE" "$IMAGE_KEY" "$VMWARE_CONFIG" | tee "$COMPOSE_START" COMPOSE_ID=$(get_build_info ".build_id" "$COMPOSE_START") # Wait for the compose to finish. greenprint "โฑ Waiting for compose to finish: ${COMPOSE_ID}" while true; do sudo composer-cli --json compose info "${COMPOSE_ID}" | tee "$COMPOSE_INFO" > /dev/null COMPOSE_STATUS=$(get_build_info ".queue_status" "$COMPOSE_INFO") # Is the compose finished? if [[ $COMPOSE_STATUS != RUNNING ]] && [[ $COMPOSE_STATUS != WAITING ]]; then break fi # Wait 30 seconds and try again. sleep 30 done # Capture the compose logs from osbuild. greenprint "๐Ÿ’ฌ Getting compose log and metadata" get_compose_log "$COMPOSE_ID" get_compose_metadata "$COMPOSE_ID" # Kill the journal monitor sudo pkill -P ${WORKER_JOURNAL_PID} # Did the compose finish with success? if [[ $COMPOSE_STATUS != FINISHED ]]; then echo "Something went wrong with the compose. ๐Ÿ˜ข" exit 1 fi if [ "$IMAGE_TYPE" = "vmdk" ]; then greenprint "๐Ÿ‘ท๐Ÿป Building VM in vSphere" $GOVC_CMD vm.create -u "${VC8_GOVMOMI_USERNAME}":"${VC8_GOVMOMI_PASSWORD}"@"${VC8_GOVMOMI_URL}" \ -k=true \ -pool="${VC8_GOVMOMI_CLUSTER}"/Resources \ -dc="${VC8_GOVMOMI_DATACENTER}" \ -ds="${VC8_GOVMOMI_DATASTORE}" \ -folder="${VC8_GOVMOMI_FOLDER}" \ -net="${VC8_GOVMOMI_NETWORK}" \ -net.adapter=vmxnet3 \ -m=4096 -c=2 -g=rhel8_64Guest -on=true -firmware=efi \ -disk="${IMAGE_KEY}"/"${IMAGE_KEY}".vmdk \ --disk.controller=scsi \ "${IMAGE_KEY}" elif [ "$IMAGE_TYPE" = "ova" ]; then greenprint "๐Ÿ‘ท๐Ÿป Modifying network of the VM in vSphere" $GOVC_CMD vm.network.add -u "${VC8_GOVMOMI_USERNAME}":"${VC8_GOVMOMI_PASSWORD}"@"${VC8_GOVMOMI_URL}" \ -k=true \ -net="${VC8_GOVMOMI_NETWORK}" \ -net.adapter=vmxnet3 \ -vm="${IMAGE_KEY}" \ -net="${VC8_GOVMOMI_NETWORK}" # start the vm greenprint "๐Ÿ‘ท๐Ÿป Powering on the VM" $GOVC_CMD vm.power -u "${VC8_GOVMOMI_USERNAME}":"${VC8_GOVMOMI_PASSWORD}"@"${VC8_GOVMOMI_URL}" \ -k=true \ -wait=true \ -on \ "${IMAGE_KEY}" fi # tagging vm as testing object $GOVC_CMD tags.attach -u "${VC8_GOVMOMI_USERNAME}":"${VC8_GOVMOMI_PASSWORD}"@"${VC8_GOVMOMI_URL}" \ -k=true \ -c "osbuild-composer testing" gitlab-ci-test \ "/${VC8_GOVMOMI_DATACENTER}/vm/${VC8_GOVMOMI_FOLDER}/${IMAGE_KEY}" greenprint "Getting IP of created VM" VM_IP=$($GOVC_CMD vm.ip -u "${VC8_GOVMOMI_USERNAME}":"${VC8_GOVMOMI_PASSWORD}"@"${VC8_GOVMOMI_URL}" -k=true -v4=true "${IMAGE_KEY}") # Wait for the node to come online. greenprint "โฑ Waiting for VM to respond to ssh" LOOP_COUNTER=1 while [ $LOOP_COUNTER -le 30 ]; do if ssh-keyscan "$VM_IP" > /dev/null 2>&1; then echo "SSH is up!" ssh-keyscan "$VM_IP" | sudo tee -a /root/.ssh/known_hosts break fi # ssh-keyscan has a 5 second timeout by default, so the pause per loop # is 10 seconds when you include the following `sleep`. echo "Retrying in 5 seconds..." sleep 5 ((LOOP_COUNTER++)) done greenprint "๐Ÿ›ƒ Checking that system is running" for LOOP_COUNTER in {0..10}; do RESULT="$(running_test_check "$VM_IP")" if [[ $RESULT == 0 ]]; then echo "System is running! ๐Ÿฅณ" greenprint "๐Ÿ’š Success" exit 0 fi sleep 5 done greenprint "โŒ Failure" exit 1