Check if remote node is fully compliant with DSC configuration

This topic contains 2 replies, has 2 voices, and was last updated by Profile photo of Rolf Lobker Rolf Lobker 8 months ago.

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #34215
    Profile photo of Rolf Lobker
    Rolf Lobker
    Participant

    I'm creating a script which;
    – Creates a new VM
    – Transfers metaconfig.mof to VM, which;
    — Sets LCM to Pull mode and grabs GUID.mof which;
    — Change hostname
    — Change IP
    — Dcpromo

    Afterwards my script will do psremoting to this machine to create OU structure, install software et cetera.

    I need to check if the VM is in the desired state before continuing. But when I grab the Node info from the pull server NodeComplaint equals True and Status equals 0 before the actual dcpromo ran. How can I programmatically wait for DSC to actually finish?

    Setting the pull mode:

    Configuration SetPullMode {
        param(
            [string]$guid,
            [string]$computername
        )
    
        Node $Computername
        {
            LocalConfigurationManager
            {
                ConfigurationMode = 'ApplyAndAutoCorrect'
                ConfigurationID = $guid
                RefreshMode = 'Pull'
                DownloadManagerName = 'WebDownloadManager'
                DownloadManagerCustomData = @{
                    ServerUrl = 'http://172.20.20.1:8080/PSDSCPullServer.svc';
                    AllowUnsecureConnection = 'true'
                    }
                RebootNodeIfNeeded = $True
            }
        }
    }
    $Guid = New-Guid
    SetPullMode -guid $guid -computername localhost

    Generating MOF:

    Configuration DC01 {
        Param (
            [PScredential]$Credential
        )
    
        Import-DscResource -Module xNetworking,xActiveDirectory,PSDesiredStateConfiguration,xComputerManagement
    
        Node $AllNodes.NodeName {
    
            xComputer ComputerName {
                Name = 'DC01'
                DependsOn = "[xIPAddress]IPAddress"
            }
    
            xIPAddress IPAddress {
                InterfaceAlias = "Ethernet"
                IPAddress = $AllNodes.IP
                AddressFamily = "IPV4"
                SubnetMask = $AllNodes.Mask 
            }
            xDefaultGatewayAddress Gateway {
                InterfaceAlias = "Ethernet"
                AddressFamily = "IPV4"
                Address = $AllNodes.Gateway
                DependsOn = "[xIPAddress]IPAddress"
            }
            xDNSServerAddress DNSServer {
                InterfaceAlias = "Ethernet"
                AddressFamily = "IPV4"
                Address = $AllNodes.IP
                DependsOn = "[xIPAddress]IPAddress"
            }
    
    
            File ADFiles            
            {            
                DestinationPath = 'C:\NTDS'            
                Type = 'Directory'            
                Ensure = 'Present'            
            }
            
            File Unattend
            {            
                DestinationPath = "C:\unattend.xml"
                Type = 'File'            
                Ensure = 'Absent'            
            } 
            
            File WindowsImage
            {            
                DestinationPath = "C:\Convert-WindowsImageInfo.txt"
                Type = 'File'            
                Ensure = 'Absent'            
            }      
                        
            WindowsFeature ADDSInstall             
            {             
                Ensure = "Present"             
                Name = "AD-Domain-Services"             
            }            
                
            # Optional GUI tools            
            WindowsFeature ADDSTools            
            {             
                Ensure = "Present"             
                Name = "RSAT-ADDS"             
            }  
            
            WindowsFeature DotNet35
            {
                Ensure = "Present"
                Name = "Net-Framework-Core"
            }          
                
            # No slash at end of folder paths            
            xADDomain FirstDS             
            {             
                DomainName = $AllNodes.DomainName            
                DomainAdministratorCredential = $Credential             
                SafemodeAdministratorPassword = $Credential          
                DatabasePath = 'C:\NTDS'            
                LogPath = 'C:\NTDS'            
                DependsOn = "[WindowsFeature]ADDSInstall","[File]ADFiles","[xComputer]ComputerName"
                           
            }
                
            File Done
            {
                DestinationPath = "C:\Temp"
                Type = 'Directory'            
                Ensure = 'Present'
                DependsOn = "[xADDomain]FirstDS","[WindowsFeature]DotNet35"
            }
                        
        }
    } 

    Prepare .mof for machine to pull:

    $ConfigData = @{             
        AllNodes = @(             
            @{  
                NodeName = "localhost"
                DomainName = "$DomainName"
                RetryCount = 20      
                RetryIntervalSec = 30
                PsDscAllowPlainTextPassword = $true
                PSDscAllowDomainUser = $True
                IP=$DC01
                Mask=$MaskBits
                Gateway=$Gateway
            }            
        )             
    } 
    
    DC01 -ConfigurationData $ConfigData -Credential $DomainCredentials -Verbose 
    
    Rename-Item .\DC01\localhost.mof -NewName "$guid.mof"
    New-DscChecksum .\DC01
    
    Get-ChildItem .\DC01 | Move-Item -Destination "$env:ProgramFiles\WindowsPowerShell\DscService\Configuration"

    After IP and hostname is set the machine reboots; the Pull server tells me:

    ConfigurationId NodeCompliant LastComplianceTime StatusCode
    ————— ————- —————— ———-
    372c6f01-c8df-4473-ac9e-c8de841a22d5 True 2016-01-23T12:51:35.3841422Z 0

    But LCM is not done yet.

    This all works fine if I wait a while but I need some way to check if this process is done before continuing.
    I tried this, but that fails because the result looks like completion before the reboot after Dcpromo;

    While ($nodeDone -eq $False) {
        Write-Verbose "Testing Node compliance..."
        $TestNode = (QueryNodeInformation).Value | 
            Where-Object -Property ConfigurationId -eq $Guid | 
            Where-Object -Property StatusCode -eq 0 | 
            Where-Object -Property NodeCompliant -eq $True
        Start-Sleep -Seconds 5
        If ($TestNode) {$NodeDone = $True}
    }

    Should I just:

    Invoke-Command -ComputerName $DC -Credential $Cred -ScriptBlock {
    Get-DscLocalConfigurationManager
    }
    

    .. and take the errors for granted until .LCMState EQ 'Idle'

    Or am I missing something else?

    #34267
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Chuck a wait for domain resource in there. Then, add a logging resource that logs a message, and which depends on the domain wait having completed. That'll keep the LCM in Pending (or should) until it all unravels.

    #34289
    Profile photo of Rolf Lobker
    Rolf Lobker
    Participant

    Yup, that works.

            xWaitForADDomain WaitForAD
            {
                DomainName = $AllNodes.DomainName
                RetryIntervalSec = 30
                RetryCount = 999
                DomainUserCredential = $Credential
            }

    Now I can check the compliance server and see if for this guid Nodecompliant -eq $True, Status -eq 0 and Dirty -eq $False.

Viewing 3 posts - 1 through 3 (of 3 total)

You must be logged in to reply to this topic.