F5 - Enable, Disable, or Force Offline Member with optional wait for connections to drop
Octopus.Script exported 09/21/2016 by spuder belongs to 'F5' category.
F5 - Enable, Disable, or Force Offline Member with optional wait for connections to drop
Parameters
When steps based on the template are included in a project's deployment process, the parameters below can be set.
Wait on Connections?
If checked, the deployment won't continue until current connections on the node = 0
Max. Wait Time (seconds)
Defaults to 5 minutes
LTM Status
State member will be put into (Enabled, Disabled, Offline)
Disabled continues to process persistent and active connections. It can accept new connections only if the connections belong to an existing persistence session.
Offline allows existing connections to time out, but no new connections are allowed.
LTM Pool name
Name of F5 pool
LTM Member IP
IP Address of F5 pool member. Default will auto discover the ip address of Tentacle.
LTM Member port
LTM Host name
LTM username
Credential used to access F5 Soap API
LTM password
Credential used to access F5 Soap API
Kill connections when <=
The default is to wait until there are no connections left on the node. If you don't want to wait for zero connections before deploying, you can put a value here and when that number of connections is reached the deployment will happen killing the rest of the connected sessions.
Script body
#Load the F5 powershell iControl snapin
#https://help.octopus.com/t/the-windows-powershell-snap-in-webadministration-is-not-installed-on-this-computer/4290
Add-PSSnapin iControlSnapin;
function WaitFor-ConnectionCount()
{
param(
$pool_name,
$member,
[int]$MaxWaitTime = 300, #defaults to 5 minutes
$ConnectionCount = 0
)
$vals = $member.Split( (, ':'));
$member_addr = $vals[0];
$member_port = $vals[1];
Write-Host "Waiting for current connections to drop to "$OctopusParameters['ConnectionCount']
$MemberDef = New-Object -TypeName iControl.CommonIPPortDefinition;
$MemberDef.address = $member_addr;
$MemberDef.port = $member_port;
$MemberDefAofA = New-Object -TypeName "iControl.CommonIPPortDefinition[][]" 1,1
$MemberDefAofA[0][0] = $MemberDef;
$cur_connections = 100;
$elapsed = [System.Diagnostics.Stopwatch]::StartNew();
while ( $cur_connections -gt $ConnectionCount -and $elapsed.ElapsedMilliseconds -lt ($MaxWaitTime * 1000))
{
$MemberStatisticsA = (Get-F5.iControl).LocalLBPoolMember.get_statistics( (, $pool_name), $MemberDefAofA);
$MemberStatisticEntry = $MemberStatisticsA[0].statistics[0];
$Statistics = $MemberStatisticEntry.statistics;
foreach ($Statistic in $Statistics)
{
$type = $Statistic.type;
$value = $Statistic.value;
if ( $type -eq "STATISTIC_SERVER_SIDE_CURRENT_CONNECTIONS" )
{
# just use the low value. Odds are there aren't over 2^32 current connections.
# If your site is this big, you'll have to convert this to a 64 bit number.
$cur_connections = $value.low;
Write-Host "Current Connections: $cur_connections"
}
}
Start-Sleep -s 5
}
}
$Pool = $OctopusParameters['PoolName'].trim();
If ([string]::IsNullOrWhiteSpace($OctopusParameters['MemberIP'])) {
Write-Host "No IP Adress was provided on the 'LTM Member IP`, using [System.Net.Dns]::GetHostAddresses to resolve it"
$ip = $([System.Net.Dns]::GetHostAddresses("$($OctopusParameters['Octopus.Machine.Hostname'])") | Where {$_.AddressFamily -ne 'InterNetworkV6'}).IpAddressToString
if ($ip -is [array]) {
Write-Host "Found multiple ipv4 addresses, using first address $($ip[0])"
$ip = $ip[0]
}
} Else {
$ip = $OctopusParameters['MemberIP']
}
$Member = $ip+":"+$OctopusParameters['MemberPort']
Write-Host "Member is $Member"
# Gets the hostname of the current machine being deployed.
$curhost = hostname
Write-host "Currently deploying to $curhost"
If (($OctopusParameters['EnableOrDisable'] -ne "Enabled") -and ($OctopusParameters['WaitForConnections'] -eq "True"))
{
Initialize-F5.iControl -HostName $OctopusParameters['HostName'] -Username $OctopusParameters['Username'] -Password $OctopusParameters['Password']
Write-Host "Setting $curhost to $($OctopusParameters['EnableOrDisable']) in $Pool pool";
Set-F5.LTMPoolMemberState -Pool $Pool -Member $Member -state $OctopusParameters['EnableOrDisable'];
Write-Host "Waiting for connections to drain before deploying. This could take a while...."
WaitFor-ConnectionCount -pool_name $Pool -member $Member -MaxWaitTime $OctopusParameters['MaxWaitTime'] -ConnectionCount $OctopusParameters['ConnectionCount']
if ($OctopusParameters['EnableOrDisable'] -eq "Disabled")
{
Write-Host "Setting $curhost to Offline in $Pool pool";
# We've now waited the desired amount, go ahead and force offline and move on with deployment
Set-F5.LTMPoolMemberState -Pool $Pool -Member $Member -state Offline;
}
}
Else
{
Initialize-F5.iControl -HostName $OctopusParameters['HostName'] -Username $OctopusParameters['Username'] -Password $OctopusParameters['Password']
Write-host "Setting $curhost to $($OctopusParameters['EnableOrDisable']) in $Pool pool."
Set-F5.LTMPoolMemberState -Pool $Pool -Member $Member -state $OctopusParameters['EnableOrDisable'];
}
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
Show JSON{
"Id": "6775501d-cafb-493e-ba67-ec95c9500562",
"Name": "F5 - Enable, Disable, or Force Offline Member with optional wait for connections to drop",
"Description": "F5 - Enable, Disable, or Force Offline Member with optional wait for connections to drop",
"Version": 36,
"ExportedAt": "2016-09-21T17:50:00.631+00:00",
"ActionType": "Octopus.Script",
"Author": "spuder",
"Parameters": [
{
"Id": "c27ab1f7-5303-48fe-a8e5-80aa638a054f",
"Name": "WaitForConnections",
"Label": "Wait on Connections?",
"HelpText": "If checked, the deployment won't continue until current connections on the node = 0",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "becfb740-d954-4250-9818-4c561f210ec5",
"Name": "MaxWaitTime",
"Label": "Max. Wait Time (seconds)",
"HelpText": "Defaults to 5 minutes",
"DefaultValue": "300",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "9a0e97c0-d972-4707-b477-c1903090f508",
"Name": "EnableOrDisable",
"Label": "LTM Status",
"HelpText": "State member will be put into (Enabled, Disabled, Offline) \n\n- **Disabled** continues to process persistent and active connections. It can accept new connections only if the connections belong to an existing persistence session. \n\n- **Offline** allows existing connections to time out, but no new connections are allowed.",
"DefaultValue": "Disabled",
"DisplaySettings": {
"Octopus.ControlType": "Select",
"Octopus.SelectOptions": "Enabled|Enable\nDisabled|Disable\nOffline|Forced Offline"
}
},
{
"Id": "7e1b8bc0-b950-4394-9e92-3a00ce3fce3a",
"Name": "PoolName",
"Label": "LTM Pool name",
"HelpText": "Name of F5 pool",
"DefaultValue": "pl_DummyDeployWeb",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "adf16144-16be-437a-ac81-199ca1de1e0e",
"Name": "MemberIP",
"Label": "LTM Member IP",
"HelpText": "IP Address of F5 pool member. Default will auto discover the ip address of Tentacle.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "a37006fa-b34e-4f17-b16a-e7e82981b002",
"Name": "MemberPort",
"Label": "LTM Member port",
"HelpText": "",
"DefaultValue": "80",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "df633633-bf98-45d3-86cf-335b97902dca",
"Name": "HostName",
"Label": "LTM Host name",
"HelpText": null,
"DefaultValue": "192.168.45.204",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "3d43e5a4-4527-4b7c-bf88-319818f0d498",
"Name": "Username",
"Label": "LTM username",
"HelpText": "Credential used to access F5 Soap API",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "a3349f60-5cdf-4ab4-9213-a74843149643",
"Name": "Password",
"Label": "LTM password",
"HelpText": "Credential used to access F5 Soap API",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "0ea7a048-0aa3-4387-a4cc-11e6cd8df6cb",
"Name": "ConnectionCount",
"Label": "Kill connections when <=",
"HelpText": "The default is to wait until there are no connections left on the node. If you don't want to wait for zero connections before deploying, you can put a value here and when that number of connections is reached the deployment will happen killing the rest of the connected sessions.",
"DefaultValue": "0",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptBody": "#Load the F5 powershell iControl snapin\n#https://help.octopus.com/t/the-windows-powershell-snap-in-webadministration-is-not-installed-on-this-computer/4290\nAdd-PSSnapin iControlSnapin;\n\nfunction WaitFor-ConnectionCount() \n{ \n param(\n $pool_name, \n $member,\n [int]$MaxWaitTime = 300, #defaults to 5 minutes\n $ConnectionCount = 0\n )\n $vals = $member.Split( (, ':'));\n $member_addr = $vals[0];\n $member_port = $vals[1];\n\n Write-Host \"Waiting for current connections to drop to \"$OctopusParameters['ConnectionCount']\n\n $MemberDef = New-Object -TypeName iControl.CommonIPPortDefinition;\n $MemberDef.address = $member_addr;\n $MemberDef.port = $member_port;\n $MemberDefAofA = New-Object -TypeName \"iControl.CommonIPPortDefinition[][]\" 1,1\n $MemberDefAofA[0][0] = $MemberDef;\n $cur_connections = 100;\n $elapsed = [System.Diagnostics.Stopwatch]::StartNew();\n\n while ( $cur_connections -gt $ConnectionCount -and $elapsed.ElapsedMilliseconds -lt ($MaxWaitTime * 1000))\n {\n $MemberStatisticsA = (Get-F5.iControl).LocalLBPoolMember.get_statistics( (, $pool_name), $MemberDefAofA);\n $MemberStatisticEntry = $MemberStatisticsA[0].statistics[0];\n $Statistics = $MemberStatisticEntry.statistics;\n foreach ($Statistic in $Statistics)\n {\n $type = $Statistic.type;\n $value = $Statistic.value;\n if ( $type -eq \"STATISTIC_SERVER_SIDE_CURRENT_CONNECTIONS\" )\n {\n # just use the low value. Odds are there aren't over 2^32 current connections.\n # If your site is this big, you'll have to convert this to a 64 bit number.\n $cur_connections = $value.low; \n Write-Host \"Current Connections: $cur_connections\"\n }\n }\n Start-Sleep -s 5\n }\n}\n\n$Pool = $OctopusParameters['PoolName'].trim();\n\nIf ([string]::IsNullOrWhiteSpace($OctopusParameters['MemberIP'])) {\n Write-Host \"No IP Adress was provided on the 'LTM Member IP`, using [System.Net.Dns]::GetHostAddresses to resolve it\"\n $ip = $([System.Net.Dns]::GetHostAddresses(\"$($OctopusParameters['Octopus.Machine.Hostname'])\") | Where {$_.AddressFamily -ne 'InterNetworkV6'}).IpAddressToString\n if ($ip -is [array]) {\n Write-Host \"Found multiple ipv4 addresses, using first address $($ip[0])\"\n $ip = $ip[0]\n }\n} Else {\n $ip = $OctopusParameters['MemberIP']\n}\n\n$Member = $ip+\":\"+$OctopusParameters['MemberPort']\nWrite-Host \"Member is $Member\"\n\n# Gets the hostname of the current machine being deployed.\n$curhost = hostname\n\nWrite-host \"Currently deploying to $curhost\"\n\nIf (($OctopusParameters['EnableOrDisable'] -ne \"Enabled\") -and ($OctopusParameters['WaitForConnections'] -eq \"True\"))\n{\n Initialize-F5.iControl -HostName $OctopusParameters['HostName'] -Username $OctopusParameters['Username'] -Password $OctopusParameters['Password']\n Write-Host \"Setting $curhost to $($OctopusParameters['EnableOrDisable']) in $Pool pool\";\n Set-F5.LTMPoolMemberState -Pool $Pool -Member $Member -state $OctopusParameters['EnableOrDisable'];\n Write-Host \"Waiting for connections to drain before deploying. This could take a while....\"\n WaitFor-ConnectionCount -pool_name $Pool -member $Member -MaxWaitTime $OctopusParameters['MaxWaitTime'] -ConnectionCount $OctopusParameters['ConnectionCount']\n if ($OctopusParameters['EnableOrDisable'] -eq \"Disabled\") \n {\n Write-Host \"Setting $curhost to Offline in $Pool pool\";\n # We've now waited the desired amount, go ahead and force offline and move on with deployment\n Set-F5.LTMPoolMemberState -Pool $Pool -Member $Member -state Offline;\n }\n}\nElse\n{\n Initialize-F5.iControl -HostName $OctopusParameters['HostName'] -Username $OctopusParameters['Username'] -Password $OctopusParameters['Password']\n Write-host \"Setting $curhost to $($OctopusParameters['EnableOrDisable']) in $Pool pool.\"\n Set-F5.LTMPoolMemberState -Pool $Pool -Member $Member -state $OctopusParameters['EnableOrDisable'];\n}\n",
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.RunOnServer": "false",
"Octopus.Action.Script.ScriptFileName": null,
"Octopus.Action.Package.FeedId": null,
"Octopus.Action.Package.PackageId": null
},
"Category": "F5",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates/f5-enable-disable-member.json",
"Website": "/step-templates/6775501d-cafb-493e-ba67-ec95c9500562",
"Logo": "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",
"$Meta": {
"Type": "ActionTemplate"
}
}Provided under the Apache License version 2.0.