A script to quickly configure a host for redundancy

May 22, 2017 / 0 comments / in General  / by CygNet Blog Admin

In preparation for WESC, I had to configure four identical CygNet hosts for redundancy.  Doing the same thing four times didn’t sound like a lot of fun so I decided to write a powershell script!  This is in no way supported or official, but it might help some of you out whenever you find yourself needing to spin up a new CygNet server or configure an existing one for redundancy.  If starting from scratch, you will need to install CygNet via the setup program to get the baseline, and then this script will configure the server to be redundant.  Specifically it will create multiple ARS/RSM service pairs that are properly configured.  For those of you not doing redundancy, you can tweak it to mass modify your config files with specific values or add nonstandard services to your site.

I make no guarantee these techniques will work in perpetuity, but I can say they were at least tested with the 8.5.1 release and I can think of no reason why they wouldn’t work with the previous few releases.  Hopefully it’s helpful, but I make no promises.  If you have any questions or find a problem, feel free to comment and I’ll try to respond.

#Assumptions

#  1) Directory contains a single ARS and RSM service directory

#  2) RSM service is currently configured to own the single ARS

 

#Steps

#  0) If on a host already running CygNet, skip to step #5

#  1) Disable UAC. (Can by done by running this powershell command):

#         Set-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -Value 0 -Force;

#  2) Install CygNet

#  3) Start site

#  4) Once Host Manager shows a "RUNNING" status, stop the site

#  5) Remove installed site from Host Manager

#  6) Edit the variables in this script.

#  7) Run script

#  8) Add all the created RSM services to Host Manager

#  9) Start sites

 

 

#Configurable variables

$ServicesDir = "c:\cygnet\services"

$SiteName = "CYGNET"  #This must match the site name you used in the setup program

$RedundantRSM = "RSM_CLP" #Service name of redundant RSM

$SvcPortBase = 6090 #Base SVC_PORT value to use for new non-redundant RSM services

$AssociatedAUD = "[5410]BASTION.AUD"

$AssociatedELS = "[5410]BASTION.ELS"

$NonRedundantPairs = @(

                       (new-object psobject -Property @{rsm="RSMLP1";ars="ARSLP1";arslicensemaster=$false})

                       (new-object psobject -Property @{rsm="RSMLP2";ars="ARSLP2";arslicensemaster=$false})

                       (new-object psobject -Property @{rsm="RSMLP3";ars="ARSLP3";arslicensemaster=$false;domain=5413})

                      ) #Always include service name for non-redundant rsm/ars pairs (Whether there are two or three).  Include 'domain' property only for pair running on ambient domain of this host.  There should always be only one

 

 

###############

## FUNCTIONS

###############

 

##### Example:

#$tokens = @((new-object psobject -Property @{keyword="REPL_SOURCE";value="[5410]CYGNET.ACS";disabled=$false}))

#UpdateConfigFile c:\cygnet\services\acs.cfg $tokens

function UpdateConfigFile([string]$file, $tokens)

{

    (Get-ChildItem $file) |

        Foreach-Object {

            (Get-Content $_.FullName) |

                Foreach-Object {

           

                    $line = $_

                    $tokens | % {

                        if ($line -like ($_.keyword + "*") -or $line -like ("#" + $_.keyword + "*"))

                        {

                            if ($line -match ("(?<flag>[#]?)" + $_.keyword + "(?<spaces>\s*)(?<value>.*)"))

                            {

                                $value = $matches["value"]

                                if ($_.psobject.Properties.Name -contains "value" -eq $true)

                                {

                                    $value = $_.value

                                }

                                elseif ($_.psobject.Properties.Name -contains "find" -eq $true -and $_.psobject.Properties.Name -contains "replace" -eq $true)

                                {

                                    $value = $matches["value"] -replace $_.find, $_.replace

                                }

 

                                if ($_.psobject.Properties.Name -contains "disabled" -eq $false)

                                {

                                    $line = $matches["flag"] + $_.keyword +  $matches["spaces"] + $value

                                }

                                elseif ($_.disabled -eq $true)

                                {

                                    $line = "#" + $_.keyword +  $matches["spaces"] + $value

                                }

                                else

                                {

                                    $line = $_.keyword +  $matches["spaces"] + $value

                                }

                            }

                        }

                    }

 

                   $line  #Push the line back through the pipe

 

               } | Set-Content $_.FullName

         }

}

 

##### Example:

#$tokens = [System.Collections.ArrayList]@()

#$tokens.Add("ACS.EXE#ACSD.exe")

#FindAndReplace "C:\test.txt" $tokens

function FindAndReplace([string]$file, [System.Collections.ArrayList]$tokens)

{

    (Get-ChildItem $file) |

        Foreach-Object {

            (Get-Content $_.FullName) |

                Foreach-Object {

           

                   foreach ($element in $Tokens)

                   {

                        if ($element -ne "")

                        {

                           $tmp = $element.split("#")

                           $_ = ($_ -replace $tmp[0], $tmp[1])

                        }

                   }

                   $_  #Push the line back through the pipe

 

               } | Set-Content $_.FullName

         }

}

 

###############

## SCRIPT

###############

 

cd $ServicesDir

 

#Verify input

if ((Get-ChildItem | ? {$_.Name -match "RSM" -or $_.Name -match "ARS"}).Count -ne 2)

{

    Write-output "Directory appears malformed"

    exit;

}

 

#Generate non-redundant RSM/ARS pairs

$NonRedundantPairs | % { Copy-Item RSM $_.rsm -recurse; Copy-Item ARS $_.ars -recurse }

remove-item "ARS" -recurse

 

### Update ARS config files

$NonRedundantPairs | % {

        $tokens = @(

                    (new-object psobject -Property @{keyword="BACKUP_PATH";find="\\ARS";replace="\$($_.ars)"})

                    (new-object psobject -Property @{keyword="SERVICE";value="$SiteName.$($_.ars)"})

                    (new-object psobject -Property @{keyword="LICENSE_MASTER";value=(@{$true="YES";$false="NO"}[$_.arslicensemaster]);disabled=$false})

                    (new-object psobject -Property @{keyword="REDUNDANT";disabled=$true})

                    (new-object psobject -Property @{keyword="AUD";disabled=$false;value=$AssociatedAUD})

                    (new-object psobject -Property @{keyword="ELS";disabled=$false;value=$AssociatedELS})

                    )

        UpdateConfigFile "$($_.ars)\Ars.cfg" $tokens

}

 

### Update ARS ServiceDefs files

$NonRedundantPairs | % {

    $ServiceDefsFile = Get-ChildItem $_.ars | ? { $_.Name -like "ServiceDefs.*.db" }

    if ($ServiceDefsFile.Count -eq 0)

    {

        Write-output "Failed to add services to " $_.ars

    }

    else

    {

        $data = (Get-content $ServiceDefsFile[0].FullName -encoding byte)

        $ServiceDefsFile | Remove-item

 

        if ($_.psobject.Properties.Name -contains "domain" -eq $true)

        {

            $path = "$ServicesDir\$($_.ars)\ServiceDefs.$($_.domain).db"

            new-item $path | out-null

            $br = New-Object System.IO.BinaryWriter([System.IO.File]::Open($path, [System.IO.FileMode]::Create))

            $br.Write([uint16]47940)

            $br.Write([int16]$_.domain)

            $br.Write($data, 4, ($data.length-4))

            $br.flush()

            $br.close()

        }

    }

}

 

### Update non-redundant RSM config files

$SvcPortIndex = 0

$NonRedundantPairs | % {

        $tokens = @(

                    (new-object psobject -Property @{keyword="BACKUP_PATH";find="\\RSM";replace="\$($_.rsm)"})

                    (new-object psobject -Property @{keyword="SERVICE";value="$SiteName.$($_.rsm)"})

                    (new-object psobject -Property @{keyword="SVC_PORT";value=$SvcPortBase + $SvcPortIndex++})

                    (new-object psobject -Property @{keyword="RSM_NAME";value=$_.rsm})

                    (new-object psobject -Property @{keyword="REDUNDANT";disabled=$true})

                    (new-object psobject -Property @{keyword="AUD";disabled=$false;value=$AssociatedAUD})

                    (new-object psobject -Property @{keyword="ELS";disabled=$false;value=$AssociatedELS})

                    )

        UpdateConfigFile "$($_.rsm)\Rsm.cfg" $tokens }

 

### Update non-redundant RSM service defs

$NonRedundantPairs | % {

    $rsmName = $_.rsm

    $arsName = $_.ars

    $xml = New-Object -TypeName XML

    $xml.Load("$ServicesDir\$rsmName\SvcDef.rsx")

    $xml.rsmdata.servicedefs.SelectNodes("//servicedef") | ? { $_.service -notmatch "ARS" } | % {$_.ParentNode.RemoveChild($_) | out-null }

    $xml.rsmdata.servicedefs.SelectNodes("//servicedef") | ? { $_.service -match "ARS" } | % {

            $_.service = $_.service -replace "ARS", $arsName;

            $_.exedir = $_.exedir -replace "ARS", $arsName;

            $_.datadir = $_.datadir -replace "ARS", $arsName }

    $xml.Save("$ServicesDir\$rsmName\SvcDef.rsx")

}

 

### Rename redundant RSM

Rename-Item RSM $RedundantRSM

 

### Update redundant RSM config file

$tokens = @(

            (new-object psobject -Property @{keyword="BACKUP_PATH";find="\\RSM";replace="\$RedundantRSM"})

            (new-object psobject -Property @{keyword="SERVICE";value="$SiteName.$RedundantRSM"})

            (new-object psobject -Property @{keyword="RSM_NAME";value=$RedundantRSM})

            (new-object psobject -Property @{keyword="REDUNDANT";value="TRUE";disabled=$false})

            (new-object psobject -Property @{keyword="AUD";disabled=$false;value=$AssociatedAUD})

            (new-object psobject -Property @{keyword="ELS";disabled=$false;value=$AssociatedELS})

            )

UpdateConfigFile "$RedundantRSM\Rsm.cfg" $tokens

 

### Update redundant RSM service defs

$xml = New-Object -TypeName XML

$xml.Load("$ServicesDir\$RedundantRSM\SvcDef.rsx")

$xml.rsmdata.servicedefs.SelectNodes("//servicedef") | ? { $_.service -match "ARS" } | % {$_.ParentNode.RemoveChild($_) | out-null }

$xml.Save("$ServicesDir\$RedundantRSM\SvcDef.rsx")

 

### Enable redundancy for remaining services

Get-ChildItem | ? { ($NonRedundantPairs | % { $_.rsm}) -notcontains $_.Name -and ($NonRedundantPairs | % { $_.ars}) -notcontains $_.Name } | Get-ChildItem -recurse | ? { $_.Name -like "*.cfg" } | % {

    $tokens = @(

                (new-object psobject -Property @{keyword="REDUNDANT";value="TRUE";disabled=$false})

                )

    UpdateConfigFile $_.FullName $tokens }

 

### Update site name for all config files (If using default of XXX)

$tokens = [System.Collections.ArrayList]@()

$tokens.Add("XXX#$SiteName")

get-childitem -recurse |? {$_.Extension -eq ".cfg"} | % { FindAndReplace $_.FullName $tokens }

 

 

Write-output "Done"

Share this entry
Share by Mail



Comments

Blog post currently doesn't have any comments.
{{com.name}}           {{com.blogCommentDateFormatted}}

Leave Comment

Please correct the following error(s):

  • {{ error }}

Subscribe to this blog post

Enter your email address to subscribe to this post and receive notifications of new comments by email.


Search the CygNet Blog

Subscribe to the CygNet Blog

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Tags