Forum Discussion

Anush's avatar
Anush
Icon for Nimbostratus rankNimbostratus
Jul 17, 2015

pools members status using icontrol

Hi Experts,

 

we are in situation where our clients want to check the pool members status and we are not willing to give them a ready only access of our F5s. I searched little bit and found that it can be done by icontrol but could not find any details. if anyone ran into this situation before can you please share the solution details.

 

Thanks

 

4 Replies

  • This is an interesting subject, and I'd also love to hear other peoples answers. If we're talking real-time checks you might be better off with SNMP.

     

    Reason being that giving people access through iControl basically gives them access to the GUI of the F5, as they have to be able to access it via https to query via iControl. REST is even worse at the moment as it needs full admin access on top of that.

     

    I did see one company use a combination or REST and an XML gateway. They then could filter which REST methods that was allowed through the XML gateway and they could also use the Active directory to grant permissions.

     

    Generally I'd recommend against letting people do polling against the F5s since it really does not take much to bring them down with a simple configuration mistake in ie. "SoapUI". I saw this happen during a demonstration once and it was pretty scary.

     

    With SNMP you could let the chosen monitoring software, ie Zabbix poll the pool members while the clients poll Zabbix via SOAP.

     

    OR you can use a virtual server and let them poll that instead. I wrote this iRule to add status information from Office clients (some of the information actually includes pool member statuses). Maybe you can rewrite it to your liking? Please note that I'm not sure how TMOS gets the pool member statuses and the performance impact in doing so may times. We've had no performance issues at all though.

     

    when CLIENT_ACCEPTED {
    
        set originaluri ""
        set urisenttoserver ""
        set originalhost ""
        set hostsenttoserver ""
        set chosenpool ""
        set memberstatus ""
    
        if { [class match [IP::remote_addr] equals OurOffices] || [IP::addr [IP::remote_addr] equals "192.168.0.0/16"] } {
            set internal 1
        } else {
            set internal 0
        }
    
    }
    
    when HTTP_REQUEST {
        if { $internal eq 1 } {
            set httpreqstarttime [clock clicks -milliseconds]
            set originaluri [HTTP::uri]
            set originalhost [HTTP::host]
        }
    }
    
    when LB_SELECTED {
    
        if { $internal eq 1 } {
            set selectedpool [LB::server pool]
            set selectedserver [LB::server addr]
            set selectedport [LB::server port]
    
            Get the members of the currently selected pool
            set mbrs [members -list $selectedpool]
    
            Get the status for each member
            foreach mbr $mbrs {
                set mbrlist [split $mbr " "]
                set memberip [lindex $mbrlist 0]
                set memberport [lindex $mbrlist 1]
                set status [LB::status pool $selectedpool member $memberip $memberport]
                set memberstatus "$memberstatus$mbr $status;"
            }
        }
    }
    
    when HTTP_REQUEST_RELEASE {
        if { $internal eq 1 } {
            set urisenttoserver [HTTP::uri]
            set hostsenttoserver [HTTP::host]
        }
    }
    
    when HTTP_REQUEST_SEND {
        if { $internal eq 1 } {
            set httpreqsenttime [clock clicks -milliseconds]
        }
    }
    
    when HTTP_RESPONSE {
        if { $internal eq 1 } {
            set timetakenserver [expr {[clock clicks -milliseconds] - $httpreqsenttime}]
            HTTP::header insert X-TimeTaken-Server "$timetakenserver"
            HTTP::header insert X-Original-URI $originaluri
            HTTP::header insert X-URI-Sent-To-Server $urisenttoserver
            HTTP::header insert X-Virtual-Server-Name [virtual name]
    
            if { $selectedpool eq "" } {
                HTTP::header insert X-Selected-Pool "No pool selected"
            } else {
                HTTP::header insert X-Selected-Pool $selectedpool
                HTTP::header insert X-Active-Members [active_members $selectedpool]
            }
    
            if { $selectedserver eq "" } {
                HTTP::header insert X-Selected-Server "No server selected"
            } else {
                HTTP::header insert X-Selected-Server $selectedserver
            }
    
            if { $selectedport eq "" } {
                HTTP::header insert X-Selected-Port "No port selected"
            } else {
                HTTP::header insert X-Selected-Port $selectedport
            }
    
            if { $memberstatus eq "" } {
                HTTP::header insert X-Member-Status "No members"
            } else {
                HTTP::header insert X-Member-Status $memberstatus
            }
    
    
            HTTP::header insert X-Original-Host $originalhost
            HTTP::header insert X-Host-Sent-To-Server $hostsenttoserver
        }
    }
    
    when HTTP_RESPONSE_RELEASE {
        if { $internal eq 1 } {
            set timetakenbigip [expr {[clock clicks -milliseconds] - $httpreqstarttime - $timetakenserver}]
            HTTP::header insert X-TimeTaken-BigIP "$timetakenbigip"
        }
    }
    

    Hope that helps. If you did not ask for real-time information there is already pre-made tools to generate a report of the current configuration in the code share. 🙂

     

    /Patrik

     

  • Anush's avatar
    Anush
    Icon for Nimbostratus rankNimbostratus

    Hi Patrick,

     

    Thank you very much for your response. can you please explain me this irule little bit more? how does it work? what client needs to do on their side to get pool status info?

     

    Thanks

     

  • Hi!

     

    Sorry for the late reply, I've been a bit busy. 🙂

     

    I guess the iRule did a bit more than you asked, and might seem overwhelming at first. I wrote another one, more aligned to the scope of your question.

     

    If you create a data group list and add ie. 192.168.0.0/16 as a network for internal requests and/or your Office external IP you can show the status of any pool with this iRule.

     

    So steps to implement it:

     

    1. Create the data group list called Office_IPs (or rename it according to your liking)
    2. Create iRule (see code below).
    3. Create a virtual server with an HTTP profile
    4. Assign the iRule to the virtual server

    How to use it:

     

    1. Open a browser.
    2. Navigate to the virtual server and add a query string:

    If the pool exists you'll get the answer in XML

     

    
        session_disabled
        up
    
    

    Otherwise you'll get this:

     

    The pool /Partition/Mypool-443_pool does not exist.
    

    Please note that you have to add the partition when using the pool name. If you don't use partitions and store everything in /Common you could always rewrite the rule to use /Common as default and skip the partition part.

     

    The actual iRule:

     

    when CLIENT_ACCEPTED {
    
        Check if the request is internal or not.
        Office IPs are a data group list with the IPs you want to allow.
    
        if { [class match [IP::remote_addr] equals Office_IPs] } {
            set internal 1
        } else {
            set internal 0
        }
    
    }
    
    when HTTP_REQUEST {
    
        if { $internal eq 1 } {
    
            Save the content of the query string into selectedpool
            set selectedpool [URI::query [HTTP::uri] showstatus]
    
            Check if the showstatus query parameter exists or not
            if { $selectedpool ne "" } {
    
                Decode the parameter into readable format
                set selectedpool [URI::decode $selectedpool]
    
                Check if the pool exists, otherwise reply with a message
                if { [catch { set mbrs [members -list $selectedpool] } ] } {
                    The pool did not exist
                    HTTP::respond 200 content "The pool $selectedpool does not exist." Content-Type "text/plain" Connection "Close"
                } else {
    
                    The pool existed
                    Prepare the xml content
                    set xml "\n"
    
                    Get the status for each member of the pool
                    foreach mbr $mbrs {
                        set mbrlist [split $mbr " "]
                        set memberip [lindex $mbrlist 0]
                        set memberport [lindex $mbrlist 1]
                        set status [LB::status pool $selectedpool member $memberip $memberport]
    
                        Append the member information into the file
                        set xml "$xml\t$status\n"
    
                    }
    
                    Add the XML footer
                    set xml "$xml"
    
                    Reply with the data
                    HTTP::respond 200 content $xml Content-Type "text/plain" Connection "Close"
                }
            }
        }
    }