A question came across the forums a while ago around how to get a human readable version of the configuration on the BIG-IP LTM from the iControl APIs.  This question comes up in one form or another every so often so I figured it would be good to write it down with some sample code. 

Introduction

In the forum post, the user wanted an equivalent to the system level "bigpipe list" command from the iControl APIs.  Under the seems, the "bigpipe list" command is just an alias for echoing out the contents of the bigip.conf configuration file so really this question boils down to how to download the contents of a file on the system and echo it to the console.  In the System.ConfigSync interface, the download_file method will do just that.  This example will show how to use the download_file method to download a system configuration file to the local disk and then echo the contents of that file to the console.

Usage

The arguments for this application are the address, username, and password of the BIG-IP.  This is declared in the top of the script with the following param statement.  There is also a Write-Usage function to display the arguments to the user.

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

$DEFAULT_CHUNK_SIZE = (64*1024);

Set-PSDebug -strict;

function Write-Usage()
{
  Write-Host "Usage: BigpipeList.ps1 host uid pwd [config:bigip.conf|bigip_base.conf]";
  exit;
}

Initialization

As is with all of my PowerShell scripts, the initialization component will look to see if the iControlSnapIn is loaded into the current PowerShell session.  If not, the Add-PSSnapIn Cmdlet is called to add the snapin into the runtime.  Then a call to the Initialize-F5.iControl cmdlet to setup the connection to the BIG-IP.  If configuration succeeds, then the local Download-Configuration function will be called with the specified configuration file (or bigip.conf if one is not).

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

#-------------------------------------------------------------------------
# Main Application Logic
#-------------------------------------------------------------------------
if ( ($g_bigip -eq $null) -or ($g_uid -eq $null) -or ($g_pwd -eq $null) )
{
  Write-Usage;
}

if ( $g_config -eq $null ) { $g_config = "bigip.conf" }

if ( Do-Initialize )
{
  Download-Configuration $g_config;
  Get-Content $g_config;
}
else
{
  Write-Error "ERROR: iControl subsystem not initialized"
}

Downloading a File

The local Download-Configuration function will take as a parameter a configuration file name.  It then creates some variables for the local file to be downloaded in the current directory and the remote file which resides in the "/config" directory on the BIG-IP.  After that, the real fun begins.  We start with creating a System.ConfigSync.FileTransferContext object to house the download context and file data.  A download chunk size of 64k is used and a local BinaryWriter is created for the local file.  The file is actually ascii, but the BinaryWriter will work for both ascii and binary files in case you want to extend this to download other non-ascii files.

Then a loop is entered with consecutive calls to the System.ConfigSync.download_file method.  After the method call, the chunked contents are appended to the local file and the loop is repeated until we get a chain type of FILE_LAST OR FILE_FIRST_AND_LAST indicating an end of file occurred.  When the loop is existed, the file system objects are closed and control is returned to the calling code.  In that code (seen above), the Get-Content PowerShell Cmdlet is called with the local file and the contents of that file are presented to the console.

function Download-Configuration()
{
  param($config_name);
  
  #Write-Host "Downloading Configuration file $config_name"
  
  $loc = Get-Location
  $local_file = "$loc\$config_name";
  
  $remote_file = "/config/$config_name";
  
  $ctx = New-Object -TypeName iControl.SystemConfigSyncFileTransferContext;
  $chunk_size = $DEFAULT_CHUNK_SIZE;
  $file_offset = 0;
  $bContinue = 1;
  $mode = [System.IO.FileMode]::CreateNew;
  if ( Test-Path $local_file )
  {
    $mode = [System.IO.FileMode]::Truncate;
  }
  
  $fs = New-Object -TypeName System.IO.FileStream -argumentList ($local_file, $mode);
  $w = New-Object -TypeName System.IO.BinaryWriter -argumentList ($fs);
  
  while($bContinue -eq 1)
  {
    $ctx = (Get-F5.iControl).SystemConfigSync.download_file($remote_file, $chunk_size, [ref]$file_offset);
    $w.Write($ctx.file_data, 0, $ctx.file_data.Length);

    #Write-Host "Bytes Transferred: $file_offset";
    if ( ($ctx.chain_type -eq "FILE_LAST") -or ($ctx.chain_type -eq "FILE_FIRST_AND_LAST") )
    {
      $bContinue = 0;
    }
  }
  $w.Close()
  $fs.Close()
}

Conclusion

The download_file method in the System.ConfigSync interface can be used in some interesting ways and this tech tip illustrates how it can be used to emulate one of the system level bigpipe commands.

 

Get the Flash Player to see this player.