VMWare.Templates.psm1

using module .\Classes\VMWare.Auth.psm1
using module .\VMWare.Authentication.psm1

<#
    .SYNOPSIS
        Creates a VM based on a template. Will prompt the user for all settings needed.
#>

function New-VMFromTemplate {
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $false)]
        [String]$ServerName = '',
        [Parameter(Mandatory = $false)]
        [String]$ServerNameRegex = '^[A-Z]{2}-[A-Z]{2}-[A-Z]{2}-[A-Z]-[A-Z]{2}[0-9]{2}$',
        [Parameter(Mandatory = $false)]
        [String]$OSCustomizationSpec,
        [Parameter(Mandatory = $false)]
        [String]$Template,
        [Parameter(Mandatory = $false)]
        [String]$Cluster,
        [Parameter(Mandatory = $false)]
        [String]$VirtualNetwork,
        [Parameter(Mandatory = $false)]
        [String]$DataStore,
        [Parameter(Mandatory = $false)]
        [Int]$CPUCores,
        [Parameter(Mandatory = $false)]
        [Int]$MemoryGB
    )

    $errorPref = $ErrorActionPreference
    $ErrorActionPreference = 'Stop' # Stop on all errors

    # Connect to VSphere
    [VMWareAuth]::GetInstance() | Out-Null

    # Get settings to use - or use defaults if valid
    $_Spec = Select-FromObjectList(Get-OSCustomizationSpec) -DefaultValue $OSCustomizationSpec
    $_Template = Select-FromObjectList(Get-Template) -DefaultValue $Template
    $_Cluster = Select-FromObjectList(Get-Cluster) -DefaultValue $Cluster
    $_Network = Select-FromObjectList(Get-VirtualNetwork) -DefaultValue $VirtualNetwork
    $_DataStore = Select-FromObjectList(Get-Datastore) -DefaultValue $DataStore
    $_Cores = Read-ValidInput -Prompt 'Enter Number of CPU Cores' -Regex '^2|4|6|8|10|12|16|20|24|32$' -DefaultValue $CPUCores
    $_MemoryGB = Read-ValidInput -Prompt 'Enter GB of Memory' -Regex '^([1-4][0-9])|[2-9]$' -DefaultValue $MemoryGB

    # Get and confirm name
    $_ServerName = Read-ValidInput -Prompt 'Enter Server Name' -Regex $ServerNameRegex -DefaultValue $ServerName

    Write-Output "Validating $_ServerName is available..."
    $dnsResult = Resolve-DnsName $_ServerName
    if ($null -ne $dnsResult) {
        throw 'There appears to already be a DNS record for that machine name. Confirm it is available to use.'
    }

    # Confirm Settings
    Write-Output @{
        Spec       = $_Spec.Name
        Template   = $_Template.Name
        Cluster    = $_Cluster.Name
        Network    = $_Network.Name
        DataStore  = $_DataStore.Name
        ServerName = $_ServerName
        CPUCores   = $_Cores
        MemoryGB   = $_MemoryGB
    }

    if ($pscmdlet.ShouldProcess($_ServerName, 'create')){
        # Create VM
        $VM = New-VM -Name $_ServerName -Template $_Template -OSCustomizationSpec $_Spec -ResourcePool $_Cluster -Datastore $_DataStore.Name -Confirm:$false

        # Set Network
        $Adapters = Get-NetworkAdapter $VM
        $Adapters | Set-NetworkAdapter -NetworkName $_Network -Confirm:$false | Out-Null

        # Set CPU / Memory
        Set-VM -VM $VM -NumCpu $_Cores -CoresPerSocket $($_Cores / 2) -MemoryGB $_MemoryGB -Confirm:$false | Out-Null

        # Start VM
        Start-VM $VM -Confirm:$false
    }

    $ErrorActionPreference = $errorPref # Set back to previous value
}