Src/LabSwitch.ps1

function NewLabSwitch {
<#
    .SYNOPSIS
        Creates a new lab network switch object.
    .DESCRIPTION
        Permits validation of custom NonNodeData\Lability\Network entries.
#>

    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param (
        ## Virtual switch name
        [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNullOrEmpty()]
        [System.String] $Name,

        ## Virtual switch type
        [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [ValidateSet('Internal','External','Private')]
        [System.String] $Type,

        ## Physical network adapter name (for external switches)
        [Parameter(ValueFromPipelineByPropertyName)] [ValidateNotNull()]
        [System.String] $NetAdapterName,

        ## Share host access (for external virtual switches)
        [Parameter(ValueFromPipelineByPropertyName)] [ValidateNotNull()]
        [System.Boolean] $AllowManagementOS = $false,

        ## Virtual switch availability
        [Parameter(ValueFromPipelineByPropertyName)] [ValidateSet('Present','Absent')]
        [System.String] $Ensure = 'Present'
    )
    begin {
        if (($Type -eq 'External') -and (-not $NetAdapterName)) {
            throw ($localized.MissingParameterError -f 'NetAdapterName');
        }
    } #end begin
    process {
        $newLabSwitch = @{
            Name = $Name;
            Type = $Type;
            NetAdapterName = $NetAdapterName;
            AllowManagementOS = $AllowManagementOS;
            Ensure = $Ensure;
        }
        if ($Type -ne 'External') {
            [ref] $null = $newLabSwitch.Remove('NetAdapterName');
            [ref] $null = $newLabSwitch.Remove('AllowManagementOS');
        }
        return $newLabSwitch;
    } #end process
} #end NewLabSwitch

function ResolveLabSwitch {
<#
    .SYNOPSIS
        Resolves the specified switch using configuration data.
#>

    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param (
        ## Switch Id/Name
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.String] $Name,

        ## PowerShell DSC configuration document (.psd1) containing lab metadata.
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.Collections.Hashtable]
        [Microsoft.PowerShell.DesiredStateConfiguration.ArgumentToConfigurationDataTransformationAttribute()]
        $ConfigurationData
    )
    process {
        $networkSwitch = $ConfigurationData.NonNodeData.$($labDefaults.ModuleName).Network.Where({ $_.Name -eq $Name });
        if ($networkSwitch) {
            $networkHashtable = @{};
            foreach ($key in $networkSwitch.Keys) {
                [ref] $null = $networkHashtable.Add($key, $networkSwitch.$Key);
            }
            $networkSwitch = NewLabSwitch @networkHashtable;
        }
        elseif (Get-VMSwitch -Name $Name -ErrorAction SilentlyContinue) {
            ## Use an existing virtual switch with a matching name if one exists
            WriteWarning -Message ($localized.UsingExistingSwitchWarning -f $Name);
            $existingSwitch = Get-VMSwitch -Name $Name;
            $networkSwitch = @{
                Name = $existingSwitch.Name;
                Type = $existingSwitch.SwitchType;
                AllowManagementOS = $existingSwitch.AllowManagementOS;
                IsExisting = $true;
            }
            if ($existingSwitch.NetAdapterInterfaceDescription) {
                $networkSwitch['NetAdapterName'] = (Get-NetAdapter -InterfaceDescription $existingSwitch.NetAdapterInterfaceDescription).Name;
            }
        }
        else {
            ## Create an internal switch
            $networkSwitch = @{ Name = $Name; Type = 'Internal'; }
        }
        return $networkSwitch;
    } #end process
} #end function ResolveLabSwitch

function TestLabSwitch {
<#
    .SYNOPSIS
        Tests the current configuration a virtual network switch.
    .DESCRIPTION
        Tests a virtual network switch configuration using the xVMSwitch DSC resource.
#>

    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param (
        ## Switch Id/Name
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.String] $Name,

        ## PowerShell DSC configuration document (.psd1) containing lab metadata.
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.Collections.Hashtable]
        [Microsoft.PowerShell.DesiredStateConfiguration.ArgumentToConfigurationDataTransformationAttribute()]
        $ConfigurationData
    )
    process {
        $networkSwitch = ResolveLabSwitch @PSBoundParameters;
        if (($null -ne $networkSwitch.IsExisting) -and ($networkSwitch.IsExisting -eq $true)) {
            ## The existing virtual switch may be of a type not supported by the DSC resource.
            return $true;
        }
        ImportDscResource -ModuleName xHyper-V -ResourceName MSFT_xVMSwitch -Prefix VMSwitch;
        return TestDscResource -ResourceName VMSwitch -Parameters $networkSwitch;
    } #end process
} #end function TestLabSwitch

function SetLabSwitch {
<#
    .SYNOPSIS
        Sets/invokes a virtual network switch configuration.
    .DESCRIPTION
        Sets/invokes a virtual network switch configuration using the xVMSwitch DSC resource.
#>

    [CmdletBinding()]
    param (
        ## Switch Id/Name
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.String] $Name,

        ## PowerShell DSC configuration document (.psd1) containing lab metadata.
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.Collections.Hashtable]
        [Microsoft.PowerShell.DesiredStateConfiguration.ArgumentToConfigurationDataTransformationAttribute()]
        $ConfigurationData
    )
    process {
        $networkSwitch = ResolveLabSwitch @PSBoundParameters;
        if (($null -eq $networkSwitch.IsExisting) -or ($networkSwitch.IsExisting -eq $false)) {
            ImportDscResource -ModuleName xHyper-V -ResourceName MSFT_xVMSwitch -Prefix VMSwitch;
            [ref] $null = InvokeDscResource -ResourceName VMSwitch -Parameters $networkSwitch;
        }
    } #end process
} #end function SetLabSwitch

function RemoveLabSwitch {
<#
    .SYNOPSIS
        Removes a virtual network switch configuration.
    .DESCRIPTION
        Deletes a virtual network switch configuration using the xVMSwitch DSC resource.
#>

    [CmdletBinding(SupportsShouldProcess)]
    param (
        ## Switch Id/Name
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.String] $Name,

        ## Specifies a PowerShell DSC configuration document (.psd1) containing the lab configuration.
        [Parameter(Mandatory, ValueFromPipeline)]
        [System.Collections.Hashtable]
        [Microsoft.PowerShell.DesiredStateConfiguration.ArgumentToConfigurationDataTransformationAttribute()]
        $ConfigurationData
    )
    process {
        $networkSwitch = ResolveLabSwitch @PSBoundParameters;
        if (($null -eq $networkSwitch.IsExisting) -or ($networkSwitch.IsExisting -eq $false)) {
            if ($PSCmdlet.ShouldProcess($Name)) {
                $networkSwitch['Ensure'] = 'Absent';
                ImportDscResource -ModuleName xHyper-V -ResourceName MSFT_xVMSwitch -Prefix VMSwitch;
                [ref] $null = InvokeDscResource -ResourceName VMSwitch -Parameters $networkSwitch;
            }
        }
    } #end process
} #end function RemoveLabSwitch