Automating my way out of ancillary tasks with PowerShell

After creating a handful of virtual machines for ramping up on the different Linux distros, certain configuration patterns started to emerge. Repeating those same settings over and over again in Hyper-V Manager or even PowerShell’s command line interface is kind of tedious. Good thing is scripts are a great way to automate those repetitive configuration tasks away.

In my case, the settings I kept copying over and over again were:

  • Two cores;
  • Network adapter bound to a virtual switch with external connectivity;
  • Automatic Checkpoints turned off;

And then there were other settings that although varied between distros and installation options within those distros, had to be configured each and every time:

  • Virtual machine name;
  • RAM size;
  • Hard drive size;
  • Path to installation ISO;
  • Secure Boot;

So after learning and getting comfortable with the different PowerShell cmdlets, I started prototyping a few scripts. At first, the scripts were kind of lame and buggy, but as I learned more about the features of Hyper-V and how those features are exposed through PowerShell, the scripts were improved little by little much in the spirit of Kaizen – continuous improvement.

The important thing here is realizing this as a learning tool and as such starting small and improving as you go and as new requirements make themselves known.

Important as well is knowing when to stop. The purpose of this exercise isn’t creating a production-ready script, but to create a script that will allow me to get back as soon as possible to what I settled out to do in the first place: Create virtual machines so I could learn something else.

If you are curious enough, you can find the source code for one of the early versions of the scripts as a gist over on GitHub. If you are even more curious, you can see the entire history of how the code evolved also on GitHub.

Since that early prototype, the code has evolved quite a bit from a collection of discrete scripts to the current version which is implemented as a PowerShell module and incorporates all the learnings of the last few weeks – including a best practice for creating virtual hard disks for use with Linux file systems. Good luck trying remember that one every time you create a new VM for Linux!

function Get-OrphanedVHDs {
$rootedVHDs = (Get-VM).HardDrives.Path + (Get-VM | Get-VMSnapshot).HardDrives.Path
Return Get-ChildItem (Get-VMHost).VirtualHardDiskPath | Where-Object { $_.FullName -notin $rootedVHDs }
}
function New-VirtualMachine {
Param(
$Name,
$MemoryBytes,
$VHDSizeBytes,
$IsoPath,
$SecureBootTemplate,
$SwitchName
)
# If a switch name hasn't been provided, it'll try to find a default.
if (!$SwitchName) {
$Switches = Get-VMSwitch | Where-Object SwitchType -eq 'External'
#If there's only one switch with external connectivity, that's it.
#Else, a switch name should have been provided.
if ($Switches.Count -eq 1) {
$SwitchName = $Switches.Name
}
}
$VHDPath = Join-Path -Path (Get-VMHost).VirtualHardDiskPath -ChildPath ($Name + ".vhdx")
if ($SecureBootTemplate -eq "MicrosoftWindows") {
$null = New-VHD -Path $VHDPath -SizeBytes $VHDSizeBytes
}
else {
$null = New-VHD -Path $VHDPath -SizeBytes $VHDSizeBytes -BlockSizeBytes 1MB
}
$VM = New-VM -Name $Name -MemoryStartupBytes $MemoryBytes -Generation 2 -BootDevice VHD -SwitchName $SwitchName -VHDPath $VHDPath
Set-VM $VM -ProcessorCount 2 -MemoryMaximumBytes $MemoryBytes -AutomaticCheckpointsEnabled $false
Add-VMDvdDrive $VM -Path $IsoPath
Set-VMFirmware $VM -BootOrder ((Get-VMFirmware $VM).BootOrder | ? BootType -eq 'Drive')
if ($SecureBootTemplate) {
Set-VMFirmware $VM -SecureBootTemplate $SecureBootTemplate
}
else {
Set-VMFirmware $VM -EnableSecureBoot Off
}
Return $VM
}
function Remove-VirtualMachine {
Param(
$VMName
)
$vm = Get-VM $VMName
$snapshot = (Get-VMSnapshot $vm | ? ParentSnapshotName -eq $null)
if ($snapshot) {
$vhds = $snapshot.HardDrives.Path
}
else {
$vhds = $vm.HardDrives.Path
}
Remove-VM $vm -Force
Remove-Item $vhds
}
view raw Power-V.psm1 hosted with ❤ by GitHub

Certainly there are a lot of opportunities for improvement (documentation, error handling and resilience in general just to name a few), but those are left as an exercise for future self. Meanwhile, let me get back to playing with those VMs.

Published by

Alfred Myers

I have been interested in computers since I got my hands on a magazine about digital electronics back in 1983 and programming them has been paying the bills since 1991. Having focused on Microsoft-centric technology stacks for the best part of two decades, in recent years I’ve been educating myself on open source technologies such as Linux, networking and the open web platform.