Dear all,
I have a huge configuration of an application development server that needs to reboot a few times.
I’ve configured the LCM with ‘RebootNodeIfNeeded = $True’ and I’m using xPendingReboot to control the reboots throughout the config. I’m not using a pull server.
At some point in the config I don’t want the node to auto-reboot anymore. But AFAIK I can only change the RebootNodeIfNeeded setting by running Set-DscLocalConfigurationManager again.
I tried something like this:
Script DisableAutoReboot {
SetScript = {
Set-DscLocalConfigurationManager -Path c:\DSC\DisableAutoReboot
}
TestScript = {
$val = $True
If ((Get-DscLocalConfigurationManager).RebootNodeIfNeeded) {
$val = $False
}
return $val
}
GetScript = {
@{Result = (Get-DscLocalConfigurationManager).RebootNodeIfNeeded}
}
}
}
}
But then I get: The Start-DscConfiguration cmdlet is in progress and must return before Set-DscLocalConfigurationManager can be invoked.
My question is, is this even possible? Apologies if this is a beginner question.
Jacqueline
donj
April 29, 2017, 8:04am
2
It’s really not. You’re correct in that you have to reconfigure the LCM, and you can’t do that while it’s processing a configuration. The most you could do is manually inject a new meta-MOF, but it wouldn’t be processed until the next run.
Thanks for the answer. I will break up the Configuration in smaller pieces then.
I have a similar problem and ended up breaking it into sections and then checking to see it a reboot needed to occur. In some cases I wanted to trigger a reboot in others the various resources were potentially triggering a reboot.
I ended up using the Get-PendingReboot script by Brian Wilhite, and modifying it to also look for my particular reboot trigger
So I use the following function to Push my configurations, you will notice the call to WaitForServer that takes a parameter of $EncodedText. $EncodedText is just a structure of server information that I use to set up the configuration data and track which servers I want to deploy as part of this scenario.
Function DoDscStuff($mofpath,$title)
{
if (Test-Path (Join-path $mofpath -ChildPath "*") -Include *.mof)
{
#
# To get the output to a log file
# https://github.com/PowerShell/SharePointDsc/issues/218
#
Dump '----------------------------------------------------------------------------'
Dump " $title"
Dump '----------------------------------------------------------------------------'
Dump ' '
Dump ('MOFPath = {0}' -f $mofPath)
$errorCount = 0
$Error.Clear()
if($LogToScreen)
{
Start-DscConfiguration -Path $mofpath -Wait -Force -credential $InstallerCredential -Verbose
if( $error.Count -gt $errorCount )
{
$AccessDeniedError = $false
$dscErrors = $error[$errorCount..($error.Count - 1)];
Foreach($prob in $dscErrors)
{
if($prob.FullyQualifiedErrorId -like '*0x80070005*')
{
$AccessDeniedError = $true
break;
}
}
if($AccessDeniedError)
{
$errorCount = 0
$Error.Clear()
Write-Host 'Attempting alternate credentials' -ForegroundColor Yellow
Start-DscConfiguration -Path $mofpath -Wait -Force -credential $ChildDomainCred -Verbose
}
}
}
else
{
Start-DscConfiguration -Path $mofpath -Wait -Force -credential $InstallerCredential -Verbose -Debug *>> $logFile
if( $error.Count -gt $errorCount )
{
$AccessDeniedError = $false
$dscErrors = $error[$errorCount..($error.Count - 1)];
Foreach($prob in $dscErrors)
{
if($prob.FullyQualifiedErrorId -like '*Access is Denied*')
{
$AccessDeniedError = $true
break;
}
}
if($AccessDeniedError)
{
$errorCount = 0
$Error.Clear()
Write-Host 'Attempting alternate credentials' -ForegroundColor Yellow *>> $logFile
Start-DscConfiguration -Path $mofpath -Wait -Force -credential $ChildDomainCred -Verbose -Debug *>> $logFile
}
}
}
Dump ' '
Dump '----------------------------------------------------------------------------'
if( $error.Count -gt $errorCount )
{
$dscErrors = $error[$errorCount..($error.Count - 1)];
Dump "The following errors occurred during dsc configuration"
Dump ($dscErrors | fl * | out-string)
$NonTermErrorFound = $false
Foreach($prob in $dscErrors)
{
if($prob.FullyQualifiedErrorId -like '*NonTerminatingError*')
{
$NonTermErrorFound =$true
break
}
}
if(!$NonTermErrorFound){throw $dscErrors[-1];}
}
else
{
WaitForServers $EncodedText
}
}
}
Function WaitForServers{
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true,Position=0)]
[string]$EncodedText
,[Parameter(Mandatory = $false)]
[int]$sleep=20
)
$Servers = ConvertFrom-Json ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($EncodedText)))
$Computers = $Servers | ?{$_.BuildMe -eq 1} | Select-Object -ExpandProperty name
$ServersToReboot = ((Get-PendingReboot -ComputerName $Computers)|?{$_.RebootPending -eq $true} | Select-Object -ExpandProperty Computer)
if ($ServersToReboot -ne $null)
{
Restart-Computer $ServersToReboot -Force -Wait -For WinRM -Timeout 300 -Delay 5
#Clean up any reboots triggered by ECI
$HKLM = [UInt32] "0x80000002"
Foreach($server in $ServersToReboot)
{
$WMI_Reg = [WMIClass] "\\$server\root\default:StdRegProv"
$WMI_Reg.DeleteKey($HKLM, "Software\DesiredStateConfiguration\RebootPending") | Out-Null
}
}
}
I use the following script to set my Reboot Flag so that I can control when it gets set
Script Reboot
{
SetScript = Format-DscScriptBlock -Node $Node -ScriptBlock {
Write-Verbose "Setting Reboot Pending"
New-Item -Path "HKLM:\Software\DesiredStateConfiguration\RebootPending" -Force ;
return $true;
}
TestScript =Format-DscScriptBlock -Node $Node -ScriptBlock {
return (Boolean result from your Test);
}
GetScript = {@{Result = 'Doing Nothing'}}
}
Hope this help in some small way.
Joe