ariste.info
  • MSDyn365 & Azure DevOps ALM
  • Get my book!
  • ISV License Generator
  • About me
    • About me
    • Subscribe
    • Contact
  • Logo
  • LinkedIn

Unified experience ALM

  • Welcome to the new ALM guide
    • Introduction
    • Prerequisites
  • Create and prepare Azure DevOps organization and project
    • Create an Azure DevOps organization
    • Create an Azure DevOps project
    • Enable TFVC projects in Azure DevOps
    • Add CI/CD agents with an Azure subscription
  • Unified development environment
    • What are unified developer environments?
    • Transition to a capacity-based model
    • Deploying a unified developer environment using PowerShell
    • Deploy an UDE environment from PPAC
    • Upgrade version in a Unified Development Environment
    • Useful links
  • Using Visual Studio
    • Connect Visual Studio to your UDE
    • Deploy code to a Unified Development Environment
  • Pipelines
    • What’s new in the pipelines?

Legacy Guide

  • Welcome
    • Welcome!
  • Dynamics 365 for Finance & Operations & Azure DevOps
    • Intro
    • Package and model planning
    • Azure DevOps
    • First steps
    • The build server
    • Visual Studio
    • Some advice
    • Branching strategies
  • Azure Pipelines
    • Builds
    • Continuous integration
    • Gated check-ins
    • Set up the new Azure DevOps tasks for Packaging and Model Versioning
  • Azure hosted build for Dynamics 365 Finance & SCM
    • Intro
    • Azure agents
    • How does it work?
    • What do I need?
    • Azure DevOps artifacts
    • Prepare Azure DevOps
    • Configure pipeline
    • Update for version 10.0.18 and greater
  • Azure DevTest Labs powered builds
    • Intro
    • Azure DevTest Labs
    • Getting and preparing the VHD
    • Create a DevTest Labs account
    • Creating the VM
    • Preparing the VM
    • Create a new image
    • Azure DevOps pipelines
    • Run the build
    • Times
    • Show me the money
    • Some final remarks
  • Add and build .NET projects
    • Intro
    • Build .NET in your pipeline
    • Add a C# project to FnO
    • Build pipelinebui
    • Things I don’t like/understand/need to investigate
  • Release Pipelines
    • Intro
    • Setting up Release Pipeline in Azure DevOps for Dynamics 365 for Finance and Operations
    • AAD app creation
    • Create the release pipeline in DevOps
    • Creating the LCS connection
    • New Azure DevOps release tasks: MSAL authentication and ADAL deprecation
  • Automation
    • Update VMs using pipelines and d365fo.tools
    • Builds
    • Releases
    • But I like to add some human touch to it
    • Extra bonus
    • Update a variable in a release
  • LCS DB API
    • Call the LCS Database Movement API from your Azure DevOps Pipelines
    • Automating Prod to Dev DB copies
    • Restore a data package with Azure DevOps Pipelines
  • Secure your Azure Pipelines with Azure Key Vault
    • Azure Key Vault
    • Securing your Azure DevOps Pipelines
View Categories
  • ariste.info
  • Dynamics 365 F&O Dev ALM guide
  • Legacy Guide
  • Automation
  • Update VMs using pipelines and d365fo.tools

Update VMs using pipelines and d365fo.tools

Now that Microsoft will also update additional Dynamics 365 Finance and Operations Sandbox environments, partners and customers will only need to take care of updating cloud-hosted environments, as we’ve always done. I’m sure each team manages this differently, maybe leaving it to each developer to update their VM, or there’s someone in the customer or partner side that will do it. That’s in the best cases, maybe nobody is updating the developer machines…

If you want to know more about builds, releases, and the Dev ALM of Dynamics 365 you can read my full guide on MSDyn365 & Azure DevOps ALM.

Today, I’m bringing you a PowerShell script that you can run in a pipeline that will automatically update all your developer virtual machines!

Update script #

As I’ve already done many times, I’ll be using Mötz Jensen‘s d365fo.tools to run all the operations. This is the complete script:
# CHANGE THIS!!
$AssetId = "LCS_ASSET_ID"
$User = "YOUR_USER"
$Pass = "YOUR_USER_PASSWORD"
$ClientId = "AAD AppId"
$ProjectId = "LCS_PROJECT_ID"

#Get LCS auth token
Get-D365LcsApiToken -ClientId $ClientId -Username $User -Password $Pass -LcsApiUri https://lcsapi.lcs.dynamics.com | Set-D365LcsApiConfig -ProjectId $ProjectId

Get-D365LcsApiConfig

# Get list of all LCS project environments
$Environments = Get-D365LcsEnvironmentMetadata -TraverseAllPages

$StartedEnvs = @()

Write-Host "=================== STARTING ENVIRONMENTS ==================="
Foreach ($Env in $Environments)
{
    # Start Dev VMs only
    if ($Env.EnvironmentType -eq "DevTestDev" -and $Env.CanStart)
    {
        $EnvStatus = Invoke-D365LcsEnvironmentStart -EnvironmentId $Env.EnvironmentId

        if ($EnvStatus.IsSuccess -eq "True") {
            Write-Host ("Environment {0} started." -f $Env.EnvironmentName)

            $StartedEnvs += $Env.EnvironmentId
        }
        else {
            Write-Host ("Environment {0} couldn't be started. Error message: {1}" -f $Env.EnvironmentName, $EnvStatus.ErrorMessage)
        }
    }
}
Write-Host "=================== STARTING ENVIRONMENTS DONE ==================="

Write-Host "=================== SLEEPING FOR 180 seconds ==================="

# Wait 3 minutes for the VMs to start
Start-Sleep -Seconds 180

$Retries = 0

Write-Host "=================== STARTING DEPLOYMENT ==================="
Do
{
    Foreach ($EnvD in $StartedEnvs)
    {
        $EnvStatus = Get-D365LcsEnvironmentMetadata -EnvironmentId $EnvD

        # If the VM has started, deploy the DP
        if ($EnvStatus.DeploymentStatusDisplay -eq "Deployed")
        {
            $OpResult = Invoke-D365LcsDeployment -AssetId $AssetId -EnvironmentId $EnvD

            if ($OpResult.IsSuccess -eq "True") {
                Write-Host ("Updating environment {0} has started." -f $EnvD)

                $StartedEnvs = $StartedEnvs -notmatch $EnvD
            }
            else {
                Write-Host ("Updating environment {0} has failed. Error Message: {1}." -f $EnvD, $OpResult.ErrorMessage)
                Write-Host ("Will retry {0} more time(s)" -f 3 - $Retries)
            }
        }
    }

    $Retries++
} While ($StartedEnvs.Count -ne 0 -or $Retries -eq 3)

Write-Host "=================== STARTING DEPLOYMENT DONE ==================="

Write-Host "Done"
Now let’s take a look at the steps.

Authenticating and getting environments #

The first step will be authenticating to LCS with the Get-D365LcsApiToken cmdlet and getting a list of all our environments with Get-D365LcsEnvironmentMetadata. This includes the sandbox and prod environments, but don’t worry, these won’t be updated. In the last line, we’ll be initializing an array to store the IDs of started environments in the next step.
# CHANGE THIS!!
$AssetId = "LCS_ASSET_ID"
$User = "YOUR_USER"
$Pass = "YOUR_USER_PASSWORD"
$ClientId = "AAD AppId"
$ProjectId = "LCS_PROJECT_ID"

#Get LCS auth token
Get-D365LcsApiToken -ClientId $ClientId -Username $User -Password $Pass -LcsApiUri https://lcsapi.lcs.dynamics.com | Set-D365LcsApiConfig -ProjectId $ProjectId

Get-D365LcsApiConfig

# Get list of all LCS project environments
$Environments = Get-D365LcsEnvironmentMetadata -TraverseAllPages

$StartedEnvs = @()

Starting developer VMs #

Now that we have a list with our environments, we need to start only the cloud-hosted ones. We will attain this by looping through the list we got in the first part and filtering on the EnvironmentType property where it equals DevTestDev. And using the Invoke-D365LcsEnvironmentStart cmdlet we will start each VM. Next we will check if the operation succeeds, or it doesn’t. When we’ve done this for all VMs, we’ll call the Start-Sleep cmdlet and give 3 minutes to the VMs to start.
Write-Host "=================== STARTING ENVIRONMENTS ==================="
Foreach ($Env in $Environments)
{
    # Start Dev VMs only
    if ($Env.EnvironmentType -eq "DevTestDev" -and $Env.CanStart)
    {
        $EnvStatus = Invoke-D365LcsEnvironmentStart -EnvironmentId $Env.EnvironmentId

        if ($EnvStatus.IsSuccess -eq "True") {
            Write-Host ("Environment {0} started." -f $Env.EnvironmentName)

            $StartedEnvs += $Env.EnvironmentId
        }
        else {
            Write-Host ("Environment {0} couldn't be started. Error message: {1}" -f $Env.EnvironmentName, $EnvStatus.ErrorMessage)
        }
    }
}
Write-Host "=================== STARTING ENVIRONMENTS DONE ==================="

Write-Host "=================== SLEEPING FOR 180 seconds ==================="

# Wait 3 minutes for the VMs to start
Start-Sleep -Seconds 180

Trigger the updates #

In the final part, we will start deploying the update to each running VM. Looping through the array we created in the beginning, we’ll use the Get-D365LcsEnvironmentMetadata command to get the status of the VM, and if it’s running we’ll start the deployment using the Invoke-D365LcsDeployment cmdlet. If the operation succeeds, we’ll remove that environment from the array and continue, otherwise we’ll try again up until three times (note that everything is inside a Do-While loop).
$Retries = 0

Write-Host "=================== STARTING DEPLOYMENT ==================="
Do
{
    Foreach ($EnvD in $StartedEnvs)
    {
        $EnvStatus = Get-D365LcsEnvironmentMetadata -EnvironmentId $EnvD

        # If the VM has started, deploy the DP
        if ($EnvStatus.DeploymentStatusDisplay -eq "Deployed")
        {
            $OpResult = Invoke-D365LcsDeployment -AssetId $AssetId -EnvironmentId $EnvD

            if ($OpResult.IsSuccess -eq "True") {
                Write-Host ("Updating environment {0} has started." -f $EnvD)

                $StartedEnvs = $StartedEnvs -notmatch $EnvD
            }
            else {
                Write-Host ("Updating environment {0} has failed. Error Message: {1}." -f $EnvD, $OpResult.ErrorMessage)
                Write-Host ("Will retry {0} more time(s)" -f 3 - $Retries)
            }
        }
    }

    $Retries++
} While ($StartedEnvs.Count -ne 0 -or $Retries -eq 3)

Write-Host "=================== STARTING DEPLOYMENT DONE ==================="

Write-Host "Done"
And after this we should see all our dev VMs servicing on LCS.

Running it in a pipeline #

Once the script is working, running it in a pipeline is totally trivial, and you can do it in a build or a release pipeline, it’s up to you. My pipeline looks like this:
Update pipeline
Dev update pipeline
I’m installing d365fo.tools in the first step with the following script:
Install-Module -Name d365fo.tools -AllowClobber -Scope CurrentUser -Force -Confirm:$false
And in the second task, I’ll be running the update script we’ve just seen at the beginning of this post. Of course, you can do it all in a single task, but I prefer to split it in two because it looks prettier to me.
Remember this isn't the kind of automation we're interested in
Remember, this isn’t the kind of automation we’re interested in

Some advice #

Credentials #
Of course, if you run this in a pipeline DO NOT put the service account credentials there, either use an Azure Key Vault or a variable group with secret values in your pipelines’ library:
Update VMs using pipelines and d365fo.tools
AZDO pipelines library variable group
Not so automated #
Of course, the only really automagic part of this is the starting and updating of the VMs. When the servicing is done, you need to stop the VMs. You can also run a pipeline that stops them after X hours, that’s up to you. Also, if servicing fails you have to resume the operations or fix whatever is wrong and resume them, that’s pretty manual. And that’s all, I hope this helps, specially if you have lots of CHE VMs because updating all of them manually is a bit slow if you have to do it from LCS.

Subscribe! #

Receive an email when a new post is published
What are your Feelings
Share This Article :
  • Facebook
  • X
  • LinkedIn
  • Pinterest
Still stuck? How can I help?

How can I help?

Builds

Write A Comment Cancel Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Table of Contents
  • Update script
  • Authenticating and getting environments
  • Starting developer VMs
  • Trigger the updates
  • Running it in a pipeline
    • Some advice
      • Credentials
      • Not so automated
  • Dynamics 365 Community
  • Subscribe!
  • Microsoft MVP
  • LinkedIn
  • Privacy Policy
  • Contact
  • About me

© 2024 ariste.info. Designed by CazaPelusas.

Top

    Type above and press Enter to search. Press Esc to cancel.