Forum Discussion
And here is the script that I have made:
- the handler calls it and passes parameters to it: pool name for IPv4, pool name for IPv6 (or 0 if none), percentage of members that have to be up
- the script goes through a pool and counts the members, then sees how many are online / total
-
script then goes through all the virtual addresses and stores in an array those that are mapped to the specified pools
-
if the available members/total < percentage, then loop through the array of VIPs stored previously and if the BGP advertisement is not already disabled, then disable it (this avoids doing the same operation twice but is not necessarily saving significant CPU power or anything; I was just obsessed to do it)
The optimization possibilities are of course present but this should serve as a nice template for someone wanting to develop on this.
modify script qlPool_min_members.v1 {
app-service none
definition {
set total 0
set total_v6 0
set usable 0
set usable_v6 0
set i 0
set i_v6 0
set err_pn 1
set err_dst 1
set err_adv 1
populate pool and percent variables with the arguments passed to the script
foreach var { pni pni_v6 percent } {
set $var $EVENT::context($var)
}
fetch number of available members in each of the two pools and store also the VIPs for each pool in an array
foreach obj [tmsh::get_status /ltm pool $pni detail] {
puts $obj
foreach member [tmsh::get_field_value $obj members] {
puts $member
incr total
if { [tmsh::get_field_value $member status.availability-state] == "available" && \
[tmsh::get_field_value $member status.enabled-state] == "enabled" } {
incr usable
}
}
}
if { $pni_v6 != 0 } {
foreach obj [tmsh::get_status /ltm pool $pni_v6 detail] {
puts $obj
foreach member [tmsh::get_field_value $obj members] {
puts $member
incr total_v6
if { [tmsh::get_field_value $member status.availability-state] == "available" && \
[tmsh::get_field_value $member status.enabled-state] == "enabled" } {
incr usable_v6
}
}
}
}
store the VIPs for a pool in an array v4/v6
foreach obj [tmsh::get_config /ltm virtual] {
puts $obj
set err_pn [tmsh::get_field_value $obj pool pn]
set err_dst [tmsh::get_field_value $obj destination vipport]
puts $err_pn
if { $err_pn == 1 && $err_dst == 1 } {
if { $pn == $pni } {
puts "bla bla $pn $vipport"
set vip($i) [string range $vipport 0 [expr [string last ":" $vipport]-1]]
puts $vip($i)
incr i
} elseif { $pn == $pni_v6 } {
set vip_v6($i_v6) [string range $vipport 0 [expr [string last "." $vipport]-1]]
puts $vip_v6($i_v6)
incr i_v6
}
}
}
see if we obey our up/down criteria for a pool and disable VIP BGP advertisement if not
IPv4
if { {expr $usable.0 / $total} < $percent } {
puts "smaller than $percent"
foreach i [array names vip] {
puts $vip($i)
foreach member [tmsh::get_config /ltm virtual-address $vip($i)] {
puts "member=$member"
set err_adv [tmsh::get_field_value $member route-advertisement adv]
if { $err_adv == 1 } {
puts "inside if"
tmsh::modify ltm virtual-address $vip($i) route-advertisement disabled
tmsh::log "Route advertisement disabled for $vip($i)"
}
}
}
} else {
puts "bigger than $percent"
foreach i [array names vip] {
puts $vip($i)
foreach member [tmsh::get_config /ltm virtual-address $vip($i)] {
puts "member=$member"
set err_adv [tmsh::get_field_value $member route-advertisement adv]
if { $err_adv == 0 } {
puts "inside it is disabled"
tmsh::modify ltm virtual-address $vip($i) route-advertisement enabled
tmsh::log "Route advertisement enabled for $vip($i)"
}
}
}
}
IPv6
if { $pni_v6 != 0 } {
if { {expr $usable_v6.0 / $total_v6} < $percent } {
puts "smaller than $percent"
foreach i_v6 [array names vip_v6] {
puts $vip_v6($i_v6)
foreach member [tmsh::get_config /ltm virtual-address $vip_v6($i_v6)] {
puts "member=$member"
set err_adv [tmsh::get_field_value $member route-advertisement adv]
if { $err_adv == 1 } {
puts "inside if and pool members are not up to the percentage value"
tmsh::modify ltm virtual-address $vip_v6($i_v6) route-advertisement disabled
tmsh::log "Route advertisement disabled for $vip_v6($i_v6)"
}
}
}
} else {
puts "bigger than $percent"
foreach i_v6 [array names vip_v6] {
puts $vip_v6($i_v6)
foreach member [tmsh::get_config /ltm virtual-address $vip_v6($i_v6)] {
puts "member=$member"
set err_adv [tmsh::get_field_value $member route-advertisement adv]
if { $err_adv == 0 } {
puts "inside if and pool members should be up"
tmsh::modify ltm virtual-address $vip_v6($i_v6) route-advertisement enabled
tmsh::log "Route advertisement enabled for $vip_v6($i_v6)"
}
}
}
}
}
}
description none
events none
}
Handler:
create sys icall handler periodic qlPool_min_members script qlPool_min_members.v1 arguments { { name pni value BLA } { name pni_v6 value V6-BLA } { name percent value 0.5 } } interval 60 first-occurrence 2015-04-04:10:00:00
TODO
See if there is a nice way to convert the iCall script into an iAPP for easier administration.
Here I can find no resource on the F5 site...if anyone can help with an example, it would be great:
-
iCall script sample
-
iApp with the same iCall