Forum Discussion

GavinW_29074's avatar
GavinW_29074
Icon for Nimbostratus rankNimbostratus
Apr 10, 2012

Name-Based Virtual Host iApp...

Hi there,

I'm trying to create an iApp template which will support Name Based virtual hosting as found in Apache...

I've created an iRule to handle the pool selection logic, which will look-up the Hostname against a computed Data-group name and return the relevant pool.

Will attach a copy of the iRule for reference.

I'm now trying to create an iApp template that will handle the creation of the required application components. I can safely handle the creation of the VS & empty Data-group, however I'm struggling with the pool creation and Data-group population logic.

Currently I've got a table in the iApp presentation layer as follows:

      table vhosts {
        string hostname required
        string desc
        string addr required validator "IpAddress"
        string port default "8080" required validator "PortNumber" display "small"
        optional ( lb_method_choice == "ratio-member" ||
          lb_method_choice == "ratio-node" ||
          lb_method_choice == "ratio-session" ||
          lb_method_choice == "ratio-least-connections-memeber" ||
          lb_method_choice == "ratio-least-connections-node" ||
          lb_method_choice == "dynamic-ratio-member" ||
          lb_method_choice == "dynamic-ratio-node" ) {
            string ratio default "1" validator "NonNegativeNumber" display "small"
        }
      } 

This table allows the entry of:

HTTP Hostname

Back-end server hostname

Back-end server IP Address

Back-end server Port

Back-end connection ratio.

What I want to do is parse the above table and use it to do the following:

Create a pool for each unique hostname, which could contain 1 or more back-end servers.

Populate a Data-group with the http hostname and corresponding pool name.

Any thoughts/pointers welcome.

Regards

Gavin

  • Michael_Earnhar's avatar
    Michael_Earnhar
    Historic F5 Account
    Hello Gavin,

    For processing tables - make sure you check out https://devcentral.f5.com/wiki/iApp.Working-with-Tables.ashx. It provides a nice succinct method for iterating over an entire table. Another method that i've used before is called import_table which makes the table into a two dimensional array. As for creating pool and data-groups those should be tmsh::create/modify commands and should work very similar to how they do in TMSH.

        tmsh::include "f5.ntr_utils_devcentral"
        array set ips [tmsh::run_proc f5.ntr_utils_devcentral:import_table { $::basic__ips ary }]
        set baseName ip_match_profile__$tmsh::app_name
        set pBuffer ""
        set nBuffer ""
        for {set i 0} {$i < [llength ${::basic__ips}]} {incr i} {
            if {$ips(invert__$i) == "Yes"} {
                lappend nBuffer "$ips(network__$i)/$ips(netmask__$i) \{ data $baseName \}"
            } else {
                lappend pBuffer "$ips(network__$i)/$ips(netmask__$i) \{ data $baseName \}"
            }   
        }   
        if { $pBuffer != "" } { 
            tmsh::create ltm data-group internal ${baseName}-p type ip records add \{ [join $pBuffer] \}
        } else {
            tmsh::create ltm data-group internal ${baseName}-p type ip
        }   
        if { $nBuffer != "" } { 
            tmsh::create ltm data-group internal ${baseName}-n type ip records add \{ [join $nBuffer] \}
        } else {
            tmsh::create ltm data-group internal ${baseName}-n type ip
        }
     

    proc import_table { table_local type } {
        set row_count 0
        array set row_result {}
        array set col_result {}
        array set rowcol_result {}
        foreach row ${table_local} {
            set element_count 0
            set names ""
            foreach element [split $row "\n"] {
                if { ($element_count > 0) && ($element_count < [expr [llength [split $row "\n"]] - 1])} {
                    if { [llength $element] > 1 } {
                        set value "[lindex $element 1]"
                        set column "[lindex $element 0]"
                        lappend ary_result "${column}__${row_count}" 
                        lappend ary_result "${value}" 
                        lappend comma_result "${column},${row_count}" 
                        lappend comma_result "${value}" 
                        lappend row_result($row_count) ${value}
                        lappend col_result($column) ${value}
                        lappend rowcol_result($row_count) "[list $column ${value}]"
                        lappend names $column
                    }
                }
                incr element_count
            }
            incr row_count
        }
        switch $type {
            row 
                {
                    foreach row [array names row_result] {
                        lappend result $row
                        lappend result $row_result($row)
                    }
                    set final_result ${result}
                }
            col
                {
                    foreach col [array names col_result] {
                        lappend result $col
                        lappend result $col_result($col)
                    }
                    set final_result ${result}
                }
            names
                {
                    set final_result ${name}s
                }
            rowcol
                {
                    foreach row [array names rowcol_result] {
                        lappend result $row
                        lappend result $rowcol_result($row)
                    }
                    set final_result ${result}
                }
            comma
                {
                    set final_result $comma_result
                }
            ary
                {
                    set final_result $ary_result
                }
            default
                {
                    set final_result $ary_result
                }
        }
        return ${final_result}
    }