PowerShell DSC Journey – Day 17

Alright. So yesterday I worked through some issues in the Set-TargetResource Function and left off with a big one still remaining. Namely, that even though I have Ensure = Present in my test of the Function, it is running through the Ensure = Absent portion of the script if the Hardware Profile already exists, which doesn’t make any sense.

Here is the section of the Function in question.

#Check to see if Hardware Profile exists
        Write-Verbose "Checking if the Hardware Profile $Name exists"
        $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer

        If($HWProfile.Name -match $Name)
        {
            Write-Verbose "The Hardware Profile was found"
            #Set Variables for the Hardware Profile
            $ResourceHWProfile = Get-SCHardwareProfile -VMMServer $VMMServer | Where-Object Name -eq $Name

            #Set this variable for use later
            $HWProfileID = $ResourceHWProfile.ID

            #If Hardware Profile Should not exist, remove it
            Write-Verbose "Ensure set to $Ensure"
            If($Ensure = "Absent")
            {
                Write-Verbose "Hardware Profile $Name Should be $Ensure"
                Get-SCHardwareProfile -VMMServer $VMMServer -ID $HWProfileID | Remove-SCHardwareProfile
                Write-Verbose "Hardware Profile $Name is $Ensure"
            }

And if I run this Test with a Hardware Profile that already exists, this is the output that I get.

Set-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -Ensure Present -Verbose
PS C:\USERS\jacob.benson\Downloads\physdiskwrite-0.5.3> Set-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -Ensure Present -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER1
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager.R2Aliases.ps1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManagerLibraryClientCleanup.ps1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: Checking if the Hardware Profile DSCWEB Hardware Profile exists
VERBOSE: The Hardware Profile was found
VERBOSE: Ensure set to Present
VERBOSE: Hardware Profile DSCWEB Hardware Profile Should be Absent
(Then it displays the Hardware Profile)
VERBOSE: Hardware Profile DSCWEB Hardware Profile is Absent

And I know it’s removing it because the Hardware Profile disappears from VMM. The question is, why? I can see from the Verbose output that $Ensure is set to Present, so why is the Function ignoring that? As another test, if I run the same test but set $Ensure to Absent, it removes it. But that was really just a diversion to avoid thinking about the real problem because I am completely stumped.

I change my Else block to ElseIf($Ensure = “Present”) and that has no effect. It just jumps right into the If Absent block and deleted the Hardware Profile. Lacking ideas I start going through the xVMHyperV Set-TargetResource function searching for Ensure to see how they do it. And they are using -eq in the If statement instead of =. Does this really make a difference? Yes, that’s the answer. After I change it to that, it evaluates the parameter properly. I feel like this is a very simple mistake that I made solely because of my lack of experience and knowledge of PowerShell.

Doing a little research in PowerShell using Get-Help I discover the following:

  • = is an Assignment Operator.  It sets the value of a variable to a specified value
  • -eq is a Comparison Operator.  It compares to objects looking for an identical value
  • Thus, = does not equal -eq.  I feel dumb.  I should have known that.

That being said, when I run my test using an existing Hardware Profile now (with Ensure = Present), I get this for output.

PS C:\scripts> Set-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -Ensure Present -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER1
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager.R2Aliases.ps1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManagerLibraryClientCleanup.ps1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: Checking if the Hardware Profile DSCWEB Hardware Profile exists
VERBOSE: The Hardware Profile was found
VERBOSE: Ensure set to Present
VERBOSE: DVDDrive is already set properly
VERBOSE: CPUCount is Default Hardware Configuration efault Hardware Configuration - Gen 2 DSCWEB Hardware Profile.CPUCount, should be 1
VERBOSE: CPUCount Set to 1
VERBOSE: VMNetwork set to Default Hardware Configuration Default Hardware Configuration - Gen 2 DSCWEB Hardware Profile.VirtualNetworkAdapters.VMNetwork, should be 
Set-SCVirtualNetworkAdapter : Cannot validate argument on parameter 'VirtualNetwork'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At line:101 char:144
+ ... rofile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
+                                                                ~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Set-SCVirtualNetworkAdapter], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.SetNICCmdlet
 
VERBOSE: VMNetwork set to

Clearly there are a couple of issues here. The DVDDrive section looks OK, but then in the CPU section I get this beauty for Verbose output.

VERBOSE: CPUCount is Default Hardware Configuration Default Hardware Configuration - Gen 2 DSCWEB Hardware Profile.CPUCount, should be 1

Yeah, that’s not real useful. Looking at this it appears that $HWProfile.CPCount is not what I think it is. Actually I think it’s because I used $HWProfile instead of the $ResourceHWProfile variable. This is going to require a fix in a lot of places. I make those changes and try my test again. I get the expected output, except that I get the same error about the VirtualNetworkAdapter that I got above. This goes back to my work in the previous blog post about how to handle this, because I don’t want to make this parameter mandatory. So, I need to add in some additional logic to my Function here.

If($VMNetwork)
                    {

                        If($VMNetwork -ne $ResourceHWProfile.VirtualNetworkAdapters.VMNetwork)
                        {
                            Write-Verbose "VMNetwork set to $ResourceHWProfile.VirtualNetworkAdapters.VMNetwork, should be $VMNetwork"
                            Get-SCVirtualNetworkAdapter -VMMServer $VMMSErver -HardwareProfile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
                            Write-Verbose "VMNetwork set to $VMNetwork"
                        }
                        Else
                        {
                            Write-Verbose "VMNetwork is already set to $VMNetwork"
                        }
                    }
                    Else
                    {
                        Write-Verbose "No VMNetwork was specified"
                    }#EndVMNetwork

And now when I run my test, I get exactly the output that I would expect.

PS C:\scripts> Set-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -Ensure Present -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER1
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager.R2Aliases.ps1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManagerLibraryClientCleanup.ps1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: Checking if the Hardware Profile DSCWEB Hardware Profile exists
VERBOSE: The Hardware Profile was found
VERBOSE: Ensure set to Present
VERBOSE: DVDDrive is already set properly
VERBOSE: CPUCount is already set to 1
VERBOSE: No VMNetwork was specified

Boom!
I do various tests with different CPU, DVDDrive and VMNetwork settings and everything looks good. I do make a change to one line of Verbose output, but other than that everything checks out fine. This is really cool. I have an actual functioning DSC Custom Resource. Tomorrow I am going to turn this thing into a Module, and try out an actual DSC Configuration and see if that actually works before adding in my additional parameters.