Announcing a new VSTS Extension for Starting and Stopping Azure DevTest Labs VMs

Background

I have recently been posting on using Azure to host private VSTS build/release agents to avoid agent queue deadlocking issues with more complex release pipelines. One of the areas discussed is reducing cost of running a private agent in Azure by only running the private agent within a limited time range, when you guess it might be needed. I have done this using DevTest Labs Auto Start and Auto Stop features. This works, but is it not better to only start the agent VM when it is actually really needed, not when you guess it might be? I need this private agent only when working on my VSTS extensions, not something I do everyday. Why waste CPU cycles that are never used?

New VSTS Extension

I had expected there would already be a VSTS  extension to Start and Stop DevTest Lab VMs, but the Microsoft provided extension for DevTest Labs only provides tasks for the creation and deletion of VMs within a lab. So I am pleased to announce the release of my new DevTest Labs VSTS Extension to fill this gap, adding tasks to start and stop a DevTest Lab VM on demand from within a build or a release. My Usage I have been able to use the tasks in this extension to start my private Azure hosted agent only when I need it for functional tests within a release. However, they could equally be used for a variety of different testing scenarios where any form of pre-built/configured VMs needs to be started or stopped as opposed to slower processes of creating/deploying a new deployment of a DevTest lab VM. In may case I added an extra agent phases to my release pipeline to start the VM prior to it being needed. image I could also have used another agent phase to stop the VM once the tests were completed. However, I made the call to leave the VM running and let DevTest Labs’ Auto Stop shut it down at the end of the day. The reason for this is that VM start up and shutdown is still fairly slow, a minute or two, and I often find I need to run a set of function tests a few times during my development cycle; so it is a bit more efficient to leave the VM running until the end of the day. Only taking the start-up cost once. You may have course have different needs, hence providing both the Start and Stop Tasks

Development

This new extension aims to act as a supplement to the Microsoft provided Azure DevTest Lab Extension. Hence to make development and adoption easier, it uses exactly the same source code structure and task parameters as the Microsoft provided extension. The task parameters being:

  • Azure RM Subscription - Azure Resource Manager subscription to configure before running.
  • Source Lab VM ID - Resource ID of the source lab VM. The source lab VM must be in the selected lab, as the custom image will be created using its VHD file. You can use any variable such as $(labVMId), the output of calling Create Azure DevTest Labs VM, that contains a value in the form /subscriptions/{subId}/resourceGroups/{rgName}/providers/Microsoft.DevTestLab/labs/{labName}/virtualMachines/{vmName}.

The issue I had was that the DevTest Labs PowerShell API did not provide a command to start or stop a VM in a lab. I needed to load the Azure PowerShell library to use the Invoke-AzureRmResourceAction  command. This requires you first call Login-AzureRmAccount to authenticate prior to calling the actual Invoke-AzureRmResourceAction required. This required a bit of extra code to get and reuse the AzureRM endpoint to find the authentication details.``` # Get the parameters $ConnectedServiceName = Get-VstsInput -Name "ConnectedServiceName"

Get the end point from the name passed as a parameter

$Endpoint = Get-VstsEndpoint -Name $ConnectedServiceName -Require

Get the authentication details

$clientID = $Endpoint.Auth.parameters.serviceprincipalid $key = $Endpoint.Auth.parameters.serviceprincipalkey $tenantId = $Endpoint.Auth.parameters.tenantid $SecurePassword = $key | ConvertTo-SecureString -AsPlainText -Force $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $clientID, $SecurePassword

Authenticate

Login-AzureRmAccount -Credential $cred -TenantId $tenantId -ServicePrincipal Important to note that for this code to work you have to set the task’s **task.json** to run **PowerShell3** and package the Powershell VSTS API module in with the task. "execution": { "PowerShell3": { "target": "$(currentDirectory)\StartVM.ps1", "argumentFormat": "", "workingDirectory": "$(currentDirectory)"     }   }

1
2### In Summary
3
4I have certainly found this extension useful, and I have leant more that I had expect I would about VSTS endpoints and Azure authentication. Hope it is useful to you too.