Forum Discussion

kwondra34_26054's avatar
kwondra34_26054
Icon for Nimbostratus rankNimbostratus
Jun 23, 2016

F5 iControl REST - API calls required to get Load Balancer, Virtual Server URL, IP, Port, Pool Name/Status/Members

Hi everyone,

I am attempting to use the F5 REST API to create a csv containing the following fields (potentally others if they are available, but these will suffice):

- Virtual Server (URL/Name) or Pool Name (or both)
- Virtual Server Port
- VIP IP Address
- Pool Status (available, offline, unknown)
- Pool Members (comma separated)
- Associated Load Balancer (where a given VIP/URL lives)

I am using the Ruby F5 gem for the REST interface and it works nicely, however

bigip["ltm/pool"].get
(the data returned by tm/ltm/pool) is giving me JSON that is missing the VIP IP Address and it is treating all pool members as separate hashes.

In short, I am trying to use one or multiple API calls to gather data that looks like this:

F5 LTM Host   Virtual Server (URL)  VIP (IP Addr)  Port   Pool Name               Pool Status    Pool Members
bigip.domain  vip-name.domain-1234  10.10.255.254  1234   vip-name.domain-1234    available      10.10.10.1:555; 10.10.10.2:556

Also, I was hoping to find out what portion of the API has data linking VIP URL to an IP address?

Any help is greatly appreciated!

Thanks in advance!

8 Replies

  • Tried to edit question in two browser, but it "saves" but it doesn't update anything (even after refresh/clear cache). In any case, just wanted to add an additional note. tm/ltm/pool doesn't store IP address which is one of the key elements I need. Additionally, I tried to re-order my original list to match my desired output, but since I cannot edit the question, I wanted to provide the list of desired fields (in proper order) here: - F5 Load Balancer (where a given VIP/URL lives) - Virtual Server (URL/Name) - VIP IP Address - Virtual Server Port - Pool Name - Pool Status (available, offline, unknown) - Pool Members (comma separated) Thanks in advance!
  • JG's avatar
    JG
    Icon for Cumulonimbus rankCumulonimbus

    I suppose there aren't many people using ruby here. I am not a ruby person - I can't even find an F5 icontrol lib for ruby (v1) that I can download and run a test with.

     

    However, from what I can read from the F5 iControlREST api doc, the way of getting what you want will involve two API calls:

     

    1.

     

    Run what I guess might be a valid ruby command "bigip["ltm/virtual"].get" with the URI param "expandSubcollections=true", which will provide the name of the pool associated with each virtual server;

     

    2.

     

    You then run "bigip["/ltm/pool"].get" on each pool name from the list gotten from the step above and you will see the particulars associated with that pool.

     

    I hope this helps.

     

  • I did something similar using Powershell 4.0. You are also going to need the BIG IP 11.5.3 (I guess at least), I'm using 11.6.1. Maybe my code can shed some light for you... it's a very simple one:

     

        function Get-F5Token(
    [Parameter(Mandatory=$True)] 
    [string]$currentf5
    )
    { 
        $username="admin" 
        $password="admin"
        $url="https://"+$currentf5+"/mgmt/shared/authn/login"
        $payload='{"username":"'+$username+'","password":"'+$password+'","loginProviderName":"tmos"}'
        Convert Username/Password to Base64 and create Header
        $bytesauth  = [System.Text.Encoding]::UTF8.GetBytes($username+":"+$password)
        $authvalue = "Basic "+[System.Convert]::ToBase64String($bytesauth)
        $headers = @{ Authorization = $authvalue }
    
        return ((Invoke-WebRequest  -headers $headers -contenttype "application/json" -Method POST -uri $url -body $payload).content |Convertfrom-Json).token
    }
    
     Allow self-signed certificates
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    $global:Authentication = (Get-F5Token 10.10.66.92)
    $global:tokenheader = @{ "X-F5-Auth-Token" = $Authentication.token }
      Create timer
    $backgroundTimer = New-Object System.Timers.Timer
     Set interval (ms)
    $backgroundTimer.Interval = 5000
    
     Make sure timer stops raising events after each interval
    $backgroundTimer.AutoReset = $true
    
    if((Get-EventSubscriber | where { $_.SourceIdentifier -eq "renewToken" }) -eq $null){
         Have powershell "listen" for the event in the background
        Register-ObjectEvent $backgroundTimer -EventName 'Elapsed' -SourceIdentifier 'renewToken' -Action { 
        $global:Authentication = (Get-F5Token 10.10.66.92)
        $global:tokenheader = @{ "X-F5-Auth-Token" = $global:Authentication.token }
           Restart timer
          $backgroundTimer.Start()
        }
    
    } 
    
     Enable the timer, with that we will get a new token every 5 seconds.
    $backgroundTimer.Enabled = $true
    
    Get information regarding this F5:
    $ltm  = new-object Psobject
    $ltm | Add-Member irule $null
    $ltm | Add-Member pool $null
    $ltm | Add-Member vs $null
    $ltm | add-member policies $null 
    
    $ltm.policies = @(New-Object psobject -Property @{
                vsname = $null;
                policy = $null; 
                })

    Now all the informations regarding VirtualServers, Irules, Pools are going to be in the object called $ltm

     

    • kwondra34_26054's avatar
      kwondra34_26054
      Icon for Nimbostratus rankNimbostratus

      Thank you so much! This helps tremendously. I will review this and give it a shot. I'll mark the answer as correct or at least helpful soon.

       

  • JG's avatar
    JG
    Icon for Cumulonimbus rankCumulonimbus

    Here's my 2c: A quickly-put-together Python script, as seems to be something many of us will need at one time or another. It probably can be made more efficient, but it does the job as it is - very close to what you want; and hey, I'm not a Python fan myself, at least not yet.

    !/usr/bin/python
    
     This script displays some information about all virtual servers and 
     associated server pool and pool members. The output has ';' as the field 
     delimiter.
    
    -------------------------------------------------------------------------
    from f5.bigip import ManagementRoot
    
     This gets rid of the warning message about SSL certificate issues.
    import requests.packages.urllib3
    requests.packages.urllib3.disable_warnings()
    
    mgmt = ManagementRoot("mgmt_IP_address", "admin", 'admin')
    
    vservers = mgmt.tm.ltm.virtuals.get_collection()
    pools = mgmt.tm.ltm.pools.get_collection()
    
    print "Virtual Server Name;Virtual Server Destination;Virtual Server Partition;Pool Name;Pool LB Mode;Pool Member Name (address)(state)"
    
    for vs in vservers:
        s = ''
        s += vs.name + ';'
    
        if hasattr(vs, 'destination'):
            s += vs.destination + ';'
        else:
            s += ';'
    
        vs_partition = vs.partition
        s += vs_partition + ';'
    
        if hasattr(vs, 'pool'):
            pool_name_from_vs = vs.pool
            for pool in pools:
                if ( pool_name_from_vs == pool.fullPath ):
                    s += pool.name + ';'
                    s += pool.loadBalancingMode + ';'
                    if hasattr(pool, 'session'):
                        s += pool.session + ';'
                    if hasattr(pool, 'state'):
                        s += pool.state + ';'
                    for member in pool.members_s.get_collection():
                        s += member.name + '(' + member.address + ')'
                        s += '(' + member.state + '),'
            s = s[:-1]
        else:
            s += ";;"
            print s
            continue
    
        print s
    

    [Edit: Changed pool.name to pool.fullPath.]

  • JG's avatar
    JG
    Icon for Cumulonimbus rankCumulonimbus

    I have put together the following Ruby script for this purpose. There is certainly room for improvement.

    !/usr/local/bin/ruby -w
    
    require 'rubygems'
    require 'rest-client'
    require 'json'
    
     define program-wide variables
    BIGIP_ADDRESS = 'mgmt_IP_addr'
    BIGIP_USER = 'admin'
    BIGIP_PASS = 'admin'
    SLEEP_TIME = 20
    
    bigip = RestClient::Resource.new(
           "https://{BIGIP_ADDRESS}/mgmt/tm/", 
           :user => BIGIP_USER, 
           :password => BIGIP_PASS, 
           :headers => { :content_type => 'application/json' },
           :verify_ssl => false
    )
    
     Get virtual servers:
    
    vservers = bigip['ltm/virtual'].get
    vservers_obj = JSON.parse(vservers)
    
     Get pools:
    
    pools = bigip['ltm/pool?expandSubcollections=true'].get
    pools_obj = JSON.parse(pools)
    
     Output header:
    puts "Virtual Server Name;Virtual Server Destination;Virtual Server Partition;Pool Name;Pool LB Mode;Pool Member Name (address)(state)"
    $output = ''
    
     Process data:
    
    vservers_obj.each do |vserver_obj|
        vserver_obj.each do |vserver_obj_element|
            if vserver_obj_element.is_a?(Array)
                vserver_obj_element.each do |vserver_obj_element_property|
                    if vserver_obj_element_property.is_a?(Hash)
                        if vserver_obj_element_property.has_key?("name")
                            vs_name = vserver_obj_element_property.fetch("name")
                            $output = $output + vs_name + ';'
                        end
                        if vserver_obj_element_property.has_key?("destination")
                            vs_destination = vserver_obj_element_property.fetch("destination")
                            $output = $output + vs_destination + ';'
                        end
                        if vserver_obj_element_property.has_key?("partition")
                            vs_partition = vserver_obj_element_property.fetch("partition")
                            $output = $output + vs_partition + ';'
                        end
                        if vserver_obj_element_property.has_key?("pool")
                            pool_name_from_vs = vserver_obj_element_property.fetch("pool")
                            pools_obj.each_pair do |key, val|
                                next if key == "kind"
                                next if key == "selfLink"
                                for x in 0..(val.length-1)
                                    if val[x]["fullPath"] == pool_name_from_vs
                                        $output = $output + val[x]["name"] + ";" + val[x]["loadBalancingMode"]
                                        if val[x].has_key?("membersReference")
                                            val[x]["membersReference"].each_pair do |mrefkey,mrefval|
                                                next if mrefkey == "link"
                                                next if mrefkey == "isSubcollection"
                                                for i in 0..(mrefval.length-1)
                                                    if i == 0
                                                        $output = $output + ";" + mrefval[i]["name"] + "(" + mrefval[i]["address"] + ")(" + mrefval[i]["state"] + "),"
                                                    else
                                                        $output = $output + mrefval[i]["name"] + "(" + mrefval[i]["address"] + ")(" + mrefval[i]["state"] + "),"
                                                    end
                                                    if i == mrefval.length-1
                                                        $output.chop!
                                                        $output += "\n"
                                                    end
                                                end
                                            end
                                        else
                                            $output = $output + ";;\n"
                                        end
                                        break
                                    end
                                end
                            end
                        else
                            $output = $output + ";;\n"
                        end
                    end
                end
            end
        end
    end
    
    puts $output
    
    ---END---
    
  • @kwondra34 which did you end using, Ruby or Python?...did you try the Python way?

     

    Thanks!