Demo DSC – Part 2

In Part 1 of this series I talked about how I demo’d the building of a Domain Controller. In Part 2 I am going to talk about how I demo’d building a Pull Server, an App Server, and used the two servers to show how a Pull Server works and what needs to be done to make the magic happen. If you didn’t read Part 1, here is the disclaimer:

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

The outline for this part of my Demo looked like this:

  1. Talk about the purpose of a Pull server (Can also be used to push and write Configurations)
    1. Show how nothing is configured (name, domain, roles/features, etc
    2. Open ISE, Run BuildPullServer Script
    3. Will reboot. While rebooting show the computer account on the DC
    4. Login as domain account
      1. Create share C:\WebServerFiles, share with everyone (explain why we need it later). Explain that this could have been done with DSC, I just choose not to.  This Share will come into play later.
      2. Copy website files to this share (I created a “website” in Word to use with a Web Server, that will come in the last part of this series)

Here is the Configuration script in its entirety.  It’s also available on Github.

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

}

Configuration BuildLabPullServer{

    param(
        
        [parameter(Mandatory)]
        [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]$DNSIP,

        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$Gateway,

        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$Subnet
    )

    #unsecure, not safe or recommended way to do this
    $Creds = ConvertTo-SecureString "Passw0rd!" -AsPlainText -Force
    $DomainAdminCred = New-Object System.Management.Automation.PSCredential ("$Domain\Administrator", $Creds)
    $SafeModeAdminCred = New-Object System.Management.Automation.PSCredential ("Administrator", $Creds)

    Import-DscResource -ModuleName xActiveDirectory,xNetworking,xComputerManagement,xPendingReboot,xSystemSecurity,xRemoteDesktopAdmin,xTimeZone,xWinEventLog,xPSDesiredStateConfiguration

    Node $NodeName{

        LocalConfigurationManager{
            RebootNodeifNeeded = $True
        }

        xIPAddress PULLServerIP{
            IPAddress = $IP
            DefaultGateway = $Gateway
            SubnetMask = $Subnet
            AddressFamily = "IPv4"
            InterfaceAlias = "Ethernet"
        }

                
        xDNSServerAddress DomainDNS{
            Address = $DNSIP
            InterfaceAlias = "Ethernet"
            AddressFamily = "IPv4"
        }

        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"
        }        
        
        WindowsFeature DSCServiceFeature{
            Ensure = "Present"
            Name = "DSC-Service"        
        } 

        xDSCWebService PSDSCPullServer{
          Ensure = "Present"
          EndpointName = "PSDSCPullServer"
          Port = 8080
          PhysicalPath = "$env:SystemDrive\inetpub\wwwroot\PSDSCPullServer"
          CertificateThumbPrint = "AllowUnencryptedTraffic"
          ModulePath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules"
          ConfigurationPath  = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Configuration"
          State = "Started"
          DependsOn = "[WindowsFeature]DSCServiceFeature"
        }

       xDscWebService PSDSCComplianceServer{
          Ensure = "Present"
          EndpointName = "PSDSCComplianceServer"
          Port = 9080
          PhysicalPath = "$env:SystemDrive\inetpub\wwwroot\PSDSCComplianceServer"
          CertificateThumbPrint = "AllowUnencryptedTraffic"
          State = "Started"
          IsComplianceServer = $true
          DependsOn = ("[WindowsFeature]DSCServiceFeature","[xDSCWebService]PSDSCPullServer")
        }
        
	    xComputer JoinDomain{
	       Name = $ComputerName
	       DomainName = $Domain
               Credential = $DomainAdminCred
	       DependsOn = "[xIPAddress]PULLServerIP","[xDNSServerAddress]DomainDNS"
           
	    }

       xPendingReboot DomainJoin{
            Name = "Check for reboot after domain join"
       }
    }#Node

}#configuration

BuildLabPullServer -ConfigurationData $ConfigData -NodeName localhost -computername $YourComputerName -Domain $YourDomain -IP $YourIP -Gateway $YourGateway -Subnet 24 -DNSIP $YourDNSIP -OutputPath $YourPath
Set-DscLocalConfigurationManager -Path $YourPath
Get-DSCLocalConfigurationManager
Start-DscConfiguration -Wait -Force -Verbose -Path $YourPath

With that done I then built what I called an App Server. Don’t think that I somehow deployed an Application using DSC (I didn’t) but with a Web Server the last part of my demo I needed to call it something that sort of made sense so I called it an App Server. The build script for the App Server is below, and you can see that it’s much smaller than the previous two build scripts. In this case I wanted to show a minimal configuration for a build script and then demonstrate the process of configuring the App Server to pull a new Configuration.

Here is the Configuration script in its entirety.It’s also available on GitHub.

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

}

Configuration BuildLabAppServer{

    param(
        
        [parameter(Mandatory)]
        [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]$DNSIP,

        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$Gateway,

        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$Subnet
    )

    #unsecure, not safe or recommended way to do this
    $Creds = ConvertTo-SecureString "Passw0rd!" -AsPlainText -Force
    $DomainAdminCred = New-Object System.Management.Automation.PSCredential ("$Domain\Administrator", $Creds)
    $SafeModeAdminCred = New-Object System.Management.Automation.PSCredential ("Administrator", $Creds)

    Import-DscResource -ModuleName xNetworking,xComputerManagement,xPendingReboot,xActiveDirectory

    Node $NodeName{

        LocalConfigurationManager{
            RebootNodeIfNeeded = $True
        }

        xIPAddress APPIP{
            IPAddress = $IP
            DefaultGateway = $Gateway
            SubnetMask = $Subnet
            AddressFamily = "IPv4"
            InterfaceAlias = "Ethernet"
        }
          
        xDNSServerAddress DomainDNS{
            Address = $DNSIP
            InterfaceAlias = "Ethernet"
            AddressFamily = "IPv4"
        }

        xComputer RenameAndDomainJoin{
           Name = $ComputerName
           DomainName = $Domain
           Credential = $DomainAdminCred
           DependsOn = "[xIPAddress]APPIP","[xDNSServerAddress]DomainDNS"
       }

       xPendingReboot DomainJoin{
            Name = "Check for reboot after domain join"
       }
        
    }#Node

}#configuration

BuildLabAppServer -ConfigurationData $ConfigData -NodeName localhost -computername $YourComputerName -Domain $YourDomain -IP $YourIP -Gateway $YourGateway -Subnet 24 -DNSIP $YourDNS -OutputPath $YourPath
Set-DscLocalConfigurationManager -Path $YourPath
Get-DSCLocalConfigurationManager
Start-DscConfiguration -Wait -Force -Verbose -Path $YourPath

With that done, the next step is to create a Configuration on the Pull Server for the App Server to Pull. All this Configuration does is change the TimeZone on the App Server. Nothing fancy here. There are also some other pieces at the bottom of the Configuration script I should talk about. I have hardcoded a GUID for the server in the Configuration. You can either use this one or change it to your own. I am setting the source and destination paths and sticking the GUID onto the end of the .MOF file, which is required when you are pulling a Configuration. This GUID is how the server knows which Configuration belongs to it (as we will see here shortly). I am then copying the file from the source path to the destination path, and then creating a Checksum file for the .MOF (which is also required).

Here is the Configuration script in its entirety. It’s also available on Github.

Configuration LabAppServerPullConfig{
 
    param(
 
        [string]$ComputerName
 
    )
 
    Import-DscResource -ModuleName xTimeZone
 
    Node $ComputerName{
 
        xTimeZone ServerTime{
            TimeZone = "Central Standard Time"
        }
 
    }#Node
 
}#Config
 
LabAppServerPullConfig -ComputerName $YourComputer -OutputPath $YourPath
 
$GUID = "78653f12-9e40-41fd-9b92-a9c14e3670a7"
 
$source = "$YourPath\LabAppServerPullConfig\$YourComputer.mof"
$dest = "C:\program files\windowspowershell\dscservice\configuration\$guid.mof"
Copy $source $dest
New-DSCChecksum $Dest -Force

With that done, we need to do one other thing before this is going to work. I pre-copied various DSC Resources to the Pull Server, so now we need to .ZIP up the XTimeZone resource so that it can be copied to the App Server when it pulls it’s Configuration. You do this by creating a .ZIP file of the xTimeZone Module and appending the version number to the end of it. In this case, my file name after creating the .ZIP Archive is xTimeZone_1.0.0 . This file then needs to be placed in the “$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules” folder, which is the ModulePath we specified in our Pull Server Configuration. Once that is done, we need to run the command below to also create a Checksum file for this Archive.

New-DSCChecksum -ConfigurationPath "$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules\xTimeZone_1.0.0" -Force

Next we need to create a Configuration to tell the App Server to Pull it’s Configuration. This is done by changing the Local Configuration Manager (LCM) settings on the App Server. In my demo I built this Configuration on the Pull Server and then pushed it to the App Server. The outline for this part of the demo looked like this:

  1. Create LCM Configuration. Comment out the Set line in the script. Explain the meta.mof file.
  2. Show LCM Configuration on App Server
  3. Show Consistency Task settings (there should be none)
  4. Push LCM Configuration from Pull Server to App Server
  5. Show LCM Configuration on App Server compared to previous
  6. Show Time Zone. Run Scheduled Task.
  7. Watch App Server for Time Change
    a. Change Time Zone again to something totally random
    b. Run Consistency Task again, watch Time Zone change again

Here is the Configuration script in its entirety.  It’s also available on Github.. You should also note in this script that the Configuration GUID from before makes an appearance here as well. This GUID is what tells the App Server which Configuration to look for on the Pull Server.

Configuration PushLCMConfig{

    param(
        [parameter(Mandatory=$True)]
        [ValidateNotNullorEmpty()]
        [string]$ComputerName

    )

    Node $ComputerName{
            
        LocalConfigurationManager{
            ConfigurationMode = 'ApplyAndAutoCorrect'
            ConfigurationID = "78653f12-9e40-41fd-9b92-a9c14e3670a7"
            RefreshMode = 'Pull'
            DownloadManagerName = 'WebDownloadManager'
            DownloadManagerCustomData = @{
                #Make sure to change the ServerURL to match what you are using
                ServerUrl = 'http://$PULLSERVER.DOMAIN.COM:8080/PSDSCPullServer.svc';
                AllowUnsecureConnection = 'true' }
            RebootNodeIfNeeded = $True
        }
    }
}

PushLCMConfig -ComputerName $YourComputerName -OutputPath $YourPath
Set-DscLocalConfigurationManager -ComputerName $YourComputerName -Path $YourPath -Verbose

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.

Moving SCOM 2012 R2 Data Warehouse Database to New SQL Server Cluster

This is the second of two posts in regards to moving Operations Manager 2012 R2 Databases.  The first post about moving the OperationsManager database can be found here.  I won’t rehash any of that information but will instead just get right into the How To portion.  The TechNet article for moving the SCOM DataWarehouse Database can be found here.

  1. Stop the following services on OPSMGR01 and change their type to Manual.  Otherwise they will restart and cause you problems.
    1. System Center Data Access
    2. System Center Management Configuration
  2. Stop the following services on OPSMGR02 and change their type to Manual.  Otherwise they will restart and cause you problems.
    1. System Center Data Access
    2. System Center Management Configuration
  3. On OLDSQLServer, use SQL Server Management Studio to create a full backup of the data warehouse database. The default name is OperationsManagerDW. We recommend that you also back up the associated master database.
    1. Copy backup file to \\SQLCLUSTERNODE1\SHARE
  4. Open SQL Management Studio on SQLCLUSTERNODE1 and connect to SQLCLUSTER\SCOMDW Instance
    1. Restore OperationsManagerDW Database using SQL
  5. Backup registry on OPSMGR01
  6. Backup registry on OPSMGR02
  7. Update Registry on OPSMGR01
    1. Regedit
    2. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup
    3. For each of the following keys, double-click the name, change the value to the hostname of the SQL Server-based computer now hosting the operational database, and then click OK to save your changes.
      1. DatabaseWarehouseDBServerName: SQLCLUSTER\SCOMDW
      2. DatabaseName: OperationsManagerDW
  8. Update Registry on OPSMGR02
    1. Regedit
    2. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup
    3. For each of the following keys, double-click the name, change the value to the hostname of the SQL Server-based computer now hosting the operational database, and then click OK to save your changes.
      1. DatabaseWarehouseDBServerName: SQLCLUSTER\SCOMDW
      2. DatabaseName: OperationsManagerDW
  9. Login to the server you are using for reporting off of the SCOM Data Warehouse
    1. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\System Center Operations Manager\3.0\Reporting,\ DWDBInstance double-click the name and change the value to the hostname of the SQL Server-based computer now hosting the operations manager DW database, and then click OK to save your change.
      1. In my case that would be SQLCLUSTER\SCOMDW
    1. Start the System Center Data Access Service on OPSMGR01 associated with the reporting server. This is needed to access the reports page
    2. On reporting server, change the connection strings.
      1. Open a browser and go to the reporting webpage
      2. Click Show Details and then click Data Warehouse Main. Change the Connection String to contain the new data warehouse server name, and then click Apply. SQLCLUSTER\SCOMDW.
      3. Test the connection
      4. Click Application monitoring, and then click .NET monitoring.
      5. Click AppMonitoringSource.
      6. On the AppMonitoringSource page, click Properties and change Connection string to contain SQLCLUSTER\SCOMDW, and then click Apply.
      7. Test the connection
      8. Close the browser.
    3. On SQLCLUSTERNODE1 update the OperationsManager database table. (Note that this is NOT the DataWarehouse instance!)
      1. Open SQL Server Management Studio. SQLCLUSTER\SCOM
      2. Expand Databases, OperationsManager, and Tables.
      3. Right-click dbo.MT_Microsoft$SystemCenter$DataWarehouse, and then click Edit Top 200 Rows.
      4. Change the value in the MainDatabaseServerName_2C77AA48_DB0A_5D69_F8FF_20E48F3AED0F column to SQLCLUSTER\SCOMDW
    4. Update the OperationsManager database for Application Performance Monitoring functionality.
      1. Right-click dbo.MT_Microsoft$SystemCenter$DataWarehouse$AppMonitoring, and then click Edit Top 200 Rows.
      2. Change the value in the MainDatabaseServerName_5C00C79B_6B71_6EEE_4ADE_80C11F84527A column to SQLCLUSTER\SCOMDW
      3. Do the same for the following tables.
      4. Right-click dbo. MT_Microsoft$SystemCenter$DataWarehouse$AppMonitoring_Log and then click Edit Top 200 Rows. Change the value of column Post_MainDatabaseServerName_5C00C79B_6B71_6EEE_4ADE_80C11F84527A to SQLCLUSTER\SCOMDW
      5. Right-click dbo.MT_Microsoft$SystemCenter$DataWarehouse_Log and then click Edit Top 200 Rows. Change the value of column.Pre_MainDatabaseServerName_2C77AA48_DB0A_5D69_F8FF_20E48F3AED0F TO SQLCLUSTER\SCOMDW.
      6. Close SQL Server Management Studio.
    5. On SQLCLUSTERNODE1, update the member database.
      1. Open SQL Server Management Studio and connect to SQLCLUSTER\SCOMDW instance.
      2. Expand Databases, OperationsManagerDW, and Tables.
      3. Right-click dbo.MemberDatabase, and then click Edit Top 200 Rows.
      4. Change the value in the ServerName column to reflect the name of the new SQL Server, SQLCLUSTER\SCOMDW
      5. Close SQL Server Management Studio.
    6. Update security credentials on SQLCLUSTER\SCOMDW
      1. All of my security credentials carried over and I had no issues.  However, your environment may be completely different.  Definitely make sure to read this section in the TechNet documentation
    7. Stop SQL Services relating to SCOM on OLDSQLServer
    8. Open PowerShell.  Type Write-Host “Bye Kitty” to sacrifice a kitten
    9. Restart OPSMGR01 and OSPMGR02 (this was to ensure registry setting changes were picked up)
    10. Start the following services on OPSMGR01 and change their startup type to Automatic
      1. System Center Data Access
      2. System Center Management Configuration
    11. Start the following services on OPSMGR02 and change their startup type to Automatic
      1. System Center Data Access
      2. System Center Management Configuration
    12. Spam refresh OperationsManager event log on OPSMGR01.  Hopefully you see lots of informational messages and no errors about connections to the SQL Server.

To verify a successful move of the Operations Manager Data Warehouse Database:

  1. Verify that you can successfully run a report from the console.
  2. Ensure that the health state of all management servers in the management group are Healthy.
  3. If the health state of any management server is Critical, open Health Explorer, expand Availability – <server name>, and then continue to expand until you can navigate to Data Warehouse SQL RS Deployed Management Pack List Request State. Check the associated events to determine if there is an issue accessing the data warehouse database.
  4. Check operating system events:
    1. Open the operating system’s Event viewer. Navigate to Event Viewer, and then to Operations Manager.
    2. In the Operations Manager pane, search for events with a Source of Health Service Module and a Category of Data Warehouse.
  1. The move was successful if event number 31570, 31558, or 31554 exists.
  2. There is an issue accessing the data warehouse database if event numbers 31563, 31551, 31569, or 31552 exists.
  3. Check events in Operations Manager:
    1. In the Operations console, select Monitoring.
    2. Navigate to Monitoring, Operations Manager, Health Service Module Events, and then to Performance Data Source Module Events.
    3. Search the Performance Data Source Module Events pane for events with a Date and Time that is later than the move.

 

Moving SCOM 2012 R2 Database to New SQL Server Cluster

When our System Center environment (VMM, Orchestrator, SCOM, DPM) was originally setup all the databases were installed on a single SQL Server VM (but in separate instances).  For a variety of reasons I made the decision that our System Center databases needed to at least be in a cluster configuration.  Luckily I stumbled across this excellent guide by MVP Paul Keely about configuring a SQL 2012 Cluster with Always On to be used for System Center databases.  I am not going to cover any of that here, this post is just going to be about how to move the Operations Manager database once the new cluster is built.

First, I need to go on a rant about just plain poor timing on my part.  If you don’t care to read it, skip to the next paragraph.  There is an article published by Microsoft that talks about how to move the Operational Database.  If you look at that article you will notice that it was last updated on January 19th.  That’s awesome.  You know what’s not awesome?  I first attempted to move the Operational Database on January 17th.  It failed miserably.  Why?  Because the article I was working off of didn’t include a second registry key that needed to be modified.  That’s 6 hours of my  life I will never get back.

In my environment I have two Operations Manager Management servers, in this article they are named OPSMGR01 and OPSMGR02.  When I wrote up my plan for this move I duplicated some sections that needed to be done on both servers and I kept that the same in this article.  For the SQL Server name, I used the name of the new SQL Cluster as SQLCLUSTER followed by the instance name.  If you are moving the databases to a single server you would just use the server name followed by the instance name.

  1. Stop the following services on OPSMGR01 and change their type to Manual.  Otherwise they will restart and cause you problems.
    1. System Center Data Access
    2. System Center Management Configuration
  2. Stop the following services on OPSMGR02 and change their type to Manual.  Otherwise they will restart and cause you problems.
    1. System Center Data Access
    2. System Center Management Configuration
  3. Create full backup of OperationsManager Database on OLDSQLServer using SQL
    1. Copy backup file to \\SQLCLUSTERNODE1\SHARE
  4. Open SQL Management Studio on SQLCLUSTERNODE1 and connect to SQLCLUSTER\SCOM Instance
    1. Restore OperationsManager Database using SQL
  5. Delete backup file from \\SOMEFILESHARE (Needed the space for the massive SCOM Data Warehouse Database backup that was coming next)
  6. Backup Registry on OPSMGR01
  7. Backup Registry on OPSMGR02
  8. Update Registry on OPSMGR01
    1. Regedit
    2. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup
    3. For each of the following keys, double-click the name, change the value to the hostname of the SQL Server-based computer now hosting the operational database, and then click OK to save your changes.
      1. DatabaseName: SQLCLUSTER\SCOM
      2. DatabaseServerName: OperationsManager
    4. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\System Center\2010\Common\Database and repeat step 3. (This was the aforementioned missing step)
  9. Update Registry on OPSMGR02
    1. Regedit
    2. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup
    3. For each of the following keys, double-click the name, change the value to the hostname of the SQL Server-based computer now hosting the operational database, and then click OK to save your changes.
      1. DatabaseName: SQLCLUSTER\SCOM
      2. DatabaseServerName: OperationsManager
    4. Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\System Center\2010\Common\Database and repeat step 3.
  10. Edit the following file on OPSMGR01
    1. Browse to %ProgramFiles%\System Center 2012\Operations Manager\Server\ConfigService.config
    2. Backup existing file (copy and rename to .old and place somewhere safe)
    3. Open Notepad as Administrator and open the file in Step 1.
    4. In the <Category> tags named “Cmdb” and “ConfigStore”, change the value for ServerName to the name of the new SQL server.
    5. SQLCLUSTER\SCOM
    6. Save changes and close
  11. Edit the following file on OPSMGR02
    1. Browse to %ProgramFiles%\System Center 2012\Operations Manager\Server\ConfigService.config
    2. Backup existing file (copy and rename to .old and place somewhere safe)
    3. Open Notepad as Administrator and open the file in Step 1.
    4. In the <Category> tags named “Cmdb” and “ConfigStore”, change the value for ServerName to the name of the new SQL server.
    5. SQLCLUSTER\SCOM
    6. Save changes and close
  12. Update the operational database with the new database server name on SQLCLUSTERNODE1
    1. Open SQL Server Management Studio. Connect to SQLCLUSTER\SCOM instance.
    2. Expand Databases, OperationsManager, and Tables.
    3. Right-click dbo.MT_Microsoft$SystemCenter$ManagementGroup, and then click Edit Top 200 Rows.
    4. Change the value in the SQLServerName_6B1D1BE8_EBB4_B425_08DC_2385C5930B04 column to SQLCLUSTER\SCOM
      1. The GUID part in your database isn’t going to match the one above.  It’s ok!
    5. Save the change.
  13. On SQLCLUSTERNODE1, update the operational database with the new database server name to specify the location of the Application Performance Monitoring tables
    1. Open SQL Server Management Studio. Connect to SQLCLUSTER\SCOM instance
    2. Expand Databases, OperationsManager, and Tables.
    3. Right-click dbo.MT_Microsoft$SystemCenter$OpsMgrDB$AppMonitoring, and then click Edit Top 200 Rows.
    4. Change the value in the MainDatabaseServerName_5C00C79B_6B71_6EEE_4ADE_80C11F84527A column to SC-SQLCLUS-SCOM\SCOM
      1. The GUID part in your database isn’t going to match the one above.  It’s ok!
    5. Save the change.
  14. Update security credentials on SQLCLUSTER\SCOM
    1. All of my security credentials carried over and I had no issues.  However, your environment may be completely different.  Definitely make sure to read this section in the TechNet documentation
  15. Execute these SQL commands on new OperationsManager database instance:
    1. sp_configure ‘show advanced options’,1
    2. reconfigure
    3. sp_configure ‘clr enabled’,1
    4. reconfigure
  16. Run the following SQL query (If you added the OperationsManager database to AlwaysOn before this step you can skip this step. I ran through all of this and added it to AlwaysOn once I knew for sure it was working on the new SQLCLUSTER):
    1. SELECT is_broker_enabled FROM sys.databases WHERE name=’OperationsManager’
      1. If the result of this query was an is_broker_enabled value of 1, skip this step. Otherwise, run the following SQL queries:
    2. ALTER DATABASE OperationsManager SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    3. ALTER DATABASE OperationsManager SET ENABLE_BROKER
    4. ALTER DATABASE OperationsManager SET MULTI_USER
  17. Stop SQL Services relating to SCOM on OLDSQLServer
  18. Open PowerShell.  Type Write-Host “Bye Kitty” to sacrifice a kitten
  19. Restart OPSMGR01 and OSPMGR02 (this was to ensure registry setting changes were picked up)
  20. Start the following services on OPSMGR01 and change their startup type to Automatic
    1. System Center Data Access
    2. System Center Management Configuration
  21. Start the following services on OPSMGR02 and change their startup type to Automatic
    1. System Center Data Access
    2. System Center Management Configuration
  22. Spam refresh OperationsManager event log on OPSMGR01.  Hopefully you see lots of informational messages and no errors about connections to the SQL Server.
  23. Start OperationsManager console.  Check stuff

That’s it!

2015 PowerShell Resolutions

I am stealing this idea from Boe Prox. He blogged about his own PowerShell Resolutions for 2015.

I will keep this short and sweet. In no particular order here are my PowerShell Resolutions for 2015:

  1. Figure out a PowerShell related topic to speak about that I won’t get bored with in a month or two
  2. Speak about this topic at the Omaha PowerShell User Group
  3. Speak about this topic at 2-3 other PowerShell User Groups or other organizations (local or otherwise)
  4. Start and Finish PowerShell Deep Dives Book
  5. Start and Finish Windows PowerShell Best Practices Book
  6. Implement PowerShell DSC in Production at my current place of employment
  7. Deploy Private Cloud (WAP, Azure, DSC etc) in Production at my current place of employment
  8. Write at minimum one blog post a week
  9. Schedule one hour a week on my calendar to browse PowerShell.org and TechNet forums looking for PowerShell related questions to answer
  10. Learn how to do more things in SCOM and VMM using PowerShell instead of clicking around in the GUI

That’s probably a little on the ambitious side, but we will see how it goes!  What are your PowerShell Resolutions for 2015?

Creation of the VMM Resource Group Failed

While trying to install VMM as a Highly Available following the steps in this article, I kept running into the same issue over and over and over again.  The installation would start, run for a few minutes, and then fail and rollback with this error at the end:  “Creation of the VMM resource group VMM failed.Ensure that the group name is valid, and cluster resource or group with the same name does not exist, and the group name is not used in the network.”

I first thought it was because I had pre-configured the DNS entry, but even after removing the DNS entry and verifying that neither cluster node could resolve it anymore the installation still failed.  Next I rebooted both nodes of the cluster.  The installation still failed.  My next thought is maybe I can’t use VMM as the HA VMM name so I used XXXVMM and sure enough it worked.  Now, whether or not that is because I had the VMM DNS entry created previously and it screwed something up, or because you really can’t use the VMM name, I don’t know.

At this point it said setup completed successfully, but with warnings.

 

Starting the clustered VMM service XXXVMM failed.Ensure that the user has permission, the VMM service is installed properly, and cluster resources can be brought online.A service connection point (SCP) could not be registered in Active Directory Domain Services (AD DS) for the VMM management server.Run “D:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\setup\ConfigureSCPTool.exe -install XXXVMM.nfm.com XXX\XXXVMM$” in a command window and then check AD DS. If an SCP is not registered, VMM consoles on other computers will not be able to connect to this VMM management server and deploying a Hyper-V host to a bare-metal computer will not work.

I ran the setup as a domain administrator, and am logged into the cluster node as this same domain administrator.

Looking at the Cluster event logs, this is the error I get when I try to manually bring the service online:

Failed to bring the resource VMM Service XXXVMM online.  Error code 0x80071736 The Resource failed to come online due to the failure of one or more resource providers.

Looking at Services, the System Center Virtual Machine Manager Agent service is running, but the System Center Virtual Machine Manager service is not running, and if I try to start it, it fails with the error.

In the Event Log, I find this error entry which seems pretty useful.

Cluster network name resource ‘XXXVMM’ failed to create its associated computer object in domain ‘nfm.com’ during: Resource online.

The text for the associated error code is: A constraint violation occurred.

Please work with your domain administrator to ensure that:

– The cluster identity ‘VMM-HV-CLUS01$’ has Create Computer Objects permissions. By default all computer objects are created in the same container as the cluster identity ‘VMM-HV-CLUS01$’.

– The quota for computer objects has not been reached.

– If there is an existing computer object, verify the Cluster Identity ‘VMM-HV-CLUS01$’ has ‘Full Control’ permission to that computer object using the Active Directory Users and Computers tool.

While looking in AD for this object, I also stumbled across a VMM computer object (who the hell knows where that come from) so I deleted that object as well.  I am nearly 100% certain that is what caused my installation using VMM as my VMM Cluster Name to fail.

At the very bottom of this article it outlines how to troubleshoot issues with Cluster AD Accounts.  The instructions are only slightly different for Server 2012, and it tells you how to grant only the permissions that you need.

With that done, I removed the VMM installation and tried it again, with the original VMM Cluster name (just VMM) and it worked fine, with no errors!

 

 

 

 

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.

Tecumseh Poem from Act of Valor

So live your life that the fear of death can never enter your heart.
Trouble no one about their religion; respect others in their view, and
demand that they respect yours. Love your life, perfect your life,
beautify all things in your life. Seek to make your life long and its purpose in the service of your people.
Prepare a noble death song for the day when you go over the great divide.

Always give a word or a sign of salute when meeting or passing a
friend, even a stranger, when in a lonely place. Show respect to all
people and grovel to none.

When you arise in the morning give thanks for the food and for the joy
of living. If you see no reason for giving thanks, the fault lies only
in yourself. Abuse no one and no thing, for abuse turns the wise ones
to fools and robs the spirit of its vision.

When it comes your time to die, be not like those whose hearts are
filled with the fear of death, so that when their time comes they weep
and pray for a little more time to live their lives over again in a different way.
Sing your death song and die like a hero going home.

Chief Tecumseh (Poem from Act of Valor)