Skip to content

Commit 20fb953

Browse files
authored
feat: add scripts for building, publishing images and deploying azure VM (#15953)
This PR includes a couple of dev scripts. One can change the variable names in common.sh and use build-vm-images.sh to build VM images locally and publish the image to SIG via publish-sig-image.sh and deploy an Azure VM with deploy-azure-vm.sh for testing purposes.
1 parent f285749 commit 20fb953

5 files changed

Lines changed: 233 additions & 0 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
param galleryName string
2+
param imageDefinitionName string
3+
param versionName string
4+
param location string = resourceGroup().location
5+
param regions array = [resourceGroup().location]
6+
param sourceStorageAccountId string
7+
param sourceVhdUri string
8+
param defaultReplicaCount int = 1
9+
param excludedFromLatest bool = false
10+
param allowDeletionOfReplicatedLocations bool = false
11+
param replicationMode string = 'Shallow'
12+
resource imageVersion 'Microsoft.Compute/galleries/images/versions@2024-03-03' = {
13+
name: '${galleryName}/${imageDefinitionName}/${versionName}'
14+
location: location
15+
properties: {
16+
publishingProfile: {
17+
replicaCount: defaultReplicaCount
18+
targetRegions: [
19+
for region in regions: {
20+
name: region
21+
regionalReplicaCount: defaultReplicaCount
22+
storageAccountType: 'Standard_LRS'
23+
}
24+
]
25+
excludeFromLatest: excludedFromLatest
26+
replicationMode: replicationMode
27+
}
28+
storageProfile: {
29+
osDiskImage: {
30+
hostCaching: 'ReadWrite'
31+
source: {
32+
storageAccountId: sourceStorageAccountId
33+
uri: sourceVhdUri
34+
}
35+
}
36+
}
37+
safetyProfile: {
38+
allowDeletionOfReplicatedLocations: allowDeletionOfReplicatedLocations
39+
}
40+
}
41+
tags: {}
42+
}

scripts/build-vm-images.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
set -euxo pipefail
3+
4+
# Find the absolute path of the directory containing this script
5+
SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
6+
. "$SCRIPTS_DIR/common.sh"
7+
8+
sudo rm -rf "$REPO_ROOT/base/build/work/vm-base/*"
9+
sudo rm -rf "$REPO_ROOT/base/out/images/*"
10+
11+
# Build vm-base image using azldev
12+
azldev image build vm-base --local-repo "$REPO_ROOT/base/out" --remote-repo "$REMOTE_KOJI_REPO_URL" --remote-repo-no-gpgcheck

scripts/common.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/bin/bash
2+
set -euxo pipefail
3+
4+
REPO_ROOT="$( cd "$SCRIPTS_DIR/.." &> /dev/null && pwd )"
5+
6+
# Set your Azure subscription ID
7+
export SUBSCRIPTION_ID="<your-subscription-id>"
8+
9+
# Set resource configuration
10+
export RESOURCE_GROUP_NAME="<your-resource-group-name>"
11+
export LOCATION="westus3"
12+
export STORAGE_ACCOUNT_NAME="<your-storage-account-name>"
13+
export STORAGE_CONTAINER_NAME="<your-storage-container-name>"
14+
export PUBLISHER="<your-publisher-name>"
15+
export OFFER="<your-offer-name>"
16+
export TIME_TAG="$(date +%Y%m%d-%H%M%S)"
17+
export STORAGE_BLOB_NAME="azl4-vm-base.x86_64-${TIME_TAG}.vhdfixed"
18+
export VM_NAME="${USER}-azl-vm-${TIME_TAG}"
19+
export SSH_USER="<your-ssh-username>"
20+
export SSH_PUBLIC_KEY_PATH="<path-to-your-ssh-public-key>"
21+
22+
# Set VM size based on architecture
23+
ARCH="<test-vm-architecture>" # e.g., "x86_64" or "aarch64"
24+
if [ "$ARCH" = "aarch64" ]; then
25+
export TEST_VM_SIZE="Standard_D4ps_v6"
26+
else
27+
export TEST_VM_SIZE="Standard_D4s_v5"
28+
fi
29+
30+
# Set local image path
31+
export IMAGE_PATH="$REPO_ROOT/base/out/images/vm-base/azl4-vm-base.x86_64-0.1.vhdfixed"
32+
33+
# Set gallery configuration
34+
export GALLERY_NAME="<your-gallery-name>"
35+
export GALLERY_IMAGE_DEFINITION="<your-image-definition-name>"
36+
export REMOTE_KOJI_REPO_URL="<your-remote-koji-repo-url>"
37+
38+
function get-image-version() {
39+
# If the image definition doesn't exist yet, return the initial version
40+
if ! az sig image-definition show --resource-group "$RESOURCE_GROUP_NAME" --gallery-name "$GALLERY_NAME" --gallery-image-name "$GALLERY_IMAGE_DEFINITION" >/dev/null 2>&1; then
41+
echo "0.0.1"
42+
return 0
43+
fi
44+
45+
# Get the latest version from the gallery
46+
local image_version
47+
image_version=$(az sig image-version list \
48+
--resource-group "$RESOURCE_GROUP_NAME" \
49+
--gallery-name "$GALLERY_NAME" \
50+
--gallery-image-name "$GALLERY_IMAGE_DEFINITION" --query '[].name' -o tsv |
51+
sort -t "." -k1,1n -k2,2n -k3,3n |
52+
tail -1)
53+
54+
if [ -z "$image_version" ]; then
55+
echo "0.0.1"
56+
else
57+
echo "$image_version"
58+
fi
59+
}
60+
61+
function increment-version() {
62+
local version="${1:?Usage: increment-version <major.minor.patch>}"
63+
echo "$version" | awk -F. '{print $1"."$2"."$3+1}'
64+
}

scripts/deploy-azure-vm.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
set -euxo pipefail
4+
# Find the absolute path of the directory containing this script
5+
SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
6+
. "$SCRIPTS_DIR/common.sh"
7+
8+
image_version="$(get-image-version)"
9+
az vm create \
10+
--resource-group "$RESOURCE_GROUP_NAME" \
11+
--name "$VM_NAME" \
12+
--size "$TEST_VM_SIZE" \
13+
--admin-username "$SSH_USER" \
14+
--ssh-key-values "$SSH_PUBLIC_KEY_PATH" \
15+
--image "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.Compute/galleries/$GALLERY_NAME/images/$GALLERY_IMAGE_DEFINITION/versions/$image_version" \
16+
--location "$LOCATION" \
17+
--debug

scripts/publish-sig-image.sh

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/bin/bash
2+
set -euxo pipefail
3+
# Find the absolute path of the directory containing this script
4+
SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
5+
. "$SCRIPTS_DIR/common.sh"
6+
7+
storage_account_url="https://$STORAGE_ACCOUNT_NAME.blob.core.windows.net"
8+
storage_account_resource_id="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"
9+
10+
replicationMode="Shallow"
11+
storage_blob_endpoint="$storage_account_url/$STORAGE_CONTAINER_NAME/$STORAGE_BLOB_NAME"
12+
13+
az account set --subscription "$SUBSCRIPTION_ID"
14+
15+
if [ "$(az group exists -n "$RESOURCE_GROUP_NAME")" == "false" ]; then
16+
az group create \
17+
--name "$RESOURCE_GROUP_NAME" \
18+
--location "$LOCATION"
19+
fi
20+
21+
# Ensure STORAGE_ACCOUNT_NAME exists and the managed identity has access
22+
if ! az storage account show --ids "$storage_account_resource_id"; then
23+
echo "Could not find storage account \"$STORAGE_ACCOUNT_NAME\" in the expected location. Creating the storage account."
24+
25+
if [ "$(az storage account check-name --name "$STORAGE_ACCOUNT_NAME" --query nameAvailable)" == "false" ]; then
26+
echo "Storage account name $STORAGE_ACCOUNT_NAME is not available"
27+
exit 1
28+
fi
29+
az storage account create \
30+
--resource-group "$RESOURCE_GROUP_NAME" \
31+
--name "$STORAGE_ACCOUNT_NAME" \
32+
--location "$LOCATION" \
33+
--allow-shared-key-access false
34+
fi
35+
36+
# Ensure "build_target" storage container exists
37+
containerExists=$(az storage container exists --account-name "$STORAGE_ACCOUNT_NAME" --name "$STORAGE_CONTAINER_NAME" --auth-mode login | jq .exists)
38+
if [[ $containerExists != "true" ]]; then
39+
echo "Could not find container \"$STORAGE_CONTAINER_NAME\". Creating container \"$STORAGE_CONTAINER_NAME\" in storage account \"$STORAGE_ACCOUNT_NAME\"..."
40+
az storage container create \
41+
--account-name "$STORAGE_ACCOUNT_NAME" \
42+
--name "$STORAGE_CONTAINER_NAME" \
43+
--auth-mode login
44+
fi
45+
46+
# Upload the image artifact to Storage Account
47+
azcopy copy "$IMAGE_PATH" "$storage_blob_endpoint" --blob-type=PageBlob
48+
49+
# Ensure GALLERY_NAME exists
50+
if ! az sig show -r "$GALLERY_NAME" -g "$RESOURCE_GROUP_NAME"; then
51+
echo "Could not find image gallery \"$GALLERY_NAME\" in resource group \"$RESOURCE_GROUP_NAME\". Creating the gallery."
52+
az sig create \
53+
--resource-group "$RESOURCE_GROUP_NAME" \
54+
--gallery-name "$GALLERY_NAME" \
55+
--location "$LOCATION"
56+
fi
57+
58+
# Ensure the "build_target" image-definition exists
59+
# Note: We publish only the VHD from the secure-prod the SIG
60+
imageDefinitionExists=$(az sig image-definition list -r "$GALLERY_NAME" -g "$RESOURCE_GROUP_NAME" | grep "name" | grep -c "$GALLERY_IMAGE_DEFINITION" || :;) # the "|| :;" prevents grep from halting the script when it finds no matches and exits with exit code 1
61+
if [[ $imageDefinitionExists -eq 0 ]]; then
62+
echo "Could not find image-definition \"$GALLERY_IMAGE_DEFINITION\". Creating definition \"$GALLERY_IMAGE_DEFINITION\" in gallery \"$GALLERY_NAME\"..."
63+
az sig image-definition create \
64+
--gallery-image-definition "$GALLERY_IMAGE_DEFINITION" \
65+
--publisher "$PUBLISHER" \
66+
--offer "$OFFER" \
67+
--sku "$GALLERY_IMAGE_DEFINITION" \
68+
--gallery-name "$GALLERY_NAME" \
69+
--resource-group "$RESOURCE_GROUP_NAME" \
70+
--location "$LOCATION" \
71+
--os-type Linux
72+
fi
73+
74+
image_version="$(increment-version "$(get-image-version)")"
75+
76+
# Convert comma-separated regions to JSON array for bicep template
77+
# Note: Using a single region for now
78+
REGIONS_JSON=$(echo "$LOCATION" | awk -F, '{
79+
printf "[";
80+
for(i=1;i<=NF;i++) {
81+
printf "\"%s\"", $i;
82+
if(i<NF) printf ",";
83+
}
84+
printf "]";
85+
}')
86+
# Create Image Version from storage account blob
87+
az deployment group create \
88+
--name "$GALLERY_IMAGE_DEFINITION-$image_version" \
89+
--resource-group "$RESOURCE_GROUP_NAME" \
90+
--template-file "$SCRIPTS_DIR/azure-gallery-image-base.bicep" \
91+
--parameters galleryName="$GALLERY_NAME" \
92+
imageDefinitionName="$GALLERY_IMAGE_DEFINITION" \
93+
versionName="$image_version" \
94+
location="$LOCATION" \
95+
regions="$REGIONS_JSON" \
96+
sourceStorageAccountId="$storage_account_resource_id" \
97+
sourceVhdUri="$storage_blob_endpoint" \
98+
replicationMode="$replicationMode"

0 commit comments

Comments
 (0)