Skip to content

Commit

Permalink
Automated base VM image build
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Yan <[email protected]>
  • Loading branch information
CyanDevs committed Nov 19, 2021
1 parent 8946acf commit b59ad23
Show file tree
Hide file tree
Showing 2 changed files with 278 additions and 10 deletions.
232 changes: 232 additions & 0 deletions .jenkins/infrastructure/build_base_azure_gallery_image.Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
// Copyright (c) Open Enclave SDK contributors.
// Licensed under the MIT License.


library "OpenEnclaveJenkinsLibrary@${params.OECI_LIB_VERSION}"

def buildLinuxVMBaseImage(String os_type, String os_version) {
stage('Environment setup') {
withCredentials([usernamePassword(credentialsId: 'SERVICE_PRINCIPAL_OSTCLAB',
passwordVariable: 'SERVICE_PRINCIPAL_PASSWORD',
usernameVariable: 'SERVICE_PRINCIPAL_ID'),
string(credentialsId: 'OSCTLabSubID', variable: 'SUBSCRIPTION_ID'),
string(credentialsId: 'TenantID', variable: 'TENANT_ID'),
]) {
retry(10) {
sh """
sleep 5
${helpers.WaitForAptLock()}
sudo apt-get update
sudo apt-get -y install ca-certificates curl apt-transport-https lsb-release gnupg
curl -sL https://packages.microsoft.com/keys/microsoft.asc |
gpg --dearmor |
sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null
AZ_REPO=\$(lsb_release -cs)
echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ \$AZ_REPO main" |
sudo tee /etc/apt/sources.list.d/azure-cli.list
${helpers.WaitForAptLock()}
sudo apt-get update
sudo apt-get -y install azure-cli
"""
}
sh '''
az login \
--service-principal \
-u ${SERVICE_PRINCIPAL_ID} \
-p ${SERVICE_PRINCIPAL_PASSWORD} \
--tenant ${TENANT_ID}
az account set -s ${SUBSCRIPTION_ID}
'''
}
}
withEnv([
"BUILD_RESOURCE_GROUP=jenkins-build-image-base-${os_type}-${os_version}-${GALLERY_IMAGE_VERSION}",
"BUILD_VM_NAME=VM-${os_type}-${os_version}-${GALLERY_IMAGE_VERSION}",
"IMAGE_URN=${helpers.getAzureImageUrn(os_type, os_version)}",
"GALLERY_IMAGE_DEFINITION=${os_type}_${os_version}_LTS_Gen2"
]) {
stage("Create Resource Group") {
sh """
az group create --name "${BUILD_RESOURCE_GROUP}" --location "${params.AZURE_REGION}"
"""
}
try {
stage("Create VM") {
def EXISTING_SUBNET_ID = sh(
returnStdout: true,
script: """
az network vnet subnet show \
--resource-group "${JENKINS_RESOURCE_GROUP}" \
--name "${JENKINS_SUBNET_NAME}" \
--vnet-name "${JENKINS_VNET_NAME}" \
--query id \
--out tsv
"""
).trim()
sh """
echo "Creating VM"
az vm create \
--resource-group "${BUILD_RESOURCE_GROUP}" \
--location "${params.AZURE_REGION}" \
--name "${BUILD_VM_NAME}" \
--size Standard_DC2s \
--os-disk-size-gb 128 \
--subnet "${EXISTING_SUBNET_ID}" \
--public-ip-address "" \
--authentication-type ssh \
--generate-ssh-keys \
--image ${env.IMAGE_URN}
"""
def BUILD_VM_PRIVATE_IP = sh(
returnStdout: true,
script: """
az vm show \
--resource-group "${env.BUILD_RESOURCE_GROUP}" \
--name "${env.BUILD_VM_NAME}" \
--show-details \
--query privateIps \
--out tsv
"""
).trim()
withEnv(["BUILD_VM_PRIVATE_IP=${BUILD_VM_PRIVATE_IP}"]) {
retry(5) {
sh '''
sleep 30
ssh -o StrictHostKeyChecking=no oeadmin@${BUILD_VM_PRIVATE_IP} \
"unset HISTFILE && \
while sudo ps aux | grep -E '[a]pt|[d]pkg'; do sleep 5; done"
'''
sh '''
ssh -o StrictHostKeyChecking=no oeadmin@${BUILD_VM_PRIVATE_IP} \
"unset HISTFILE && \
sudo apt-get update && \
sudo apt-get -y install apt-transport-https ca-certificates && \
sudo apt-get -y upgrade && \
sudo apt-get -y dist-upgrade && \
sudo sed -i 's/\\".*\\"/\\"0\\"/' /etc/apt/apt.conf.d/20auto-upgrades && \
sudo systemctl disable apt-daily-upgrade.timer && \
sudo systemctl disable apt-daily.timer"
'''
}
withCredentials([usernamePassword(credentialsId: JENKINS_USER_CREDS_ID,
usernameVariable: 'SSH_USERNAME',
passwordVariable: 'SSH_PASSWORD')
]) {
sh '''
ssh -o StrictHostKeyChecking=no oeadmin@${BUILD_VM_PRIVATE_IP} \
"unset HISTFILE && \
sudo echo '${SSH_USERNAME}:${SSH_PASSWORD}' | sudo chpasswd && \
sudo sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
sudo /usr/sbin/waagent -force -deprovision+user && \
sync"
'''
}
}
}
stage("Generalize VM") {
sh """
echo "Generalize VM"
az vm deallocate \
--resource-group "${env.BUILD_RESOURCE_GROUP}" \
--name "${env.BUILD_VM_NAME}"
az vm generalize \
--resource-group "${env.BUILD_RESOURCE_GROUP}" \
--name "${env.BUILD_VM_NAME}"
"""
}
stage("Upload Image") {
def BUILD_VM_ID = sh(
returnStdout: true,
script: """
az vm show \
--resource-group "${env.BUILD_RESOURCE_GROUP}" \
--name "${env.BUILD_VM_NAME}" \
--query 'id'
"""
).trim()
sh """
echo "Upload Image to Shared Image Gallery"
echo "Note: the Shared Image Gallery and Image Definition needs to be created manually"
az sig image-version delete \
--resource-group "${GALLERY_RESOURCE_GROUP}" \
--gallery-name "${GALLERY_NAME}" \
--gallery-image-definition "${GALLERY_IMAGE_DEFINITION}" \
--gallery-image-version "${GALLERY_IMAGE_VERSION}"
az sig image-version create \
--resource-group "${GALLERY_RESOURCE_GROUP}" \
--gallery-name "${GALLERY_NAME}" \
--gallery-image-definition "${GALLERY_IMAGE_DEFINITION}" \
--gallery-image-version "${GALLERY_IMAGE_VERSION}" \
--managed-image "${BUILD_VM_ID}" \
--target-regions ${params.REPLICATION_REGIONS.split(',').join(' ')} \
--replica-count 1
"""
}
} finally {
stage("Cleanup Resource Group") {
sh """
az group delete --name "${BUILD_RESOURCE_GROUP}" --yes
"""
}
}
}
}


pipeline {
agent {
label globalvars.AGENTS_LABELS["ubuntu-nonsgx"]
}
options {
timeout(time: 90, unit: 'MINUTES')
}
parameters {
string(name: 'REPOSITORY_NAME', defaultValue: 'openenclave/openenclave', description: 'GitHub repository to checkout')
string(name: 'BRANCH_NAME', defaultValue: 'master', description: 'The branch used to checkout the repository')
string(name: 'GALLERY_RESOURCE_GROUP', defaultValue: 'OE-Jenkins-Images', description: 'Target resource group used to save the base Azure images')
string(name: 'OE_DEPLOY_IMAGE', defaultValue: 'oetools-deploy:latest', description: 'Docker image and versions used to run packer')
string(name: 'AZURE_REGION', defaultValue: 'westeurope', description: 'Images location')
string(name: 'REPLICATION_REGIONS', defaultValue: 'westeurope,eastus,uksouth,eastus2', description: 'Replication regions for the shared gallery images definitions (comma-separated)')
string(name: "OECI_LIB_VERSION", defaultValue: 'master', description: 'Version of OE Libraries to use')
}
environment {
JENKINS_USER_CREDS_ID = 'oeadmin-credentials'
OETOOLS_REPO_CREDENTIALS_ID = 'oejenkinscidockerregistry'
DOCKER_REGISTRY = 'oejenkinscidockerregistry.azurecr.io'
JENKINS_RESOURCE_GROUP = 'OE-Jenkins-terraform'
JENKINS_VNET_NAME = 'OE-Jenkins-terraform-test'
JENKINS_SUBNET_NAME = 'subnet1'
GALLERY_NAME = 'Vanilla_Images'
GALLERY_IMAGE_DATE = helpers.get_date(".")
GALLERY_IMAGE_VERSION = "${GALLERY_IMAGE_DATE}${BUILD_NUMBER}"
}
stages {
stage('Build') {
parallel {
stage("Ubuntu 18.04") {
steps {
script {
buildLinuxVMBaseImage("Ubuntu", "18.04")
}
}
}
stage("Ubuntu 20.04") {
steps {
script {
buildLinuxVMBaseImage("Ubuntu", "20.04")
}
}
}
}
}
}
post {
always {
sh """
az logout || true
az cache purge
az account clear
"""
}
}
}
56 changes: 46 additions & 10 deletions .jenkins/library/vars/helpers.groovy
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright (c) Open Enclave SDK contributors.
// Licensed under the MIT License.

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

/****************************************
* Shared Library for Helpers and Commands
****************************************/
Expand All @@ -11,24 +14,26 @@ def CmakeArgs(String build_type = "RelWithDebInfo", String code_coverage = "OFF"
}

def WaitForAptLock() {
def aptWait = """
i=0
return """
counter=0
max=600
step=5
echo "Checking for locks..."
# Check for locks
while fuser /var/lib/dpkg/lock > /dev/null 2>&1 ||
fuser /var/lib/dpkg/lock-frontend > /dev/null 2>&1 ||
fuser /var/lib/apt/lists/lock > /dev/null 2>&1; do
while sudo fuser /var/lib/dpkg/lock > /dev/null 2>&1 ||
sudo fuser /var/lib/dpkg/lock-frontend > /dev/null 2>&1 ||
sudo fuser /var/lib/apt/lists/lock > /dev/null 2>&1 ||
sudo ps aux | grep -E "[a]pt|[d]pkg"; do
# Wait up to 600 seconds to lock to be released
if (( i > 600 )); then
if (( \${counter} > \${max} )); then
echo "Timeout waiting for lock."
exit 1
fi
echo "Waiting for apt/dpkg locks..."
i=\${i++}
sleep 1
counter=\$((\${counter}+\${step}))
sleep \${step}
done
"""
return aptWait

}

def TestCommand() {
Expand Down Expand Up @@ -477,3 +482,34 @@ def releaseInstall(String release_version = null, String oe_package = "open-encl
"""
}
}

/**
* Get today's date in YYYYMMDD format
*
* @param delimiter Optional argument to place a delimiter between YYYY, MM, and DD.
*/
def get_date(String delimiter = "") {
return (
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy")) +
delimiter +
LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM")) +
delimiter +
LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd"))
)
}

/* Returns Azure Image URNs for OS type
*
* @param os_type The OS distribution (Currently only "ubuntu")
* @param os_version The OS distribution version ("18.04", "20.04")
*/
def getAzureImageUrn(String os_type, String os_version) {
if (os_type.toLowerCase() != 'ubuntu' || ! os_version.matches('20.04|18.04')) {
error("Unsupported OS (${os_type}) or version (${os_version})")
}
if (os_version == '20.04') {
return "Canonical:0001-com-ubuntu-server-focal:20_04-lts-gen2:latest"
} else if (os_version == '18.04') {
return "Canonical:UbuntuServer:18_04-lts-gen2:latest"
}
}

0 comments on commit b59ad23

Please sign in to comment.