Demo DSC – Part 1

This is the first in a series of posts outlining how I presented a demo of Desired State Configuration (DSC) for the organization I work for. This was never intended to demonstrate all the features and capabilities of DSC (there’s a lot!), but instead was done to show at a high level the kinds of things that are possible and to start a discussion about where it fits into our organization immediately and going forward.

My demo was done using 4 Server 2012 R2 Virtual Machines on a single VMWare ESXi host. Because this environment was in a lab (with some unique networking challenges) and to make things easier for me during the demo I just copied the set of files from a Windows 8.1 machine on the same network as the host onto each VM individually.  I built and ran this demo using Wave 9 DSC Resources.  I switched to Wave 10 halfway through and had a problem with the xComputerManagement Resource (In Wave 10 it doesn’t properly evaluate the condition of whether or not the Computer Names match or not), and switched back to Wave 9 after that to avoid any further problems.  You will also notice in the script that I hardcoded credentials which is definitely not the recommended way to do it in a production environment.

The first thing I wanted to do was to build a Domain Controller on a brand new domain, that would be the foundation for showcasing other features of DSC in the rest of the demo. My outline for this part of the demo looked like this:

  1. Show New Server Build
    1. Show how nothing is configured (name, domain, time zone, IEESC, IP address etc)
    2. Open ISE, Run BuildDC Script. Show computer rename and restart section.
    3. Will restart – Talk about what just happened.
  2. Continue Server Build Post Reboot
    1. Login after reboot, show post Reboot scheduled task kicking off
      1. Show IP address change
      2. Wait for restart again (Approx 3:15 total at this point)
    2. Login after restart with Domain credentials
      1. Show Firewall Status
      2. Event Log Configuration
      3. Time Zone Configuration
  3. Run entire Configuration again to show nothing happens.

Here is the entire BuildDC Configuration Script in it’s entirety.  It’s also available on GitHub.

 

$ConfigData =@{
    AllNodes = @(
        @{NodeName = 'localhost';
          PSDSCAllowPlainTextPassword = $True
          }
    )
 
}
 
Configuration BuildDC{
 
    Param(
 
        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$NodeName,
 
        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$ComputerName,
 
        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$Domain,
 
        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$IP,
 
        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$Gateway,
 
        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$Subnet
 
        #[pscredential]$DomainAdminCred,
        #[pscredential]$SafeModeAdminCred
 
    )#Param
 
    #unsecure, not safe or recommended way to do this
    $Creds = ConvertTo-SecureString "Passw0rd!" -AsPlainText -Force
    $DomainAdminCred = New-Object System.Management.Automation.PSCredential ("Administrator", $Creds)
    $SafeModeAdminCred = New-Object System.Management.Automation.PSCredential ("Administrator", $Creds)
 
    Import-DscResource -ModuleName xActiveDirectory,xNetworking,xComputerManagement,xPendingReboot,xSystemSecurity,xRemoteDesktopAdmin,xTimeZone,xWinEventLog
 
    Node $NodeName{
 
        LocalConfigurationManager{
            RebootNodeifNeeded = $True
        }
 
        xComputer RenameDC{
           Name = $ComputerName
       }
 
        File Scripts{
            Ensure = "Present"
            Type = "Directory"
            DestinationPath = "C:\Scripts"
        }
 
        xIEESC SetAdminIEESC{
            UserRole = "Administrators"
            IsEnabled = $False           
        }
 
        xUAC UAC{
            Setting = "NeverNotifyAndDisableAll"         
        }
 
        xTimeZone ServerTime{
            TimeZone = "Central Standard Time"
 
        }
 
        xRemoteDesktopAdmin RemoteDesktopSettings
        {
           Ensure = 'Present'
           UserAuthentication = 'Nonsecure'
        }
 
        xIPAddress SiteDCIP{
            IPAddress = $IP
            DefaultGateway = $Gateway
            SubnetMask = $Subnet
            AddressFamily = "IPv4"
            InterfaceAlias = "Ethernet"
            DependsOn = "[File]Scripts"
        }
 
        WindowsFeature AD-Domain-Services {
            Ensure = "Present"
            Name   = "AD-Domain-Services"
            DependsOn = "[xIPAddress]SiteDCIP"
        }
        WindowsFeature RSAT-AD-AdminCenter {
            Ensure = "Present"
            Name   = "RSAT-AD-AdminCenter"
        }
        WindowsFeature RSAT-ADDS {
            Ensure = "Present"
            Name   = "RSAT-ADDS"
        }
        WindowsFeature RSAT-AD-PowerShell {
            Ensure = "Present"
            Name   = "RSAT-AD-PowerShell"
        }
        WindowsFeature RSAT-AD-Tools {
            Ensure = "Present"
            Name   = "RSAT-AD-Tools"
        }
        WindowsFeature RSAT-Role-Tools {
            Ensure = "Present"
            Name   = "RSAT-Role-Tools"
        }
        WindowsFeature Telnet-Client{
            Ensure = "Present"
            Name = "Telnet-Client"
        }
 
        Service ADDomainWebServices{
            State = "Running"
            StartupType = "Automatic"
            BuiltInAccount = "LocalSystem"
            Name = "ADWS"
        }
 
        xADDomain BuildSiteDC{
            DomainAdministratorCredential = $DomainAdminCred
            SafeModeAdministratorPassword = $SafeModeAdminCred
            DomainName = $Domain
            DependsOn = "[WindowsFeature]AD-Domain-Services","[Service]ADDomainWebServices"                     
        }
 
        xPendingReboot PostDomainDeploy{
            Name = "Test for reboot after building a domain"
        }
        
        xDNSServerAddress DCDNS{
            Address = $IP
            InterfaceAlias = "Ethernet"
            AddressFamily = "IPv4"
            DependsOn = "[xPendingReboot]PostDomainDeploy"
        }
        
        xWinEventLog DirectoryService{
            LogName = "Directory Service"
            DependsOn = "[xDNSServerAddress]DCDNS"
            LogMOde = "Circular"
            MaximumSizeInBytes = 16MB
        }
        
 
    }#Node
 
 
}#Configuration
 
BuildDC -NodeName localhost -Domain YourDomain.com -IP $SomeIP -Gateway $SomeGateway -Subnet 24 -OutputPath C:\Scripts\BuildDC -ConfigurationData $ConfigData -ComputerName $YourComputerName
Set-DscLocalConfigurationManager -Path $YourPath
Get-DSCLocalConfigurationManager
Start-DscConfiguration -Wait -Force -Verbose -Path $YourPath

Exploring the PowerShell DSC xPendingReboot Resource

While building a DSC Demo for the new job this week I got the chance to explore using many of the “new” Resources that have been released.  One of those Resources is the xPendingReboot which I am going to talk about here, because the documentation wasn’t very clear (to me anyways after having been away from DSC for a long time) on how to use it properly.

The TechNet article on the Resource and an article by the Scripting Guy can be found at the links below.

https://gallery.technet.microsoft.com/scriptcenter/xPendingReboot-PowerShell-b269f154

http://blogs.technet.com/b/heyscriptingguy/archive/2014/10/15/use-powershell-dsc-to-check-pending-reboot.aspx

If you just look at it, you would assume you could do something like this to check for a reboot:

Configuration TestPendingReboot{

    Param(
        [string]$ComputerName='localhost'
    )

    Import-DSCResource -ModuleName xPendingReboot

    Node $ComputerName{

        xPendingReboot PreTest{
            Name = "Check for a pending reboot before changing anything"
        }
        
    }

}

However, you would be wrong! If we create the .MOF file for this Configuration and run this against the local system (which has a reboot pending after a computer rename), the system doesn’t actually reboot itself, it just notifies you that a reboot is pending.

TestPendingReboot -OutputPath C:\Scripts\TestPendingReboot
Start-DscConfiguration -Wait -Force -Verbose -Path .\TestPendingReboot

VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.
VERBOSE: An LCM method call arrived from computer WIN-74EKGETUJS6 with user sid S-1-5-21-2712606644-3520791333-1947032181-500.
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ Start  Set      ]
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ Start  Resource ]  [[xPendingReboot]PreTest]
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ Start  Test     ]  [[xPendingReboot]PreTest]
VERBOSE: [WIN-74EKGETUJS6]:                            [[xPendingReboot]PreTest] A pending reboot was found for PendingComputerRename.
VERBOSE: [WIN-74EKGETUJS6]:                            [[xPendingReboot]PreTest] Setting the DSCMachineStatus global variable to 1.
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ End    Test     ]  [[xPendingReboot]PreTest]  in 0.4020 seconds.
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ Start  Set      ]  [[xPendingReboot]PreTest]
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ End    Set      ]  [[xPendingReboot]PreTest]  in 0.0150 seconds.
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ End    Resource ]  [[xPendingReboot]PreTest]
VERBOSE: [WIN-74EKGETUJS6]:                            [] A reboot is required to progress further. Please reboot the system.
WARNING: [WIN-74EKGETUJS6]:                            [] A reboot is required to progress further. Please reboot the system.
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ End    Set      ]    in  3.2110 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 3.763 seconds

Well, that’s great and all but it didn’t reboot the machine like I needed it to. Looking at those examples, maybe I need to add the LocalConfigurationManager piece to make this work?

Configuration TestPendingReboot{

    Param(
        [string]$ComputerName='localhost'
    )

    Import-DSCResource -ModuleName xPendingReboot

    Node $ComputerName{

        xPendingReboot PreTest{
            Name = "Check for a pending reboot before changing anything"
        }

        LocalConfigurationManager{
            RebootNodeIfNeeded = $True
        }
        
    }

}

When you build this Configuration you will immediately notice you get a localhost.mof as well as a localhost.meta.mof . The Meta.mof is a result of making a change to the Local Configuration Manager (LCM) and should be a hint that something needs to be done with it :). The TechNet article uses a RebootNodeifNeeded = ‘True’ instead of the Boolean $True, which is not correct. If you try to build the Configuration using ‘True’ you get this error:

ConvertTo-MOFInstance : System.ArgumentException error processing property 'RebootNodeIfNeeded' OF TYPE 'LocalConfigurationManager': Cannot convert value "System.String" to type "System.Boolean". Boolean parameters accept only 
Boolean values and numbers, such as $True, $False, 1 or 0.
At line:285 char:16
+     $aliasId = ConvertTo-MOFInstance $keywordName $canonicalizedValue
+                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-Error], InvalidOperationException
    + FullyQualifiedErrorId : FailToProcessProperty,ConvertTo-MOFInstance
Errors occurred while processing configuration 'TestPendingReboot'.
At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:3189 char:5
+     throw $errorRecord
+     ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (TestPendingReboot:String) [], InvalidOperationException
    + FullyQualifiedErrorId : FailToProcessConfiguration

I am going to ignore the localhost.meta.mof file for now and just try this again to see what happens. And the exact same thing happens. If you are wondering if moving the LocalConfigurationManager section ahead of the xPendingReboot section matters or will help, it won’t. You actually need to change the LCM setting on the computer before starting the Configuration, because right now it is set to this. Notice the RebootNodeIfNeeded section at the bottom:

PS C:\Scripts> Get-DscLocalConfigurationManager


ActionAfterReboot              : ContinueConfiguration
AllowModuleOverWrite           : False
CertificateID                  : 
ConfigurationDownloadManagers  : {}
ConfigurationID                : 
ConfigurationMode              : ApplyAndMonitor
ConfigurationModeFrequencyMins : 15
Credential                     : 
DebugMode                      : {NONE}
DownloadManagerCustomData      : 
DownloadManagerName            : 
LCMCompatibleVersions          : {1.0, 2.0}
LCMState                       : PendingReboot
LCMVersion                     : 2.0
MaxPendingConfigRetryCount     : 
StatusRetentionTimeInDays      : 10
PartialConfigurations          : {}
RebootNodeIfNeeded             : False
RefreshFrequencyMins           : 30
RefreshMode                    : PUSH
ReportManagers                 : {}
ResourceModuleManagers         : {}
PSComputerName    

You do that by using this command:

Set-DscLocalConfigurationManager -Path .\TestPendingReboot -Verbose
VERBOSE: Performing the operation "Start-DscConfiguration: SendMetaConfigurationApply" on target "MSFT_DSCLocalConfigurationManager".
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendMetaConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguratio
n'.
VERBOSE: An LCM method call arrived from computer WIN-74EKGETUJS6 with user sid S-1-5-21-2712606644-3520791333-1947032181-500.
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ Start  Set      ]
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ Start  Resource ]  [MSFT_DSCMetaConfiguration]
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ Start  Set      ]  [MSFT_DSCMetaConfiguration]
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ End    Set      ]  [MSFT_DSCMetaConfiguration]  in 0.0160 seconds.
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ End    Resource ]  [MSFT_DSCMetaConfiguration]
VERBOSE: [WIN-74EKGETUJS6]: LCM:  [ End    Set      ]    in  0.0160 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Set-DscLocalConfigurationManager finished in 0.09 seconds.

Get-DscLocalConfigurationManager


ActionAfterReboot              : ContinueConfiguration
AllowModuleOverWrite           : False
CertificateID                  : 
ConfigurationDownloadManagers  : {}
ConfigurationID                : 
ConfigurationMode              : ApplyAndMonitor
ConfigurationModeFrequencyMins : 15
Credential                     : 
DebugMode                      : {NONE}
DownloadManagerCustomData      : 
DownloadManagerName            : 
LCMCompatibleVersions          : {1.0, 2.0}
LCMState                       : Ready
LCMVersion                     : 2.0
MaxPendingConfigRetryCount     : 
StatusRetentionTimeInDays      : 10
PartialConfigurations          : {}
RebootNodeIfNeeded             : True
RefreshFrequencyMins           : 30
RefreshMode                    : PUSH
ReportManagers                 : {}
ResourceModuleManagers         : {}
PSComputerName                 : 

Now when we start the Configuration, we get the exact same result as above, plus an automatic reboot!
PendingReboot






If you want everything in one file, you can find it here.

PowerShell DSC Journey – Day 23

No intro. Going right back into trying to add a Network Adapter and a VMNetwork to that adapter. I look first at the hardware profile, and lo and behold I have 9 legacy network adapters, which is interesting because yesterday I had none. So, I remove them all first.

Ok, first things first, let’s make sure I can get the network I want, which I can do using this command:

Get-SCVMNetwork | Where Name -eq $VMNetwork

The next thing I can do is try to create a new network adapter on the Hardware Profile, which I can do using this command.

New-SCVirtualNetworkAdapter -HardwareProfile $ResourceHWProfile

However, this creates a Legacy network adapter. After reading the help file I determine that I need the -Synthetic parameter in order to make it a non-legacy network adapter.

So, that’s all working now. Next step is to see if I can actually set the Virtual Network on the adapter itself, which is where I failed so hard yesterday. This works.

PS C:\Scripts> Get-SCVirtualNetworkAdapter -HardwareProfile $ResourceHWProfile | Set-SCVirtualNetworkAdapter -VirtualNetwork "Server Traffic Virtual Switch"


SlotId                                     : 0
VirtualNetwork                             : Server Traffic Virtual Switch
VMwarePortGroup                            : 
MACAddressType                             : Dynamic
EthernetAddressType                        : Dynamic
PhysicalAddressType                        : Dynamic
MACAddress                                 : 
EthernetAddress                            : 
PhysicalAddress                            : 
RequiredBandwidth                          : 0
VirtualNetworkAdapterType                  : Synthetic
VmwAdapterIndex                            : 
LogicalNetwork                             : 
VMNetwork                                  : 
VMNetworkServiceSetting                    : 
VMSubnet                                   : 
PortClassification                         : 
VirtualNetworkAdapterPortProfileSet        : 
LogicalSwitch                              : 
GuestIPNetworkVirtualizationUpdatesEnabled : False
MACAddressSpoofingEnabled                  : False
MACAddressesSpoofingEnabled                : False
VMNetworkOptimizationEnabled               : False
VLanEnabled                                : False
VLanID                                     : 0
UsesSriov                                  : False
IsUsedForHostManagement                    : False
VirtualNetworkAdapterComplianceStatus      : Compliant
TemplateNicName                            : 
VirtualNetworkAdapterComplianceErrors      : {}
PerfNetworkKBytesRead                      : 0
PerfNetworkKBytesWrite                     : 0
DeviceID                                   : 
IPv4AddressType                            : Dynamic
IPv6AddressType                            : Dynamic
IPv4Addresses                              : {}
IPv6Addresses                              : {}
ObjectType                                 : VirtualNetworkAdapter
Accessibility                              : Public
Name                                       : Jacobs Profile
IsViewOnly                                 : False
Description                                : 
AddedTime                                  : 6/25/2014 3:31:39 PM
ModifiedTime                               : 6/25/2014 3:33:19 PM
Enabled                                    : True
MostRecentTask                             : Change properties of network adapter
ServerConnection                           : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection
ID                                         : cd305001-19bb-476f-80af-1b44600211b9
MarkedForDeletion                          : False
IsFullyCached                              : True
MostRecentTaskIfLocal                      : Change properties of network adapter

So, let’s try this next. And it works. I swear I did this a billion times but I am not even to go back and look because it might make me angry or depressed. Or both.

PS C:\Scripts> Get-SCVirtualNetworkAdapter -HardwareProfile $ResourceHWProfile | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork


SlotId                                     : 0
VirtualNetwork                             : Server Traffic Virtual Switch
VMwarePortGroup                            : 
MACAddressType                             : Dynamic
EthernetAddressType                        : Dynamic
PhysicalAddressType                        : Dynamic
MACAddress                                 : 
EthernetAddress                            : 
PhysicalAddress                            : 
RequiredBandwidth                          : 0
VirtualNetworkAdapterType                  : Synthetic
VmwAdapterIndex                            : 
LogicalNetwork                             : 
VMNetwork                                  : 
VMNetworkServiceSetting                    : 
VMSubnet                                   : 
PortClassification                         : 
VirtualNetworkAdapterPortProfileSet        : 
LogicalSwitch                              : 
GuestIPNetworkVirtualizationUpdatesEnabled : False
MACAddressSpoofingEnabled                  : False
MACAddressesSpoofingEnabled                : False
VMNetworkOptimizationEnabled               : False
VLanEnabled                                : False
VLanID                                     : 0
UsesSriov                                  : False
IsUsedForHostManagement                    : False
VirtualNetworkAdapterComplianceStatus      : Compliant
TemplateNicName                            : 
VirtualNetworkAdapterComplianceErrors      : {}
PerfNetworkKBytesRead                      : 0
PerfNetworkKBytesWrite                     : 0
DeviceID                                   : 
IPv4AddressType                            : Dynamic
IPv6AddressType                            : Dynamic
IPv4Addresses                              : {}
IPv6Addresses                              : {}
ObjectType                                 : VirtualNetworkAdapter
Accessibility                              : Public
Name                                       : Jacobs Profile
IsViewOnly                                 : False
Description                                : 
AddedTime                                  : 6/25/2014 3:31:39 PM
ModifiedTime                               : 6/25/2014 3:34:10 PM
Enabled                                    : True
MostRecentTask                             : Change properties of network adapter
ServerConnection                           : Microsoft.SystemCenter.VirtualMachineManager.Remoting.ServerConnection
ID                                         : cd305001-19bb-476f-80af-1b44600211b9
MarkedForDeletion                          : False
IsFullyCached                              : True
MostRecentTaskIfLocal                      : Change properties of network adapter

So, let’s run my Configuration and see what happens again. And it works. Of course it does.

PS C:\Scripts> Start-DscConfiguration -Wait -Verbose -Path .\TestSCVMMHardware
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredState
Configuration'.
VERBOSE: An LCM method call arrived from computer MyComp with user sid S-1-5-21-738551990-92959840-526660263-26386.
VERBOSE: [MyComp]: LCM:  [ Start  Set      ]
VERBOSE: [MyComp]: LCM:  [ Start  Resource ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]: LCM:  [ Start  Test     ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMMServer is MY-VMM-SERVER1
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Hardware Profile Name is Jacobs Profile
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager
.R2Aliases.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManager
LibraryClientCleanup.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMMServer was found and is 'MY-VMM-SERVER1'
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Hardware Profile is Jacobs Profile
VERBOSE: [MyComp]: LCM:  [ End    Test     ]  [[cSCVMM_Hardware]MyHardwareProfile]  in 1.8182 seconds.
VERBOSE: [MyComp]: LCM:  [ Start  Set      ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMMServer is MY-VMM-SERVER1
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Hardware Profile Name is Jacobs Profile
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager
.R2Aliases.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManager
LibraryClientCleanup.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Checking if the Hardware Profile Jacobs Profile exists
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] The Hardware Profile was found
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Ensure set to Present
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] No setting specified for DVDDrive.  No changes made
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] CPUCount is already set to 2
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMNetwork should be Server Traffic Virtual Switch.  Setting VMNetwork
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMNetwork set to Server Traffic Virtual Switch
VERBOSE: [MyComp]: LCM:  [ End    Set      ]  [[cSCVMM_Hardware]MyHardwareProfile]  in 2.8620 seconds.
VERBOSE: [MyComp]: LCM:  [ End    Resource ]  [[cSCVMM_Hardware]MyHardwareProfile]
WARNING: The specified ConfigurationModeFrequencyMins was over-written to a multiple of RefreshFrequencyMins
VERBOSE: [MyComp]: LCM:  [ End    Set      ]    in  4.7235 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 2.879 seconds

I then add most of the same code to the section of Set-TargetResource for when a Hardware Profile doesn’t exist. Now let me delete my profile and try it. And of course I get some errors because I am using the $ResourceHWProfile variable in this section of code instead of just $Name. So, I change it to this.

            If($VMNetwork)
            {
                Write-Verbose "VMNetwork should be $VMNetwork.  Setting VMNetwork"

                New-SCVirtualNetworkAdapter -HardwareProfile $Name -Synthetic
                Get-SCVirtualNetworkAdapter -HardwareProfile $Name | Set-SCVirtualNetworkAdapter -VirtualNetwork $VMNetwork
                Write-Verbose "VMNetwork set to $VMNetwork"
            }
            Else
            {
                Write-Verbose "No setting specified for VMNetwork.  No changes made"
            }

And that works as well. One interesting thing to note. There is a lot of Write-Verbose commands I have that aren’t being written after this section of code. And I have no idea why either.

VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] The Hardware Profile was not found.  Creating new Hardware Profile Jacobs Profile
VERBOSE: [MyComp]: LCM:  [ End    Set      ]  [[cSCVMM_Hardware]MyHardwareProfile]  in 2.4584 seconds.
VERBOSE: [MyComp]: LCM:  [ End    Resource ]  [[cSCVMM_Hardware]MyHardwareProfile]
WARNING: The specified ConfigurationModeFrequencyMins was over-written to a multiple of RefreshFrequencyMins
VERBOSE: [MyComp]: LCM:  [ End    Set      ]    in  4.3398 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 2.644 seconds

Well, that’s working now so I am happy. Now that I have a functioning Resource that does what I wanted it to do, this will be the last post in the series 🙂

PowerShell DSC Journey – Day 22

Alright, after my little fiasco yesterday I need to do a little re-configuring of my Configuration because of course DSC will not allow a Plain text password.

PS C:\Scripts> C:\Users\jacob.benson\SkyDrive\PowerShell\DSC\TestSCVMMHardware.ps1
ConvertTo-MOFInstance : System.InvalidOperationException error processing property 'Credential' OF TYPE 'cSCVMM_Hardware': Converting and storing encrypted passwords as plain text is not recommended for security reasons. If you understand the risks, you 
can add a property named “PSDscAllowPlainTextPassword” with a value of “$true” to your DSC configuration data, for each node where you want to allow plain text passwords. For more information about DSC configuration data, see the TechNet Library topic, 
http://go.microsoft.com/fwlink/?LinkId=386620.
At C:\Users\jacob.benson\SkyDrive\PowerShell\DSC\TestSCVMMHardware.ps1:13 char:9
+   cSCVMM_Hardware
At line:180 char:16
+     $aliasId = ConvertTo-MOFInstance $keywordName $canonicalizedValue
+                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-Error], InvalidOperationException
    + FullyQualifiedErrorId : FailToProcessProperty,ConvertTo-MOFInstance
Errors occurred while processing configuration 'TestSCVMMHardware'.
At C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:2203 char:5
+     throw $errorRecord
+     ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (TestSCVMMHardware:String) [], InvalidOperationException
    + FullyQualifiedErrorId : FailToProcessConfiguration

Here is the new version of the Configuration.

$ConfigData = @{
    AllNodes = @(
        @{
            NodeName = "localhost"
            PSDSCAllowPlainTextPassword = $True
            }
    )
}

Configuration TestSCVMMHardware
{

    param
    (
        [PSCredential]$Credential = (Get-Credential)
    )

    Import-DscResource -Module cSCVMM

    node $AllNodes.NodeName
    {
        cSCVMM_Hardware MyHardwareProfile
        {
            VMMServer = "MY-VMM-SERVER1"
            CPUCount = 2
            DVDDrive = $True
            Ensure = "Present"
            Name = "Jacobs Profile"
            VMNetwork = "Server Traffic"
            Credential = $Credential
       }

    }

}

TestSCVMMHardware -ConfigurationData $ConfigData

Now, let’s try to run this and see what breaks. And. Nothing breaks. I am literally speechless. Seriously.

PS C:\Scripts> C:\Users\jacob.benson\SkyDrive\PowerShell\DSC\TestSCVMMHardware.ps1
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:


    Directory: C:\Scripts\TestSCVMMHardware


Mode                LastWriteTime     Length Name                                                                                                                                                                   
----                -------------     ------ ----                                                                                                                                                                   
-a---         6/24/2014   2:27 PM       1770 localhost.mof 

Well. Here goes nothing. And I forgot to change something back in .psm1 file when I was messing around with it yesterday that caused this entire thing to blow up. I will spare you all the red text but here is the error.

PS C:\Scripts> Start-DscConfiguration -Wait -Verbose -Path .\TestSCVMMHardware
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredState
Configuration'.
VERBOSE: An LCM method call arrived from computer OM808-IT-293 with user sid S-1-5-21-738551990-92959840-526660263-26386.
VERBOSE: [MyComp]: LCM:  [ Start  Set      ]
Importing module cSCVMM_Hardware failed with error - At C:\Program Files\WindowsPowerShell\Modules\cSCVMM\DscResources\cSCVMM_Hardware\cSCVMM_Hardware.psm1:10 char:67
+ ...      $Credential = [System.Management.Automation.PSCredential]::Empty

With that fixed I try to run it, and I don’t get any errors, but clearly I have something to fix with my Test-TargetResource function because it just skipped running Set-TargetResource.

PS C:\Scripts> Start-DscConfiguration -Wait -Verbose -Path .\TestSCVMMHardware
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredState
Configuration'.
VERBOSE: An LCM method call arrived from computer MyComp with user sid S-1-5-21-738551990-92959840-526660263-26386.
VERBOSE: [MyComp]: LCM:  [ Start  Set      ]
VERBOSE: [MyComp]: LCM:  [ Start  Resource ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]: LCM:  [ Start  Test     ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMMServer is MY-VMM-SERVER1
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Hardware Profile Name is Jacobs Profile
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager
.R2Aliases.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManager
LibraryClientCleanup.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.psd1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading 'Assembly' from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\Microsoft.BackgroundIntelligen
tTransfer.Management.Interop.dll'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading 'FormatsToProcess' from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.Format.ps
1xml'.
VERBOSE: [MyComp]: LCM:  [ End    Test     ]  [[cSCVMM_Hardware]MyHardwareProfile]  in 7.3940 seconds.
VERBOSE: [MyComp]: LCM:  [ Skip   Set      ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]: LCM:  [ End    Resource ]  [[cSCVMM_Hardware]MyHardwareProfile]
WARNING: The specified ConfigurationModeFrequencyMins was over-written to a multiple of RefreshFrequencyMins
VERBOSE: [MyComp]: LCM:  [ End    Set      ]    in  7.7470 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 4.705 seconds

So, let’s see if we can figure out what’s going on. I am pretty sure this section is the problem.

    $result = $false

    #Check to see if Credential and VMMServer is valid
    $ResourceVMMServer = Get-SCVMMServer -ComputerName $VMMServer -Credential $Credential
        If($ResourceVMMServer)
        {
            Return $true
        }
        Else
        {
            Return $false
        }

I set the $result to $false, then tested for the $VMMServer, and returned $True, so DSC was like “oh hey, everything is gravy.” Fail on my part. Let’s fix this. I already know if the Credential or VMMServer is invalid that it will fail, so I just need to check to make sure $ResourceVMMServer exists and then do the rest of my checks. I am pretty sure this is going to fail for a couple of reasons, but I am going to test this anyways in the interest of full disclosure :).

    $ResourceVMMServer = Get-SCVMMServer -ComputerName $VMMServer -Credential $Credential
        If($ResourceVMMServer)
        {
            Write-Verbose "VMMServer was found and is $ResourceVMMServer"

            try{

                $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer | Where-Object Name -eq $Name -ErrorAction Stop
                Write-Verbose "Hardware Profile is $HWProfile"

                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')
            }
        }

I run several of my tests that I expect to return both $True and $False. I made a few changes and added one line, so here is the new and improved section of my code.

    $ResourceVMMServer = Get-SCVMMServer -ComputerName $VMMServer -Credential $Credential
        If($ResourceVMMServer)
        {
            Write-Verbose "VMMServer was found and is '$VMMServer'"

            try{

                $HWProfile = Get-SCHardwareProfile -VMMServer $VMMServer | Where-Object Name -eq $Name -ErrorAction Stop
                If($HWProfile){Write-Verbose "Hardware Profile is $HWProfile"}

                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

                }
            }

So, let’s try this again! HOLY BUCKETS IT WORKED! Minus, one small issue.

PS C:\Scripts> Start-DscConfiguration -Wait -Verbose -Path .\TestSCVMMHardware
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredState
Configuration'.
VERBOSE: An LCM method call arrived from computer MyComp with user sid S-1-5-21-738551990-92959840-526660263-26386.
VERBOSE: [MyComp]: LCM:  [ Start  Set      ]
VERBOSE: [MyComp]: LCM:  [ Start  Resource ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]: LCM:  [ Start  Test     ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMMServer is MY-VMM-SERVER1
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Hardware Profile Name is Jacobs Profile
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager
.R2Aliases.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManager
LibraryClientCleanup.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMMServer was found and is 'MY-VMM-SERVER1'
VERBOSE: [MyComp]: LCM:  [ End    Test     ]  [[cSCVMM_Hardware]MyHardwareProfile]  in 1.8714 seconds.
VERBOSE: [MyComp]: LCM:  [ Start  Set      ]  [[cSCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] VMMServer is MY-VMM-SERVER1
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Hardware Profile Name is Jacobs Profile
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager
.R2Aliases.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManager
LibraryClientCleanup.ps1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmach
inemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] Checking if the Hardware Profile Jacobs Profile exists
VERBOSE: [MyComp]:                            [[cSCVMM_Hardware]MyHardwareProfile] The Hardware Profile was not found.  Creating new Hardware Profile Jacobs Profile
VERBOSE: [MyComp]: LCM:  [ End    Set      ]  [[cSCVMM_Hardware]MyHardwareProfile]  in 3.7302 seconds.
VERBOSE: [MyComp]: LCM:  [ End    Resource ]  [[cSCVMM_Hardware]MyHardwareProfile]
WARNING: The specified ConfigurationModeFrequencyMins was over-written to a multiple of RefreshFrequencyMins
VERBOSE: [MyComp]: LCM:  [ End    Set      ]    in  5.8367 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 3.555 seconds

dsc62

Now, the one issue there is that no VMNetwork was set. Probably because there is no network adapter, which I am guessing I forgot to include in my Set-TargetResource. Let’s take a look.

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

Yeah, that’s not going to work. I need to create the adapter first. Turns out it’s easier than I thought it would be. Just kidding, I can’t use the parameter for $VMNetwork, it needs to be a different type.

                        If($VMNetwork -ne $ResourceHWProfile.VirtualNetworkAdapters.VMNetwork)
                        {
                            Write-Verbose "VMNetwork should be $VMNetwork.  Setting VMNetwork"
                            New-SCVirtualNetworkAdapter -VMMServer $VMMServer -HardwareProfile $ResourceHWProfile -VMNetwork $VMNetwork
                            Write-Verbose "VMNetwork set to $VMNetwork"
                        }
New-SCVirtualNetworkAdapter : Cannot bind parameter 'VMNetwork'. Cannot convert the "Server Traffic Virtual Switch" value of type "System.String" to type 
"Microsoft.SystemCenter.VirtualMachineManager.VMNetwork".
At line:1 char:98
+ ... reProfile "Jacobs Profile" -VMNetwork "Server Traffic Virtual Switch"
+                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-SCVirtualNetworkAdapter], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.NewNICCmdlet

Which opens a whole new can of worms because I need to check to make sure that is a valid VM Network somewhere. For the purposes of this, I am going to assume that if it should be present, it is a valid name. Actually I lied. We aren’t going to do that, because that opens up a giant mess when it comes to creating a new Virtual Network.

After banging away on this for about the last 30 minutes I am going to stop here for the day and pick it up again tomorrow. I am currently stuck on getting the right object type from Get-SCVMNetwork to pass to……..oh hell…wait a minute. Just kidding! Kidding again. I have a moment of genius! And this is also where I hate Virtual Machine Manager anymore. Only thing good to say is that I learned a hell of a lot more than I ever wanted to know about VMM cmdlets this afternoon.

So, let me delete the Hardware Profile and run my Configuration again. The network adapter didn’t get created. My brain is exhausted. I’m done for today. For real this time.

PowerShell DSC Journey – Day 21

Alright, when I left off I had added in some testing for the $Credential Property of the Resource in the Get-TargetResource and Test-TargetResource functions. Today I am going to do the same with Set-TargetResource, and then test my Configuration to see what I did wrong. If I survive that I will try to create a Hardware Profile with my Resource.

First things first, I add this same section to Set-TargetResource.

#Check to see if Credential and VMMServer is valid
    $ResourceVMMServer = Get-SCVMMServer -ComputerName $VMMServer -Credential $Credential

I think that is all I need to do here because Get-SCHardwareProfile and Set-SCHardwareProfile don’t require a credential.

I run my first test, and everything works great except the test removed the DVD Drive. Which it wasn’t supposed to do. And there is all some verbage for the CPU Count that is incorrect, and it looks like I need to add a case for when CPUCount is not specified.

PS C:\Scripts> Set-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -Ensure Present -Verbose
cmdlet Set-TargetResource at command pipeline position 1
Supply values for the following parameters:
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

MostRecentTaskIfLocal : Remove virtual DVD drive

VERBOSE: DVDDrive has been removed
VERBOSE: CPUCount is DSCWEB Hardware Profile.CPUCount, should be 0
Set-SCHardwareProfile : Cannot validate argument on parameter 'CPUCount'. The 0 argument is less than the minimum allowed range of 1. Supply an argument that is greater than or equal to 1 and then try the 
command again.
At line:97 char:80
+ ...      Set-SCHardwareProfile -HardwareProfile $Name -CPUCount $CPUCount
+                                                                 ~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Set-SCHardwareProfile], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.SetHWConfigCmdlet
 
VERBOSE: CPUCount Set to 0
VERBOSE: No VMNetwork was specified

Ok, let’s tackle the DVD Drive issue first. I didn’t specify an option for it, it was already present, and the profile was set to Ensure = Present, so it should not have been removed. Here is the code block.

 If($DVDDrive -eq $ResourceHWProfile.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"
                        }
                    }

What is happening is I am not specifying a value for the DVDDrive Property. So as far as it is concerned, the last Else statement gets executed. I am going to need to add a case for not specifying the DVDDrive Property. I reconfigured this code to look like this instead.

If($DVDrive)
                    {
                        If($DVDDrive -eq $ResourceHWProfile.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"
                            }
                        }
                    }
                    Else
                    {
                        Write-Verbose "No setting specified for DVDDrive.  No changes made"
                    }

And that works exactly like it should. Now I need to do the same thing for CPUCount. This also works just fine. And it’s also at this point that I realize that I already have the VMNetwork parameter setup that way. Apparently it never occurred to me I would need to do the same thing for the others. Oh well. Moving along! I run a few more test and make a few more minor changes and tweaks but I am not going to bore you with those details. I just needed to update the part of the function that creates a new Hardware Profile with the same If checks as above.

And now. Let’s see how badly I have failed here. Let’s test this bad boy.

PS C:\Scripts> Test-xDscSchema -Path 'C:\Program Files\WindowsPowerShell\Modules\cSCVMM\DSCResources\cSCVMM_Hardware\cSCVMM_Hardware.schema.mof' -Verbose
VERBOSE: The path to the schema file has been verified.
VERBOSE: The schema file has passed mofcomp's syntax check.
VERBOSE: Testing the schema file's compliance to Desired State Configuration's contracts.
VERBOSE: Perform operation 'Get CimClass' with following parameters, ''namespaceName' = root\microsoft\windows\DesiredStateConfiguration,'className' = tmp65B2'.
VERBOSE: Operation 'Get CimClass' complete.
True

Pretty good. So far. I don’t expect this to continue.

PS C:\Scripts> Test-xDscResource -Name cSCVMM_Hardware -Verbose
VERBOSE: Testing the schema.mof file.
VERBOSE: The path to the schema file has been verified.
VERBOSE: The schema file has passed mofcomp's syntax check.
VERBOSE: Testing the schema file's compliance to Desired State Configuration's contracts.
VERBOSE: Perform operation 'Get CimClass' with following parameters, ''namespaceName' = root\microsoft\windows\DesiredStateConfiguration,'className' = tmp9D53'.
VERBOSE: Operation 'Get CimClass' complete.
VERBOSE: Testing the .psm1 file.
VERBOSE: Loading module from path 'C:\Program Files\WindowsPowerShell\Modules\cSCVMM\DSCResources\cSCVMM_Hardware\cSCVMM_Hardware.psm1'.
VERBOSE: Importing function 'Get-jnx34np3.c3iTargetResource'.
VERBOSE: Importing function 'Set-jnx34np3.c3iTargetResource'.
VERBOSE: Importing function 'Test-jnx34np3.c3iTargetResource'.
VERBOSE: The schema.mof and .psm1 files were both indivually correct.
VERBOSE: Result of testing Get-TargetResource for it's mandatory properties: True.
VERBOSE: Result of testing Set-TargetResource for no read properties: True.
VERBOSE: Result of testing Get-TargetResource for no read properties: True.
True

Well. That was unexpected. I guess on to the next thing. Let’s try my Configuration again. Here is my current Configuration.

Configuration TestSCVMMHardware
{

    param
    (
        [pscredential]$Credential = (Get-Credential)
    )

    Import-DscResource -Module cSCVMM

    node localhost
    {
        cSCVMM_Hardware MyHardwareProfile
        {
            VMMServer = "MY-VMM-SERVER1"
            CPUCount = 2
            DVDDrive = $True
            Ensure = "Present"
            Name = "Jacobs Profile"
            VMNetwork = "Server Traffic"
       }
BOOM!  RED TEXT NATION!
 
PS C:\Scripts> C:\users\jacob.benson\SkyDrive\PowerShell\DSC\TestSCVMMHardware.ps1
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
cSCVMM\cSCVMM_Hardware : Class 'cSCVMM_Hardware' requires that a value of type 'MSFT_Credential' be provided for property 'Credential'.
At C:\users\jacob.benson\SkyDrive\PowerShell\DSC\TestSCVMMHardware.ps1:13 char:9
+         cSCVMM_Hardware MyHardwareProfile
+         ~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-Error], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingValueForMandatoryProperty,cSCVMM\cSCVMM_Hardware
 
Errors occurred while processing configuration 'TestSCVMMHardware'.
At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:2203 char:5
+     throw $errorRecord
+     ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (TestSCVMMHardware:String) [], InvalidOperationException
    + FullyQualifiedErrorId : FailToProcessConfiguration

}

}

Alright. So….I declared my credential variable to be of the type [pscredential]. Maybe it needs to be [MSFT_Credential]? Let’s try it. But wait, I have the bright idea that I should check to see how the ADDomain resource handles it, and I find my answer in the .psm1 file for the resource.

	[Required, EmbeddedInstance("MSFT_Credential")] String DomainAdministratorCredential;
	[Required, EmbeddedInstance("MSFT_Credential")] String SafemodeAdministratorPassword;
	[write,EmbeddedInstance("MSFT_Credential")] String DnsDelegationCredential;

Looks like I need to update my Resource.

PS C:\Scripts> $Credential = New-xDscResourceProperty -Name Credential -Type MSFT_Credential -Attribute Required -Description "Valid credential for connecting to VMM Server"
New-xDscResourceProperty : Cannot validate argument on parameter 'Type'. The argument "MSFT_Credential" does not belong to the set "Uint8,Uint16,Uint32,Uint64,Sint8,Sint16,Sint32,Sint64,Real32,Real64,Char16,Strin
g,Boolean,DateTime,Hashtable,PSCredential,Uint8[],Uint16[],Uint32[],Uint64[],Sint8[],Sint16[],Sint32[],Sint64[],Real32[],Real64[],Char16[],String[],Boolean[],DateTime[],Hashtable[],PSCredential[]" specified by 
the ValidateSet attribute. Supply an argument that is in the set and then try the command again.
At line:1 char:63
+ ... w-xDscResourceProperty -Name Credential -Type MSFT_Credential -Attrib ...
+                                                   ~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [New-xDscResourceProperty], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,New-xDscResourceProperty

Hmmm. How else would you get the schema.mof to show that Type? Then I look at the schema.mof for my resource and get my answer.

	[Required, EmbeddedInstance("MSFT_Credential"), Description("Valid credential for connecting to VMM Server")] String Credential;

So the type Credential, automatically changes to that in the schema. Good to know. Now I try my Resource using [MSFT_Credential]$Credential and that fails.

PS C:\Scripts> C:\users\jacob.benson\SkyDrive\PowerShell\DSC\TestSCVMMHardware.ps1
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
TestSCVMMHardware : Unable to find type [MSFT_Credential]. Make sure that the assembly that contains this type is loaded.
At C:\users\jacob.benson\SkyDrive\PowerShell\DSC\TestSCVMMHardware.ps1:27 char:1
+ TestSCVMMHardware -Credential (Get-Credential)
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (MSFT_Credential:TypeName) [], RuntimeException
    + FullyQualifiedErrorId : TypeNotFound

This has me stumped. Nothing of use in the DSC Event Logs. Comparing my .psm1 file to the ADDomain.psm1 file, I notice that all of their credentials are of the type [PSCredential] while mine is of the type [System.Management.Automation.PSCredential]. Which is weird (I think?). I try to change the parameter in my Configuration to the type [System.Management.Automation.PSCredential] but I get the same error. So I am going to change the .psm1 type to just [pscredential] and see what happens. I reloaded everything and change the type for Credential back to [PSCredential] and the same thing still happens.

I am stumped. Going to call it a day on that front.

Edit: Thanks to Jason Hofferle for helping figure out what I was doing wrong (and it was something dumb). I was so wrapped up in the thought that I did something wrong in my Resource that I didn’t bother to specify the Credential property in my actual Configuration.

        cSCVMM_Hardware MyHardwareProfile
        {
            VMMServer = "MY-VMM-SERVER1"
            CPUCount = 2
            DVDDrive = $True
            Ensure = "Present"
            Name = "Jacobs Profile"
            VMNetwork = "Server Traffic"
            Credential = $Credential
       }

PowerShell DSC Journey – Day 20

When I left off yesterday I was trying to actually run a Configuration to create a Hardware Profile, and quickly realized that I was going to need a Credential parameter in order to do this, because not just anyone can connect to a Virtual Machine Manager server. So today’s post is going to be about adding a Credential property to my Configuration.

I am going to be referencing the Active Directory resource for this because I know that uses a credential parameter to authenticate to Active Directory. First thing first, let’s create a new DSC Resource Property.

$Credential = New-xDscResourceProperty -Name Credential -Type PSCredential -Attribute Required -Description "Valid credential for connecting to VMM Server"

Then I will need to update my resource with this new Property.

PS C:\Scripts> Update-xDscResource -Name cSCVMM_Hardware -Property $Credential,$DVDDrive,$VMNetwork,$CPUCount,$Ensure,$Name,$VMMServer -Force -Verbose
VERBOSE: Successfully found a property with the attribute Key.
VERBOSE: All of the properties had unique names.
VERBOSE: Testing the schema.mof file.
VERBOSE: The path to the schema file has been verified.
VERBOSE: The schema file has passed mofcomp's syntax check.
VERBOSE: Testing the schema file's compliance to Desired State Configuration's contracts.
VERBOSE: Perform operation 'Get CimClass' with following parameters, ''namespaceName' = root\microsoft\windows\DesiredStateConfiguration,'className' = tmp859B'.
VERBOSE: Operation 'Get CimClass' complete.
VERBOSE: Testing the .psm1 file.
VERBOSE: Loading module from path 'C:\Program Files\WindowsPowerShell\Modules\cSCVMM\DSCResources\cSCVMM_Hardware\cSCVMM_Hardware.psm1'.
VERBOSE: Importing function 'Get-u5nqc0u5.hl4TargetResource'.
VERBOSE: Importing function 'Set-u5nqc0u5.hl4TargetResource'.
VERBOSE: Importing function 'Test-u5nqc0u5.hl4TargetResource'.
VERBOSE: The schema.mof and .psm1 files were both indivually correct.
VERBOSE: Result of testing Get-TargetResource for it's mandatory properties: True.
VERBOSE: Result of testing Set-TargetResource for no read properties: True.
VERBOSE: Result of testing Get-TargetResource for no read properties: True.
VERBOSE: The generated resource was tested and found acceptable.

And here is what my schema.mof file looks like:

[ClassVersion("1.0.0.0"), FriendlyName("")]
class cSCVMM_Hardware : OMI_BaseResource
{
	[Required, EmbeddedInstance("MSFT_Credential"), Description("Valid credential for connecting to VMM Server")] String Credential;
	[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;
};

And this is a snippet of the Get-TargetResource function show the additional property as well.

function Get-TargetResource
{
	[CmdletBinding()]
	[OutputType([System.Collections.Hashtable])]
	param
	(
		[parameter(Mandatory = $true)]
		[System.Management.Automation.PSCredential]
		$Credential,

Now, that’s all well and good, but how do I go about testing this in Get-TargetResource? Let’s take a look at what the Active Directory resource does. It looks like it is using the Credential property when testing other properties, so I will do the same. I believe I only need to add this where other commands need to authenticate to the VMMServer, and I should probably test to make sure the credential is valid. Get-SCHardwareProfile doesn’t require a credential, only the VMMServer name, so I don’t think I need to do anything there. I did add this to the Get-TargetResource function.

#Check to see if Credential and VMMServer is valid
$ResourceVMMServer = Get-SCVMMServer -ComputerName $VMMServer -Credential $Credential

And I suppose I should test this now to see what breaks. This test prompted me for the credential and completed successfully.

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -Verbose
cmdlet Get-TargetResource at command pipeline position 1
Supply values for the following parameters:
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 Hardware Profile was found
VERBOSE: The Resource Hardware Profile is DSCWEB Hardware Profile

Name                           Value                                                                                                                                                                                
----                           -----                                                                                                                                                                                
VMNetwork                                                                                                                                                                                                           
Name                           DSCWEB Hardware Profile                                                                                                                                                              
DVDDrive                       True                                                                                                                                                                                 
Ensure                         Present                                                                                                                                                                              
CPUCount                       1                                                                                                                                                                                    
VMMServer                      MY-VMM-SERVER1

Just to be safe I tried the same test but added a -Credential (Get-Credential) command and everything worked fine.

Here is a test where I submitted a completely bogus credential that has no permissions to anything.

PS C:\Scripts> Get-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -Verbose
cmdlet Get-TargetResource at command pipeline position 1
Supply values for the following parameters:
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'.
Get-SCVMMServer : You cannot access VMM management server MY-VMM-SERVER1. (Error ID: 1604)
 
Contact the Virtual Machine Manager administrator to verify that your account is a member of a valid user role and then try the operation again.
At line:37 char:26
+ ... VMMServer = Get-SCVMMServer -ComputerName $VMMServer -Credential $Cre ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCVMMServer], CarmineException
    + FullyQualifiedErrorId : 1604,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.ConnectServerCmdlet

Here is what I added to my Test-TargetResource Function.

    #Check to see if Credential and VMMServer is valid
    $ResourceVMMServer = Get-SCVMMServer -ComputerName $VMMServer -Credential $Credential
        If($ResourceVMMServer)
        {
            Return $true
        }
        Else
        {
            Return $false
        }

So let’s test this out. I am astounded this is actually working properly. With valid credential:

PS C:\Scripts> Test-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MY-VMM-SERVER1 -Ensure Present -Verbose
cmdlet Test-TargetResource at command pipeline position 1
Supply values for the following parameters:
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'.
True

With non valid Credential:

PS C:\Scripts> Test-TargetResource -Name "DSCWEB Hardware Profile" -VMMServer MDC-SC-VMM01 -Ensure Present -Verbose
cmdlet Test-TargetResource at command pipeline position 1
Supply values for the following parameters:
VERBOSE: VMMServer is MDC-SC-VMM01
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'.
Get-SCVMMServer : You cannot access VMM management server MDC-SC-VMM01. (Error ID: 1604)
 
Contact the Virtual Machine Manager administrator to verify that your account is a member of a valid user role and then try the operation again.
At line:51 char:26
+ ... VMMServer = Get-SCVMMServer -ComputerName $VMMServer -Credential $Cre ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ReadError: (:) [Get-SCVMMServer], CarmineException
    + FullyQualifiedErrorId : 1604,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.ConnectServerCmdlet
False

I am running out of time today and feel like this is a great place to stop. I will move on to the Set-TargetResource function tomorrow!

PowerShell DSC Journey – Day 19

Alright, so in my last post I was able to resolve the issue with my Custom Resource not showing up under Get-DSCResource (because as usual I was doing something dumb).

Proof!

PS C:\Scripts> Get-DscResource

ImplementedAs   Name                      Module                         Properties                                        
-------------   ----                      ------                         ----------                                        
Binary          File                                                     {DestinationPath, Attributes, Checksum, Content...
PowerShell      SCVMM_Hardware            cSCVMM                         {Name, VMMServer, CPUCount, DependsOn...}         

Now, let’s try and write a Configuration! Look ma, no errors!

Configuration TestSCVMMHardware
{

    Import-DscResource -Module cSCVMM

}

Let’s build this out for a test.

Configuration TestSCVMMHardware
{

    Import-DscResource -Module cSCVMM

    node localhost
    {
        SCVMM_Hardware MyHardwareProfile
        {
            VMMServer = "MDC-SC-VMM01"
            CPUCount = 2
            DVDDrive = $True
            Ensure = "Present"
            Name = "Jacobs Profile"
            VMNetwork = "Server Traffic"
       }

    }

}

TestSCVMMHardware

I run this Configuration and the .MOF gets created.

    Directory: C:\Scripts\TestSCVMMHardware


Mode                LastWriteTime     Length Name                                                                                                                                                                   
----                -------------     ------ ----                                                                                                                                                                   
-a---         6/19/2014   2:14 PM       1294 localhost.mof 

When I run this configuration I immediately encounter two errors.

PS C:\Scripts> Start-DscConfiguration -Path .\TestSCVMMHardware -Wait -Verbose
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredState
Configuration'.
VERBOSE: An LCM method call arrived from computer MyComp with user sid S-1-5-21-738551990-92959840-526660263-26386.
VERBOSE: [MyComp]: LCM:  [ Start  Set      ]
VERBOSE: [MyComp]: LCM:  [ Start  Resource ]  [[SCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]: LCM:  [ Start  Test     ]  [[SCVMM_Hardware]MyHardwareProfile]
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] VMMServer is MY-VMM-SERVER
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] Hardware Profile Name is Jacobs Profile
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\virtualmachinemanager.
R2Aliases.ps1'.
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\VirtualMachineManagerL
ibraryClientCleanup.ps1'.
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachi
nemanager\..\..\virtualmachinemanager.R2AdvFunc.psm1'.
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachi
nemanager\..\..\Microsoft.SystemCenter.VirtualMachineManager.dll'.
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] Loading module from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.psd1'.
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] Loading 'Assembly' from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\Microsoft.BackgroundIntelligent
Transfer.Management.Interop.dll'.
VERBOSE: [MyComp]:                            [[SCVMM_Hardware]MyHardwareProfile] Loading 'FormatsToProcess' from path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\BitsTransfer\BitsTransfer.Format.ps1
xml'.
You cannot contact the VMM management server. The credentials provided have insufficient privileges on MY-VMM-SERVER.
Ensure that your account has access to the VMM management server MY-VMM-SERVER, and then try the operation again.
    + CategoryInfo          : ReadError: (:) [], CimException
    + FullyQualifiedErrorId : 1605,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.GetSCHWConfigCmdlet
    + PSComputerName        : localhost
 
VERBOSE: [MyComp]: LCM:  [ End    Test     ]  [[SCVMM_Hardware]MyHardwareProfile]  in 4.6853 seconds.
The PowerShell DSC resource cSCVMM_Hardware threw one or more non-terminating errors while running the Test-TargetResource functionality. These errors are logged to the ETW channel called 
Microsoft-Windows-DSC/Operational. Refer to this channel for more details.
    + CategoryInfo          : InvalidOperation: (:) [], CimException
    + FullyQualifiedErrorId : NonTerminatingErrorFromProvider
    + PSComputerName        : localhost
 
The SendConfigurationApply function did not succeed.
    + CategoryInfo          : NotSpecified: (root/Microsoft/...gurationManager:String) [], CimException
    + FullyQualifiedErrorId : MI RESULT 1
    + PSComputerName        : localhost
 
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 3.203 seconds

The first issue crossed my mind literally as I was hitting enter to start the Configuration. That is, am I going to need a credential variable to pull this off because not just anyone can connect to a VMM Server. This error came from running PowerShell as Administrator. When I run PowerShell as my elevated account (which has access) this is what happens.

PS C:\Scripts> Start-DscConfiguration -Path .\TestSCVMMHardware -Wait -Verbose
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft
/Windows/DesiredStateConfiguration'.
The WS-Management service cannot process the request. The WMI service returned an 'access denied' error. 
    + CategoryInfo          : PermissionDenied: (root/Microsoft/...gurationManager:String) [], CimException
    + FullyQualifiedErrorId : HRESULT 0x80338104
    + PSComputerName        : localhost
 
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 10.109 seconds

I am going to try this (although if it works this not a valid solution as far as I am concerned), and this shouldn’t work but I am going to try it anyways.

Configuration TestSCVMMHardware
{

    param
    (
        [pscredential]$Credential = (Get-Credential)
    )

    Import-DscResource -Module cSCVMM

    node localhost
    {
        SCVMM_Hardware MyHardwareProfile
        {
            VMMServer = "MDC-SC-VMM01"
            CPUCount = 2
            DVDDrive = $True
            Ensure = "Present"
            Name = "Jacobs Profile"
            VMNetwork = "Server Traffic"
       }

    }

}

TestSCVMMHardware -Credential (Get-Credential)

And it did exactly what I thought it should do (which is nice for a change).

You cannot contact the VMM management server. The credentials provided have insufficient privileges on MY-VMM-SERVER1.
Ensure that your account has access to the VMM management server MY-VMM-SERVER1, and then try the operation again.
    + CategoryInfo          : ReadError: (:) [], CimException
    + FullyQualifiedErrorId : 1605,Microsoft.SystemCenter.VirtualMachineManager.Cmdlets.GetSCHWConfigCmdlet
    + PSComputerName        : localhost

So, I am going to need a $Credential parameter. That sounds like a good place to start tomorrow 🙂

PowerShell DSC Journey – Day 18

Yesterday I finished up modifying the Set-TargetResource function and doing all the tests and it seems to be working exactly the way that I want. The next step today is to turn this into a module, import it, write a DSC Configuration and see if it actually works.

I already have my SCVMM_Hardware.psm1 file, so I just need to add a module manifest file.

PS C:\scripts> New-ModuleManifest -Path 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware\SCVMM_Hardware.psd1' -Author "Jacob Benson" -PowerShellVersion 4.0 -RootModule 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware\SCVMM_Hardware.psm1' -Verbose
VERBOSE: Performing the operation "Creating the "C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware\SCVMM_Hardware.psd1" module manifest file." on target "C:\Program Files\WindowsPowerShell\Mod
ules\DSCResources\SCVMM_Hardware\SCVMM_Hardware.psd1".

Looking at the other DSC Resources, none of them specify a root module, so I guess we will see if this breaks it or not. They also have multiple resources associated with each module, so that could be part of the reason as well.

This article on TechNet says to “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”, but the module manifest they show has the root module as ”, which doesn’t match up with what they are saying. I am just going to try it this way and see what happens. Because that’s what I do. Actually, I am going to change something up here to prepare for my other SCVMM Resource.

  • Rename the root folder to cSCVMM
  • Create a DSCResources folder underneath
  • Create a cSCVMM_Hardware folder, move my .psm1 and schema.mof files into this folder
  • Create the module manifest and place it in the root cSCVMM folder

Round 2.

PS C:\scripts> New-ModuleManifest -Path 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\cSCVMM\cSCVMM.psd1' -Author "Jacob Benson" -PowerShellVersion 4.0 -RootModule 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\SCVMM_Hardware\SCVMM_Hardware.psm1' -Verbose
VERBOSE: Performing the operation "Creating the "C:\Program Files\WindowsPowerShell\Modules\DSCResources\cSCVMM\cSCVMM.psd1" module manifest file." on target "C:\Program Files\WindowsPowerShell\Modules\DSCResource
s\cSCVMM\cSCVMM.psd1".

So far so good! (No errors anyways). I am going to restart ISE and see if it loads the module or what happens. This is where I had so much trouble in my previous post. And I ran into the same issue. If I say Get-Module -Name cSCVMM nothing happens. If I do Get-Module -ListAvailable it shows up in the list. So first thing, I am going to get rid of the root module path and see what happens.

PS C:\Scripts> New-ModuleManifest -Path 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\cSCVMM\cSCVMM.psd1' -Author "Jacob Benson" -PowerShellVersion 4.0 -Verbose
VERBOSE: Performing the operation "Creating the "C:\Program Files\WindowsPowerShell\Modules\DSCResources\cSCVMM\cSCVMM.psd1" module manifest file." on target "C:\Program Files\WindowsPowerShell\Modules\DSCResource
s\cSCVMM\cSCVMM.psd1".

Same thing. Move it out of the DSCResources folder, same thing.

Looking at the other resources, they have a CLR version and a description, so let’s just try that (although I am sure that has nothing to do with it).

New-ModuleManifest -Path 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\cSCVMM\cSCVMM.psd1' -Author "Jacob Benson" -PowerShellVersion 4.0 -ClrVersion 4.0 -Description "Module with DSC Resources for System Center Virtual Machine Manager" -Verbose

Long story short, turns out (once again) that I just don’t know what I am doing. Once you import it by name, you can then get the information on it. Duh.

PS C:\Scripts> Import-Module cSCVMM -Verbose
VERBOSE: Loading module from path 'C:\Program Files\WindowsPowerShell\Modules\DSCResources\cSCVMM\cSCVMM.psd1'.

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

ModuleType Version    Name                                ExportedCommands                                                                                                                                          
---------- -------    ----                                ----------------                                                                                                                                          
Manifest   1.0        cSCVMM                                                                                                                                                                                        

So, now that I wasted a bunch of time on that, let’s see if I can remember how to build a Configuration :).

First issue I run into is, when I do Import-DSCResource -Module cSCVMM it acts like it has no idea what the hell that is. So, uh, what do I do about that?

Configuration TestSCVMMHardwareProfile
{
    Import-DscResource -Module xNetworking
    Import-DscResource -Module cSCVMM

    node localhost
    {

    }
}

So, yeah. My .psm1 file is exporting the commands, so that shouldn’t be a problem. I guess first thing first, let’s run Get-DSCResource and see what happens.

PS C:\Scripts> Get-DSCResource
Exception calling "Substring" with "2" argument(s): "Length cannot be less than zero.
Parameter name: length"
At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:2336 char:13
+             $moduleName = $moduleFolder.FullName.Substring($folder.Le ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

I get that error, but then all of the DSCResources are listed (except for mine).

Further investigation reveals this.

PS C:\Scripts> Get-DscResource -Name cSCVMM
Exception calling "Substring" with "2" argument(s): "Length cannot be less than zero.
Parameter name: length"
At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:2336 char:13
+             $moduleName = $moduleFolder.FullName.Substring($folder.Le ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException
 
CheckResourceFound : The term 'cSCVMM' 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

Alright, so that’s fun. I am going to backup here and try something referencing the steps in this article.

I create a “new” DSCResource using my properties. And guess what? Even then it doesn’t show up as a DSC Resource. So, that’s good right? I don’t think so. That article makes it seem like it should be pretty simple, so I don’t know what’s going on.

Next step, I am going to test this on WMF 4.0 (I am using WMF 5.0 Preview). And the same thing happens there. So that’s good I guess. I really have no idea what is going on here. Completely. Puzzled.

Time to stop for the day. Hopefully I think of something before tomorrow as of what to try next.

Edit: I was able to resolve this issue with the help of Don Jones on the PowerShell.org forums.

When I first created the Resource what I did was this:

New-xDscResource -Name cSCVMM_Hardware -Property $DVDDrive, $VMNetwork, $CPUCount, $Ensure, $Name, $VMMServer -FriendlyName "SCVMM_Hardware" -ClassVersion 1.0 -Path 'C:\Program Files\WindowsPowerShell\Modules\'

What I should have done was this:
New-xDscResource -Name cSCVMM_Hardware -Property $DVDDrive, $VMNetwork, $CPUCount, $Ensure, $Name, $VMMServer -FriendlyName “SCVMM_Hardware” -ClassVersion 1.0 -Path ‘C:\Program Files\WindowsPowerShell\Modules\cSCVMM’

Since I didn’t specify the Module name it just created the DSC Resources folder and that messed up everything. Lesson learned!

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.