mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Workflow runs fail in the "Get Location" step with:
jq: error (at <stdin>:9): string ("100") and number (0) cannot be added
Use tonumber to explicitly convert string to number instead of the "+ 0"
trick.
Signed-off-by: Anirudh Rayabharam <anrayabh@microsoft.com>
247 lines
9.0 KiB
YAML
247 lines
9.0 KiB
YAML
name: MSHV Infra Setup
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
ARCH:
|
|
description: 'Architecture for the VM'
|
|
required: true
|
|
type: string
|
|
KEY:
|
|
description: 'SSH Key Name'
|
|
required: true
|
|
type: string
|
|
OS_DISK_SIZE:
|
|
description: 'OS Disk Size in GB'
|
|
required: true
|
|
type: number
|
|
RG:
|
|
description: 'Resource Group Name'
|
|
required: true
|
|
type: string
|
|
VM_SKU:
|
|
description: 'VM SKU'
|
|
required: true
|
|
type: string
|
|
secrets:
|
|
MI_CLIENT_ID:
|
|
required: true
|
|
RUNNER_RG:
|
|
required: true
|
|
STORAGE_ACCOUNT_PATHS:
|
|
required: true
|
|
ARCH_SOURCE_PATH:
|
|
required: true
|
|
USERNAME:
|
|
required: true
|
|
outputs:
|
|
RG_NAME:
|
|
description: 'Resource group of the VM'
|
|
value: ${{ jobs.infra-setup.outputs.RG_NAME }}
|
|
VM_NAME:
|
|
description: 'Name of the VM'
|
|
value: ${{ jobs.infra-setup.outputs.VM_NAME }}
|
|
PRIVATE_IP:
|
|
description: 'Private IP of the VM'
|
|
value: ${{ jobs.infra-setup.outputs.PRIVATE_IP }}
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ github.event_name }}
|
|
cancel-in-progress: true
|
|
jobs:
|
|
infra-setup:
|
|
name: ${{ inputs.ARCH }} VM Provision
|
|
runs-on: mshv
|
|
outputs:
|
|
RG_NAME: ${{ steps.rg-setup.outputs.RG_NAME }}
|
|
VM_NAME: ${{ steps.vm-setup.outputs.VM_NAME }}
|
|
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
|
|
steps:
|
|
- name: Install & login to AZ CLI
|
|
env:
|
|
MI_CLIENT_ID: ${{ secrets.MI_CLIENT_ID }}
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "Installing Azure CLI if not already installed"
|
|
if ! command -v az &>/dev/null; then
|
|
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
|
else
|
|
echo "Azure CLI already installed"
|
|
fi
|
|
az --version
|
|
echo "Logging into Azure CLI using Managed Identity"
|
|
az login --identity --client-id "${MI_CLIENT_ID}"
|
|
|
|
- name: Get Location
|
|
id: get-location
|
|
env:
|
|
SKU: ${{ inputs.VM_SKU }}
|
|
STORAGE_ACCOUNT_PATHS: ${{ secrets.STORAGE_ACCOUNT_PATHS }}
|
|
run: |
|
|
set -eufo pipefail
|
|
# Extract vCPU count from SKU (e.g., "Standard_D2s_v3" => 2)
|
|
if ! [[ "$SKU" =~ ^Standard_[A-Za-z]+([1-9][0-9]*) ]]; then
|
|
printf 'Cannot extract vCPU count from SKU: %q\n' "$SKU"
|
|
exit 1
|
|
fi
|
|
vcpu=${BASH_REMATCH[1]}
|
|
|
|
SUPPORTED_LOCATIONS=$(echo "$STORAGE_ACCOUNT_PATHS" | jq -r 'to_entries[] | .key')
|
|
|
|
for location in $SUPPORTED_LOCATIONS; do
|
|
family=$(az vm list-skus --size "$SKU" --location "$location" --resource-type "virtualMachines" --query '[0].family' -o tsv)
|
|
if [[ -z "$family" ]]; then
|
|
echo "Cannot determine VM family for SKU: $SKU in $location"
|
|
continue
|
|
fi
|
|
|
|
remaining=$(az vm list-usage --location "$location" --query "[?name.value=='$family'] | [0]" -o json |
|
|
jq '(.limit | tonumber) - (.currentValue | tonumber) >= ($ARGS.positional[0] | tonumber)' --jsonargs "$vcpu")
|
|
if [[ "$remaining" = true ]]; then
|
|
echo "Sufficient quota found in $location"
|
|
echo "location=$location" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
done
|
|
|
|
echo "No location found with sufficient vCPU quota for SKU: $SKU"
|
|
exit 1
|
|
|
|
- name: Create Resource Group
|
|
id: rg-setup
|
|
env:
|
|
LOCATION: ${{ steps.get-location.outputs.location }}
|
|
RG: ${{ inputs.RG }}
|
|
STORAGE_ACCOUNT_PATHS: ${{ secrets.STORAGE_ACCOUNT_PATHS }}
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "Creating Resource Group: $RG"
|
|
# Create the resource group
|
|
echo "Creating resource group in location: ${LOCATION}"
|
|
az group create --name "${RG}" --location "${LOCATION}"
|
|
echo "RG_NAME=${RG}" >> $GITHUB_OUTPUT
|
|
echo "Resource group created successfully."
|
|
|
|
- name: Generate SSH Key
|
|
id: generate-ssh-key
|
|
env:
|
|
KEY: ${{ inputs.KEY }}
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "Generating SSH key: $KEY"
|
|
mkdir -p ~/.ssh
|
|
ssh-keygen -t rsa -b 4096 -f ~/.ssh/"${KEY}" -N ""
|
|
|
|
- name: Create VM
|
|
id: vm-setup
|
|
env:
|
|
KEY: ${{ inputs.KEY }}
|
|
LOCATION: ${{ steps.get-location.outputs.location }}
|
|
OS_DISK_SIZE: ${{ inputs.OS_DISK_SIZE }}
|
|
RG: ${{ inputs.RG }}
|
|
RUNNER_RG: ${{ secrets.RUNNER_RG }}
|
|
USERNAME: ${{ secrets.USERNAME }}
|
|
VM_SKU: ${{ inputs.VM_SKU }}
|
|
VM_IMAGE_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_image
|
|
VM_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_${{ github.run_id }}
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "Creating $VM_SKU VM: $VM_NAME"
|
|
|
|
# Extract subnet ID from the runner VM
|
|
echo "Retrieving subnet ID..."
|
|
SUBNET_ID=$(az network vnet list --resource-group "$RUNNER_RG" --query "[?contains(location, '${LOCATION}')].{SUBNETS:subnets}" | jq -r ".[0].SUBNETS[0].id")
|
|
if [[ -z "${SUBNET_ID}" ]]; then
|
|
echo "ERROR: Failed to retrieve Subnet ID."
|
|
exit 1
|
|
fi
|
|
|
|
# Extract image ID from the runner VM
|
|
echo "Retrieving image ID..."
|
|
IMAGE_ID=$(az image show --resource-group "$RUNNER_RG" --name "$VM_IMAGE_NAME" --query "id" -o tsv)
|
|
if [[ -z "${IMAGE_ID}" ]]; then
|
|
echo "ERROR: Failed to retrieve Image ID."
|
|
exit 1
|
|
fi
|
|
|
|
# Create VM
|
|
az vm create \
|
|
--resource-group "${RG}" \
|
|
--name "${VM_NAME}" \
|
|
--subnet "${SUBNET_ID}" \
|
|
--size "${VM_SKU}" \
|
|
--location "${LOCATION}" \
|
|
--image "${IMAGE_ID}" \
|
|
--os-disk-size-gb "${OS_DISK_SIZE}" \
|
|
--public-ip-sku Standard \
|
|
--storage-sku Premium_LRS \
|
|
--public-ip-address "" \
|
|
--admin-username "${USERNAME}" \
|
|
--ssh-key-value ~/.ssh/"${KEY}".pub \
|
|
--security-type Standard \
|
|
--output json
|
|
|
|
az vm boot-diagnostics enable --name "${VM_NAME}" --resource-group "${RG}"
|
|
|
|
echo "VM_NAME=${VM_NAME}" >> "$GITHUB_OUTPUT"
|
|
echo "VM creation process completed successfully."
|
|
|
|
- name: Get VM Private IP
|
|
id: get-vm-ip
|
|
env:
|
|
RG: ${{ inputs.RG }}
|
|
VM_NAME: ${{ inputs.ARCH }}_${{ steps.get-location.outputs.location }}_${{ github.run_id }}
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "Retrieving VM Private IP address..."
|
|
# Retrieve VM Private IP address
|
|
PRIVATE_IP=$(az vm show -g "${RG}" -n "${VM_NAME}" -d --query privateIps -o tsv)
|
|
if [[ -z "$PRIVATE_IP" ]]; then
|
|
echo "ERROR: Failed to retrieve private IP address."
|
|
exit 1
|
|
fi
|
|
echo "PRIVATE_IP=$PRIVATE_IP" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Wait for SSH availability
|
|
env:
|
|
KEY: ${{ inputs.KEY }}
|
|
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
|
|
USERNAME: ${{ secrets.USERNAME }}
|
|
run: |
|
|
echo "Waiting for SSH to be accessible..."
|
|
timeout 120 bash -c 'until ssh -o StrictHostKeyChecking=no -i ~/.ssh/"${KEY}" -- "${USERNAME}@${PRIVATE_IP}" "exit" 2>/dev/null; do sleep 5; done'
|
|
echo "VM is accessible!"
|
|
|
|
- name: Remove Old Host Key
|
|
env:
|
|
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "Removing the old host key"
|
|
ssh-keygen -R "$PRIVATE_IP"
|
|
|
|
- name: SSH into VM and Install Dependencies
|
|
env:
|
|
KEY: ${{ inputs.KEY }}
|
|
PRIVATE_IP: ${{ steps.get-vm-ip.outputs.PRIVATE_IP }}
|
|
USERNAME: ${{ secrets.USERNAME }}
|
|
run: |
|
|
set -eufo pipefail
|
|
ssh -i ~/.ssh/"${KEY}" -o StrictHostKeyChecking=no -- "${USERNAME}@${PRIVATE_IP}" << EOF
|
|
set -eufo pipefail
|
|
echo "Logged in successfully."
|
|
echo "Installing dependencies..."
|
|
sudo tdnf install -y git moby-engine moby-cli clang llvm pkg-config make gcc glibc-devel
|
|
echo "Installing Rust..."
|
|
curl -sSf https://sh.rustup.rs | sh -s -- --default-toolchain stable --profile default -y
|
|
export PATH="\$HOME/.cargo/bin:\$PATH"
|
|
cargo --version
|
|
sudo mkdir -p /etc/docker/
|
|
echo '{"default-ulimits":{"nofile":{"Hard":65535,"Name":"nofile","Soft":65535}}}' | sudo tee /etc/docker/daemon.json
|
|
sudo systemctl stop docker
|
|
sudo systemctl enable docker.service
|
|
sudo systemctl enable containerd.service
|
|
sudo systemctl start docker
|
|
sudo groupadd -f docker
|
|
sudo usermod -a -G docker "${USERNAME}"
|
|
sudo systemctl restart docker
|
|
EOF
|