Skip to content

Instantly share code, notes, and snippets.

@Sarafian
Created October 11, 2016 11:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Sarafian/507a035636b36694fe2a0bf665236cd1 to your computer and use it in GitHub Desktop.
Save Sarafian/507a035636b36694fe2a0bf665236cd1 to your computer and use it in GitHub Desktop.
#Requires -RunAsAdministrator
<#
.Synopsis
Creates a new Hyper-V instance from a named template.
.DESCRIPTION
Imports an existing Hyper-V export into a new instance, set-up the local client host/ip resoltution and generate bootstrapping powershell script.
.PARAMETER OSVersion
The code name for operating system
.PARAMETER VMName
The name of the new instance
#>
param(
[Parameter(Mandatory=$true)]
[string]$OSVersion,
[Parameter(Mandatory=$true)]
[string]$VMName
)
$rootPath="C:\Users\Public\Documents\Hyper-V"
$exportPath=Join-Path $rootPath "Exports"
$vmNameToImport="Template-$OSVersion"
$importPath=Join-Path $exportPath $vmNameToImport
$importPath=Join-Path $importPath "Virtual Machines"
$vmcxPathToImport=Get-ChildItem $importPath -Filter "*.vmcx" |Select-Object -ExpandProperty FullName -First 1
if(Get-VM -Name $VMName -ErrorAction SilentlyContinue)
{
throw "VM with name $VMName already exists"
}
Import-VM -Path $vmcxPathToImport -Copy -GenerateNewId
Rename-VM $vmNameToImport –NewName $VMName
Get-VMHardDiskDrive -VMName $VMName |ForEach-Object {
$vhd=$_
$newPath = Join-Path (Split-Path $vhd.Path -Parent) "$vmName.vhdx"
Rename-Item $vhd.Path $newPath
Set-VMHardDiskDrive -VMName $vhd.VMName -Path $newPath –ControllerType $vhd.ControllerType –ControllerNumber $vhd.ControllerNumber -ControllerLocation $vhd.ControllerLocation
}
$null=Start-VM -Name $VMName
while((Get-VM -Name $VMName).NetworkAdapters.IPAddresses.Count -eq 0)
{
}
$vmIpAddress = (Get-VM -Name $VMName).NetworkAdapters.IPAddresses[0]
Add-HostEntry -Name $VMName -Address $vmIpAddress -Force
$trustedHostsItem=Get-Item WSMan:\localhost\Client\TrustedHosts | Select-Object -ExpandProperty Value
if($trustedHostsItem.Length -gt 0)
{
$trustedHosts=$trustedHostsItem -split ','
}
else
{
$trustedHosts=@()
}
if($trustedHosts -notcontains $VMName)
{
$trustedHosts+=$vmName
Set-Item WSMan:\localhost\Client\TrustedHosts -Value ($trustedHosts -join ',') -Force
}
$vmAdministratorCredentials=New-HyperVMAdministratorCredential
$vmAdministratorPassword=$vmAdministratorCredentials |Show-Credential |Select-Object -ExpandProperty Password
$netArgs=@(
"use"
"\\$vmName"
"/user:.\$($vmAdministratorCredentials.Username)"
"$vmAdministratorPassword"
)
Start-Process -FilePath "net" -ArgumentList $netArgs -Wait -NoNewWindow
$initCommands= @(
"#Set execution policy to unrestricted"
"Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force"
"#Set timezone"
"Set-TimeZone -Name 'Central European Standard Time'"
"#Enable the num lock"
"Set-ItemProperty -Path 'HKCU:\Control Panel\Keyboard' -Name InitialKeyboardIndicators -Value 2"
"#Enable powershell remoting"
"Enable-PSRemoting -Force"
"#Rename the computer"
"Rename-Computer -NewName $VMName -Force"
"#Enable file sharing"
"Get-NetFirewallRule -DisplayGroup 'File and Printer Sharing*'|Enable-NetFirewallRule"
"#Restart"
"Restart-Computer -Force"
"#Finish"
)
$initCmd=$initCommands -join [System.Environment]::NewLine
Write-Host "From withing the Virtual OS, execute the following Powershell script."
Write-Host $initCmd
#Requires -RunAsAdministrator
<#
.Synopsis
Creates a new Hyper-V template.
.DESCRIPTION
Creates a new Hyper-V instance, drives the OS install, exports the VM and removes the artifacts.
.PARAMETER OSVersion
The code name for operating system
.PARAMETER MediaPath
The path to the iso media to drive the operating system installation
#>
param(
[Parameter(Mandatory=$true)]
[ValidateSet("2016","2016DE")]
[string]$OSVersion,
[Parameter(Mandatory=$true)]
[string]$MediaPath
)
$vmName = "Template-$OSVersion"
if(Get-VM -Name $vmName -ErrorAction SilentlyContinue)
{
throw "VM with name $vmName already exists"
}
$rootPath="C:\Users\Public\Documents\Hyper-V"
$vhdPath=Join-Path $rootPath "Virtual Hard Disks\$VMName.vhdx"
$existingVMSwitch=Get-VMSwitch |Where-Object -Property SwitchType -EQ External|Select-Object -First 1
if(-not $existingVMSwitch)
{
$netAdapterName=Get-NetAdapter |Where-Object -Property Name -Like "Ethernet*"|Select-Object -ExpandProperty Name -First 1
New-VMSwitch -name "External Virtual Switch" -NetAdapterName $netAdapterName -AllowManagementOS $true
}
$switch=Get-VMSwitch |Where-Object -Property SwitchType -EQ External|Select-Object -ExpandProperty Name -First 1
New-VM -Name $vmName -MemoryStartupBytes 1GB -Generation 2 -NewVHDPath $vhdPath -NewVHDSizeBytes 50GB -SwitchName $switch
Add-VMDvdDrive -VMName $vmName -Path $MediaPath
Start-VM -Name $vmName
Write-Host "Execute windows updates (sconfig 6,A,A) and shutdown the $OSVersion installation on $vmName."
Pause
Stop-VM -Name $vmName -Force
$exportPath=Join-Path $rootPath "Exports"
Export-VM -Name $vmName -Path $exportPath
Get-VMHardDiskDrive -VMName $vmName |ForEach-Object {
#TODO Needs checking how to delete the hard disk drive
Remove-Item -Path (Join-Path $_.Path $_.Name) -Force|Out-Null
#Output object for next pipeline cmdlet
$_
}|Remove-VMHardDiskDrive
Remove-VM -Name $vmName -Force
#Requires -RunAsAdministrator
<#
.Synopsis
Remove a Hyper-V instance.
.DESCRIPTION
Stop the Hyper-V instance and remove the disk and virtual machine
.PARAMETER VMName
The name of the instance to remove
#>
param(
[Parameter(Mandatory=$true)]
[string]$VMName
)
$rootPath="C:\Users\Public\Documents\Hyper-V"
Stop-VM -Name $VMName -Force
Get-VMHardDiskDrive -VMName $VMName |ForEach-Object {
Remove-Item $_.Path
$_|Remove-VMHardDiskDrive
}
Remove-VM -Name $VMName -Force
@Sarafian
Copy link
Author

To create a Windows Server 2016 template

New-HVTemplate.ps1 -OSVersion 2016 -MediaPath "14393.0.160715-1616.RS1_RELEASE_SERVER_EVAL_X64FRE_EN-US.ISO"

Then to create an instance

New-HV.ps1 -OSVersion 2016 -VMName "VM201601"

To remove

Remove-HV.ps1 -VMName "VM201601"

@Sarafian
Copy link
Author

New-HV.ps1 depends on cmdlet New-HyperVMAdministratorCredential to acquire the credential required to access this VM. I have such a cmdlet in my profile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment