Tuesday, November 24, 2015

Create a new VM from an image

I have two standalone Hyper-V hosts and I needed to create multiple VMs on each host. I don't have SCVMM or any other management suite, so I decided to script the build. Being the good lazy sysadmin that I am, a quick search landed me on Jeffery Hicks page at http://www.altaro.com/hyper-v/create-virtual-machine-from-template-powershell/.

Mr Hicks script did almost exactly what I wanted, except he is building from an ISO image. I wanted a fully updated image that was ready to go. This means creating a template and syspreping the system. Now that I have a fully updated Server 2012 R2 vhdx image we can modify the script to use a copy of this as the base for our new systems.

Possible Feature enhancements


  • Currently this script needs to be run from the Hyper-V host, but I plan on improving it to run remotely
  • Add a loop to create multiple machines at once
  • Expand the menu to include Win7, Win8.1, Win10, Server 2008 R2, Server 2016 images

The Script



#requires -version 3.0
<#
.Synopsis
Provision a new Hyper-V virtual machine based on a template
.Description
This script will create a new Hyper-V virtual machine based on a template or
hardware profile. You can create a small, medium or large virtual machine. All
virtual machines will use the same virtual switch and the same paths for the
virtual machine and VHDX file.  

This script requires the Hyper-V 3.0 PowerShell module.
Credit goes to Jeffery Hicks
http://www.altaro.com/hyper-v/create-virtual-machine-from-template-powershell/

.Example
PS C:\Scripts\> .\New-VMFromTemplate lab101 -VMType small -passthru
Name       State CPUUsage(%) MemoryAssigned(M) Uptime   Status
----       ----- ----------- ----------------- ------   ------
lab101     Off   0           0                 00:00:00 Operating normally
.Link
New-VM
Set-VM
#>

[cmdletbinding(SupportsShouldProcess)]
Param(
    [Parameter(Position=0,Mandatory,HelpMessage="Enter the name of your new virtual machine")]
    [ValidateNotNullOrEmpty()]
    [string]$VMName,
    [ValidateSet("small","medium","large")]
    [string]$VMType="small",
    [switch]$Passthru
)

#define parameter values based on VM Type
Switch ($VMType) {
    "small" {
        $MemoryStartup=2048MB
        $VHDSize=150GB
        $ProcCount=1
        $MemoryMinimum=512MB
        $MemoryMaximum=4096MB
    }
    "medium" {
        $MemoryStartup=4096MB
        $VHDSize=200GB
        $ProcCount=2
        $MemoryMinimum=1024MB
        $MemoryMaximum=8192MB
    }
    "large" {
        $MemoryStartup=8192MB
        $VHDSize=200GB
        $ProcCount=4
        $MemoryMinimum=4096MB
        $MemoryMaximum=16GB
    }
} #end switch

Write-Verbose "Creating new $VMType virtual machine"

$SwitchName = "v207"
$VMRoot = "D:\Hyper-V"
$VMPath = "${VMRoot}\${VMName}"
$VHDimage = "D:\sysadmin\images\Server2012R2.vhdx"
$VHDPath = "${VMPath}\Virtual Hard Disks\"
$VHDName = "${VMPath}\Virtual Hard Disks\${VMName}.vhdx"

mkdir $VHDPath

Convert-VHD -Path $VHDimage -DestinationPath $VHDName


#define a hash table of parameters for New-VM
$newParam = @{
 Name=$VMName
 SwitchName=$SwitchName
 MemoryStartupBytes=$MemoryStartup
 Generation=2
 Path=$VMRoot
 VHDPath=$VHDName
 ErrorAction="Stop"
}
#define a hash table of parameters for Set-VM
$setParam = @{
 ProcessorCount=$ProcCount
 DynamicMemory=$True
 MemoryMinimumBytes=$MemoryMinimum
 MemoryMaximumBytes=$MemoryMaximum
 ErrorAction="Stop"
}
if ($Passthru) {
    $setParam.Add("Passthru",$True)
}
Try {
    Write-Verbose "Creating new virtual machine"
    Write-Verbose ($newParam | out-string)
    $VM = New-VM @newparam
}
Catch {
    Write-Warning "Failed to create virtual machine $Name"
    Write-Warning $_.Exception.Message
    #bail out
    Return
}


if ($VM) {
    Try {
        Write-Verbose "Configuring new virtual machine"
        Write-Verbose ($setParam | out-string)
        $VM | Set-VM @setparam
    }
    Catch {
    Write-Warning "Failed to configure virtual machine $Name"
    Write-Warning $_.Exception.Message
    #bail out
    Return
    }
}

Monday, November 23, 2015

Install .NET Framework 3.5 on Windows 8.1

There are some legacy applications that require .NET Framework 3.5 or older on Windows 8.1. This is a feature that you should be able to add via Windows Feature or download from Windows Updates, but that didn't work for me.

Windows 8.1 Enterprise failed to .Net 3.5 using either method, so I went back to the source. Using the Win8.1 Ent media on USB flash drive, you can add the feature by specifying the source folder.

From and Administrative command prompt:

# Set the drive letter for your flash drive, in my case e:
DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:e:\sources\sxs

I created a batch script with this command and added to the root of my Win8.1 flash drive to save time in the future.