Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for additional disc_formats #374

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ RUN apt-get update -y && \
libffi-dev \
openssl \
python-pip \
qemu-utils \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you check how much this affects the Docker image size?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure.. this is how it reads from docker image ls

kubenow/provisioners   master              8b17915e9767        2 days ago          1.09GB
kubenow/provisioners   0.3.2               dc845cc33fea        7 days ago          1.02GB

unzip && \
`# Add google cloud` \
echo "deb http://packages.cloud.google.com/apt cloud-sdk-xenial main" \
332 changes: 332 additions & 0 deletions bin/helpers/openstack.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
#!/usr/bin/env bash

function get_image_status() {
local image_name=$1
local image_id
local image_details
image_id=$(get_image_id "${image_name}")
image_details="$(glance image-show "${image_id}")"

printf '%s' "${image_details}" |
grep -w "status" |
awk -F "|" '{print $3;}' |
tr -d '[:space:]'
}

function get_image_id() {
local image_name=$1
local image_list
image_list="$(glance image-list)"

printf '%s' "${image_list}" |
grep -w "${image_name}" |
awk -F "|" '{print $2;}' |
tr -d '[:space:]'
}

function get_server_image_disc_format() {
local image_id=$1
local image_details
image_details="$(glance image-show "${image_id}")"

printf '%s' "${image_details}" |
grep -w "disk_format" |
awk -F "|" '{print $3;}' |
tr -d '[:space:]'
}

function image_exists() {
local image_name=$1
local image_id
image_id=$(get_image_id "${image_name}")

if [[ "${image_id}" != "" ]]; then
echo "true"
else
echo "false"
fi
}

function get_server_uploaded_image_checksum() {
local image_id=$1
local image_details
image_details="$(glance image-show "${image_id}")"

printf '%s' "${image_details}" |
grep -w "checksum" |
awk -F "|" '{print $3;}' |
tr -d '[:space:]'
}

function is_image_downloaded_already() {
local download_filepath=$1

if [[ -e ${download_filepath} ]]; then
echo "true"
else
echo "false"
fi
}

function is_uploaded_disc_format_as_expected() {
local image_name=$1
local glance_disc_format=$2
local image_id
image_id=$(get_image_id "${image_name}")
server_disc_format=$(get_server_image_disc_format "${image_id}")

if [[ "${server_disc_format}" == "${glance_disc_format}" ]]; then
echo "true"
else
echo "false"
fi
}

function is_image_already_uploaded() {
local image_name=$1
local glance_disc_format=$2
local image_id
image_id=$(get_image_id "${image_name}")

if [[ "${image_id}" == "" ]]; then
echo "false"
else
echo "true"
fi
}

function wait_for_image_activation() {
local image_name=$1;
local wait_time
local max_wait
local sleep_time
local status
wait_time=0
max_wait=300
sleep_time=3
status="nothing"

# Wait until image status is "active"
while [[ "${status}" != "active" && ${wait_time} -lt ${max_wait} ]]; do
# allow for image to be ready
sleep ${sleep_time}
wait_time=$((wait_time + sleep_time))
status=$(get_image_status "${image_name}")
done

echo "${status}"
}

function get_host_uploaded_image_checksum() {
local image_name=$1
local glance_disc_format=$2
local image_url=$3
local upload_filepath="/tmp/${image_name}.${glance_disc_format}"
local checksum

if [[ "${glance_disc_format}" == "qcow2" ]]; then
# Download the checksum of the qcow2 image from Kubenow servers
curl "${image_url}/${image_name}.md5" \
-o "${upload_filepath}.md5" \
--connect-timeout 30 \
--max-time 30

checksum=$(cut -f1 -d ' ' "${upload_filepath}.md5")
else
# Generate the md5 from the local file which is present on the local disc
checksum=$(md5sum "${upload_filepath}" | awk '{print $1}')
fi

echo "${checksum}"
}

function verify_uploaded_image() {
local image_name=$1
local glance_disc_format=$2
local image_url=$3
local image_list
local image_id
local image_details
local server_checksum
local host_checksum
image_id=$(get_image_id "${image_name}")
server_checksum=$(get_server_uploaded_image_checksum "${image_id}")

if [[ ${#server_checksum} != 32 ]]; then
echo "No valid server_checksum field on server, skipping checksum verification step"
else
host_checksum=$(get_host_uploaded_image_checksum "${image_name}" "${glance_disc_format}" "${image_url}")

if [ "${host_checksum}" != "${server_checksum}" ]; then
echo >&2 "Server checksum: ${server_checksum}"
echo >&2 "Expected checksum: ${host_checksum}"
echo >&2 "The server image checksum does not match expectations"
echo >&2 "Something might have failed on file transfer."
echo >&2 "Please delete image ${image_name} from Openstack and try again."
exit 1
else
echo "Uploaded image checksum is OK"
fi
fi
}

function upload_image() {
local image_name=$1
local glance_disc_format=$2
local image_url=$3
local upload_filepath="/tmp/${image_name}.${glance_disc_format}"
local min_disc=5
local image_size
local image_size_number
image_size=$(du -sh --block-size=G --apparent-size "${upload_filepath}" | awk '{print $1}')
image_size_number=${image_size::-1}

if [[ "${glance_disc_format}" == "raw" ]]; then
min_disc=${image_size_number};
fi

# Upload image
echo "Starting upload of ${image_name}"
echo -e "\n"
echo "image source: ${upload_filepath}"
echo "image name: ${image_name}"
echo "image format: ${glance_disc_format}"
echo "image size: ${image_size_number} GB"
echo -e "\n"
glance image-create \
--file "${upload_filepath}" \
--disk-format "${glance_disc_format}" \
--min-disk "${min_disc}" \
--container-format bare \
--name "${image_name}" \
--progress

echo "Verifying the uploaded image"
echo -e "\n"

post_image_upload_checks "${image_name}" "${glance_disc_format}" "${image_url}"
}

function verify_downloaded_image() {
local download_filename=$1
local download_url=$2
local download_filepath="/tmp/${download_filename}"

echo "Downloading ${download_url}/${download_filename}.md5 file"
curl "${download_url}/${download_filename}.md5" \
-o "${download_filepath}.md5" \
--connect-timeout 30 \
--max-time 30

# Verify md5sum of downloaded file
echo "Checking md5 sum"
md5result=$(
cd /tmp || exit;
md5sum -c "${download_filename}.md5"
)
if [[ "${md5result}" != *": OK"* ]]; then
echo >&2 "Wrong checksum of downloaded image."
echo >&2 "Something might have failed on file transfer."
echo >&2 "Please try again."
exit 1
else
echo "Checksum of downloaded image OK"
fi
}

function post_image_upload_checks() {
local image_name=$1
local glance_disc_format=$2
local image_url=$3
local is_uploaded_disc_format_as_expected
local image_id
image_id=$(get_image_id "${image_name}")
server_image_disc_format=$(get_server_image_disc_format "${image_id}")
is_uploaded_disc_format_as_expected=$(is_uploaded_disc_format_as_expected "${image_name}" "${glance_disc_format}")

# Verify the server image is in the expected glance_disc_format
if [[ "${is_uploaded_disc_format_as_expected}" == "false" ]]; then
echo >&2 "Host image disc format: ${glance_disc_format}"
echo >&2 "Server image disc format: ${server_image_disc_format}"
echo >&2 "${image_name} disc format on the server is not as expected"
echo >&2 "Delete the server image and retry the kn init process"
exit 1
fi

# Verify uploaded image checksums
verify_uploaded_image "${image_name}" "${glance_disc_format}" "${image_url}"
}

function download_image() {
local download_filename=$1
local download_url=$2
local download_filepath="/tmp/${download_filename}"

echo "Downloading image to local /tmp/"
echo -e "\n"
curl "${download_url}/${download_filename}" \
-o "${download_filepath}" \
--connect-timeout 30 \
--max-time 1800

echo "Verifying the md5 checksum of the downloaded image"
echo -e "\n"
verify_downloaded_image "${download_filename}" "${download_url}"
}

function maybe_download_image(){
local image_name=$1
local glance_disc_format=$2
local download_url=$3
local download_filename="${image_name}.qcow2"
local download_filepath="/tmp/${image_name}.qcow2"
local is_image_downloaded_already
is_image_downloaded_already=$(is_image_downloaded_already "${download_filepath}")

if [[ "${is_image_downloaded_already}" == "false" ]]; then
download_image "${download_filename}" "${download_url}"
else
echo "${download_filename} is already downloaded"
echo "Verifying the downloaded image checksum"
echo -e "\n"

verify_downloaded_image "${download_filename}" "${download_url}"
fi
}

function maybe_convert_image(){
local image_name=$1
local glance_disc_format=$2
local download_url=$3
local download_filename="${image_name}.qcow2"
local download_filepath="/tmp/${image_name}.qcow2"
local upload_filepath="/tmp/${image_name}.${glance_disc_format}"
local qemu_installed
local is_image_downloaded_already
is_image_downloaded_already=$(is_image_downloaded_already "${download_filepath}")
qemu_installed=$(which qemu-img)

if [[ ! -e ${upload_filepath} ]]; then
if [[ "${qemu_installed}" == "" ]]; then
echo >&2 "qemu-utils package is missing - image cannot be converted"
echo >&2 "Please ensure that qemu-img is available."
exit 1
else
if [[ "${is_image_downloaded_already}" == "false" ]]; then
echo >&2 "No file found at ${download_filepath}"
echo >&2 "Please ensure image has been downloaded"
exit 1
fi

echo "${download_filepath} has not yet been converted to the ${glance_disc_format} format"
echo "Starting the image conversion from qcow2 to ${glance_disc_format}..."
echo -e "\n"

qemu-img convert -q -f qcow2 -O "${glance_disc_format}" "${download_filepath}" "${upload_filepath}"

echo "${image_name}.qcow2 conversion to ${upload_filepath} complete"
fi
else
echo "${upload_filepath} already exists and so does not require conversion"
fi
}
155 changes: 36 additions & 119 deletions bin/image-create-openstack.sh
Original file line number Diff line number Diff line change
@@ -1,142 +1,59 @@
#!/usr/bin/env bash

# Checks and uploads specified Image to user's OpenStack account.
# Downloads image first from an Amazon S3 storage account to host,
# then uploads image to openstack teenancy.
# Uses curl and python-glanceclient to do the job.
#
# 1. Downloads image first from an Amazon S3 storage (using curl and python-glance client)
#
# 2. Converts the image to the required format (if needed)
#
# 3. Uploads image to openstack tenancy. (using curl and python-glance client)
#
#
#
# Env vars
#
# KN_IMAGE_NAME
# KN_DISC_FORMAT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid confusion with image format on image downloaded change "disk_format" to "glance_disk_format"

# KN_IMAGE_BUCKET_URL

#
# Exit immediately if a command exits with a non-zero status

set -e

# shellcheck disable=SC1091
source bin/helpers/openstack.sh
KN_IMAGE_BUCKET_URL=${KN_IMAGE_BUCKET_URL:-"https://s3.eu-central-1.amazonaws.com/kubenow-eu-central-1"}

echo "Started script image-create-openstack"

if [ -z "$KN_IMAGE_NAME" ]; then
if [ -z "${KN_IMAGE_NAME}" ]; then
echo >&2 "env KN_IMAGE_NAME must be set for this script to run"
exit 1
fi

KN_IMAGE_BUCKET_URL=${KN_IMAGE_BUCKET_URL:-"https://s3.eu-central-1.amazonaws.com/kubenow-eu-central-1"}
file_name="$KN_IMAGE_NAME.qcow2"

# Check if image is present already
echo "List images available in OpenStack..."
image_list="$(glance image-list)"
image_id="$(printf '%s' "$image_list" |
grep "\s$KN_IMAGE_NAME\s" |
awk -F "|" '{print $2;}' |
tr -d '[:space:]')"

# If it exist then exit here
if [ -n "$image_id" ]; then
echo "file exists - no need to upload, exit image-upload script"
exit 0
fi

# If it doesn't exist then download it
echo "Image not present in OpenStack"
echo "Downloading image to local /tmp/"
curl "$KN_IMAGE_BUCKET_URL/$file_name" \
-o "/tmp/$file_name" \
--connect-timeout 30 \
--max-time 1800

echo "Download md5 sum file"
curl "$KN_IMAGE_BUCKET_URL/$file_name.md5" \
-o "/tmp/$file_name.md5" \
--connect-timeout 30 \
--max-time 1800

# Verify md5sum of downloaded file
echo "Check md5 sum"
md5result=$(
cd /tmp
md5sum -c "$file_name.md5"
)
if [[ "$md5result" != *": OK"* ]]; then
echo >&2 "Wrong checksum of downloaded image."
echo >&2 "Something might have failed on file transfer."
echo >&2 "Please try again."
if [ -z "${KN_DISC_FORMAT}" ]; then
echo >&2 "env KN_DISC_FORMAT must be set for this script to run"
exit 1
else
echo "Checksum of downloaded image OK"
fi

# Upload image
echo "Uploading image"
glance image-create \
--file "/tmp/$file_name" \
--disk-format qcow2 \
--min-disk 20 \
--container-format bare \
--name "$KN_IMAGE_NAME" \
--progress

# Wait until image status is "active"
wait_time=0
max_wait=300
sleep_time=3
status="nothing"
echo "Wait until image status is active"
while [[ $status != "active" && $wait_time -lt $max_wait ]]; do
# allow for image to be ready
sleep $sleep_time
wait_time=$((wait_time + sleep_time))

# get image id from image-name
image_list="$(glance image-list)"
image_id="$(printf '%s' "$image_list" |
grep "\s$KN_IMAGE_NAME\s" |
awk -F "|" '{print $2;}' |
tr -d '[:space:]')"

# get status of image
image_details="$(glance image-show "$image_id")"
status="$(printf '%s' "$image_details" |
grep -w "status" |
awk -F "|" '{print $3;}' |
tr -d '[:space:]')"
done

# Verify md5 of uploaded image
echo "Verify md5 of present/uploaded image..."
echo "List images available in OpenStack..."
image_list="$(glance image-list)"
image_id="$(printf '%s' "$image_list" |
grep "\s$KN_IMAGE_NAME\s" |
awk -F "|" '{print $2;}' |
tr -d '[:space:]')"
function init() {
local image_name=$1
local glance_disc_format=$2
local bucket_url=$3
local is_image_previously_uploaded

# If the image exists, return true, otherwise return false
is_image_previously_uploaded=$(is_image_already_uploaded "${image_name}" "${glance_disc_format}")
if [[ "${is_image_previously_uploaded}" == "false" ]]; then
maybe_download_image "${image_name}" "${glance_disc_format}" "${bucket_url}"
maybe_convert_image "${image_name}" "${glance_disc_format}" "${bucket_url}"
upload_image "${image_name}" "${glance_disc_format}" "${bucket_url}"
else
echo "${image_name}.${glance_disc_format} is already present - no need to upload"
fi
}

# Get checksum of uploaded file
image_details="$(glance image-show "$image_id")"
checksum="$(printf '%s' "$image_details" |
grep -w "checksum" |
awk -F "|" '{print $3;}' |
tr -d '[:space:]')"
init "${KN_IMAGE_NAME}" "${KN_DISC_FORMAT}" "${KN_IMAGE_BUCKET_URL}"

# Only verify checksum if there is one on server (a 32 char value in the checksum field)
if [[ ${#checksum} != 32 ]]; then
echo "No valid checksum field on server, skipping checksum verification"
else
# Get checksum of bucket image
echo "Download md5 sum file :-)"
curl "$KN_IMAGE_BUCKET_URL/$file_name.md5" \
-o "/tmp/$file_name.md5" \
--connect-timeout 30 \
--max-time 1800

md5only=$(cut -f1 -d ' ' "/tmp/$file_name.md5")
if [ "$md5only" != "$checksum" ]; then
echo >&2 "Wrong checksum of present/uploaded image."
echo >&2 "Something might have failed on file transfer."
echo >&2 "Please delete image $KN_IMAGE_NAME from Openstack and try again."
exit 1
else
echo "Checksum OK"
fi
fi

echo "Image upload done"
5 changes: 5 additions & 0 deletions bin/kn-apply
Original file line number Diff line number Diff line change
@@ -11,6 +11,10 @@ host_cloud=$(jq -r '.provider' <<<"$kn_config")
image_name=$(jq -r '.boot_image' <<<"$kn_config")
skip_image_import=$(jq -r '.skip_image_import' <<<"$kn_config")

disc_format=$(grep -w "disc_format" config.tfvars |
cut -d "=" -f 2- |
awk -F\" '{print $(NF-1)}')

# Check for recognized cloud provider
if ! grep -qw "$host_cloud" <<<"openstack gce azure aws"; then
echo >&2 "Error: unrecognized host cloud '$host_cloud' in config file config.tfvars"
@@ -22,6 +26,7 @@ if [[ "$skip_image_import" != "true" ]] && [[ "$host_cloud" != 'aws' ]]; then
export KN_GCE_ACCOUNT_FILE_PATH="$PWD/service-account.json"
export TF_VARS_FILE="$PWD/config.tfvars"
export KN_IMAGE_NAME="$image_name"
export KN_DISC_FORMAT="$disc_format"
/KubeNow_root/bin/image-create-"$host_cloud".sh
fi

1 change: 1 addition & 0 deletions templates/config.tfvars.openstack-template
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ kubeadm_token = "your-kubeadm-token" # Autogenerated kubeadm token
floating_ip_pool = "your-pool-name"
external_network_uuid = "external-net-uuid" # The uuid of the external network in the OpenStack tenancy
boot_image = "kubenow-v051"
disc_format = "qcow2"

# Master configuration
# obs: too small flavors might cause diffuse errors on your installation