test/api.sh: verify VMDK images from S3 in VSphere
Extend the `api.sh` test to verify the VMDK images uploaded to S3 in VSphere by booting them and configuring using cloud-init. Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
parent
c6507c21b9
commit
27c260daaf
1 changed files with 272 additions and 2 deletions
|
|
@ -168,9 +168,14 @@ function checkEnvSubscription() {
|
|||
printenv API_TEST_SUBSCRIPTION_ORG_ID API_TEST_SUBSCRIPTION_ACTIVATION_KEY > /dev/null
|
||||
}
|
||||
|
||||
function checkEnvVSphere() {
|
||||
printenv GOVMOMI_USERNAME GOVMOMI_PASSWORD GOVMOMI_URL GOVMOMI_CLUSTER GOVC_DATACENTER GOVMOMI_DATASTORE GOVMOMI_FOLDER GOVMOMI_NETWORK > /dev/null
|
||||
}
|
||||
|
||||
case $CLOUD_PROVIDER in
|
||||
"$CLOUD_PROVIDER_AWS" | "$CLOUD_PROVIDER_AWS_S3")
|
||||
checkEnvAWS
|
||||
[[ "${IMAGE_TYPE}" == "${IMAGE_TYPE_VSPHERE}" ]] && checkEnvVSphere
|
||||
;;
|
||||
"$CLOUD_PROVIDER_GCP")
|
||||
checkEnvGCP
|
||||
|
|
@ -270,6 +275,37 @@ function cleanupAzure() {
|
|||
fi
|
||||
}
|
||||
|
||||
function cleanupVSphere() {
|
||||
# since this function can be called at any time, ensure that we don't expand unbound variables
|
||||
GOVC_CMD="${GOVC_CMD:-}"
|
||||
VSPHERE_VM_NAME="${VSPHERE_VM_NAME:-}"
|
||||
VSPHERE_CIDATA_ISO_PATH="${VSPHERE_CIDATA_ISO_PATH:-}"
|
||||
|
||||
greenprint "🧹 Cleaning up the VSphere VM"
|
||||
$GOVC_CMD vm.destroy \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
"${VSPHERE_VM_NAME}"
|
||||
|
||||
greenprint "🧹 Cleaning up the VSphere Datastore"
|
||||
$GOVC_CMD datastore.rm \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
-ds="${GOVMOMI_DATASTORE}" \
|
||||
-f \
|
||||
"${VSPHERE_CIDATA_ISO_PATH}"
|
||||
|
||||
$GOVC_CMD datastore.rm \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
-ds="${GOVMOMI_DATASTORE}" \
|
||||
-f \
|
||||
"${VSPHERE_VM_NAME}"
|
||||
}
|
||||
|
||||
function dump_db() {
|
||||
# Disable -x for these commands to avoid printing the whole result and manifest into the log
|
||||
set +x
|
||||
|
|
@ -293,6 +329,7 @@ function cleanup() {
|
|||
;;
|
||||
"$CLOUD_PROVIDER_AWS_S3")
|
||||
cleanupAWSS3
|
||||
[[ "${IMAGE_TYPE}" == "${IMAGE_TYPE_VSPHERE}" ]] && cleanupVSphere
|
||||
;;
|
||||
"$CLOUD_PROVIDER_GCP")
|
||||
cleanupGCP
|
||||
|
|
@ -414,9 +451,28 @@ function installClientAzure() {
|
|||
$AZURE_CMD version
|
||||
}
|
||||
|
||||
function installClientVSphere() {
|
||||
if ! hash govc; then
|
||||
greenprint "Installing govc"
|
||||
pushd "${WORKDIR}"
|
||||
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
|
||||
GOVC_CMD="${WORKDIR}/govc"
|
||||
chmod +x "${GOVC_CMD}"
|
||||
popd
|
||||
else
|
||||
echo "Using pre-installed 'govc' from the system"
|
||||
GOVC_CMD="govc"
|
||||
fi
|
||||
|
||||
$GOVC_CMD version
|
||||
}
|
||||
|
||||
case $CLOUD_PROVIDER in
|
||||
"$CLOUD_PROVIDER_AWS" | "$CLOUD_PROVIDER_AWS_S3")
|
||||
installClientAWS
|
||||
[[ "${IMAGE_TYPE}" == "${IMAGE_TYPE_VSPHERE}" ]] && installClientVSphere
|
||||
;;
|
||||
"$CLOUD_PROVIDER_GCP")
|
||||
installClientGCP
|
||||
|
|
@ -589,6 +645,35 @@ function createReqFileAWSS3() {
|
|||
EOF
|
||||
}
|
||||
|
||||
# the VSphere test case does not create any additional users,
|
||||
# since this is not supported by the service UI
|
||||
function createReqFileAWSS3VSphere() {
|
||||
cat > "$REQUEST_FILE" << EOF
|
||||
{
|
||||
"distribution": "$DISTRO",
|
||||
"customizations": {
|
||||
"payload_repositories": [
|
||||
{
|
||||
"baseurl": "$PAYLOAD_REPO_URL"
|
||||
}
|
||||
],
|
||||
"packages": [
|
||||
"postgresql",
|
||||
"dummy"
|
||||
]${SUBSCRIPTION_BLOCK}
|
||||
},
|
||||
"image_request": {
|
||||
"architecture": "$ARCH",
|
||||
"image_type": "${IMAGE_TYPE}",
|
||||
"repositories": $(jq ".\"$ARCH\"" /usr/share/tests/osbuild-composer/repositories/"$DISTRO".json),
|
||||
"upload_options": {
|
||||
"region": "${AWS_REGION}"
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
function createReqFileGCP() {
|
||||
# constrains for GCP resource IDs:
|
||||
# - max 62 characters
|
||||
|
|
@ -678,7 +763,11 @@ case $CLOUD_PROVIDER in
|
|||
createReqFileAWS
|
||||
;;
|
||||
"$CLOUD_PROVIDER_AWS_S3")
|
||||
createReqFileAWSS3
|
||||
if [[ "${IMAGE_TYPE}" == "${IMAGE_TYPE_VSPHERE}" ]]; then
|
||||
createReqFileAWSS3VSphere
|
||||
else
|
||||
createReqFileAWSS3
|
||||
fi
|
||||
;;
|
||||
"$CLOUD_PROVIDER_GCP")
|
||||
createReqFileGCP
|
||||
|
|
@ -897,6 +986,84 @@ function _instanceCheck() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Create a cloud-int user-data file
|
||||
#
|
||||
# Returns:
|
||||
# - path to the user-data file
|
||||
#
|
||||
# Arguments:
|
||||
# $1 - default username
|
||||
# $2 - path to the SSH public key to set as authorized for the user
|
||||
function _createCIUserdata() {
|
||||
local _user="$1"
|
||||
local _ssh_pubkey_path="$2"
|
||||
|
||||
local _ci_userdata_dir
|
||||
_ci_userdata_dir="$(mktemp -d -p "${WORKDIR}")"
|
||||
local _ci_userdata_path="${_ci_userdata_dir}/user-data"
|
||||
|
||||
cat > "${_ci_userdata_path}" <<EOF
|
||||
#cloud-config
|
||||
users:
|
||||
- name: "${_user}"
|
||||
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
||||
ssh_authorized_keys:
|
||||
- "$(cat "${_ssh_pubkey_path}")"
|
||||
EOF
|
||||
|
||||
echo "${_ci_userdata_path}"
|
||||
}
|
||||
|
||||
# Create a cloud-int meta-data file
|
||||
#
|
||||
# Returns:
|
||||
# - path to the meta-data file
|
||||
#
|
||||
# Arguments:
|
||||
# $1 - VM name
|
||||
function _createCIMetadata() {
|
||||
local _vm_name="$1"
|
||||
|
||||
local _ci_metadata_dir
|
||||
_ci_metadata_dir="$(mktemp -d -p "${WORKDIR}")"
|
||||
local _ci_metadata_path="${_ci_metadata_dir}/meta-data"
|
||||
|
||||
cat > "${_ci_metadata_path}" <<EOF
|
||||
instance-id: ${_vm_name}
|
||||
local-hostname: ${_vm_name}
|
||||
EOF
|
||||
|
||||
echo "${_ci_metadata_path}"
|
||||
}
|
||||
|
||||
# Create an ISO with the provided cloud-init user-data file
|
||||
#
|
||||
# Returns:
|
||||
# - path to the created ISO file
|
||||
#
|
||||
# Arguments:
|
||||
# $1 - path to the cloud-init user-data file
|
||||
# $2 - path to the cloud-init meta-data file
|
||||
function _createCIUserdataISO() {
|
||||
local _ci_userdata_path="$1"
|
||||
local _ci_metadata_path="$2"
|
||||
|
||||
local _iso_path
|
||||
_iso_path="$(mktemp -p "${WORKDIR}" --suffix .iso)"
|
||||
mkisofs \
|
||||
-input-charset "utf-8" \
|
||||
-output "${_iso_path}" \
|
||||
-volid "cidata" \
|
||||
-joliet \
|
||||
-rock \
|
||||
-quiet \
|
||||
-graft-points \
|
||||
"${_ci_userdata_path}" \
|
||||
"${_ci_metadata_path}"
|
||||
|
||||
echo "${_iso_path}"
|
||||
}
|
||||
|
||||
# Verify image in EC2 on AWS
|
||||
function verifyInAWS() {
|
||||
$AWS_CMD ec2 describe-images \
|
||||
|
|
@ -1039,6 +1206,109 @@ function verifyDisk() {
|
|||
greenprint "✅ ${filename} image info verified"
|
||||
}
|
||||
|
||||
# Verify VMDK image in VSphere
|
||||
function verifyInVSphere() {
|
||||
local _filename="$1"
|
||||
greenprint "Verifying VMDK image: ${_filename}"
|
||||
|
||||
# Create SSH keys to use
|
||||
local _vsphere_ssh_key="${WORKDIR}/vsphere_ssh_key"
|
||||
ssh-keygen -t rsa-sha2-512 -f "${_vsphere_ssh_key}" -C "${SSH_USER}" -N ""
|
||||
|
||||
VSPHERE_VM_NAME="osbuild-composer-vm-${TEST_ID}"
|
||||
|
||||
# create cloud-init ISO with the configuration
|
||||
local _ci_userdata_path
|
||||
_ci_userdata_path="$(_createCIUserdata "${SSH_USER}" "${_vsphere_ssh_key}.pub")"
|
||||
local _ci_metadata_path
|
||||
_ci_metadata_path="$(_createCIMetadata "${VSPHERE_VM_NAME}")"
|
||||
greenprint "💿 Creating cloud-init user-data ISO"
|
||||
local _ci_iso_path
|
||||
_ci_iso_path="$(_createCIUserdataISO "${_ci_userdata_path}" "${_ci_metadata_path}")"
|
||||
|
||||
VSPHERE_IMAGE_NAME="${VSPHERE_VM_NAME}.vmdk"
|
||||
|
||||
# import the built VMDK image to VSphere
|
||||
# import.vmdk seems to be creating the provided directory and
|
||||
# if one with this name exists, it appends "_<number>" to the name
|
||||
greenprint "🚧 Converting the downloaded VMDK image to be streamOptimized"
|
||||
qemu-img convert -O vmdk -o subformat=streamOptimized "${_filename}" "${WORKDIR}/${VSPHERE_IMAGE_NAME}"
|
||||
greenprint "💿 ⬆️ Importing the converted VMDK image to VSphere"
|
||||
$GOVC_CMD import.vmdk \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
-ds="${GOVMOMI_DATASTORE}" \
|
||||
"${WORKDIR}/${VSPHERE_IMAGE_NAME}" \
|
||||
"${VSPHERE_VM_NAME}"
|
||||
|
||||
# create the VM, but don't start it
|
||||
greenprint "🖥️ Creating VM in VSphere"
|
||||
$GOVC_CMD vm.create \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
-pool="${GOVMOMI_CLUSTER}"/Resources \
|
||||
-ds="${GOVMOMI_DATASTORE}" \
|
||||
-folder="${GOVMOMI_FOLDER}" \
|
||||
-net="${GOVMOMI_NETWORK}" \
|
||||
-net.adapter=vmxnet3 \
|
||||
-m=4096 -c=2 -g=rhel8_64Guest -on=true -firmware=bios \
|
||||
-disk="${VSPHERE_VM_NAME}/${VSPHERE_IMAGE_NAME}" \
|
||||
-disk.controller=ide \
|
||||
-on=false \
|
||||
"${VSPHERE_VM_NAME}"
|
||||
|
||||
# upload ISO, create CDROM device and insert the ISO in it
|
||||
greenprint "💿 ⬆️ Uploading the cloud-init user-data ISO to VSphere"
|
||||
VSPHERE_CIDATA_ISO_PATH="${VSPHERE_VM_NAME}/cidata.iso"
|
||||
$GOVC_CMD datastore.upload \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
-ds="${GOVMOMI_DATASTORE}" \
|
||||
"${_ci_iso_path}" \
|
||||
"${VSPHERE_CIDATA_ISO_PATH}"
|
||||
|
||||
local _cdrom_device
|
||||
greenprint "🖥️ + 💿 Adding a CD-ROM device to the VM"
|
||||
_cdrom_device="$($GOVC_CMD device.cdrom.add \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
-vm "${VSPHERE_VM_NAME}")"
|
||||
|
||||
greenprint "💿 Inserting the cloud-init ISO into the CD-ROM device"
|
||||
$GOVC_CMD device.cdrom.insert \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
-ds="${GOVMOMI_DATASTORE}" \
|
||||
-vm "${VSPHERE_VM_NAME}" \
|
||||
-device "${_cdrom_device}" \
|
||||
"${VSPHERE_CIDATA_ISO_PATH}"
|
||||
|
||||
# start the VM
|
||||
greenprint "🔌 Powering up the VSphere VM"
|
||||
$GOVC_CMD vm.power \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
-on "${VSPHERE_VM_NAME}"
|
||||
|
||||
HOST=$($GOVC_CMD vm.ip \
|
||||
-u "${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}" \
|
||||
-k=true \
|
||||
-dc="${GOVC_DATACENTER}" \
|
||||
"${VSPHERE_VM_NAME}")
|
||||
greenprint "⏱ Waiting for the VSphere VM to respond to ssh"
|
||||
_instanceWaitSSH "${HOST}"
|
||||
|
||||
_ssh="ssh -oStrictHostKeyChecking=no -i ${_vsphere_ssh_key} $SSH_USER@$HOST"
|
||||
_instanceCheck "${_ssh}"
|
||||
|
||||
greenprint "✅ Successfully verified VSphere image with cloud-init"
|
||||
}
|
||||
|
||||
# Verify s3 blobs
|
||||
function verifyInAWSS3() {
|
||||
|
|
@ -1071,7 +1341,7 @@ function verifyInAWSS3() {
|
|||
|
||||
"${IMAGE_TYPE_VSPHERE}")
|
||||
curl "${S3_URL}" --output "${WORKDIR}/disk.vmdk"
|
||||
verifyDisk "${WORKDIR}/disk.vmdk"
|
||||
verifyInVSphere "${WORKDIR}/disk.vmdk"
|
||||
;;
|
||||
*)
|
||||
greenprint "No validation method for image type ${IMAGE_TYPE}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue