From 41aa818f0c635473f8be531a49cc60d0c4d694d8 Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Mon, 7 Aug 2017 17:32:51 -0700 Subject: [PATCH 1/3] oem/oracle: Add some scripts to manage images/instances --- oem/oracle/common.sh | 40 +++++++++++++ oem/oracle/get-console-output | 35 ++++++++++++ oem/oracle/launch-instance | 105 ++++++++++++++++++++++++++++++++++ oem/oracle/upload-image | 74 ++++++++++++++++++++++++ 4 files changed, 254 insertions(+) create mode 100644 oem/oracle/common.sh create mode 100755 oem/oracle/get-console-output create mode 100755 oem/oracle/launch-instance create mode 100755 oem/oracle/upload-image diff --git a/oem/oracle/common.sh b/oem/oracle/common.sh new file mode 100644 index 0000000000..36c4a6a16a --- /dev/null +++ b/oem/oracle/common.sh @@ -0,0 +1,40 @@ +# Get the tenancy ID, which is also the ID of the root compartment. +# Unconditionally uses the first profile in the conffile. +get_tenancy_id() { + local line=$(grep -m 1 "^tenancy=" "$HOME/.oraclebmc/config") + echo "${line#*=}" +} + +# Pick an availability domain by listing them and choosing the first one. +get_availability_domain() { + local compartment="$1" + bmcs iam availability-domain list \ + -c "${compartment}" | jq -r ".data[0].name" +} + +# Pick a subnet ID by picking the first VCN and then the first subnet in the +# specified availability domain. +get_subnet_id() { + local compartment="$1" + local availability_domain="$2" + local vcn=$(bmcs network vcn list \ + -c "${compartment}" | jq -r ".data[0].id") + bmcs network subnet list \ + -c "${compartment}" \ + --vcn-id "${vcn}" | jq -r ".data[] | select(.[\"availability-domain\"] == \"${availability_domain}\").id" +} + +# Get the object storage namespace ID. +get_namespace_id() { + bmcs os ns get | jq -r ".data" +} + +# Get the ID of some arbitrary image. Useful for iPXE boot, which requires +# an image ID but doesn't seem to use it. +get_an_image_id() { + local compartment="$1" + bmcs compute image list \ + -c "${compartment}" \ + --operating-system "CentOS" \ + --operating-system-version 7 | jq -r '.data[0].id' +} diff --git a/oem/oracle/get-console-output b/oem/oracle/get-console-output new file mode 100755 index 0000000000..c18ffccf0b --- /dev/null +++ b/oem/oracle/get-console-output @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e -o pipefail + +# Parse args +usage="Usage: $0 [args] -i instance-id +Options: + -i INSTANCE-ID Instance ID + -h This ;-) +" +while getopts "i:h" OPTION +do + case "${OPTION}" in + i) instance_id="${OPTARG}" ;; + h) echo "${usage}"; exit 2 ;; + *) exit 2 ;; + esac +done + +if [[ -z "${instance_id}" ]]; then + echo "Instance ID is required." >&2 + exit 2 +fi + +id=$(bmcs compute console-history capture --instance-id "${instance_id}" | jq -r .data.id) +trap 'bmcs compute console-history delete --instance-console-history-id "${id}" --force' EXIT +while true; do + state=$(bmcs compute console-history get --instance-console-history-id "${id}" | jq -r '.data["lifecycle-state"]') + if [[ "${state}" = SUCCEEDED ]]; then + break + fi + sleep 1 +done +# Default length is 10 KB; maximum is 1 MB. Request at least that much. +bmcs compute console-history get-content --instance-console-history-id "${id}" --file - --length 2000000 diff --git a/oem/oracle/launch-instance b/oem/oracle/launch-instance new file mode 100755 index 0000000000..23a6290d72 --- /dev/null +++ b/oem/oracle/launch-instance @@ -0,0 +1,105 @@ +#!/bin/bash + +set -e -o pipefail + +. common.sh + +# Initialize vars +compartment=$(get_tenancy_id) +availability_domain=$(get_availability_domain "${compartment}") +image_id=$(get_an_image_id "${compartment}") +subnet_id=$(get_subnet_id "${compartment}" "${availability_domain}") +name= +shape="BM.Standard1.36" +ipxe=0 +ignition= +baseurl="http://alpha.release.core-os.net/amd64-usr/current" +bucket_base="users.developer.core-os.net/$USER/bmcs" + +# Parse args +usage="Usage: $0 [args] -n name +Options: + -c COMPARTMENT Compartment ID (default: ${compartment}) + -a AVAIL-DOMAIN Availability domain ID (default: ${availability_domain}) + -n NAME Instance name + -s SHAPE Instance shape (default: ${shape}) + -S SUBNET-ID Subnet ID to use (default: ${subnet_id}) + -i IGNITION Path to Ignition config + -p Boot with iPXE + -I IMAGE-ID Image ID to use; only relevant for non-iPXE (default: ${image_id}) + -b BASEURL URL to the image mirror; only relevant for iPXE (default: ${baseurl}) + -B BUCKET-BASE GS bucket and relative path for iPXE script (default: ${bucket_base}) + -h This ;-) +" +while getopts "c:a:n:s:S:i:pI:b:B:h" OPTION +do + case "${OPTION}" in + c) compartment="${OPTARG}" ;; + a) availability_domain="${OPTARG}" ;; + n) name="${OPTARG}" ;; + s) shape="${OPTARG}" ;; + S) subnet_id="${OPTARG}" ;; + i) ignition="${OPTARG}" ;; + p) ipxe=1 ;; + I) image_id="${OPTARG}" ;; + b) baseurl="${OPTARG}" ;; + B) bucket_base="${OPTARG}" ;; + h) echo "${usage}"; exit 2 ;; + *) exit 2 ;; + esac +done + +if [[ -z "${name}" ]]; then + echo "Instance name is required." >&2 + exit 2 +fi + +launch_args=() + +if [[ "${ipxe}" = 1 ]]; then + # Make scratch dir + tmpdir=$(mktemp -d bmcs-XXXXXX) + trap "rm -rf '${tmpdir}'" EXIT + + if [[ -n "${ignition}" ]]; then + # Generate OEM image + mkdir -p "${tmpdir}/usr/share/oem" + cp "${ignition}" "${tmpdir}/usr/share/oem/ign.ign" + pushd "${tmpdir}" >/dev/null + find usr | cpio -o -H newc --quiet | gzip -c > oem.cpio.gz + popd >/dev/null + + # Upload it. Don't delete it afterward, since the instance could + # reboot at any point and need the OEM image again. + oempath="${bucket_base}/$(mktemp -u XXXXXXX)" + gsutil -q cp "${tmpdir}/oem.cpio.gz" "gs://${oempath}" + + ignition_initrd_args="initrd=ignition coreos.config.url=oem:///ign.ign" + ignition_initrd_cmd="initrd --name ignition http://${oempath}" + fi + + # Create iPXE script + cat >"${tmpdir}/ipxe" <&2 + exit 2 +fi + +if [[ -z "${path}" ]]; then + echo "Image file is required." >&2 + exit 2 +fi + +object=$(mktemp -u XXXXXXXXXXXXXXXX) + +# Upload object +bmcs os object put \ + --namespace "${namespace}" \ + --bucket-name "${bucket}" \ + --file "${path}" \ + --name "${object}" +trap 'bmcs os object delete \ + --namespace "${namespace}" \ + --bucket-name "${bucket}" \ + --name "${object}" \ + --force' EXIT + +# Initiate import +image_id=$(bmcs compute image create \ + --compartment-id "${compartment}" \ + --display-name "${display_name}" \ + --image-source-details "{\"objectName\": \"${object}\", \"bucketName\": \"${bucket}\", \"namespaceName\": \"${namespace}\", \"sourceType\": \"objectStorageTuple\"}" | \ + jq -r .data.id) + +# Wait for import +echo "Waiting for import..." +state=IMPORTING +while [[ "$state" = IMPORTING ]]; do + sleep 10 + state=$(bmcs compute image get --image-id "${image_id}" | jq -r '.data["lifecycle-state"]') +done +echo "${state} ${image_id}" From 1ea637794c86be2ddfc77b6d33a017dfc8d5362e Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Tue, 8 Aug 2017 15:00:32 -0700 Subject: [PATCH 2/3] oem/oracle: Add option to add kernel arguments to iPXE script --- oem/oracle/launch-instance | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/oem/oracle/launch-instance b/oem/oracle/launch-instance index 23a6290d72..cea9c542b3 100755 --- a/oem/oracle/launch-instance +++ b/oem/oracle/launch-instance @@ -15,6 +15,7 @@ ipxe=0 ignition= baseurl="http://alpha.release.core-os.net/amd64-usr/current" bucket_base="users.developer.core-os.net/$USER/bmcs" +kargs= # Parse args usage="Usage: $0 [args] -n name @@ -29,9 +30,10 @@ Options: -I IMAGE-ID Image ID to use; only relevant for non-iPXE (default: ${image_id}) -b BASEURL URL to the image mirror; only relevant for iPXE (default: ${baseurl}) -B BUCKET-BASE GS bucket and relative path for iPXE script (default: ${bucket_base}) + -k ARGS Additional kernel command line arguments for iPXE script -h This ;-) " -while getopts "c:a:n:s:S:i:pI:b:B:h" OPTION +while getopts "c:a:n:s:S:i:pI:b:B:k:h" OPTION do case "${OPTION}" in c) compartment="${OPTARG}" ;; @@ -44,6 +46,7 @@ do I) image_id="${OPTARG}" ;; b) baseurl="${OPTARG}" ;; B) bucket_base="${OPTARG}" ;; + k) kargs="${OPTARG}" ;; h) echo "${usage}"; exit 2 ;; *) exit 2 ;; esac @@ -82,7 +85,7 @@ if [[ "${ipxe}" = 1 ]]; then cat >"${tmpdir}/ipxe" < Date: Thu, 10 Aug 2017 23:22:53 -0700 Subject: [PATCH 3/3] oem/oracle: Update for oraclebmc-cli 2.4.6 bmcs compute image create --image-source-details is deprecated. --- oem/oracle/upload-image | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/oem/oracle/upload-image b/oem/oracle/upload-image index 3c4176ee06..8a3be511a8 100755 --- a/oem/oracle/upload-image +++ b/oem/oracle/upload-image @@ -58,11 +58,12 @@ trap 'bmcs os object delete \ --force' EXIT # Initiate import -image_id=$(bmcs compute image create \ +image_id=$(bmcs compute image import from-object \ --compartment-id "${compartment}" \ --display-name "${display_name}" \ - --image-source-details "{\"objectName\": \"${object}\", \"bucketName\": \"${bucket}\", \"namespaceName\": \"${namespace}\", \"sourceType\": \"objectStorageTuple\"}" | \ - jq -r .data.id) + --namespace "${namespace}" \ + --bucket-name "${bucket}" \ + --name "${object}" | jq -r .data.id) # Wait for import echo "Waiting for import..."