Creating Hyper-V VM’s with Desired State Configuration
I'm looking to automate the build of my test environment that runs as Hyper-V virtual machines on my Windows 8.1 Laptop computer. To get started, I thought I would take a look at the xHyper-V DSC resource to create the actual VM's. There's also no reason this shouldn't work on a Windows Server that's running the Hyper-V role.
The Hyper-V role has already been added to my Windows 8.1 computer. I also have a previously created
virtual hard drive (vhdx) file that has been loaded with the Windows Server 2012 R2 operating system
and all of the available Windows updates. That OS has been syspreped, an unattend.xml
file has been
added to it to set the local administrator password when a new VM is created using a differencing
disk based on this parent vhdx, and the vhdx has been marked as read only.
I've downloaded the
DSC Resource Kit Wave 9
which contains the most recent versions of all of the Microsoft created DSC resources to include the
xHyper-V DSC resource. What's the x
stand for? Experimental.
The xHyper-V resource has been extracted from the downloaded DSC Resource Kit Wave 9 zip file and
added to the C:\Program Files\WindowsPowerShell\Modules
folder on my Windows 8.1 computer that I
want to create the VM's on.
I've created a configuration as shown in the following example:
1Configuration MrHyperV_VM {
2
3 param (
4 [Parameter(Mandatory)]
5 [string]$VMName,
6
7 [Parameter(Mandatory)]
8 [string]$baseVhdPath,
9
10 [Parameter(Mandatory)]
11 [string]$ParentPath,
12
13 [Parameter(Mandatory)]
14 [string]$VMSwitchName
15 )
16
17 Import-DscResource -module xHyper-V
18
19 xVMSwitch switch {
20 Name = $VMSwitchName
21 Ensure = 'Present'
22 Type = 'Internal'
23 }
24
25 xVHD DiffVHD {
26 Ensure = 'Present'
27 Name = $VMName
28 Path = $baseVhdPath
29 ParentPath = $ParentPath
30 Generation = 'vhdx'
31 }
32
33 xVMHyperV CreateVM {
34 Name = $VMName
35 SwitchName = $VMSwitchName
36 VhdPath = Join-Path -Path $baseVhdPath -ChildPath "$VMName.vhdx"
37 ProcessorCount = 1
38 MaximumMemory = 2GB
39 MinimumMemory = 512MB
40 RestartIfNeeded = 'True'
41 DependsOn = '[xVHD]DiffVHD', '[xVMSwitch]switch'
42 State = 'Running'
43 Generation = 'vhdx'
44 }
45}
I've run this configuration so it's loaded in memory in my current PowerShell session:
1Get-Command -CommandType Configuration
I'll now call the configuration along with the necessary parameters and values which creates the MOF file:
1MrHyperV_VM -VMName Test01 -baseVhdPath 'D:\Hyper-V\Virtual Hard Disks' -ParentPath 'D:\Hyper-V\Virtual Hard Disks\Template\Server2012R2Core-Template_011915.vhdx' -VMSwitchName 'Internal Virtual Switch'
The MOF file is applied to my local computer using the Start-DscConfiguration
cmdlet:
1Start-DscConfiguration -Wait -Path .\MrHyperV_VM -Verbose
A new virtual machine named Test01 has been created as specified in the configuration:
1Get-VM -Name Test01
Piping a few cmdlets together, allows you to see the virtual hard drive information for the newly created VM to include its location, type (differencing), and its parent:
1Get-VM -Name Test01 | Get-VMHardDiskDrive | Get-VHD
As shown here, the IP address of the VM can easily be obtained from the Hyper-V host:
1Get-VM -Name Test01 | Get-VMNetworkAdapter
Now to add the IPv4 address to the trusted host list on my pc so I can run commands on the VM via
PowerShell remoting. This is necessary because of Kerberos mutual authentication not being available
due to the new VM being in a workgroup by default. For security reasons, the IP should be removed
from the trusted host list once the new VM is added to the domain. You should NEVER add "*" to the
trusted host list <period>
.
1Set-Item -Path WSMan:\localhost\Client\TrustedHosts -Value "$((Get-VM -Name Test01 | Get-VMNetworkAdapter).ipaddresses -match '\d{1,3}(\.\d{1,3}){3}')" -Concatenate -Force
You can see that it has indeed been added:
1Get-Item -Path WSMan:\localhost\Client\TrustedHosts
Now to test running a command on the VM from my pc with PowerShell remoting:
1Invoke-Command -ComputerName 192.168.29.108 {
2 $PSVersionTable.PSVersion
3} -Credential (Get-Credential)
One thing to note is that PowerShell remoting is enabled by default on Windows Server 2012 and higher which is why no changes had to be made on the VM to accomplish this.
At this point, I should be able to create a DSC configuration to add the VM to the domain and make all of the configuration changes I want to it. I wrote about that process in a previous blog article on Use a certificate with PowerShell DSC to add a server to Active Directory without hard coding a password.
If Desired State Configuration is something that you're interested in, you should definitely take a look at the video from the January Mississippi PowerShell User Group meeting.
µ