Building my Orion Server [Hyper-V Scripting Edition] – Step 1

This is part 1 of a multi-part post on updates that I’ve made to How I Build an Orion Server.  Primarily, it will be three parts.  If you have VMware, I’ve also got a script edition for that as well.

  1. Building my Orion Servers in Hyper-V
  2. Configuring the disks on the VM after OS install
  3. Configuring the VM with the new disks

In my role with SolarWinds, I need to build Orion Servers nearly every week.  I’ve come up with a great way to configure them and I’ve documented this in the previous linked post, but doing the same thing over and over again is just prone to human error.  So I’m back to my old adage:

  • Doing it once?  Do it by hand.
  • Doing it twice?  Think about automating.
  • Doing it thrice?  You need to script this.
  • Doing it more?  Aren’t you glad you scripted this?

So we’ll start with the basics.  Building the VM itself.  I build all of my Orion Servers in Hyper-V – it’s just a personal preference.  If you use another hypervisor, feel free to change out the script for your needs.

So, there’s some basic information that I need when I build any VM.  Most of this is CPU count, Memory, and Hard Disks.  I’m crunched for space on my current Hyper-V server, so I always use Dynamic Hard Disks.  This is not the idea for performance, so I’ve given myself the option to instead change that setting in the script in the variable declaration.

So, here’s my variable declaration:

#region Variable Declaration
$VMName = "OrionServer" # Server Name
$CPUCount     = 4       # Number of CPU's to give the VM
$CPUReserve   = 50      # Percentage of CPU's being reserved
$RAMBoot      = 8GB     # Startup Memory
$RAMMin       = 8GB     # Minimum Memory (should be the same as RAMBoot)
$RAMMax       = 16GB    # Maximum Memory
$DynamicDisks = $true   # Use Dynamic Disks?
$Vlan         = 300     # VLAN assignment for the Network Adapter
# Sizes and count of the disks
$VHDSizes = [ordered]@{ "C" = 40GB; # Boot
                        "D" = 26GB; # Page 
                        "E" = 40GB; # Programs
                        "F" = 10GB; # Web
                        "G" = 10GB  # Logs
                      }
#endregion

Easy part is done.  I’ve configured how I want the Orion Server to be architected (at least the general framework).

Next is going through the motions of using these variables to create a VM.

I’m going to start with the hard disks.  I’ve already declared them by drive letter and by size, but I need a few more things before creating them.  Namely the path.  What I do for the Path is pretty simple: I put them with all the other Virtual Hard Disks.  I get this from using Get-VMHost to get the Default Path.  Then I take the drive list and the default path and put it all together into a new PowerShell Object.

# Assume that we want to make all the VHDs in the default location for this server.
$VHDRoot = Get-Item -Path ( Get-VMHost | Select-Object -ExpandProperty VirtualHardDiskPath )

# Convert the hash table of disks into PowerShell Objects (easier to work with)
$VHDs = $VHDSizes.Keys | ForEach-Object { New-Object -TypeName PSObject -Property ( [ordered]@{ "ServerName" = $VMName; "Drive" = $_; "SizeBytes" = $VHDSizes[$_] } ) }
# Extend this object with the name that we'll want to use for the VHD
### My naming scheme is [MACHINENAME]_[DriveLetter].vhdx - adjust to match your own.
$VHDs | Add-Member -MemberType ScriptProperty -Name VHDPath -Value { Join-Path -Path $VHDRoot -ChildPath ( $this.ServerName + "_" + $this.Drive + ".vhdx" ) } -Force

# Create the VHDs
$VHDs | ForEach-Object { 
    if ( -not ( Test-Path -Path $_.VHDPath -ErrorAction SilentlyContinue ) )
    {
        Write-Verbose -Message "Creating VHD at $( $_.VHDPath ) with size of $( $_.SizeBytes / 1GB ) GB"
        New-VHD -Path $_.VHDPath -SizeBytes $_.SizeBytes -Dynamic:$DynamicDisks | Out-Null
    }
    else
    {
        Write-Host "VHD: $( $_.VHDPath ) already exists!" -ForegroundColor Red
    }
}

Got variables, got disks, now I just need to create the VM.  I do this in a series of 5 steps.

# Step 1 - Create the VM itself (shell) with no Hard Drives to Start
$VM = New-VM -Name $VMName -MemoryStartupBytes $RAMBoot -SwitchName ( Get-VMSwitch | Select-Object -First 1 -ExpandProperty Name ) -NoVHD -Generation 2 -BootDevice NetworkAdapter
# Step 2 - Bump the CPU Count
$VM | Set-VMProcessor -Count $CPUCount -Reserve $CPUReserve
# Step 3 - Set the Memory for the VM
$VM | Set-VMMemory -DynamicMemoryEnabled:$true -StartupBytes $RAMBoot -MinimumBytes $RAMMin -MaximumBytes $RAMMax
# Step 4 - Set the VLAN for the Network device
$VM | Get-VMNetworkAdapter | Set-VMNetworkAdapterVlan -Access -VlanId $Vlan
# Step 5 - Add Each of the VHDs
$VHDs | ForEach-Object { $VM | Add-VMHardDiskDrive -Path $_.VHDPath }

So that’s it.

After it’s executed, this is what I get:

That’s pretty much it.  The same script works on Hyper-V for Server 2012 R2 and for Server 2016!

Now I boot it up use my Windows Deployment Server to install Server 2012 R2 Server 2016 and go from there.

The next post will include an optimized way that I handle the post-image configuration.  It’s basically a scripted version of my original post.

Keep on Rambling!