VMWare.VM.psm1

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

<#
    .SYNOPSIS
        Enables VM Based Security on a VM. Must first turn it off if it is running.
#>

function Enable-VMVBS {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $True)]
        [String]$ServerName
    )

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

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

    # Get VM
    $VM = Get-VM -Name $ServerName

    # Check Setting
    if($VM.ExtensionData.config.Flags.VbsEnabled -eq $true){
        Write-Output "The VM: $ServerName is already configured for VBS"
        return
    }

    # Check if Running or Suspended and Shutdown
    $StartVM = $false;
    if($VM.PowerState -ne 'PoweredOff'){
        Write-Warning "Need to shutdown VM: $ServerName to enable VBS"
        $StartVM = $true;
        Wait-GuestShutdown -VM $VM
    }

    # Enable VBS
    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
    $spec.flags = New-Object VMware.Vim.VirtualMachineFlagInfo
    $spec.flags.VbsEnabled = $True
    $spec.BootOptions = New-Object VMware.Vim.VirtualMachineBootOptions
    $spec.BootOptions.EfiSecureBootEnabled = $true
    $VM.ExtensionData.ReconfigVM($spec)

    # Start VM if it was running before
    if($StartVM){
        Start-VM $VM
    }

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

<#
    .SYNOPSIS
        Uses the guest shutdown functionality and then waits for the shutdown.
#>

function Wait-GuestShutdown {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $True)]
        [VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl]$VM
    )

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

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

    # Get VM
    $VM = Get-VM -Name $ServerName

    # Start Shutdown - returns immediately
    switch ($VM.PowerState) {
        'PoweredOff' { return }
        'PoweredOn' {Shutdown-VMGuest -VM $VM}
        'Suspended' {Throw 'Not tested for Suspended VMs. Please update code'}
    }

    # Wait and check for status
    while ($VM.PowerState -ne 'PoweredOff') {
        Write-Progress "Waiting for $ServerName guest to shutdown"
        $VM = Get-VM -Name $ServerName
        Start-Sleep -Seconds 2
    }

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

<#
    .SYNOPSIS
        Get the IP address of the VM.
#>

function Get-VMIP {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $True)]
        [String]$ServerName
    )

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

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

    # Get VM
    $VM = Get-VM -Name $ServerName

    # Get IPv4 Addresses
    $IPs = $VM.guest.IPAddress | Where-Object {$_ -match '^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$' }

    # Allow selection if there is more than 1 IP
    return (Select-FromList $IPs).Value

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