diff --git a/.github/workflows/mshv-infra.yaml b/.github/workflows/mshv-infra.yaml deleted file mode 100644 index 25e37e574..000000000 --- a/.github/workflows/mshv-infra.yaml +++ /dev/null @@ -1,276 +0,0 @@ -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 - echo "Checking SKU availability for $SKU in $location..." - sku_info=$(az vm list-skus --size "$SKU" --location "$location" --resource-type "virtualMachines" -o json) - - if [[ "$(echo "$sku_info" | jq 'length')" -eq 0 ]]; then - echo "SKU $SKU is not available in $location" - continue - fi - - family=$(echo "$sku_info" | jq -r '.[0].family // empty') - if [[ -z "$family" ]]; then - echo "Cannot determine VM family for SKU: $SKU in $location" - continue - fi - - restrictions=$(echo "$sku_info" | jq '.[0].restrictions // []') - if [[ "$(echo "$restrictions" | jq 'length')" -gt 0 ]]; then - echo "SKU $SKU has provisioning restrictions in $location:" - echo "$restrictions" | jq -r '.[] | "- \(.type): \(.reasonCode // \"unknown\") \(.displayText // \"\")"' - continue - fi - - usage=$(az vm list-usage --location "$location" -o json) - usage_item=$(echo "$usage" | jq --arg family "$family" ' - ([.[] | select(.name.value | test($family; "i"))] + - [.[] | select(.name.value | test("vcpus|cores"; "i"))]) - | first // empty - ') - - if [[ -z "$usage_item" || "$usage_item" == "null" ]]; then - echo "Failed to determine vCPU quota for $location" - echo "Available usage metric names in $location:" - echo "$usage" | jq -r '.[].name.value' - continue - fi - - available_vcpus=$(echo "$usage_item" | jq '(.limit | tonumber) - (.currentValue | tonumber)') - if [[ "$available_vcpus" -ge "$vcpu" ]]; then - echo "Found location $location with available capacity and quota ($available_vcpus vCPUs available)" - echo "location=$location" >> "$GITHUB_OUTPUT" - exit 0 - fi - - echo "Not enough vCPU quota in $location: $available_vcpus available, need $vcpu" - done - - echo "No location found with sufficient vCPU quota and SKU capacity 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 diff --git a/.github/workflows/mshv-integration.yaml b/.github/workflows/mshv-integration.yaml deleted file mode 100644 index 5ab92b0f0..000000000 --- a/.github/workflows/mshv-integration.yaml +++ /dev/null @@ -1,129 +0,0 @@ -name: Cloud Hypervisor Tests (MSHV) (x86_64) -on: [pull_request_target, merge_group] -permissions: {} - -jobs: - infra-setup: - name: MSHV Infra Setup (x86_64) - uses: ./.github/workflows/mshv-infra.yaml - with: - ARCH: x86_64 - KEY: azure_key_${{ github.run_id }} - OS_DISK_SIZE: 512 - RG: MSHV-INTEGRATION-${{ github.run_id }} - VM_SKU: Standard_D16s_v5 - secrets: - MI_CLIENT_ID: ${{ secrets.MSHV_MI_CLIENT_ID }} - RUNNER_RG: ${{ secrets.MSHV_RUNNER_RG }} - STORAGE_ACCOUNT_PATHS: ${{ secrets.MSHV_STORAGE_ACCOUNT_PATHS }} - ARCH_SOURCE_PATH: ${{ secrets.MSHV_X86_SOURCE_PATH }} - USERNAME: ${{ secrets.MSHV_USERNAME }} - - run-tests: - name: Integration Tests (x86_64) - needs: infra-setup - if: ${{ always() && needs.infra-setup.result == 'success' }} - runs-on: mshv - steps: - - name: Run integration tests - timeout-minutes: 60 - env: - KEY: azure_key_${{ github.run_id }} - PR_NUMBER: ${{ github.event.pull_request.number }} - REPO_URL: https://github.com/cloud-hypervisor/cloud-hypervisor.git - REPO_DIR: cloud-hypervisor - PRIVATE_IP: ${{ needs.infra-setup.outputs.PRIVATE_IP }} - RG: MSHV-${{ github.run_id }} - USERNAME: ${{ secrets.MSHV_USERNAME }} - run: | - set -eufo pipefail - echo "Connecting to the VM via SSH..." - ssh -i ~/.ssh/"${KEY}" -o StrictHostKeyChecking=no -- "${USERNAME}@${PRIVATE_IP}" << EOF - set -e - echo "Logged in successfully." - export PATH="\$HOME/.cargo/bin:\$PATH" - - if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then - git clone --depth 1 "$REPO_URL" "$REPO_DIR" - cd "$REPO_DIR" - git fetch origin pull/${{ github.event.pull_request.number }}/merge - git checkout FETCH_HEAD - else - git clone --depth 1 --single-branch --branch "${{ github.ref_name }}" "$REPO_URL" "$REPO_DIR" - cd "$REPO_DIR" - fi - - echo "Loading VDPA kernel modules..." - sudo modprobe vdpa - sudo modprobe vhost_vdpa - sudo modprobe vdpa_sim - sudo modprobe vdpa_sim_blk - sudo modprobe vdpa_sim_net - - echo "Creating VDPA devices..." - sudo vdpa dev add name vdpa-blk0 mgmtdev vdpasim_blk - sudo vdpa dev add name vdpa-blk1 mgmtdev vdpasim_blk - sudo vdpa dev add name vdpa-blk2 mgmtdev vdpasim_net - - echo "Setting permissions..." - for i in 0 1 2; do - dev="/dev/vhost-vdpa-\$i" - if [ -e "\$dev" ]; then - sudo chown \$USER:\$USER "\$dev" - sudo chmod 660 "\$dev" - else - echo "Warning: Device \$dev not found" - fi - done - - sudo ./scripts/dev_cli.sh tests --integration - EOF - - - name: Dump dmesg - if: always() - continue-on-error: true - env: - KEY: azure_key_${{ github.run_id }} - PRIVATE_IP: ${{ needs.infra-setup.outputs.PRIVATE_IP }} - USERNAME: ${{ secrets.MSHV_USERNAME }} - run: | - ssh -i ~/.ssh/"${KEY}" -o StrictHostKeyChecking=no -- "${USERNAME}@${PRIVATE_IP}" sudo dmesg - - - name: Dump serial console logs - if: always() - continue-on-error: true - env: - RG_NAME: ${{ needs.infra-setup.outputs.RG_NAME }} - VM_NAME: ${{ needs.infra-setup.outputs.VM_NAME }} - run: | - set -eufo pipefail - az vm boot-diagnostics get-boot-log --name "${VM_NAME}" --resource-group "${RG_NAME}" | jq -r - - cleanup: - name: Cleanup - needs: run-tests - if: always() - runs-on: mshv - steps: - - name: Delete RG - env: - RG: MSHV-INTEGRATION-${{ github.run_id }} - run: | - if az group exists --name "${RG}"; then - az group delete --name "${RG}" --yes --no-wait - else - echo "Resource Group ${RG} does not exist. Skipping deletion." - fi - echo "Cleanup process completed." - - - name: Delete SSH Key - env: - KEY: azure_key_${{ github.run_id }} - run: | - if [ -f ~/.ssh/"${KEY}" ]; then - rm -f ~/.ssh/"${KEY}" ~/.ssh/"${KEY}.pub" - echo "SSH key deleted successfully." - else - echo "SSH key does not exist. Skipping deletion." - fi - echo "Cleanup process completed."