Enable an Application Server on all Web Farms

on Friday, June 20, 2014

Last time, I looked at Enabling/Disabling an Application Server within a single Web Farm. I’ll try to continue on that same thread and update the script to Enable or Disable an Application Server on all Web Farms on a Proxy Server.

The core of the work is done by searching for all web farms which use the server, Get-WebFarmsByAppServer. After that, it’s just a matter of calling a mass update function, Set-WebFarmsAppServerEnabled.

<#
.SYNOPSIS
 Retrieves a list of all Web Farms which contain the given list of App Servers on the given Proxy Server.

 This is used to retrieve the list of Web Farms which will need to up updated in order to remove a single
 server from all Web Farms at once.

 The resulting list will be of type [System.Collections.Generic.List[PSObject]]. The 
 inner PSObject's will have these properties:

 WebFarmName The name of the web farm which has the given App Server in its list
 AppServerName The search will look for both shorthand names (App1) and FQDN's (App1.your.domain.here), this
   will have the value which was matched
 Enabled  Is the server currently enabled.

.PARAMETER ServerName
 The name of the proxy server to update. If this parameter is not supplied, the local computers config
 file will be updated.

.PARAMETER AppServerNames
 The name of the App Servers to search for.

.EXAMPLE
 Get-WebFarmsByAppServer -ServerName "Proxy1" -AppServerNames "App1"
#>
Function Get-WebFarmsByAppServer {
Param (
 [string] $ServerName = $env:COMPUTERNAME,
 [Parameter(Mandatory = $true)]
 [System.Array] $AppServerNames
)
 $configPath = Get-WebConfigPath $ServerName
 $appHost = [System.Xml.XmlDocument](Read-WebConfig -ConfigPath $configPath)

 $farms = $appHost.configuration.webFarms.webfarm;

 # if there are no web farms defined, write a warning and return an empty array
 if($farms -eq $null) {
  Write-Warning "IIS Proxy $ServerName - No web farms are currently defined."
  return @();
 }

 # determine search values, check if an fqdn might also be possible value to search on
 $searchValues = New-Object System.Collections.Generic.List[string]
 $AppServerNames |% { $searchValues.Add($_); }

 <# You could add a check for Fully Qualified Domain Names along with the supplied values
 $AppServerNames |% {
  $isFqdn = $_ -match "\.your\.domain\.here"
  if($isFqdn -eq $false) {
   $fqdn = $_ + ".your.domain.here"
   try {
    $result = [System.Net.Dns]::GetHostAddresses($fqdn);

    $searchValues.Add($fqdn);
   } catch {}
  }
 }
 #>

 # search for all occurrences in the web farm list
 $found = New-Object System.Collections.Generic.List[PSObject]
 for($i = 0; $i -lt $farms.Count; $i++) {
  $farm = $farms[$i];

  $servers = New-Object System.Collections.Generic.List[System.Xml.XmlElement]
  $serverlist = $farm.server;
  $serverlist |% { $servers.Add($_); }

  for($j = 0; $j -lt $servers.Count; $j++) {
   $server = $servers[$j];

   $searchValues |% {
    if($server.address.ToLower() -eq $_.ToLower()) {
     # http://stackoverflow.com/questions/59819/how-do-i-create-a-custom-type-in-powershell-for-my-scripts-to-use
     $m = new-object PSObject
     $m.PSObject.TypeNames.Insert(0,'WebAdministrationExt.WebFarmAppServerMatch')

     $m | add-member -type NoteProperty -Name WebFarmName -Value $farm.Name
     $m | add-member -type NoteProperty -Name AppServerName -Value $server.Address
     $m | add-member -type NoteProperty -Name Enabled -Value $server.Enabled
     
     $found.Add($m);
    }
   }
  }
 }

 # return the list
 return $found;
}


<#
.SYNOPSIS
 Set the given list of AppServers to be enabled/disabled in all Web Farms on the Proxy Server.

 TODO: This could probably be updated to handle pipeline input

.PARAMETER ServerName
 The name of the proxy server to update. If this parameter is not supplied, the local computers config
 file will be updated.

.PARAMETER AppServerNames
 The name of the App Servers to set to enabled/disabled.

.PARAMETER Enabled
 Set the server to enabled or disabled.

.EXAMPLE
 $updatedFarms = Set-WebFarmsAppServerEnabled -ServerName "Proxy1" -AppServerNames "App1" -Enabled $false
#>
Function Set-WebFarmsAppServerEnabled {
[CmdletBinding()]
Param (
 [string] $ServerName = $env:COMPUTERNAME,
 [Parameter(Mandatory = $true)]
 [System.Array] $AppServerNames,
 [Parameter(Mandatory = $true)]
 [bool] $Enabled
)

 $farms = Get-WebFarmsByAppServer -ServerName $ServerName -AppServerNames $AppServerNames

 # if no farms we're found, then skip this
 if($farms -eq $null) {
  Write-Warning "IIS Proxy $ServerName - No web farms we're found which use $AppServerNames. Skipping setting the App Servers to $Enabled."
  return;
 }

 # set the servers to the desired values
 for($i = 0; $i -lt $farms.Count; $i++) {
  $farm = $farms[$i];

  # NOTE: SkipLoadBalancingDelay is set to true because it incurs a 10 second delay for each update. That could
  # be a long time for large updates. The LoadBalancingDelay was introduced to handle web deployments, this
  # function is expected to be used with Windows Server updates (Windows Servers updates will have a delay built into them).
  Set-WebFarmServerEnabled -ServerName $ServerName `
   -WebFarmName $farm.WebFarmName -AppServerName $farm.AppServerName -Enabled $Enabled `
   -SkipLoadBalancingDelay $true
 }

 return $farms;
}

0 comments:

Post a Comment


Creative Commons License
This site uses Alex Gorbatchev's SyntaxHighlighter, and hosted by herdingcode.com's Jon Galloway.