1

Fully automated (Golden) Image build and deployment to VMware Horizon using Azure DevOps, Packer and Chocolatey

Why?

In my previous post I already described that after rebuilding my home lab, it is a challenge to deploy an automated image on my vmware infrastructure. I did this with the help of packer for the Windows 10 image and for the packaging of the applications and agents I used chocolatey. 

But after the deployment of this Windows 10 image, there were still a number of actions that had to be done manually. After each adjustment in 1 of the scripts, the command with powershell had to be kicked off manually. After that you are still busy monitoring the progress of the process. And at the end the image must also be manually pushed to the correct VMware Horizon Desktop pool. All in all, a lot of actions. Every system administrator is of course a bit lazy, so why wouldn’t I automate it completely.

How?

I would like to take you along in this blog post on how to build a Windows 10 image and deploy it to a VMware Horizon Desktop Pool using Azure DevOps. As you can see in the image below, an on-premise Azure Devops Agent is required to handle the tasks in my homelab. This agent will use the PowerShell, PowerCLI and packer commands to build the image and eventually deploy it to a TST and ACC Desktop Pool.

In this blog I will show a release pipeline as well as a “regular” one. The release pipeline can be clicked together from the GUI and in the case of the “regular” a YAML file will also have to be created. In this way, a complete image deployment as code will be applied.

Let’s start!

All Files required for this project can be found on my github over here: https://github.com/roderikdeblock/Packer_AzureDevops

 

Create a new DevOps organization and/or Project

  • Go  to dev.azure.com and login with your Office 365 Personal or Work email. Agree to DevOps agreement and continue.
  • Click “New Project” on the right side of the windows and give your project a name
  • Be sure you set this project to “Private” if you don’t want to share it publicly.

 

Set up the On-Prem Agent

I used a Windows 10 Virtual Machine and already installed the following items on this machine:

  • Packer
  • PowerCLI 12.0
  • VMware.HV.Helper Module (which can be found here)

1.  Now it’s time to install the on-premise agent. Navigate to “Project Settings” at the bottom of your screen and click on “agent pools”.

2. Select “New”

3. Select “New” –> “Self -hosted” –> and give the pool a name.

4. Select the “Agents” tab and select “New Agent”

5. Select your Operating System –> Download the Agent –> Run the commands

6. At the moment the agent is running this will appear as online.

Setting up the Repo

1. If the “Repos” is not visible in your menu you can enable this by browsing to the “Project Settings” at the bottom of your screen.

2. After this it is time to set up a repo for your files.

3. I chose to upload the files from my previous post to this repo.

Setting up the Release Pipeline

1. Now it’s time to create the release pipeline. Navigate to “Pipelines” –> “Releases” and select “New” + “New release pipeline”

2. Select “Empty Job”

3. Give the Stage a name and select “Save”

4. Select “Add an artifact

5. Select “Azure Repos” and select your repo, finally click “add”

6. Now we can start building the “build image stage”

7. Select your Agent Pool

8. Add a job to the Agent by clicking “+”

9. Search for Copy and select “Copy Files” and select “Add”

10. Search for Powershell and select “Powershell” and select “Add”

11. Configure the Copy Files –> Source folder = <your_repo> –> Target = $(System.DefaultWorkingDirectory)

12. Configure the PowerShell Script. Give it a name and  select the build.ps1 and select “OK”

This is a oneliner which wil start packer with the 2 JSON files:

& 'c:\programdata\chocolatey\lib\packer\tools\packer.exe' build -var-file .\variables.json .\windows10.json

13. Now it’s time to create the next 2 Stages (Deploy_To_TST & Deploy To_Acc). Select “Add”.

14. Select “Empty job”

15. Give the Stage a name. (Deploy_To_TST)

16. Do this again for the next Stage (Deploy_To_ACC)

17. Configure the Deploy_To_TST stage by selecting this button

18. Select the “Agent Job”, your Agent Pool and select “+”

19. Search for PowerShell and add Powershell

20. Select the “Deploy_To_Horizon_TST.ps1” .

This script contains these variables and commands:

$User = "<Your_Horizon_Administrator>"
$Password = "<Your_Horizon_Administrator_Password>"
$Domain = "<Your_Domaion>"
$Server = "<Your_Connection_Server_FQDN>"
$Snapshot = "Created by Packer"
$Pool = "<Your_Desktop_Pool>"
$VMName = "<Your_VMName>"




#############################################################
##                                                         ##
##           Connect to Horizon Connection Server          ##
##                                                         ##
#############################################################

VMware.VimAutomation.HorizonView\Connect-HVServer -Server $Server -Domain $Domain -User $User -Password $Password


#############################################################
##                                                         ##
##           Push Image to Horizon ACC Pool                ##
##                                                         ##
#############################################################


Start-HVPool -SchedulePushImage -Pool $Pool -LogoffSetting WAIT_FOR_LOGOFF -ParentVM $VMName -SnapshotVM $Snapshot


#############################################################
##                                                         ##
##      Disconnect from Horizon Connection Server          ##
##                                                         ##
#############################################################

VMware.VimAutomation.HorizonView\Disconnect-HVServer -Confirm:$False

21. Click OK and Save and perform these action again for the “Deploy_TO_ACC” Stage.

22. The Release Pipeline should look like this:

23. Now there are several options to trigger this Pipeline:

  • Enable the continuous deployment trigger (Lightning icon)
  • Schedule the Pipeline
  • Pre deployment options (Select triggers, users groups that can approve, schedule , ….)
  • Post deployment options (Auto-redeploy trigger, select approvers, ….)

24. I will trigger the Pipeline manually this time by selecting “Create release” in the upper right corner –> Select “Create”

25. Release-1 is created

26. After Clicking on “Release-1” you can monitor the Packer process.

 

27. As you can see the total time of this release was 52 minutes. It could also have been 5 minutes faster since I had built in another 5 minute “sleep” for the ACC deployment. This is quite nice for building a Windows 10 image, including Windows Updates, Horizon Agents, OSOT optimize and pushing to 2 desktop pools.

28. This is just a basic setup. From here you can build further and, for example, add multiple steps for error handling and basically anything you want. It is also possible to store your variables in Azure Devops and even use variables which are present in an Azure KeyVault.

Pipeline

1.  It is also possible to go one step further and run everything as code. A YAML file is required for this. The following file contains the setup like we create in the section above.

trigger:
- main

stages:
- stage: Build_Deploy_W10
  pool: 'Default'
  jobs:  
  - job: Building_Image
    displayName: 'Building_Image'
    steps: 
    - task: CopyFiles@2
      displayName: 'Copy Files to: $(System.DefaultWorkingDirectory)'
      inputs:
       SourceFolder: '$(System.DefaultWorkingDirectory)/_screenshot'
       TargetFolder: '$(System.DefaultWorkingDirectory)'
    - task: PowerShell@2
      displayName: 'Building_Image'
      inputs:
        filePath: '$(System.DefaultWorkingDirectory)\Build.ps1'

- stage:  Deploy_To_TST
  pool: 'Default'
  jobs:  
  - job: Deploy_To_TST
    displayName: 'Deploy_To_TST'
    steps: 
    - task: PowerShell@2
      displayName: 'Building_Image'
      inputs:
       filePath: '$(System.DefaultWorkingDirectory)\Deploy_To_Horizon_ACC.ps1'
       
- stage: Deploy_To_ACC
  pool: 'Default'
  jobs:         
  - job: Deploy_To_ACC
    displayName: 'Deploy_To_ACC'
    steps: 
    - task: PowerShell@2
      displayName: 'Building_Image'
      inputs:
       filePath: '$(System.DefaultWorkingDirectory)\Deploy_To_Horizon_ACC.ps1' After creating this file. Go to "Pipelines"

2. Select “New Pipeline”

 

3. Select you repository

4. Select “existing Azure Pipelines ….”

5. Select the YAML you just created

6. Select “Run”

7. The Pipeline will run

 

Every commit in this reposity will trigger the Pipeline.

I hope that I have been able to clarify how powerful this tooling is, how you can set it up and what the possibilities are. You make things easier for yourself and your colleagues.

Roderik de Block

Roderik de Block

One Comment

  1. Very cool! I’m an aspiring SysAdmin who’s been trying to find reasons to learn a lot of the DevOps tools out now. Thank you for this awesome write up since it goes along with my want to implement some type of automation to build VM’s for my team for testing.

Leave a Reply

Your email address will not be published. Required fields are marked *