New-LabVM.psm1
# Version 2.4 (27-03-2017) <# .Synopsis This module lets you roll out your lab environment automatically. This is the second step: creating a Lab VM's. .DESCRIPTION This module lets you roll out your lab environment automatically as described in our blogs (www.365dude.nl and www.svenvanrijen.nl). This is the second step: creating Lab VM's. First step: creating a NATSwitch (New-NATSwitch). New-LabVM generates a new VM in the lab environment. IPAddress is a mandatory parameter and must be in the "172.16.10.10/24" notation. Please use the same address space as used when creating the NATSwitch. The specification of a Gateway is optional. If DNS-server is not specified, the default will be used. (172.16.10.1) The specification of a DNS-server is optional. If DNS-server is not specified, the default will be used. (8.8.8.8) For more information or help regarding this module, please visit the GitHub repo: https://github.com/ralpje/PowerShell-Lab-Module .EXAMPLE New-LabVM -VMName Test -VMIP 10.0.0.18/29 -GWIP 10.0.0.1 .EXAMPLE New-LabVM -VMName Hostname -VMIP 192.168.123.20/24 -DNSIP 192.168.123.5 -GWIP 192.168.123.1 #> function New-LabVM { [CmdletBinding( SupportsShouldProcess = $true )] [OutputType([String])] Param ( [Parameter(Mandatory = $true)] [string]$VMName, [Parameter(Mandatory = $false)] [int64]$MemoryStartupBytes = 2048MB, [Parameter(Mandatory = $true)] [string]$VMIP, [Parameter(Mandatory = $false)] [string]$GWIP = '172.16.10.1', [Parameter(Mandatory = $true)] [string]$Diskpath, [Parameter(Mandatory = $true)] [string]$ParentDisk, [Parameter(Mandatory = $true)] [string]$VMSwitch, [Parameter(Mandatory = $false)] [string]$DNSIP = '8.8.8.8', [Parameter(Mandatory = $false)] [string]$Unattendloc = 'https://raw.githubusercontent.com/ralpje/PowerShell-Lab-Module/master/Templates/unattend.xml', [Parameter(Mandatory = $false)] [boolean]$DSC = $false, [Parameter(Mandatory = $false)] [string]$DSCPullConfig, [Parameter(Mandatory = $false)] [boolean]$NestedVirt ) Begin { } Process { #region create diff disk # Create new differencing disk $maindiskpath = "$diskpath$VMName.vhdx" New-VHD -ParentPath $ParentDisk -Path $maindiskpath -Differencing Write-Verbose -Message "Created a differencing disk $maindiskpath." Start-Sleep -Seconds 2 #endregion #region copy adjusted answer file # mount VHD $VHD = Mount-VHD -Path $maindiskpath -Passthru $x = Get-Disk $vhd.Number | Get-Partition | Where-Object -FilterScript { $_.Type -eq 'Basic' } Get-Disk $vhd.Number | Set-Disk -IsOffline $false Set-Partition -PartitionNumber $x.PartitionNumber -NewDriveLetter T -DiskNumber $x.DiskNumber -ErrorAction SilentlyContinue New-PSDrive -Name T -Root t:\ -PSProvider FileSystem | Out-Null Write-Verbose -Message 'Differencing disk mounted' Start-Sleep -Seconds 2 # Copy xml from source to local temp dir New-Item -ItemType Directory -Path "$PSScriptRoot\Temp" -Force $output = "$PSScriptRoot\temp\unattended.xml" Invoke-WebRequest -Uri $unattendloc -OutFile $output Write-Verbose -Message "Unattended.xml copied from $unattendloc to $PSScriptRoot\Temp." Start-Sleep -Seconds 2 $SourceXML = "$PSScriptRoot\temp\unattended.xml" # add XML Content [xml]$Unattend = Get-Content $SourceXML $Unattend.unattend.settings[1].component[2].ComputerName = $VMName $Unattend.unattend.settings[1].component[3].Interfaces.Interface.UnicastIpAddresses.IpAddress.'#text' = $VMIP $Unattend.unattend.settings[1].component[4].Interfaces.Interface.DNSServerSearchOrder.IpAddress.'#Text' = $DNSIP $Unattend.unattend.settings[1].component[3].Interfaces.Interface.Routes.Route.NextHopAddress = $GWIP $Unattend.Save("T:\\Unattend.xml") Write-Verbose -Message "Set VM name to $VMName, IP Address to $VMIP, DNS IP to $DNSIP and GW IP to $GWIP" Start-Sleep -Seconds 2 if ($DSC -eq $true) { # Copy DSC Pull Config to TEMP $destps1 = "$PSScriptRoot\temp\DSCPullConfig.ps1" Copy-Item -Path $DSCPullConfig -Destination $destps1 Set-Location -Path "$PSScriptRoot\temp\" #Edit DSC Pull Config so it will contain the right node-name ($vmname) (Get-Content -Path '.\DSCPullConfig.ps1') -replace '\breplace\b', "$VMName" | Out-File -FilePath '.\DSCPullConfig.ps1' #Kick off DSC Pull Config to generate metamof . '.\DSCPullConfig.ps1' DscMetaConfigs @Params $sourcemof = "$PSScriptRoot\temp\DscMetaConfigs\$VMName.meta.mof" $destmof = "T:\Windows\system32\Configuration\MetaConfig.mof" Move-Item -Path $sourcemof -Destination $destmof -Force Write-Verbose -Message "Copied metaconfig.mof to T:\Windows\system32\Configuration\MetaConfig.mof" reg.exe load HKLM\Vhd T:\Windows\System32\Config\Software Set-Location -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies Set-ItemProperty -Path . -Name DSCAutomationHostEnabled -Value 2 [gc]::Collect() reg.exe unload HKLM\Vhd Write-Verbose -Message "Enabled DSC Automation Host on $VMName." } # dismount VHD Dismount-VHD $maindiskpath Write-Verbose -Message 'Differencing disk dismounted' #endregion #region create new vm # Create VM with new VHD New-VM -Name $VMName -MemoryStartupBytes $MemoryStartupBytes -SwitchName $VMSwitch -VHDPath $maindiskpath -Generation 2 -BootDevice VHD #endregion Write-Verbose -Message "Created new lab VM with name $VMName, $MemoryStartupBytes memory. The VM is connected to $VMSwitch with IP address $VMIP." Start-Sleep -Seconds 2 if ($NestedVirt -eq $true) { Set-VMProcessor -VMName $VMName -ExposeVirtualizationExtensions $true Write-Verbose -Message "Exposed Virtualization Extensions on $VMName." } #region start new vm and connect to console # Start VM Start-VM $VMName Start-Process -FilePath vmconnect -ArgumentList localhost, $VMName Write-Verbose -Message "Started $VMName." #endregion Set-Location -Path c:\ } End { } } |