Forum Discussion

jpolivy_46872's avatar
jpolivy_46872
Icon for Nimbostratus rankNimbostratus
Oct 04, 2010

LTM Network Map on a Virtual Server

The only attempt at this I have seen is the Pool_Member_Status iRule. That one does not cover my needs, mainly what Node is up behind a particular Virtual Server, just like the LTM Network Map.

 

 

I would like anyone to be able to view a Network Map like interface without having to actually log into the device.

 

 

I spent some time beating on the original Pool_Member_Status and came up with this:

 

 

Rehash from the Pool_Member_Status deployment guide with necessary modifications:

 

 

1. Create a file in the following path on the LTM

 

 

/etc/cron.daily/virtual_status_list.cron

 

 

which contains:

 

 

!/bin/bash

 

b db bigpipe.displayservicenames false

 

bp virtual | egrep -e "POOL|VIRTUAL" | awk '{print "\""$1":"$2":"$3":"$4":"$5":"$6":\","}' > /var/class/virtual_status.class

 

b load

 

exit 0

 

 

2. Change the permissions by entering:

 

 

chmod +755 /etc/cron.daily/virtual_status_list.cron

 

(Run the job before attempting to execute the iRule)

 

/etc/cron.daily/virtual_status_list.cron

 

 

3. Create a external datagroup

 

 

Main >> Local Traffic >> iRules

 

Select Data Group List

 

Click create

 

enter name: virtual_status

 

enter Type: External

 

Path / Filename: /var/class/virtual_status.class

 

File Content: String

 

 

4. Code is attached along with screen shots of sample output

 

 

Apply to a Virtual Server and hit the URL with "/status"

 

 

Any help cleaning this up would be greatly appreciated. Could probably be about half the size.

 

 

 

Right click save as and change the extension of the VIRTUAL_STATUS file to .txt to view code.
  • That looks fairly streamlined as it is. I saved the clock seconds output to a variable to avoid running it twice. I also added curly braces to the expr calls to avoid double substitution.

     

     

    
    when HTTP_REQUEST {
       if { [HTTP::uri] eq "/status" } {
    
          set time [clock format [clock seconds]]
          set response "F5 Load Balancer Status - \
          $timeF5 Load Balancer Status - [HTTP::host]
    \
          $time"
    
          set count 0 
          foreach line $::virtual_status {
             incr count 1
             set virtual_list($count) $line
          }
          append response " 
      http://www.tcl.tk/man/tcl8.4/TclCmd/expr.htm 
      
     PERFORMANCE CONSIDERATIONS 
     Enclose expressions in braces for the best speed and the smallest storage requirements. This allows the Tcl bytecode compiler to generate the best code. 
      
     As mentioned above, expressions are substituted twice: once by the Tcl parser and once by the expr command. For example, the commands 
      
     set a 3 
     set b {$a + 2} 
     expr $b*4 
      
     return 11, not a multiple of 4. This is because the Tcl parser will first substitute $a + 2 for the variable b, then the expr command will evaluate the expression $a + 2*4. 
      
     Most expressions do not require a second round of substitutions. Either they are enclosed in braces or, if not, their variable and command substitutions yield numbers or strings that don't themselves require substitutions. However, because a few unbraced expressions need two rounds of substitutions, the bytecode compiler must emit additional instructions to handle this situation. The most expensive code is required for unbraced expressions that contain command substitutions. These expressions must be implemented by generating new code each time the expression is executed.  
     "
          for {set x $count} {$x>0} {incr x -1} {
             if {$virtual_list($x) contains "VIRTUAL:ADDRESS"} {
                if {$x>2}  {
                   if {$virtual_list([expr {$x - 2}]) contains "POOL"} {
                      scan $virtual_list($x) {%[^:]:%[^:]:%[^:]:%s} trash1 trash2 v_address trash3
                      scan $virtual_list([expr {$x - 1}]) {%[^:]:%[^:]:%[^:]:%[^:]:%[^:]:%s} trash1 trash2 v_name trash3 v_port trash4
                      scan $virtual_list([expr {$x - 2}]) {%[^:]:%[^:]:%[^:]:%s} trash1 trash2 p_name trash3
                      if {$v_port contains "any"} {set v_port "ANY"} 
                      append response "ADDRESS$v_address$v_port"
                      append response "VIRTUAL SERVER  $v_name"
                      append response "POOL$p_name"
                      append response "NODEPORTSTATUS"
                      for {set y $x} {$y>3}  {incr y -1} {
                         if {$virtual_list([expr {$y - 3}]) contains "MEMBER"} {
                            scan $virtual_list([expr {$y - 3}]) {%[^:]:%[^:]:%[^:]:%[^/]/%[^:]:%[^:]} trash1 trash2 trash3 poolname addr port
                            switch -glob [LB::status pool $poolname member $addr $port] {
                               "up" {
                                  append response "$addr$port\
                                        UP"
                               }
                               "down" { 
                                  append response "$addr$port\
                                        DOWN"
                               }
                               "session_enabled" { 
                                  append response "$addr$port\
                                        ENABLED"
                               }
                               "session_disabled" { 
                                  append response "$addr$port\
                                        DISABLED"
                               }
                               default {
                                  append response "$addr$port\
                                        INVALID"
                               }
                            }
                            SWITCH END
                         }
                         else {
                            set y 0
                         }
                      }
                      append response ""   
                   }
                   else {
                      scan $virtual_list($x) {%[^:]:%[^:]:%[^:]:%s} trash1 trash2 v_address trash3
                      scan $virtual_list([expr {$x - 1}]) {%[^:]:%[^:]:%[^:]:%[^:]:%[^:]:%s} trash1 trash2 v_name trash3 v_port trash4
                      if {$v_port contains "any"} {set v_port "ANY"} 
                      append response "ADDRESS$v_address$v_port"
                      append response "VIRTUAL SERVER  $v_name"
                      append response "POOLN/A"
                      append response ""
                   }
                }
             }
          }
          append response ""  
          HTTP::respond 200 content $response "Content-Type" "text/html" "Cache-Control" "no-cache, must-revalidate" "Expires" "Mon, 26 Jul 1997 05:00:00 GMT"
       }        
    }
            Aaron