The BIG-IP Management GUI has a feature called the Network Map that includes a hierarchical summary of the objects on the system and their current statuses.  This tech tip follows on to my previous Local Traffic Summary article and will take that GUI component and break it down into the underlying iControl method calls and present an alternative implementation from within Windows PowerShell.

Introduction

The Network Map component of the BIG-IP Management GUI has two components.  This article focuses on the second component which is a Local Traffic Map that lists the a hierarchical tree of Virtual Servers, Pools, Pool Members, and iRules with their respective statuses.  An example of the Network map can be seen below:

 

This application will replicate that tree of objects and show you how to use client side caching techniques to make the application run faster.  I will be using Windows PowerShell with the iControl Cmdlets for PowerShell available from the DevCentral Labs website.  The code listed below can be consolidated into a single script (PsLocalTrafficMap.ps1) to be run directly from the command line.

First, I'm going to define the parameters for the application.  This can be done with the param statement.  We'll be needing the BIG-IP address, username, and password.  I'll also include here the declarations for a couple of global variables we'll be using for caching.

param (
  $g_bigip = $null,
  $g_uid = $null,
  $g_pwd = $null
)

Set-PSDebug -strict;

$g_vs_list = $null;
$g_vs_pool_list = $null;
$g_vs_rule_list = $null;

Initialization

The entry code checks to see if the parameters were passed in correctly.  If not, a usage message will be displayed.  If the parameters were passed in correctly, it will attempt to initialize the iControl SnapIn and authenticate with the BIG-IP and then make a call to the local Print-LocalTrafficMap function.

function Show-Usage()
{
  Write-Host "Usage: LocalTrafficSummary.ps1 host uid pwd";
  exit;
}

function Do-Initialize()
{
  $snapin = Get-PSSnapin | Where-Object { $_.Name -eq "iControlSnapIn" }
  if ( $null -eq $snapin )
  {
    Add-PSSnapIn iControlSnapIn
  }
  $success = Initialize-F5.iControl -HostName $g_bigip -Username $g_uid -Password $g_pwd;
  
  return $success;
}

if ( ($g_bigip -eq $null) -or ($g_uid -eq $null) -or ($g_pwd -eq $null) )
{
  Show-Usage;
}

if ( Do-Initialize )
{
  Print-LocalTrafficMap
}
else
{
  Write-Error "ERROR: iControl subsystem not initialized"
}

Let the fun begin

The Print-LocalTrafficMap is where all the fun happens.  The function queries all the data up front and makes use of client side caching by using the Get-VSList, Get-VSPoolList, and GET-VSRuleList functions that return cached objects to eliminate the need for multiple requests for the same data.

The function then iterates over the virtual server list and generates a status value with the local Get-ObjectStatus function described below.  The Name of the virtual server is written to the console along with the current availability and enabled status and the availability description.

Next, if there was a pool defined for the current virtual server, as indicated by the "i"th index in the pool_list array, the pool and pool member details will be analyzed.

The user friendly pool status is then generated by the Get-ObjectStatus function and the default pool along with it's status are printed to the console.

Next, we use the current pool and look for members within that pool.  If there are members present, as defined by the "i"th element of the MemberStatAofA 2-D array, we iterate over those members and extract the members address and port and generate it's status with the Get-ObjectStatus function.  Then the pool member is written to the console along with it's status string.

Lastly, the iRules are iterated and written to the console for the specific virtual server.  There is no status associated with iRules, so only the name is sent to output.

function Print-LocalTrafficMap()
{
  $vs_list = Get-VSList;
  $pool_list = Get-VSPoolList;
  $vs_statuses = (Get-F5.iControl).LocalLBVirtualServer.get_object_status( $vs_list );
  $pool_statuses = (Get-F5.iControl).LocalLBPool.get_object_status( (Sanitize-Array $pool_list) );
  $MemberStatAofA = (Get-F5.iControl).LocalLBPoolMember.get_object_status( $pool_list );
  $VSRuleAofA = Get-VSRuleList;
  
  Write-Host "***** SITE MAP FOR BIG-IP $g_bigip ******"
  
  
  for($i=0; $i -lt $vs_list.Length; $i++)
  {
    $vs = $vs_list[$i];
    
    $stat_str = Get-ObjectStatus $vs_statuses[$i];
    Write-Host "$vs (VS)";
    Write-Host "|    $stat_str"
    if ( $pool_list[$i].Length -gt 0 )
    {
      $pool = $pool_list[$i];
      $stat_str = Get-ObjectStatus $pool_statuses[$i];
      Write-Host "+-> $pool (P)"
      Write-Host "    | $stat_str"
      
      for($j=0; $j -lt $MemberStatAofA[$i].Length; $j++)
      {
        $MemberStat = $MemberStatAofA[$i][$j];
        $member = $MemberStat.member;
        $addr = $member.address;
        $port = $member.port;
        $stat_str = Get-ObjectStatus $MemberStat.object_status;
        Write-Host "    +-> ${addr}:${port} (PM)"
        Write-Host "        | $stat_str"
      }
    }
    
    if ( $VSRuleAofA[$i].Length -gt 0 )
    {
      for ($j=0; $j -lt $VSRuleAofA[$i].Length; $j++)
      {
        $RuleDef = $VSRuleAofA[$i][$j];
        $rule_name = $RuleDef.rule_name;
        Write-Host "+-> $rule_name (R)"
      }
    }
  }
}

As mentioned above, the Get-ObjectStatus function will take as input a LocalLB.ObjectStatus structure along with the name of the type of object the status is for.  The availability status and enabled_status are then extracted along with the status string.  From the Availability status and Enabled status, user friendly strings are generated and a resulting status string is returned from the function.

function Get-ObjectStatus()
{
  param (
    $object_status
  );

  $avail = $object_status.availability_status;
  $enabled = $object_status.enabled_status;

  $s_avail = "";
  $s_enabled = "";
  $s_desc = $object_status.status_description;
  
  switch($avail)
  {
    "AVAILABILITY_STATUS_GREEN" {
      $s_avail = "Available";
    }
    "AVAILABILITY_STATUS_YELLOW" {
      $s_avail = "Unavailable";
    }
    "AVAILABILITY_STATUS_RED" {
      $s_avail = "Unavailable";
    }
    "AVAILABILITY_STATUS_BLUE" {
      $s_avail = "Unknown";
    }
    "AVAILABILITY_STATUS_GRAY" {
      $s_avail = "Unavailable";
    }
    default {
      $s_avail = "Unknown";
    }
  }
  
  switch($enabled)
  {
    "ENABLED_STATUS_ENABLED" {
      $s_enabled = "Enabled";
    }
    "ENABLED_STATUS_DISABLED" {
      $s_enabled = "Disabled";
    }
    "ENABLED_STATUS_DISABLED_BY_PARENT" {
      $s_enabled = "Disabled";
    }
    default {
    }
  }
  
  return "$s_avail ($s_enabled) $s_desc";
}

Utility Functions

There are a set of helper methods are wrappers around the global cached objects for the virtual server list, virtual server pool list, and virtual server iRule list.  If the values are null, they are queried.  If non-null, the cached values are returned.  The benefit of doing this allows for a reduction in iControl requests to be made for duplication information.

function Get-VSList()
{
  if ( $null -eq $g_vs_list )
  {
    $g_vs_list = (Get-F5.iControl).LocalLBVirtualServer.get_list();
  }
  return $g_vs_list;
}

function Get-VSPoolList()
{
  if ( $null -eq $g_vs_pool_list )
  {
    $g_vs_pool_list = 
      (Get-F5.iControl).LocalLBVirtualServer.get_default_pool_name( (Get-VSList) );
  }
  return $g_vs_pool_list;
}

function Get-VSRuleList()
{
  if ( $null -eq $g_vs_rule_list )
  {
    $g_vs_rule_list = 
      (Get-F5.iControl).LocalLBVirtualServer.get_rule( (Get-VSList) );
  }
  return $g_vs_rule_list;
}

And lastly is the Sanitize-Array method that takes as input a string array and removes elements of zero size.  This is for the case where a default pool list is returned from the list of virtual servers and one or more of the virtual servers does not have a default pool in it's configuration.  If the originally returned list was passed into one of the Pool interfaces methods, it would return an error as an undefined pool.  This method helps by eliminating the empty elements.

function Sanitize-Array()
{
  param (
    [string[]]$in
  );
  
  $out = $null;
  foreach ($item in $in)
  {
    if ( $item.Length -gt 0 )
    {
      if ( $null -eq $out ) { $out = (, $item) }
      else { $out += $item }
    }
  }
  return $out;
}

Running the Script

Running this script with query all the Virtual Server, Pool, Pool Members, and iRules states and report them in a table that is similar to the one in the Management GUI illustrated above.

PS C:\> D:\dev\iControl\CodeShare\iControl\LocalTrafficMap.ps1 bigip_address username password
***** SITE MAP FOR BIG-IP bigip_address ******
xpbert-telnet (VS)
|    Unknown (Enabled) The virtual server is has no availability status
xpbert-http (VS)
|    Available (Enabled) The virtual server is available
+-> xpbert-http (P)
    | Available (Enabled) The pool is available
    +-> 10.10.10.149:80 (PM)
        | Available (Enabled) The pool member is available
xpbert-ssh (VS)
|    Available (Enabled) The virtual server is available
+-> xpbert-ssh (P)
    | Unknown (Enabled) The pool is has no availability status
    +-> 10.10.10.149:22 (PM)
        | Available (Enabled) The pool member is available
xpbert-ftp (VS)
|    Unknown (Enabled) The virtual server is has no availability status
+-> xpbert-ftp (P)
    | Unknown () The pool is not available
    +-> 10.10.10.149:21 (PM)
        | Unknown (Enabled) The pool member is has no availability status
+-> hunt_the_wumpus (R)

The full appilcation can be found in the iControl CodeShare under PsLocalTrafficMap

 

Get the Flash Player to see this player.