Author Posts

October 15, 2015 at 12:37 am

Hi all,

I am using push DSC to configure a 2 node Hyper-V cluster on Windows 2012 R2 Datacenter. This configuration creates a NIC Team called 'HostTeam' and a virtual switch called HostSwitch that is allowed to use the Management OS.

One of the problems I noticed was that one of my NIC's, the NIC Team and the virtual switch all had the same MAC address and was generating a System error 16945 (MAC conflict: A port on the virtual switch has the same MAC as one of the underlying team members on Team Nic Microsoft Network Adapter Multiplexor Driver). The solution is to change the MAC Address on the NIC Team before creating the virtual switch. This 'breaks' the DSC configuration as manual input is required.

My boss wants me to automate the resolution, so I have been forced to add a Script resource to the DSC file. I have tested this and it does work, however I did find it difficult to find much information (in simple terms I can grasp) regarding the TestScript and GetScript

Script SetNicTeamMac {
    SetScript = { 
        # Set MAC Address of NIC Team
        # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        # Get Adapter Names & MAC Addresses
        $NIC = Get-NetAdapter

        # Check for Duplicates and remove dashes
        $Dup = ($NIC.MacAddress | Group | ?{$_.Count -gt 1}).Values
        If ($Dup -gt 1){
            $DupNIC = $NIC | Where {$_.MACAddress -eq $Dup} | Select Name, @{N='MacAddress'; E={$_.MacAddress -replace '-',""}}

            # Get Highest MAC, convert to Decimal, increment by 1 and convert back to Hex
            $Max = $NIC | Sort MACAddress | Select @{N='MacAddress'; E={$_.MacAddress -replace '-',""}} -Last 1
            $Dec = [Convert]::ToInt64($Max.MacAddress, 16)
           ++$Dec
            $Mac = [Convert]::ToString($Dec, 16)

            # Assign to HostTeam - vLanId set to 0 as vSwitch will be tagged 
            Set-NetAdapterAdvancedProperty -InterfaceDescription "Microsoft Network Adapter Multiplexor Driver" -DisplayName "Mac Address" -DisplayValue $Mac
        }
    }
    TestScript = {
        $MacAddress = Get-NetAdapter HostTeam | Select MacAddress
        return ($MacAddress.MacAddress -eq $Mac)
    }
    GetScript = {
        $MacAddress = Get-NetAdapter HostTeam | Select MacAddress
        Return @{
            MacAddress = $MacAddress.MacAddress
        }
    }
    DependsOn = '[cNetworkTeam]NetworkTeam'
}

I'd appreciate it if someone could give me some pointers (ways to improve) what I've done.
Thanks
Tony

October 15, 2015 at 10:33 am

TestScript is supposed to check for your desired configuration and return $true or $false. If it returns $false, SetScript is run to correct the problem. Get is supposed to return a hash table containing the current configuration; it's not illegal to return an empty hash table. If you're not using Get-DscConfiguration, then GetScript isn't called.

But basically, it looks like what you're doing is correct.

October 16, 2015 at 1:27 am

Thanks Don, nice explanation – which leads me to review my code as this will run everytime as TestScript just checks for a MAC address on HostTeam

If I place my tests (does the NIC Team have the same MAC address as a physical NIC) in the TestScript section, can I reuse the variables (and the contents) in the SetScript section or do I need to re-define and populate those variables?

Tony

October 16, 2015 at 3:11 am

Here is the updated Script:

        Script SetNicTeamMac {
            SetScript = { 
                # Set MAC Address of Host Team
                # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                $DupNIC = $NIC | Where {$_.MACAddress -eq $Dup} | Select Name, @{N='MacAddress'; E={$_.MacAddress -replace '-',""}}

                # Get Highest MAC, convert to Decimal, increment by 1 and convert back to Hex
                $Max = $NIC | Sort MACAddress | Select @{N='MacAddress'; E={$_.MacAddress -replace '-',""}} -Last 1
                $Dec = [Convert]::ToInt64($Max.MacAddress, 16)
                ++$Dec
                $Mac = [Convert]::ToString($Dec, 16)

                # Assign to HostTeam - vLanId set to 0 as vSwitch will be tagged 
                Set-NetAdapterAdvancedProperty -InterfaceDescription "Microsoft Network Adapter Multiplexor Driver" -DisplayName "Mac Address" -DisplayValue $Mac
            }
            TestScript = {
                # Get Adapter Names & MAC Addresses
                $NIC = Get-NetAdapter
                # Check for Duplicates and remove dashes
                $Dup = ($NIC.MacAddress | Group | ?{$_.Count -gt 1}).Values
                If ($Dup -gt 1){
	                # Get duplicate NICs
 		            # Check for NIC* in NIC Name
        		    $DupName = $Dup | Where {$_.Name -Like 'NIC*'}
				}

                return ($DupName -eq 'NIC*')
            }
            GetScript = {
                $MacAddress = Get-NetAdapter HostTeam | Select MacAddress
                Return @{
                    MacAddress = $MacAddress.MacAddress
                }
            }
            DependsOn = '[cNetworkTeam]NetworkTeam'
        }

Your thoughts please.
Tony