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 NFM Default Hardware Configuration NFM Default Hardware Configuration - Gen 2 DSCWEB Hardware Profile.CPUCount, should be 1
VERBOSE: CPUCount Set to 1
VERBOSE: VMNetwork set to NFM Default Hardware Configuration NFM 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 NFM Default Hardware Configuration NFM 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.

PowerShell DSC Journey – Day 16

When I left off yesterday I had a somewhat functioning Set-TargetResource function. I use functioning in the way that when something kind of works and doesn’t throw errors but doesn’t actually do anything functions. So, today I am going to be figuring out where I screwed up my logic and getting this Resource to work. And hopefully this doesn’t turn into a smaller version of War and Peace.

Here is my Set-TargetResource in it’s entirety.

#region
function Set-TargetResource
{
	[CmdletBinding()]
	param
	(
		[System.Boolean]
		$DVDDrive,

		[System.String]
		$VMNetwork,

		[System.UInt64]
		$CPUCount,

		[ValidateSet("Present","Absent")]
		[System.String]
		$Ensure,

		[parameter(Mandatory = $true)]
		[System.String]
		$Name,

		[parameter(Mandatory = $true)]
		[System.String]
		$VMMServer
	)

	#Write-Verbose "Use this cmdlet to deliver information about command processing."

	#Write-Debug "Use this cmdlet to write debug information while troubleshooting."

	#Include this line if the resource requires a system reboot.
	#$global:DSCMachineStatus = 1

    Write-Verbose "VMMServer is $VMMServer"
    Write-Verbose "Hardware Profile Name is $Name"

    #Check if VirtualMachineManager module is present for SCVMM cmdlets
        If(!(Get-Module -ListAvailable -Name VirtualMachineManager))
        {
            Throw "The VirtualMachineManager Module was not found.  Please ensure this module is available by installing the VMM Console.  For information
            On installing the VMM Console see:  http://technet.microsoft.com/en-us/library/gg610627.aspx"
        }

    #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"
            $ResourceHWProfile = Get-SCHardwareProfile -VMMServer $VMMServer | Where-Object Name -eq $Name
            $HWProfileID = $ResourceHWProfile.ID

            #If Hardware Profile Should not exist, remove it
            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"
            }
            Else
            {
                #Hardware Profile should be present with the correct settings.  Check the settings.
                    If($DVDDrive -eq $HWProfile.VirtualDVDDrives.Enabled)
                    {
                        Write-Verbose "DVDDrive is already set properly"
                    }
                    Else
                    {
                        If($DVDDrive -eq $True)
                        {
                            New-SCVirtualDVDDrive -HardwareProfile $Name -LUN 1 -Bus 0
                            Write-Verbose "DVDDrive has been created"
                        }
                        Else
                        {
                            Get-SCVirtualDVDDrive -HardwareProfile $Name | Remove-SCVirtualDVDDrive
                            Write-Verbose "DVDDrive has been removed"
                        }
                    }

                    If($CPUCount -ne $HWProfile.CPUCount)
                    {
                        Write-Verbose "CPUCount is $HWProfile.CPUCount, should be $CPUCount"
                        Set-SCHardwareProfile -HardwareProfile $Name -CPUCount $CPUCount
                        Write-Verbose "CPUCount Set to $CPUCount"                                        
                    }
                    Else
                    {
                        Write-Verbose "CPUCount is already set to $CPUCount"
                    }
                    If($VMNetwork -ne $HWProfile.VirtualNetworkAdapters.VMNetwork)
                    {
                        Write-Verbose "VMNetwork set to $HWProfile.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 "The Hardware Profile was not found.  Creating new Hardware Profile $Name"

            New-SCHardwareProfile -VMMServer $VMMSErver -Name $Name

            If($DVDDrive -eq $True)
            {
                New-SCVirtualDVDDrive -HardwareProfile $Name -LUN 1 -Bus 0
                Write-Verbose "DVDDrive has been created"
            }
            Else
            {
                Write-Verbose "DVDDrive is set to $False, no DVDDrive created"
            }

            If($CPUCount -gt 0)
            {
                Write-Verbose "Setting CPUCount to $CPUCount"
                Set-SCHardwareProfile -HardwareProfile $Name -CPUCount $CPUCount
                Write-Verbose "CPUCount Set to $CPUCount" 
            }
            Else
            {
                Write-Verbose "CPU Count set to 0 or not specified, CPU Count should be at least 1"
            }

            If($VMNetwork -ne $null)
            {
                Write-Verbose "Setting VMNetwork to $VMNetwork"
                Get-SCVirtualNetworkAdapter -VMMServer $VMMSErver -HardwareProfile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
                Write-Verbose "VMNetwork set to $VMNetwork"
            }
            Else
            {
                Write-Verbose "VMNetwork not specified"
            }
        }
}
#endregion

The first problem I noticed is that when I run this test of my Set-TargetResource (in which I am testing for a Hardware Profile that doesn’t exist), here is the output I get.

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 not found.  Creating new Hardware Profile DSCWEB Hardware Profile


CPUCount                            : 1
Memory                              : 512
DynamicMemoryEnabled                : False
DynamicMemoryMaximumMB              : 
DynamicMemoryBufferPercentage       : 
MemoryWeight                        : 
VirtualVideoAdapterEnabled          : False
MonitorMaximumCount                 : 
MonitorResolutionMaximum            : 
BootOrder                           : 
FirstBootDevice                     : 
SecureBootEnabled                   : 
UndoDisksEnabled                    : False
CPUType                             : 3.60 GHz Xeon (2 MB L2 cache)
IsHighlyAvailable                   : False
HAVMPriority                        : 
IsDRProtectionRequired              : False
RecoveryPointObjective              : 
LimitCPUFunctionality               : False
LimitCPUForMigration                : False
ExpectedCPUUtilization              : 20
DiskIO                              : 0
NetworkUtilization                  : 0
RelativeWeight                      : 100
CPUReserve                          : 0
CPUMax                              : 100
CPUPerVirtualNumaNodeMaximum        : 
MemoryPerVirtualNumaNodeMaximumMB   : 
VirtualNumaNodesPerSocketMaximum    : 
DynamicMemoryMinimumMB              : 
NumLockEnabled                      : 
NumaIsolationRequired               : 
Generation                          : 1
VirtualDVDDrives                    : {}
ShareSCSIBus                        : False
VirtualNetworkAdapters              : {}
VirtualFibreChannelAdapters         : {}
VirtualFloppyDrive                  : DSCWEB Hardware Profile
VirtualCOMPorts                     : {COM1, COM2}
VirtualSCSIAdapters                 : {}
CapabilityProfile                   : 
CapabilityProfileCompatibilityState : Compatible
GrantedToList                       : {}
UserRoleID                          : 75700cd5-893e-4f68-ada7-50ef4668acc6
UserRole                            : Administrator
Owner                               : NFM\jacob.benson
ObjectType                          : HardwareProfile
Accessibility                       : Public
Name                                : DSCWEB Hardware Profile
IsViewOnly                          : False
Description                         : 
AddedTime                           : 6/16/2014 7:21:42 AM
ModifiedTime                        : 6/16/2014 7:21:42 AM
Enabled                             : True
MostRecentTask                      : Create hardware profile
ServerConnection                    : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection
ID                                  : 083da7f1-54af-4720-b4a4-dad908b76dfa
MarkedForDeletion                   : False
IsFullyCached                       : True
MostRecentTaskIfLocal               : Create hardware profile

VERBOSE: DVDDrive is set to False, no DVDDrive created
VERBOSE: CPU Count set to 0 or not specified, CPU Count should be at least 1
VERBOSE: Setting VMNetwork to 
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:138 char:136
+ ... rofile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
+                                                                ~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Set-SCVirtualNetworkAdapter], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.SetNICCmdlet
 
VERBOSE: VMNetwork set to 

Couple of things to note here. It didn’t find the Hardware Profile, so it created it. However, I didn’t specify anything for the DVD Drive, but the verbose output indicates that it was set to False, so it did not create a DVD Drive, so that needs to be fixed. The second issue is that the verbose output indicates that the CPU count set to 0 or not specified, CPU count should be at least 1. If I don’t specify a CPU count the Hardware Profile creation defaults to 1 CPU, so the message should indicate that. And lastly it just errored out on setting the VMNetwork because I didn’t specify one.

First things first, here is the section of code I have to handle the DVD Drive.

If($DVDDrive -eq $True)
            {
                New-SCVirtualDVDDrive -HardwareProfile $Name -LUN 1 -Bus 0
                Write-Verbose "DVDDrive has been created"
            }
            Else
            {
                Write-Verbose "DVDDrive is set to $False, no DVDDrive created"
            }

While thinking about this, it occurs to me that maybe I should set this to default to True, because I imagine that in almost every case you are going to want a DVD Drive on your server. I feel like that is a better solution than adding in another ElseIf section that has the Null case. Do people agree? I changed the parameter in the Set-TargetResource Function so that $DVDDrive = $True, and that means the existing code block should work fine.

Second minor issue is changing the Verbose text when the CPU Count is set to 0 or not specified. This particular section of code I changed from:

           If($CPUCount -gt 0)
            {
                Write-Verbose "Setting CPUCount to $CPUCount"
                Set-SCHardwareProfile -HardwareProfile $Name -CPUCount $CPUCount
                Write-Verbose "CPUCount Set to $CPUCount" 
            }
            Else
            {
                Write-Verbose "CPU Count set to 0 or not specified, CPU Count set to 1"
            }

To:

 If($CPUCount -gt 0)
            {
                Write-Verbose "Setting CPUCount to $CPUCount"
                Set-SCHardwareProfile -HardwareProfile $Name -CPUCount $CPUCount
                Write-Verbose "CPUCount Set to $CPUCount" 
            }
            Else
            {
                Write-Verbose "CPUCount set to 0 or not specified, setting CPUCount to 1"
                Set-SCHardwareProfile -HardwareProfile $Name -CPUCount 1
                Write-Verbose "CPUCount set to 1"
            }

Of course after doing this I think, should I just set the CPUCount parameter to default to 1? I mean, you need a CPU for it to run, and it defaults to 1 anyways without even setting anything. I realize the code in the Else block is a little redundant, but for consistency sake I left it that way so somebody reading it wouldn’t be like “why did he set the hardware profile in the first section and not the second?”. I could also make CPUCount a mandatory parameter, but that seems a little excessive when it just defaults to 1 anyways. Hmm. I don’t think there is a good answer to this. I am going to set CPUCount to default to 1 and just change the Else statement to use -CPUCount $CPUCount for now. I don’t like the idea of hard coding parameter values into a DSC Configuration, but in this particular case I think it is justifiable.

Alright, now for the last problem with the VMNetwork. If I don’t specify it, it shouldn’t just freak out and throw and error, it needs to say something useful. Here is my current code.

            If($VMNetwork -ne $null)
            {
                Write-Verbose "Setting VMNetwork to $VMNetwork"
                Get-SCVirtualNetworkAdapter -VMMServer $VMMSErver -HardwareProfile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
                Write-Verbose "VMNetwork set to $VMNetwork"
            }
            Else
            {
                Write-Verbose "VMNetwork not specified"
            }

The problem here is that I thought that checking to see if the parameter was not equal to Null mean it would also check to make sure it wasn’t empty. Clearly this is not the case. So how do I check for both cases? It appears based on some Google searches the best way to do this is to change it from If($VMNetwork -ne $null) to just If($VMNetwork) which checks for Null or Empty.

With those changes done, lets test again and see what happens (I deleted the Hardware Configuration created from the previous test).

Much better!

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 not found.  Creating new Hardware Profile DSCWEB Hardware Profile


CPUCount                            : 1
Memory                              : 512
DynamicMemoryEnabled                : False
DynamicMemoryMaximumMB              : 
DynamicMemoryBufferPercentage       : 
MemoryWeight                        : 
VirtualVideoAdapterEnabled          : False
MonitorMaximumCount                 : 
MonitorResolutionMaximum            : 
BootOrder                           : 
FirstBootDevice                     : 
SecureBootEnabled                   : 
UndoDisksEnabled                    : False
CPUType                             : 3.60 GHz Xeon (2 MB L2 cache)
IsHighlyAvailable                   : False
HAVMPriority                        : 
IsDRProtectionRequired              : False
RecoveryPointObjective              : 
LimitCPUFunctionality               : False
LimitCPUForMigration                : False
ExpectedCPUUtilization              : 20
DiskIO                              : 0
NetworkUtilization                  : 0
RelativeWeight                      : 100
CPUReserve                          : 0
CPUMax                              : 100
CPUPerVirtualNumaNodeMaximum        : 
MemoryPerVirtualNumaNodeMaximumMB   : 
VirtualNumaNodesPerSocketMaximum    : 
DynamicMemoryMinimumMB              : 
NumLockEnabled                      : 
NumaIsolationRequired               : 
Generation                          : 1
VirtualDVDDrives                    : {}
ShareSCSIBus                        : False
VirtualNetworkAdapters              : {}
VirtualFibreChannelAdapters         : {}
VirtualFloppyDrive                  : DSCWEB Hardware Profile
VirtualCOMPorts                     : {COM1, COM2}
VirtualSCSIAdapters                 : {}
CapabilityProfile                   : 
CapabilityProfileCompatibilityState : Compatible
GrantedToList                       : {}
UserRoleID                          : 75700cd5-893e-4f68-ada7-50ef4668acc6
UserRole                            : Administrator
Owner                               : NFM\jacob.benson
ObjectType                          : HardwareProfile
Accessibility                       : Public
Name                                : DSCWEB Hardware Profile
IsViewOnly                          : False
Description                         : 
AddedTime                           : 6/16/2014 7:56:15 AM
ModifiedTime                        : 6/16/2014 7:56:15 AM
Enabled                             : True
MostRecentTask                      : Create hardware profile
ServerConnection                    : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerC
                                      onnection
ID                                  : fdcaad29-7709-4ead-ad79-9264ae2e5820
MarkedForDeletion                   : False
IsFullyCached                       : True
MostRecentTaskIfLocal               : Create hardware profile

Connection            : None
ISOId                 : 
ISO                   : 
HostDrive             : 
BusType               : 
Bus                   : 
Lun                   : 
ISOLinked             : False
ObjectType            : VirtualDVDDrive
Accessibility         : Public
Name                  : DSCWEB Hardware Profile
IsViewOnly            : False
Description           : 
AddedTime             : 6/16/2014 7:56:15 AM
ModifiedTime          : 6/16/2014 7:56:15 AM
Enabled               : True
MostRecentTask        : Create virtual DVD drive
ServerConnection      : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection
ID                    : e6520ca7-0348-45cc-8e51-758e9ccc462c
MarkedForDeletion     : False
IsFullyCached         : True
MostRecentTaskIfLocal : Create virtual DVD drive

VERBOSE: DVDDrive has been created
VERBOSE: Setting CPUCount to 1
CPUCount                            : 1
Memory                              : 512
DynamicMemoryEnabled                : False
DynamicMemoryMaximumMB              : 
DynamicMemoryBufferPercentage       : 
MemoryWeight                        : 
VirtualVideoAdapterEnabled          : False
MonitorMaximumCount                 : 
MonitorResolutionMaximum            : 
BootOrder                           : 
FirstBootDevice                     : 
SecureBootEnabled                   : 
UndoDisksEnabled                    : False
CPUType                             : 3.60 GHz Xeon (2 MB L2 cache)
IsHighlyAvailable                   : False
HAVMPriority                        : 
IsDRProtectionRequired              : False
RecoveryPointObjective              : 
LimitCPUFunctionality               : False
LimitCPUForMigration                : False
ExpectedCPUUtilization              : 20
DiskIO                              : 0
NetworkUtilization                  : 0
RelativeWeight                      : 100
CPUReserve                          : 0
CPUMax                              : 100
CPUPerVirtualNumaNodeMaximum        : 
MemoryPerVirtualNumaNodeMaximumMB   : 
VirtualNumaNodesPerSocketMaximum    : 
DynamicMemoryMinimumMB              : 
NumLockEnabled                      : 
NumaIsolationRequired               : 
Generation                          : 1
VirtualDVDDrives                    : {DSCWEB Hardware Profile}
ShareSCSIBus                        : False
VirtualNetworkAdapters              : {}
VirtualFibreChannelAdapters         : {}
VirtualFloppyDrive                  : DSCWEB Hardware Profile
VirtualCOMPorts                     : {COM1, COM2}
VirtualSCSIAdapters                 : {}
CapabilityProfile                   : 
CapabilityProfileCompatibilityState : Compatible
GrantedToList                       : {}
UserRoleID                          : 75700cd5-893e-4f68-ada7-50ef4668acc6
UserRole                            : Administrator
Owner                               : NFM\jacob.benson
ObjectType                          : HardwareProfile
Accessibility                       : Public
Name                                : DSCWEB Hardware Profile
IsViewOnly                          : False
Description                         : 
AddedTime                           : 6/16/2014 7:56:15 AM
ModifiedTime                        : 6/16/2014 7:56:16 AM
Enabled                             : True
MostRecentTask                      : Change properties of hardware profile
ServerConnection                    : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerC
                                      onnection
ID                                  : fdcaad29-7709-4ead-ad79-9264ae2e5820
MarkedForDeletion                   : False
IsFullyCached                       : True
MostRecentTaskIfLocal               : Change properties of hardware profile

VERBOSE: CPUCount Set to 1
VERBOSE: VMNetwork not specified, no VMNetwork was set

The one thing I don’t like about this, is that it still sets it set the CPUCount, when in all actuality it was already set by default. So, I am going to change that section again to this.

            Else
            {
                Write-Verbose "CPUCount set to 0 or not specified, CPUCount set to 1 by default"
            }

I verified that the Hardware Profile has 1 CPU, the DVD Drive is Enabled, and the Virtual Network is not set. Not setting a VMNetwork appears to mean that no settings in VirtualNetworkAdapters are set, which is good to know.

Ok, with that all done, I run it again because I remember there was a problem with this. Here are the important parts from this test.

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: Hardware Profile DSCWEB Hardware Profile Should be Absent
*DISPLAYS HARDWARE PROFILE INFORMATION*
VERBOSE: Hardware Profile DSCWEB Hardware Profile is Absent

Uh. What. That looks to be a massive fail on my part. Although, I don’t understand what the problem is here. It checks if it exists, it finds that it exists, and then it is going through the block where $Ensure = Absent, even though I have $Ensure = Present. Of course, then it is removing the profile as well, which is fun. I add this line to my code right above the line for If($Ensure = Absent), Write-Verbose “Ensure set to $Ensure”.

And I get this, which is even more puzzling.

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: Hardware Profile DSCWEB Hardware Profile Should be Absent

It says that $Ensure = Present, so why the hell is it going through that block of code? I don’t understand! If I set it to Absent it does the same thing, which is fine, but why is it doing it when it is set to present????

I feel like this is a good place to stop for now so I can think a little about this and try to figure out what is going on.

PowerShell DSC Journey – Day 15

So when I left off yesterday I appeared to have my Get and Test TargetResource functions working properly, now it’s time to work on the Set-TargetResource function, which is probably where the fun will happen.

When I go to set the Resource, I have a couple of different scenarios I need to work through.

  • Hardware Profile exists, ensure equals absent
  • Hardware Profile exists, ensure equals present
  • Hardware Profile does not exist, ensure equals present

And here is what I came up with those 3 scenarios after working my way through it (and looking at the xVMHyperV Resource).  I almost immediately ran into a problem where there doesn’t seem to be a clear way to tell the Hardware Profile that it needs a DVD drive (at least not using the Set-SCHardwareProfile cmdlets).  A little research led me to the Set-SCVirtualDVDDrive cmdlets which can be associated with “a virtual machine, virtual machine template, or hardware profile used in a Virtual Machine Manager (VMM) environment.” which is perfect.  When I set the New DVD Drive I must specify a LUN and a BUS.  I am going to need some extra logic eventually to deal with what happens if you have multiple disks or whatever else, but for right now this will have to do.  I don’t even want to admit how long this took me to work through, but it appears to work.

If($HWProfile.Name -match $Name)
        {
            Write-Verbose "The Hardware Profile was found"
            $ResourceHWProfile = Get-SCHardwareProfile -VMMServer $VMMServer | Where-Object Name -eq $Name
            $HWProfileID = $ResourceHWProfile.ID

            #If Hardware Profile Should not exist, remove it
            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"
            }
            Else
            {
                #Hardware Profile should be present with the correct settings.  Check the settings.
                    If($DVDDrive -eq $HWProfile.VirtualDVDDrives.Enabled)
                    {
                        Write-Verbose "DVDDrive is already set properly"
                    }
                    Else
                    {
                        If($DVDDrive -eq $True)
                        {
                            New-SCVirtualDVDDrive -HardwareProfile $Name -LUN 1 -Bus 0
                            Write-Verbose "DVDDrive has been created"
                        }
                        Else
                        {
                            Get-SCVirtualDVDDrive -HardwareProfile $Name | Remove-SCVirtualDVDDrive
                            Write-Verbose "DVDDrive has been removed"
                        }
                    }

CPU Count is easy and straightforward, which was nice.

                    If($CPUCount -ne $HWProfile.CPUCount)
                    {
                        Write-Verbose "CPUCount is $HWProfile.CPUCount, should be $CPUCount"
                        Set-SCHardwareProfile -HardwareProfile $Name -CPUCount $CPUCount
                        Write-Verbose "CPUCount Set to $CPUCount"                                        
                    }

However, I ran into the same problem with VMNetwork that I did with the DVDDrive (which doesn’t make me happy). But since I already had that experience it was much quicker to come up with what to do about it.

If($VMNetwork -ne $HWProfile.VirtualNetworkAdapters.VMNetwork)
                    {
                        Write-Verbose "VMNetwork set to $HWProfile.VirtualNetworkAdapters.VMNetwork, should be $VMNetwork"
                        Get-SCVirtualNetworkAdapter -VMMServer $VMMSErver -HardwareProfile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
                        Write-Verbose "VMNetwork set to $VMNetwork"
                    }

Now that that is done (I feel like I just went through the ringer), all I really need to do for the next part is copy and paste the commands from above into the area where I am creating a Hardware Profile if none exists.

Write-Verbose "The Hardware Profile was not found.  Creating new Hardware Profile $Name"

            New-SCHardwareProfile -VMMServer $VMMSErver -Name $Name

            If($DVDDrive -eq $True)
            {
                New-SCVirtualDVDDrive -HardwareProfile $Name -LUN 1 -Bus 0
                Write-Verbose "DVDDrive has been created"
            }
            Else
            {
                Write-Verbose "DVDDrive is set to $False, no DVDDrive created"
            }

            Write-Verbose "Setting CPUCount to $CPUCount"
            Set-SCHardwareProfile -HardwareProfile $Name -CPUCount $CPUCount
            Write-Verbose "CPUCount Set to $CPUCount" 

            Write-Verbose "Setting VMNetwork to $VMNetwork"
            Get-SCVirtualNetworkAdapter -VMMServer $VMMSErver -HardwareProfile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
            Write-Verbose "VMNetwork set to $VMNetwork"

So I guess now we need to test this thing and see if it blows up. I am going to start with my original 3 tests and then add in some variations (providing those still work). I run the first one for an existing Hardware Profile and find out quickly I need to specify the Ensure parameter. Which means I should probably make that a mandatory property (I think?). I don’t see anyone leaving that out unintentionally but maybe I should add in some logic to check for that? I guess I will figure that out later.

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

Winning! Test #2! This does not go as well.

PS C:\Scripts> Set-TargetResource -Name "DSCWEB Hardware Profile 2" -VMMServer MY-VMM-SERVER1 -Ensure Present -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER1
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile 2
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 2 exists

Alright, so it’s basically exiting after checking if the Hardware Profile exists. In this test, the profile does not exist, so it should jump down to the Else block and create it, however that is not happening. I am ashamed to admit this but I had an extra closing bracket in the top half of the script, so it was exiting before creating the profile. When I run it again, it works, sort of. The profile is created, but it throws errors because I didn’t specify a CPU count or a VMNetwork, because they aren’t mandatory. So, I need to do some updates here I think.

            If($CPUCount -gt 0)
            {
                Write-Verbose "Setting CPUCount to $CPUCount"
                Set-SCHardwareProfile -HardwareProfile $Name -CPUCount $CPUCount
                Write-Verbose "CPUCount Set to $CPUCount" 
            }
            Else
            {
                Write-Verbose "CPU Count set to 0 or not specified, CPU Count should be at least 1"
            }

            If($VMNetwork -ne $null)
            {
                Write-Verbose "Setting VMNetwork to $VMNetwork"
                Get-SCVirtualNetworkAdapter -VMMServer $VMMSErver -HardwareProfile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
                Write-Verbose "VMNetwork set to $VMNetwork"
            }
            Else
            {
                Write-Verbose "VMNetwork not specified"
            }

For the second test, it created the Hardware Profile, with no errors, however it added “VERBOSE: Hardware Profile DSCWEB Hardware Profile 2 is Absent” after displaying the Hardware Profile, which uh….doesn’t make any sense?

PS C:\Scripts> Set-TargetResource -Name "DSCWEB Hardware Profile 2" -VMMServer MY-VMM-SERVER1-Ensure Present -Verbose
VERBOSE: VMMServer is MDC-SC-VMM01
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile 2
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 2 exists
VERBOSE: The Hardware Profile was found
VERBOSE: Hardware Profile DSCWEB Hardware Profile 2 Should be Absent


CPUCount                            : 1
Memory                              : 512
DynamicMemoryEnabled                : False
DynamicMemoryMaximumMB              : 
DynamicMemoryBufferPercentage       : 
MemoryWeight                        : 
VirtualVideoAdapterEnabled          : False
MonitorMaximumCount                 : 
MonitorResolutionMaximum            : 
BootOrder                           : 
FirstBootDevice                     : 
SecureBootEnabled                   : 
UndoDisksEnabled                    : False
CPUType                             : 3.60 GHz Xeon (2 MB L2 cache)
IsHighlyAvailable                   : False
HAVMPriority                        : 
IsDRProtectionRequired              : False
RecoveryPointObjective              : 
LimitCPUFunctionality               : False
LimitCPUForMigration                : False
ExpectedCPUUtilization              : 20
DiskIO                              : 0
NetworkUtilization                  : 0
RelativeWeight                      : 100
CPUReserve                          : 0
CPUMax                              : 100
CPUPerVirtualNumaNodeMaximum        : 
MemoryPerVirtualNumaNodeMaximumMB   : 
VirtualNumaNodesPerSocketMaximum    : 
DynamicMemoryMinimumMB              : 
NumLockEnabled                      : 
NumaIsolationRequired               : 
Generation                          : 1
VirtualDVDDrives                    : {}
ShareSCSIBus                        : False
VirtualNetworkAdapters              : {}
VirtualFibreChannelAdapters         : {}
VirtualFloppyDrive                  : 
VirtualCOMPorts                     : {COM1, COM2}
VirtualSCSIAdapters                 : {}
CapabilityProfile                   : 
CapabilityProfileCompatibilityState : Compatible
GrantedToList                       : {}
UserRoleID                          : 75700cd5-893e-4f68-ada7-50ef4668acc6
UserRole                            : Administrator
Owner                               : NFM\jacob.benson
ObjectType                          : HardwareProfile
Accessibility                       : Public
Name                                : DSCWEB Hardware Profile 2
IsViewOnly                          : False
Description                         : 
AddedTime                           : 6/12/2014 3:57:41 PM
ModifiedTime                        : 6/12/2014 3:57:41 PM
Enabled                             : True
MostRecentTask                      : Create hardware profile
ServerConnection                    : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection
ID                                  : 694bdd69-0733-40a3-ac3e-a49615c594b7
MarkedForDeletion                   : True
IsFullyCached                       : False
MostRecentTaskIfLocal               : Create hardware profile

VERBOSE: Hardware Profile DSCWEB Hardware Profile 2 is Absent

Looking at the verbose messages closer, I have a couple of issues that I need to get cleaned up. Which will be a good thing to do tomorrow.

PowerShell DSC Journey – Day 14

When I left off yesterday, I had modified my Get-TargetResource to work (hopefully) with all the new properties I had setup for my Custom Resource. Now, I am going to test this, and DSC willing I will be able to move on to the Target Resource functions today before I finish this thing out.

First I am going to run my 3 previous tests that I knew worked and see if they still work. And…I am getting mildly competent at DSC it seems.

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -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: The specified VMM Server MY-VMM-SERVER1 was found
VERBOSE: The Hardware Profile was found
VERBOSE: The Resource Hardware Profile is DSCWEB Hardware Profile

Name                           Value                                                                                                                                                                                
----                           -----                                                                                                                                                                                
VMNetwork                      Server Traffic Virtual Switch                                                                                                                                                        
Name                           DSCWEB Hardware Profile                                                                                                                                                              
DVDDrive                       True                                                                                                                                                                                 
Ensure                         Present                                                                                                                                                                              
CPUCount                       2                                                                                                                                                                                    
VMMServer                      MY-VMM-SERVER1  

Alrighty then, on to Test 2. Still winning!

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile 2" -VMMServer MDC-SC-VMM01 -Verbose
VERBOSE: VMMServer is MDC-SC-VMM01
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile 2
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: The specified VMM Server MDC-SC-VMM01 was found
VERBOSE: The Hardware Profile was not found.  Enter a valid Hardware Profile name
Unknown Hardware Profile
At line:54 char:9
+         Throw "Unknown Hardware Profile"
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Unknown Hardware Profile:String) [], RuntimeException
    + FullyQualifiedErrorId : Unknown Hardware Profile

For Test 3 I am creating a new Test with the new Properties to see what happens. And halfway into writing this test I realize that is a dumb idea. It’s dumb because I already demonstrated above that with a valid Hardware Profile and a valid VMM Server name, I can return the current properties that I have setup. On to Test-TargetResource!

Ah. It’s in Test-TargetResource that I see all my additional properties show up.

	param
	(
		[System.Boolean]
		$DVDDrive,

		[System.String]
		$VMNetwork,

		[System.UInt64]
		$CPUCount,

		[ValidateSet("Present","Absent")]
		[System.String]
		$Ensure,

		[parameter(Mandatory = $true)]
		[System.String]
		$Name,

		[parameter(Mandatory = $true)]
		[System.String]
		$VMMServer
	)

While looking at what needed to be copied from the Get-TargetResource function I realized (maybe for the second time) that there was no reason for this section of code. So I got rid of it.

    #Check if the specified VMM Server actually exists and can be connected to
    $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer
    If($VMMServer = $SCVMMServer.Name)
    {
        Write-Verbose "The specified VMM Server $VMMServer was found"
        $ResourceVMMServer = $VMMServer
    }
    Else
    {
        Write-Verbose "The specified VMM Server $VMMServer could not be found"
    }

I looked at this for a while before trying out to figure out what to do. First thing I thought was that I need to modify the section that tests the Hardware Profile. Or something. This is really making my brain hurt. I should probably start doing these at the beginning of the day instead of at the end. Anyways, here is the Test-TargetResource Function in its entirety.

function Test-TargetResource
{
	[CmdletBinding()]
	[OutputType([System.Boolean])]
	param
	(
		[System.Boolean]
		$DVDDrive,

		[System.String]
		$VMNetwork,

		[System.UInt64]
		$CPUCount,

		[ValidateSet("Present","Absent")]
		[System.String]
		$Ensure,

		[parameter(Mandatory = $true)]
		[System.String]
		$Name,

		[parameter(Mandatory = $true)]
		[System.String]
		$VMMServer
	)

    Write-Verbose "VMMServer is $VMMServer"
    Write-Verbose "Hardware Profile Name is $Name"

	#Write-Verbose "Use this cmdlet to deliver information about command processing."

	#Write-Debug "Use this cmdlet to write debug information while troubleshooting."

    #Check if VirtualMachineManager module is present for SCVMM cmdlets
    If(!(Get-Module -ListAvailable -Name VirtualMachineManager))
    {
        Throw "The VirtualMachineManager Module was not found.  Please ensure this module is available by installing the VMM Console.  For information
        On installing the VMM Console see:  http://technet.microsoft.com/en-us/library/gg610627.aspx"
    }

    $result = $false

    try{

        $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer | Where-Object Name -eq $Name -ErrorAction Stop

        If($Ensure -eq "Present")
        {
            If($DVDDrive -ne $HWProfile.VirtualDVDDrives.Enabled){Return $False}
            If($CPUCount -ne $HWProfile.CPUCount){Return $False}
            If($VMNetwork -ne $HWProfile.VirtualNetworkAdapters.VMNetwork){Return $False}

            Return $True
        }
        Else
        {
            Return $False

        }
    }
        catch [System.Management.Automation.ActionPreferenceStopException]
        {
            ($Ensure -eq 'Absent')
        }
}

Well. Let’s fill the screen with red text.

PS C:\Scripts> Test-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -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'.
False

Well that wasn’t red, but I certainly don’t want it to return False if the Hardware Profile exists so I add this change to the script. If($HWProfile -ne $Name){Return $False} . Run it again but I get the same error and it’s clear to me why. I haven’t specified the $Ensure parameter. So let’s try that out. Short version, that didn’t help, but that’s because I don’t have a DVD drive setting or anything else, so of course they are returning False. Duh. Dummy.

Let’s try this test, with the settings that I know are accurate.

PS C:\Scripts> Test-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -CPUCount 2 -DVDDrive $True -VMNetwork "Server Traffic Virtual Switch" -Ensure Present
True

Now we are talking. I am not going to bore you with a bunch more examples, but here is a summary of tests.
Ensure = Absent, Returns False
CPUCount = 4, Returns False
DVDDrive = False, Returns False
VMNetwork = Blah, Returns False
Name = Blah, Returns False

Today was a good day. Tomorrow it will be time for the Set-TargetResource Function.

PowerShell DSC Journey – Day 13

When I left off yesterday I had a functioning Custom Resource. By functioning I mean that I can run some tests without errors (unless it should error) and that it can create a new Hardware Profile name if one doesn’t exist. Other than that, it’s pretty much worthless. So, let’s add in a few more properties to the Resource and then update the Get, Set, and Test functions accordingly. I am going to out on a limb here and say that this isn’t all going to happen today.

I am going to add 3 additional Properties to my Resource. I should also mention that I got rid of Depends On, because nothing seems to use it.

$DVDDrive = New-xDSCResourceProperty -Name DVDDrive -Type Boolean -Attribute Read -Description "Should DVD Drive be created"
$VMNetwork = New-xDSCResourceProperty -Name VMNetwork -Type String -Attribute Read -Description "Name of VM Network to connect to"
$CPUCount = New-xDSCResourceProperty -Name CPUCount -Type Uint64 -Attribute Read -Description "Number of CPU's"

Update-xDscResource -Name 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware' -Property $DVDDrive,$VMNetwork,$CPUCount -ClassVersion 1.0 -Force

And of course it wouldn’t be a blog of mine if it didn’t immediately start off with an error.

New-xDSCResourceProperty : Property description {0} must contain only characters, digits, underscores and spaces.
At line:3 char:13
+ $CPUCount = New-xDSCResourceProperty -Name CPUCount -Type Uint64 -Att ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : InvalidPropertyDescriptionError,New-xDscResourceProperty

Alright, so I can’t use CPU’s but I can use CPUs. Got it. That seems kind of silly to me, but whatever. 2/2 on errors so far.

PS C:\Scripts> Update-xDscResource -Name 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware' -Property $DVDDrive,$VMNetwork,$CPUCount -ClassVersion 1.0 -Force
Test-PropertiesForResource : At least one DscResourceProperty must have the attribute Key.
At C:\Program Files\WindowsPowerShell\Modules\xDSCResourceDesigner\xDSCResourceDesigner.psm1:1548 char:13
+     $null = Test-PropertiesForResource $Property
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : NoKeyError,Test-PropertiesForResource

Alright, so I guess I need to include all the properties when I update it. Truth be told I couldn’t remember if I needed to or not so I decided to just wing it.
So, I run that with all the properties and it seems to work. However, when I open the .psm1 file, nothing has changed. That does not give me a warm and fuzzy feeling. After I do some looking around, the schema.mof has been updated with the new values, but not the .psm1 file, which I guess makes sense.

[ClassVersion("1.0"), FriendlyName("")]
class SCVMM_Hardware : OMI_BaseResource
{
	[Read, Description("Should DVD Drive be created")] Boolean DVDDrive;
	[Read, Description("Name of VM Network to connect to")] String VMNetwork;
	[Read, Description("Number of CPUs")] Uint64 CPUCount;
	[Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
	[Key, Description("Name of the hardware profile")] String Name;
	[Required, Description("Name of VMM Server")] String VMMServer;
};

While looking at this, I realize that I need to change all 3 of those from an attribute of Read to an attribute of write, because I may need to write those attributes if it’s a new Hardware Profile.
So, I make that change and update the Resource and here’s the new Schema.MOF.

[ClassVersion("1.0"), FriendlyName("")]
class SCVMM_Hardware : OMI_BaseResource
{
	[Write, Description("Should DVD Drive be created")] Boolean DVDDrive;
	[Write, Description("Name of VM Network to connect to")] String VMNetwork;
	[Write, Description("Number of CPUs")] Uint64 CPUCount;
	[Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
	[Key, Description("Name of the hardware profile")] String Name;
	[Required, Description("Name of VMM Server")] String VMMServer;
};

I am trying to figure out if I need to add in all the Parameters into the Get-TargetResource function, and it looks like I only need to declare the Parameters that are Mandatory, which I already have. All I think I need to do is add some logic for getting my other new parameters and returning those values. After poking around the xVMHyperV Resource this is what I come up with to add to the Get-TargetResource Function.

    $ResourceHWProfile = Get-SCHardwareProfile | Where-Object Name -eq $Name
    Write-Verbose "The Resource Hardware Profile is $ResourceHWProfile"

I am somewhat concerned that this probably shouldn’t go in the body of the Function, but probably in the section where I test for the Hardware Profile, but for right now I am going to leave it. I should mention at this time that I also made this change to the section where I test for the VMM Server.

    #Check if the specified VMM Server actually exists and can be connected to
    $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer
    If($VMMServer = $SCVMMServer.Name)
    {
        Write-Verbose "The specified VMM Server $VMMServer was found"
        $ResourceVMMServer = $VMMServer
    }
    Else
    {
        Write-Verbose "The specified VMM Server $VMMServer could not be found"
    }

The else part is not needed since it will just error out anyways if the server is incorrect, but for right now I am going to leave it.

I then make these changes to the returnValue section to return the correct values (or I hope at least).

	$returnValue = @{
		Ensure = If($ResourceHWProfile){"Present"}Else{"Absent"}
		Name = $ResourceHWProfile.Name
		VMMServer = $ResourceVMMServer
        DVDDrive = $ResourceHWProfile.VirtualDVDDrives.Enabled
        VMNetwork = $ResourceHWProfile.VirtualNetworkAdapters.VMNetwork
        CPUCount = $ResourceHWProfile.CPUCount
	}

I am fully expecting this to blow up in my face and it’s near the end of the day, so I am going to stop here and pick up on this again tomorrow.

PowerShell DSC Journey – Day 12

Before I get started working on the Set-TargetResource function, it occurred to me over the weekend that instead of using $Name -cin $HWProfile.Name I should be using $Name -match $HWProfile.Name because otherwise I could just put a name like “Web” and who knows what would happen. Probably not anything good.

So, I make that change and run my first test using a valid Hardware Profile name and of course it fails. Of course!

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
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: Loading module from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.psd1'.
VERBOSE: Loading 'Assembly' from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\Microsoft.BackgroundIntelligentTransfer.Management.Interop.dll'.
VERBOSE: Loading 'FormatsToProcess' from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.Format.ps1xml'.
VERBOSE: Exporting cmdlet 'Add-BitsFile'.
VERBOSE: Exporting cmdlet 'Remove-BitsTransfer'.
VERBOSE: Exporting cmdlet 'Complete-BitsTransfer'.
VERBOSE: Exporting cmdlet 'Get-BitsTransfer'.
VERBOSE: Exporting cmdlet 'Start-BitsTransfer'.
VERBOSE: Exporting cmdlet 'Resume-BitsTransfer'.
VERBOSE: Exporting cmdlet 'Set-BitsTransfer'.
VERBOSE: Exporting cmdlet 'Suspend-BitsTransfer'.
VERBOSE: Importing cmdlet 'Add-BitsFile'.
VERBOSE: Importing cmdlet 'Complete-BitsTransfer'.
VERBOSE: Importing cmdlet 'Get-BitsTransfer'.
VERBOSE: Importing cmdlet 'Remove-BitsTransfer'.
VERBOSE: Importing cmdlet 'Resume-BitsTransfer'.
VERBOSE: Importing cmdlet 'Set-BitsTransfer'.
VERBOSE: Importing cmdlet 'Start-BitsTransfer'.
VERBOSE: Importing cmdlet 'Suspend-BitsTransfer'.
VERBOSE: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was not found.  Enter a valid Hardware Profile name
Unknown Hardware Profile
At line:51 char:9
+         Throw "Unknown Hardware Profile"
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Unknown Hardware Profile:String) [], RuntimeException
    + FullyQualifiedErrorId : Unknown Hardware Profile

After verifying that the Hardware Profile didn’t get deleted I think that match probably doesn’t do what I think it does. Reading through the about_comparison_operators help file I think that I need contains and contained in. So let’s make this change and try again. It also doesn’t work, and after doing some testing, it appears I need to reverse my comparison.

If($HWProfile.Name -match $Name)
PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
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: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was found

Name                           Value                                                                                                                                                                                
----                           -----                                                                                                                                                                                
Name                           DSCWEB Hardware Profile                                                                                                                                                              
Ensure                         Present                                                                                                                                                                              
VMMServer                      MY-VMM-SERVER                                                                                                                                                                         



PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile 2" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile 2
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: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was not found.  Enter a valid Hardware Profile name
Unknown Hardware Profile
At line:52 char:9
+         Throw "Unknown Hardware Profile"
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Unknown Hardware Profile:String) [], RuntimeException
    + FullyQualifiedErrorId : Unknown Hardware Profile

Awesome!

Now, let’s move along to the entire point of this post. Alright, so we need all of our checks and things we used previously (I think? I mean shouldn’t it just bomb out on Test and Get and never reach Set anyways?). I will stick them in there anyways especially since I know they work.
So here is what I have after doing that.

#endregion

#region
function Set-TargetResource
{
	[CmdletBinding()]
	param
	(
		[ValidateSet("Present","Absent")]
		[System.String]
		$Ensure,

		[System.Boolean]
		$DependsOn,

		[parameter(Mandatory = $true)]
		[System.String]
		$Name,

		[parameter(Mandatory = $true)]
		[System.String]
		$VMMServer
	)

    Write-Verbose "VMMServer is $VMMServer"
    Write-Verbose "Hardware Profile Name is $Name"

    #Check if VirtualMachineManager module is present for SCVMM cmdlets
    If(!(Get-Module -ListAvailable -Name VirtualMachineManager))
    {
        Throw "The VirtualMachineManager Module was not found.  Please ensure this module is available by installing the VMM Console.  For information
        On installing the VMM Console see:  http://technet.microsoft.com/en-us/library/gg610627.aspx"
    }

    #Check if the specified VMM Server actually exists and can be connected to
    $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer
    If($VMMServer = $SCVMMServer.Name)
    {
        Write-Verbose "The specified VMM Server $VMMServer was found"
    }
    Else
    {
        Write-Verbose "The specified VMM Server $VMMServer could not be found"
    }

    #Check to see if the specified VMM Hardware Profile Name exists
    $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer

    If($HWProfile.Name -match $Name)
    {
        Write-Verbose "The Hardware Profile was found"
    }
    Else
    {
        Write-Verbose "The Hardware Profile was not found.  Enter a valid Hardware Profile name"
        Throw "Unknown Hardware Profile"
    }

	#Write-Verbose "Use this cmdlet to deliver information about command processing."

	#Write-Debug "Use this cmdlet to write debug information while troubleshooting."

	#Include this line if the resource requires a system reboot.
	#$global:DSCMachineStatus = 1
}
#endregion

First thing I notice is the DependsOn parameter. I don’t see this parameter listed in any of the existing Resources anywhere, so I am just going to remove it from the Set-TargetResource. The only thing I need to Set right now is the Hardware Profile name if it doesn’t exist, so I will need to modify one section of the script here.

    If($HWProfile.Name -match $Name)
    {
        Write-Verbose "The Hardware Profile was found"
    }
    Else
    {
        Write-Verbose "The Hardware Profile was not found.  Creating new Hardware Profile"
        New-SCHardwareProfile -Name $Name -Verbose
    }

And…I think that is it for now. So let’s test this baby out and see how much red text I get.
Test 1:

PS C:\Scripts> Set-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was found

That was expected. This test is where things are going to get real. For the second time in two days I feel like a DSC Wizard!

PS C:\Scripts> Set-TargetResource -Name "DSCWEB Hardware Profile 2" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile 2
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was not found.  Creating new Hardware Profile


CPUCount                            : 1
Memory                              : 512
DynamicMemoryEnabled                : False
DynamicMemoryMaximumMB              : 
DynamicMemoryBufferPercentage       : 
MemoryWeight                        : 
VirtualVideoAdapterEnabled          : False
MonitorMaximumCount                 : 
MonitorResolutionMaximum            : 
BootOrder                           : 
FirstBootDevice                     : 
SecureBootEnabled                   : 
UndoDisksEnabled                    : False
CPUType                             : 3.60 GHz Xeon (2 MB L2 cache)
IsHighlyAvailable                   : False
HAVMPriority                        : 
IsDRProtectionRequired              : False
RecoveryPointObjective              : 
LimitCPUFunctionality               : False
LimitCPUForMigration                : False
ExpectedCPUUtilization              : 20
DiskIO                              : 0
NetworkUtilization                  : 0
RelativeWeight                      : 100
CPUReserve                          : 0
CPUMax                              : 100
CPUPerVirtualNumaNodeMaximum        : 
MemoryPerVirtualNumaNodeMaximumMB   : 
VirtualNumaNodesPerSocketMaximum    : 
DynamicMemoryMinimumMB              : 
NumLockEnabled                      : 
NumaIsolationRequired               : 
Generation                          : 1
VirtualDVDDrives                    : {}
ShareSCSIBus                        : False
VirtualNetworkAdapters              : {}
VirtualFibreChannelAdapters         : {}
VirtualFloppyDrive                  : DSCWEB Hardware Profile 2
VirtualCOMPorts                     : {COM1, COM2}
VirtualSCSIAdapters                 : {}
CapabilityProfile                   : 
CapabilityProfileCompatibilityState : Compatible
GrantedToList                       : {}
UserRoleID                          : 75700cd5-893e-4f68-ada7-50ef4668acc6
UserRole                            : Administrator
Owner                               : jacob.benson
ObjectType                          : HardwareProfile
Accessibility                       : Public
Name                                : DSCWEB Hardware Profile 2
IsViewOnly                          : False
Description                         : 
AddedTime                           : 6/9/2014 2:26:08 PM
ModifiedTime                        : 6/9/2014 2:26:08 PM
Enabled                             : True
MostRecentTask                      : Create hardware profile
ServerConnection                    : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection
ID                                  : a7a31e04-5c5d-414b-9d80-43ac3782e838
MarkedForDeletion                   : False
IsFullyCached                       : True
MostRecentTaskIfLocal               : Create hardware profile

So pumped. I verify that it does in fact show up in the VMM GUI. I won’t bore you with the picture but I promise you that it is there. Now I will run my last test just for the sake of consistency.

PS C:\Scripts> Set-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER2 -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER2
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
Get-SCVMMServer : VMM is unable to connect to the VMM management server MY-VMM-SERVER2 because the specified computer name could not be resolved. (Error ID: 
1601)
 
Ensure that the computer name is correct, and then try the operation again. If the problem persists, contact your network administrator.
At line:38 char:20
+     $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCVMMServer], CarmineException
    + FullyQualifiedErrorId : 1601,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.ConnectServerCmdlet
VERBOSE: The specified VMM Server  could not be found
Get-SCHardwareProfile : Unable to connect to the VMM management server  on port 8100. (Error ID: 1606)
 
Verify that the server name and port number are correct.
At line:49 char:18
+     $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer
+                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCHardwareProfile], CarmineException
    + FullyQualifiedErrorId : 1606,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.GetSCHWConfigCmdlet
VERBOSE: The Hardware Profile was not found.  Creating new Hardware Profile
New-SCHardwareProfile : The HardwareProfile DSCWEB Hardware Profile is already in use by another HardwareProfile. (Error ID: 802, Detailed Error: )
 
Wait for the object to become available, and then try the operation again.
 
To restart the job, run the following command:
PS> Restart-Job -Job (Get-VMMServer MY-VMM-SERVER1 | Get-Job | where { $_.ID -eq "{e4c03f89-0fc5-4a12-8ebb-2da21cd34bc9}"})
At line:58 char:9
+         New-SCHardwareProfile -Name $Name -Verbose
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [New-SCHardwareProfile], CarmineException
    + FullyQualifiedErrorId : 802,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.NewHWConfigCmdlet

For right now I am OK with it trying to check the HardwareProfile even if it can’t find the VMM server, but I will probably end up adding in more logic for testing that better at some point.

Well. I have a somewhat functioning (but not very useful) Custom Resource now. Tomorrow we will start adding in more Hardware Profile parameters!

PowerShell DSC Journey – Day 10

When we left off yesterday I believed that I had a functioning Get-TargetResource function, without yet actually getting to the part where I Get anything. Which begs the question whether or not I actually need all that other stuff in there, or if it belongs in the Test-TargetResource. I honestly have no idea, I am just working off of the examples I have at my disposal. So, let’s see today if we can get some stuff returned!

Looking through examples of existing DSC Resources, I don’t see Ensure or DependsOn anywhere, except in what appears to be one special case, so I guess DSC just knows how to use them? I looked at some of Steve Murawski’s Stack Exchange Resources and that just confused me even more so I am just going to keep plugging along here. I am going to set Ensure = “Present” because the Hardware Profile should already exist (I guess?). When I get further along into creating a new Hardware Profile I imagine I will need to set this to “Absent” if the Hardware Profile does not exist. So, this is what I have.

	$returnValue = @{
		Ensure = "Present"
		Name = $Name
		VMMServer = $VMMServer
	}

And if I run one my Test-TargetResource functions that I know should work, here is what I get:

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
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.VirtualMachineManag
er.dll'.
VERBOSE: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was found

Name                           Value                                                                                                                                                           
----                           -----                                                                                                                                                           
Name                           DSCWEB Hardware Profile                                                                                                                                         
Ensure                         Present                                                                                                                                                         
VMMServer                      MY-VMM-SERVER         

HOLY CRAP IT WORKED ON THE FIRST TRY AND I AM REALLY EXCITED AND YOU CAN’T MAKE ME STOP TALKING IN ALL CAPS!!!! Well, that’s all for today, we will pick it up tomorrow with working on the Test-TargetResource.

PowerShell DSC Journey – Day 9

When I left off I had modified my Get-Target resource function to include steps for checking to make sure SCVMM cmdlets existed, and that the specified VMM Server was a valid VMM Server. Next, I need to make sure that the given Name of the Hardware Profile exists.

The issue I run into here is that the Get-SCHardwareProfile doesn’t have a Name parameter (because that would make too much sense) only an ID value.

PS C:\Scripts> Get-SCHardwareProfile -VMMServer MY-VMM-SERVER | select name,id

Name                                                                           ID                                                                            
----                                                                           --                                                                            
NFM Default Hardware Configuration                                             f9619f3d-1b0b-481f-ac9b-408fd37f8836                                          
NFM Default Hardware Configuration - Gen 2                                     032946a3-79b8-49e6-9bff-bf8c28244632                                          
DSCWEB Hardware Profile                                                        9b575a83-1f2b-4ada-883b-d7682d079757   

So, knowing the ID I can do this.

PS C:\Scripts> Get-SCHardwareProfile -VMMServer MY-VMM-SERVER -id 9b575a83-1f2b-4ada-883b-d7682d079757


CPUCount                            : 2
Memory                              : 4096
DynamicMemoryEnabled                : False
DynamicMemoryMaximumMB              : 
DynamicMemoryBufferPercentage       : 
MemoryWeight                        : 5000
VirtualVideoAdapterEnabled          : False
MonitorMaximumCount                 : 
MonitorResolutionMaximum            : 
BootOrder                           : 
FirstBootDevice                     : 
SecureBootEnabled                   : True
UndoDisksEnabled                    : False
CPUType                             : 3.60 GHz Xeon (2 MB L2 cache)
IsHighlyAvailable                   : True
HAVMPriority                        : 2000
IsDRProtectionRequired              : False
RecoveryPointObjective              : 
LimitCPUFunctionality               : False
LimitCPUForMigration                : False
ExpectedCPUUtilization              : 20
DiskIO                              : 0
NetworkUtilization                  : 0
RelativeWeight                      : 100
CPUReserve                          : 0
CPUMax                              : 100
CPUPerVirtualNumaNodeMaximum        : 
MemoryPerVirtualNumaNodeMaximumMB   : 
VirtualNumaNodesPerSocketMaximum    : 
DynamicMemoryMinimumMB              : 
NumLockEnabled                      : 
NumaIsolationRequired               : False
Generation                          : 2
VirtualDVDDrives                    : {DSCWEB Hardware Profile}
ShareSCSIBus                        : False
VirtualNetworkAdapters              : {DSCWEB Hardware Profile}
VirtualFibreChannelAdapters         : {}
VirtualFloppyDrive                  : 
VirtualCOMPorts                     : {}
VirtualSCSIAdapters                 : {DSCWEB Hardware Profile}
CapabilityProfile                   : 
CapabilityProfileCompatibilityState : 
GrantedToList                       : {}
UserRoleID                          : 75700cd5-893e-4f68-ada7-50ef4668acc6
UserRole                            : Administrator
Owner                               : 
ObjectType                          : HardwareProfile
Accessibility                       : Public
Name                                : DSCWEB Hardware Profile
IsViewOnly                          : False
Description                         : 
AddedTime                           : 4/11/2014 1:01:54 PM
ModifiedTime                        : 4/11/2014 1:03:13 PM
Enabled                             : True
MostRecentTask                      : 
ServerConnection                    : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection
ID                                  : 9b575a83-1f2b-4ada-883b-d7682d079757
MarkedForDeletion                   : False
IsFullyCached                       : True
MostRecentTaskIfLocal               : 

To make this work, I am going to need to get the ID of the profile using the name, without really using the name. I thought this was going to be complicated, but it turns out to be easier than I thought.

    #Check to see if the specified VMM Hardware Profile Name exists
    $Name = "DSCWEB Hardware Profile"
    $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer | Where-Object Name -eq $Name

So, to test this let’s do this:

    If($Name -cin $HWProfile.Name)
    {
        Write-Output "The HW Profile was found"
    }
    Else
    {
        Write-Output "The HW Profile was not found.  Enter a valid HW Profile name"
    }

And here is some output from testing this.

PS C:\Scripts>     If($Name -cin $HWProfile.Name)
    {
        Write-Output "The HW Profile was found"
    }
    Else
    {
        Write-Output "The HW Profile was not found.  Enter a valid HW Profile name"
    }
The HW Profile was found

PS C:\Scripts>     $Name = "DSCWEB Hardware Profile 2"

PS C:\Scripts>     If($Name -cin $HWProfile.Name)
    {
        Write-Output "The HW Profile was found"
    }
    Else
    {
        Write-Output "The HW Profile was not found.  Enter a valid HW Profile name"
    }
The HW Profile was not found.  Enter a valid HW Profile name

Alright, so let’s add some tests into the Get-TargetResource Function before we populate the $returnValue section.

    #Test1 Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER -Verbose
    #Test2 Get-TargetResource -Name "DSCWEB Hardware Profile 2" -VMMServer MY-VMM-SERVER -Verbose
    #Test3 Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER2 -Verbose

Let’s test the first one and see what happens.

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER -Verbose
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: The specified VMM Server @{Name=MY-VMM-SERVER} was found
Get-SCHardwareProfile : Unable to connect to the VMM management server @{Name=MY-VMM-SERVER} on port 8100. (Error ID: 1606)
 
Verify that the server name and port number are correct.
At line:40 char:18
+     $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer
+                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCHardwareProfile], CarmineException
    + FullyQualifiedErrorId : 1606,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.GetSCHWConfigCmdlet
VERBOSE: The Hardware Profile was not found.  Enter a valid Hardware Profile name

What the what? I clear all my variables (because opening a new session is too easy) and try again. Same thing. Fine, I will open a new tab in ISE. That also doesn’t work. Well, what the hell, I was just using this and it was working fine! After reading through this, I see what I am doing wrong. I need to replace Get-SCHardwareProfile -VMMServer (Get-SCVMMServer -ComputerName $VMMServer) with $HWProfile = Get-SCHardwareProfile -VMMServer $SCVMMServer . And, that doesn’t work so well either.

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer "MY-VMM-SERVER" -Verbose
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: The specified VMM Server @{Name=MY-VMM-SERVER} was found
Get-SCHardwareProfile : Cannot bind parameter 'VMMServer'. Cannot convert the "@{Name=MY-VMM-SERVER}" value of type 
"Selected.Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection" to type 
"Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection".
At line:40 char:51
+     $HWProfile = Get-SCHardwareProfile -VMMServer $SCVMMServer
+                                                   ~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-SCHardwareProfile], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.GetSCHWConfigCmdlet
 
VERBOSE: The Hardware Profile was not found.  Enter a valid Hardware Profile name

Alright. So let’s back up here for a second. Get-SCVMMServer -ComputerName MY-VMM-SERVER works fine. If I set $VMMServer = “MY-VMM-SERVER” and then run Get-SCVMMServer -ComputerName $VMMServer it works fine. If I then run $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer it works fine. So, uh, why isn’t this working for me in my Get-TargetResource function? The function is doing the exact same thing, and failing. I have no idea why.

I add the following two lines to the type of the script (underneath the parameter declaration) just to make sure nothing screwy is happening (and it isn’t).

    Write-Verbose "VMMServer is $VMMServer"
    Write-Verbose "Hardware Profile Name is $Name"

I do some more testing, and something screwy is going on. It looks like once a connection is made to the VMMServer it isn’t able to make the connection a second time in the same script? Does that even make sense? I change the $SCVMMServer parameter to return the entire SCVMMServer object, and then see if the $VMMServer matches $SCVMMServer.Name like this.

    $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer
    If($VMMServer = $SCVMMServer.Name)
    {
        Write-Verbose "The specified VMM Server $VMMServer was found"
    }
    Else
    {
        Write-Verbose "The specified VMM Server $VMMServer could not be found"
    }

    #Check to see if the specified VMM Hardware Profile Name exists
    $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer

Once I do that, it works like magic!

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was found

Alright, let’s test the next scenario.

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile 2" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile 2
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was not found.  Enter a valid Hardware Profile name

Well, that’s great and all, except that it didn’t throw an error and stop, which it needs to. So, I add the following line to my function (I place it after the Verbose line, because I figured out that once it does the Throw, there isn’t anything else that happens after that).

Now, this is better.

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile 2" -VMMServer MY-VMM-SERVER -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER
VERBOSE: Hardware Profile Name is DSCWEB Hardware Profile 2
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: The specified VMM Server MY-VMM-SERVER was found
VERBOSE: The Hardware Profile was not found.  Enter a valid Hardware Profile name
Unknown Hardware Profile
At line:49 char:9
+         Throw "Unknown Hardware Profile"
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Unknown Hardware Profile:String) [], RuntimeException
    + FullyQualifiedErrorId : Unknown Hardware Profile

And finally for my last test.

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER2 -Verbose
VERBOSE: VMMServer is MY-VMM-SERVER2
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\..\..\virtualm
achinemanager.R2AdvFunc.psm1'.
VERBOSE: Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager\..\..\Microsof
t.SystemCenter.VirtualMachineManager.dll'.
Get-SCVMMServer : VMM is unable to connect to the VMM management server MY-VMM-SERVER2 because the specified computer name could not be resolved. (Error ID: 
1601)
 
Ensure that the computer name is correct, and then try the operation again. If the problem persists, contact your network administrator.
At line:30 char:20
+     $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCVMMServer], CarmineException
    + FullyQualifiedErrorId : 1601,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.ConnectServerCmdlet
VERBOSE: The specified VMM Server  could not be found
Get-SCHardwareProfile : Unable to connect to the VMM management server  on port 8100. (Error ID: 1606)
 
Verify that the server name and port number are correct.
At line:41 char:18
+     $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer
+                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCHardwareProfile], CarmineException
    + FullyQualifiedErrorId : 1606,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.GetSCHWConfigCmdlet
VERBOSE: The Hardware Profile was not found.  Enter a valid Hardware Profile name
Unknown Hardware Profile
At line:49 char:9
+         Throw "Unknown Hardware Profile"
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Unknown Hardware Profile:String) [], RuntimeException
    + FullyQualifiedErrorId : Unknown Hardware Profile

This is great and all, except that it shouldn’t try to find the Hardware Profile if it can’t contact the VMMServer. I check the $ErrorActionPreference and it is set to continue, I want to set this (in the function) to stop. There is no reason for it to keep going if it encounters an error. I add $ErrorActionPreference = “Stop” to the beginning of the function and try my test again.

I will spare you the text, but it failed to connect to the VMMServer, and then stopped. Up next, filling out the return values section and testing that out.

PowerShell DSC Journey – Day 8

Alright. Picking up where I left off yesterday, this time I am seriously going to work on the Get, Test and Set Functions for my first custom DSC Resource. I promise I won’t get myself sidetracked by why I need the full path to import my Module :).

First things first, here is the code that was generated by the DSC Resource Designer for the Get-TargetResource Function.

function Get-TargetResource
{
	[CmdletBinding()]
	[OutputType([System.Collections.Hashtable])]
	param
	(
		[parameter(Mandatory = $true)]
		[System.String]
		$Name,

		[parameter(Mandatory = $true)]
		[System.String]
		$VMMServer
	)

	#Write-Verbose "Use this cmdlet to deliver information about command processing."

	#Write-Debug "Use this cmdlet to write debug information while troubleshooting."


	<#
	$returnValue = @{
		Ensure = [System.String]
		DependsOn = [System.Boolean]
		Name = [System.String]
		VMMServer = [System.String]
	}

	$returnValue
	#>
}

Off the top of my head, some things I need to do: Ensure SCVMM Cmdlets exist. Make sure the VMM Server is valid. See if the Hardware Profile name already exists, if so, return the appropriate values. I am also going to add regions to each section of this script so that they can be easily collapsed when working on other sections.

First task, lets make sure that the SCVMM cmdlets exist and are available. I pretty much took this section and modified it from the xVMHyper-V Resource.

<pre class="minimize:true lang:default decode:true " >    #Check if VirtualMachineManager module is present for SCVMM cmdlets
    If(!(Get-Module -ListAvailable -Name VirtualMachineManager))
    {
        Throw "The VirtualMachineManager Module was not found.  Please ensure this module is available by installing the VMM Console.  For information
        On installing the VMM Console see:  http://technet.microsoft.com/en-us/library/gg610627.aspx"
    }</pre> 

And if I run this on my desktop, I don’t get any kind of error which is what it should do. Now let me copy and paste this into a VM that doesn’t have the SCVMM cmdlets and this happens.

The VirtualMachineManager Module was not found.  Please ensure this module is available by installing the VMM Console.
 For information
        On installing the VMM Console see:  http://technet.microsoft.com/en-us/library/gg610627.aspx
At line:3 char:9
+         Throw "The VirtualMachineManager Module was not found.  Pleas ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (The VirtualMach...y/gg610627.aspx:String) [], RuntimeException
    + FullyQualifiedErrorId : The VirtualMachineManager Module was not found.  Please ensure this module is available
   by installing the VMM Console.  For information
        On installing the VMM Console see:  http://technet.microsoft.com/en-us/library/gg610627.aspx

Well, that was easy enough :). Next thing, let’s make sure that the $VMMServer is an actual VMMServer. I start out by doing this (for testing purposes to see if this is going to work).

    $VMMServer = "MY-VMM-SERVER"
    $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer | Select Name

Followed by this (because I want to see what the output type is).

PS C:\Scripts> $SCVMMServer

Name                                                                                                                                                         
----                                                                                                                                                         
MY-VMM-SERVER                                                                                                                                                 



PS C:\Scripts> $SCVMMServer | gm


   TypeName: Selected.Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection

Name        MemberType   Definition                     
----        ----------   ----------                     
Equals      Method       bool Equals(System.Object obj) 
GetHashCode Method       int GetHashCode()              
GetType     Method       type GetType()                 
ToString    Method       string ToString()              
Name        NoteProperty System.String Name=MY-VMM-SERVER

The name property is a string like the $VMMServer parameter is, so I should be able to just compare them and call it good.

    If($VMMServer = $SCVMMServer)
    {
        Write-Output "The server name matches"
    }
    Else
    {
        Write-Output "The server name does not match"
    }

PS C:\Scripts>     If($VMMServer = $SCVMMServer)
    {
        Write-Output "The server name matches"
    }
    Else
    {
        Write-Output "The server name does not match"
    }
The server name matches

That looks good. Now, I change my $VMMServer variable to MY-VMM-SERVER2 run it again and this happens.

Get-SCVMMServer : VMM is unable to connect to the VMM management server MY-VMM-SERVER2 because the specified computer name could not be resolved. (Error ID: 
1601)
 
Ensure that the computer name is correct, and then try the operation again. If the problem persists, contact your network administrator.
At line:2 char:20
+     $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer | Select  ...
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCVMMServer], CarmineException
    + FullyQualifiedErrorId : 1601,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.ConnectServerCmdlet
The server name matches

This is obviously an issue because I already stored a value in there, something that would not happen (more than likely) when someone runs this Configuration. So, let’s just clean it out quick and try this again.

PS C:\Scripts> Clear-Variable -Name VMMServer -Force
PS C:\Scripts> Clear-Variable SCVMMServer -Force
PS C:\Scripts> $VMMServer
PS C:\Scripts>
PS C:\Scripts> $SCVMMServer
PS C:\Scripts> 
PS C:\Scripts> 

And now when I run my little test I get this for the output.

Get-SCVMMServer : VMM is unable to connect to the VMM management server MY-VMM-SERVER2 because the specified computer name could not be resolved. (Error ID: 
1601)
 
Ensure that the computer name is correct, and then try the operation again. If the problem persists, contact your network administrator.
At line:2 char:20
+     $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer | Select  ...
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCVMMServer], CarmineException
    + FullyQualifiedErrorId : 1601,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.ConnectServerCmdlet
The server name does not match

So, now that we know that works, let me write this in a way that actually makes sense and can be useful.

    #Check if the specified VMM Server actually exists and can be connected to
    $SCVMMServer = Get-SCVMMServer -ComputerName $VMMServer | Select Name
    If($VMMServer = $SCVMMServer)
    {
        Write-Verbose "The VMM Server name is $VMMServer"
    }
    Else
    {
        Write-Verbose "The Server name $VMMServer could not be found"
    }

Next, let me check and see if the SCVMM Hardware Profile exists. For right now I am only concerned with using an existing SCVMM Hardware Profile. I will cross the bridge of creating a new Hardware Profile later. This is where things are going to get interesting, so I am going to save this for the next blog post 🙂

PowerShell DSC Journey – Day 7

Alright, so yesterday I was able to successfully create a very simple (and that is putting it mildly) DSC Resource. It currently only has only 3 parameters: Ensure, Depends On, and Name. Today I am going to start writing the Get,Set,Test Functions and testing them (hopefully).

Here are my 3 main references for this task:
http://blogs.technet.com/b/privatecloud/archive/2014/05/02/powershell-dsc-blog-series-part-2-authoring-dsc-resources-when-cmdlets-already-exist.aspx
http://blogs.technet.com/b/privatecloud/archive/2014/05/09/powershell-dsc-blog-series-part-3-testing-dsc-resources.aspx
http://blogs.msdn.com/b/powershell/archive/2013/11/19/resource-designer-tool-a-walkthrough-writing-a-dsc-resource.aspx
I am also referencing the MSFT_xVMHypverV.psm1 and other existing resources .PSM1 files for reference in helping me create my functions.

Since it’s the first thing in the list, I am going to start with the Get-TargetResource function. This should check and see if the Hardware Profile exists. If it exists already it should return 1 if True (Hardware Profile Name exists) and 0 if False (Hardware Profile Name does not exist).

First thing I am going to do is start with looking at the Get-SCHardwareProfile cmdlets. Which does not turn out the way I expect because it doesn’t take a name parameter, which is probably going to be a pain in the ass.

PS C:\Scripts> Help Get-SCHardwareProfile

NAME
    Get-SCHardwareProfile
    
SYNOPSIS
    Gets hardware profile objects from the VMM library.
    
    
SYNTAX
    Get-SCHardwareProfile [-VMMServer <ServerConnection>] [<CommonParameters>]
    
    Get-SCHardwareProfile [-All] [-VMMServer <ServerConnection>] [<CommonParameters>]
    
    Get-SCHardwareProfile [-ID <Guid>] [-VMMServer <ServerConnection>] [<CommonParameters>]

Looking in VMM GUI, I don’t see an ID anywhere for my existing hardware profiles. But looking at the examples in the help files shows that I can still use Where-Object Name -eq $Name to filter and I should be OK. I also realize that I am going to need a parameter for a VMM Server because that would be a horrible thing to hardcode. So I am going to backup and do that right now.

Adding this property is as easy as:

$VMMServer = New-xDscResourceProperty -Name VMMServer -Type String -Attribute Read -Description "Name of VMM Server"
Update-xDscResource -ModuleName 'SCVMM_Hardware' -Properties $Ensure, $DependsOn, $Name, $VMMServer -Force

NOT!

PS C:\Scripts> Update-xDscResource -ModuleName 'SCVMM_Hardware' -Properties $Ensure,$DependsOn,$Name,$VMMServer -Force
Update-xDscResource : A parameter cannot be found that matches parameter name 'ModuleName'.
At line:1 char:21
+ Update-xDscResource -ModuleName 'SCVMM_Hardware' -Properties $Ensure, ...
+                     ~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Update-xDscResource], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Update-xDscResource
 

PS C:\Scripts> help Update-xDscResource

NAME
    Update-xDscResource
    
SYNOPSIS
    Update an existing DscResource based on the given arguments.
    
    
SYNTAX
    Update-xDscResource [-Name] <String> [-Property] <DscResourceProperty[]> [-ClassVersion <Version>] [-NewName <String>] [-Force] [-WhatIf] [-Confirm] 
    [<CommonParameters>]

So ModuleName, no longer exists. That’s ok, it looks like it’s now Name, and I need to change Properties, to Property, no biggie!

PS C:\Scripts> Update-xDscResource -Name 'SCVMM_Hardware' -Property $Ensure, $DependsOn, $Name, $VMMServer -Force
Update-xDscResource : Cannot bind argument to parameter 'Property' because it is null.
At line:1 char:54
+ ... VMM_Hardware' -Property $Ensure, $DependsOn, $Name, $VMMServer -Force
+                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Update-xDscResource], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Update-xDscResource

LOL WHAT? Fine then, let’s look at an example.

NAME
    Update-xDscResource
    
SYNOPSIS
    Update an existing DscResource based on the given arguments.
    
    -------------------------- EXAMPLE 1 --------------------------
    
    C:\PS>Update-xDscResource -ResourceDirectory "UserResource" -Property $UserName,$Ensure,$Password -ClassVersion 1.0 -FriendlyName "User" -Force

Fine. I will read the rest of the help. Somewhere Jeffrey Snover and Don Jones are crying and a kitten probably died. I need a Name and a Property and that is all that is required. It then occurs to me that this is a new PowerShell session, and it doesn’t have the variables for Ensure, DependsOn, etc stored. So I re-run that part of my script, run it again, and I get a different error!

PS C:\Scripts> Update-xDscResource -Name 'SCVMM_Hardware' -Property $Ensure, $DependsOn, $Name, $VMMServer -Force
CheckResourceFound : The term 'SCVMM_Hardware' is not recognized as the name of a Resource.
At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:2428 char:13
+             CheckResourceFound $name $resources
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,CheckResourceFound
 
Test-ResourcePath : No module with the name SCVMM_Hardware was found in $env:PSModulePath.
At C:\Program Files\WindowsPowerShell\Modules\xDSCResourceDesigner\xDSCResourceDesigner.psm1:1536 char:15
+ ...   if (-not (Test-ResourcePath $Name ([ref]$Schema) ([ref]$Module) -Ig ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : ModuleNotFoundError,Test-ResourcePath

Well. Like hell it’s not the name of the Resource!
dsc61

So, I have the bright idea to run this fancy command to see if it can actually find it.

Get-Module -ListAvailable

And here is part of the output.

    Directory: C:\Program Files\WindowsPowerShell\Modules\DSCModules\DSCResources


ModuleType Version    Name                                ExportedCommands                                                                                   
---------- -------    ----                                ----------------                                                                                   
Script     0.0        SCVMM_Hardware                      {Get-TargetResource, Set-TargetResource, Test-TargetResource} 

It now occurs to me that maybe it can’t update it because it hasn’t been imported? So let’s try that.

PS C:\Scripts> Import-Module -Name SCVMM_Hardware
Import-Module : The specified module 'SCVMM_Hardware' was not loaded because no valid module file was found in any module directory.
At line:1 char:1
+ Import-Module -Name SCVMM_Hardware
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (SCVMM_Hardware:String) [Import-Module], FileNotFoundException
    + FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand

How can it be shown as an available Module and then not be able to import it because no valid module file was found????? I tried changing the Version to 1.0, and then importing it and that didn’t work (same errors).

After thinking about it some more, I think for some reason maybe the path just isn’t working (I borrowed the one from the blog article) and I am just going to change it to the Modules path with the rest of the DSC Resources. That also doesn’t work. I then try to import the Module from the new directory using Get-Module -Name and notice that intellisense doesn’t show it in the list. Something is definitely up. I then remember reading somewhere about how anytime you do this you also need to create a Module Manifest (or something like that) because it isn’t created by default.

After a lot of reading and not finding what I am looking for, I Googled “New DSC Resource Module Manifest” which led me to this article. It clearly states you need a module manifest, which I don’t have. Yet!

This is the important part of that section of the article. “Finally, use the New-ModuleManifest cmdlet to define a .psd1 file for your custom resource module. When you invoke this cmdlet, reference the script module (.psm1) file described in the previous section. Include Get-TargetResource, Set-TargetResource, and Test-TargetResource in the list of functions to export.” Looking at existing DSCResources however, they don’t specify those functions, they just have an *. In an effort not to complicate things I am going to go bare bones with this module manifest.

Sounds easy enough!

New-ModuleManifest -Path 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware.psd1' -Author 'Jacob Benson' 
PS C:\Scripts> Import-Module -Name SCVMM_Hardware
Import-Module : The specified module 'SCVMM_Hardware' was not loaded because no valid module file was found in any module directory.
At line:1 char:1
+ Import-Module -Name SCVMM_Hardware
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (SCVMM_Hardware:String) [Import-Module], FileNotFoundException
    + FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand

Whatever. I am going to just restart PowerShell ISE and see if that magically fixes it. And nope. It then occurs to me that maybe I’m an idiot and my Module name can’t have an underscore in it. So let’s try all of this without that. And it doesn’t matter. Same nonsense. This should not be this hard.

I do some more research, and run this command, which works completely fine. And then I try the one with the underscore, which also works. I guess that’s the way it is going to be? There is probably a reason for it, but I don’t know what that reason is. I deleted all my files and started over and went through all of this.

PS C:\Scripts> $Ensure = New-xDscResourceProperty -Name Ensure -Type String -Attribute Write -ValidateSet "Present","Absent"
$DependsOn = New-xDscResourceProperty -Name DependsOn -Type Boolean -Attribute Write
$Name = New-xDscResourceProperty -Name Name -Type String -Attribute Key -Description "Name of the hardware profile"
$VMMServer = New-xDscResourceProperty -Name VMMServer -Type String -Attribute Read -Description "Name of VMM Server"

New-xDscResource -Name SCVMM_Hardware -Property $Ensure,$DependsOn,$Name -Path 'C:\Program Files\WindowsPowerShell\Modules' -ClassVersion 1.0


    Directory: C:\Program Files\WindowsPowerShell\Modules


Mode                LastWriteTime     Length Name                                                                                                            
----                -------------     ------ ----                                                                                                            
d----         5/30/2014   1:57 PM            DSCResources                                                                                                    


    Directory: C:\Program Files\WindowsPowerShell\Modules\DSCResources


Mode                LastWriteTime     Length Name                                                                                                            
----                -------------     ------ ----                                                                                                            
d----         5/30/2014   1:57 PM            SCVMM_Hardware                                                                                                  



PS C:\Scripts> Update-xDscResource -Name SCVMM_Hardware -Property $Ensure, $DependsOn, $Name, $VMMServer -ClassVersion 1.0 -Force
CheckResourceFound : The term 'SCVMM_Hardware' is not recognized as the name of a Resource.
At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:2428 char:13
+             CheckResourceFound $name $resources
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,CheckResourceFound
 
Test-ResourcePath : No module with the name SCVMM_Hardware was found in $env:PSModulePath.
At C:\Program Files\WindowsPowerShell\Modules\xDSCResourceDesigner\xDSCResourceDesigner.psm1:1536 char:15
+ ...   if (-not (Test-ResourcePath $Name ([ref]$Schema) ([ref]$Module) -Ig ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : ModuleNotFoundError,Test-ResourcePath
 

PS C:\Scripts> Import-Module 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware\SCVMM_Hardware.psm1'

PS C:\Scripts> Get-Module -Name SCVMM_Hardware

ModuleType Version    Name                                ExportedCommands                                                                                   
---------- -------    ----                                ----------------                                                                                   
Script     0.0        SCVMM_Hardware                      {Get-atrd5cqy.juvTargetResource, Set-atrd5cqy.juvTargetResource, Test-atrd5cqy.juvTargetResource}

PS C:\Scripts> Update-xDscResource -Name SCVMM_Hardware -Property $Ensure, $DependsOn, $Name, $VMMServer -ClassVersion 1.0 -Force
CheckResourceFound : The term 'SCVMM_Hardware' is not recognized as the name of a Resource.
At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:2428 char:13
+             CheckResourceFound $name $resources
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,CheckResourceFound
 
Test-ResourcePath : No module with the name SCVMM_Hardware was found in $env:PSModulePath.
At C:\Program Files\WindowsPowerShell\Modules\xDSCResourceDesigner\xDSCResourceDesigner.psm1:1536 char:15
+ ...   if (-not (Test-ResourcePath $Name ([ref]$Schema) ([ref]$Module) -Ig ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : ModuleNotFoundError,Test-ResourcePath

I just. I don’t get it. WTF is going on?????? I am looking at the help for Update-xDSCResource again and notice something interesting. In the Parameters it has -Name but in the example it uses -ResourceDirectory. However, there is no -ResourceDirectory parameter when I try that. So, then I try this.

Update-xDscResource -Name 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware' -Property $Ensure, $DependsOn, $Name, $VMMServer -ClassVersion 1.0 -Force

And it freaking works. I clearly need to do more research into why I can’t just use the Resource Name when everything I read says I should be able to do it. I don’t get why I need to use the entire path there.

I look in the schema.mof and verify that it was in fact updated.

[ClassVersion("1.0"), FriendlyName("")]
class SCVMM_Hardware : OMI_BaseResource
{
	[Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
	[Write] Boolean DependsOn;
	[Key, Description("Name of the hardware profile")] String Name;
	[Read, Description("Name of VMM Server")] String VMMServer;
};

That’s enough for today. And maybe the rest of this week.

EDIT: Once I added C:\Program Files\WindowsPowerShell\Modules\DSCResources to my $Env:PSModulePath directory I was able to import the Module by name, without having to use the path. However, I still can’t update the Resource without using the entire path. Awesome. Not.