Ps BIG-IP Interactive Shell

Problem this snippet solves:

This sample is the beginning of a full console-based management environment for your BIG-IP. Written in PowerShell, you are able to treat your BIG-IP just like your file system and navigate through, and act on, the objects in the system.

Revision History

1.0.0 - First revision. Includes initial code for gtm.wideip, ltm.pool/poolmember/virtualserver, networking.vlan, and system.systeminfo.

How to use this snippet:

Setup And Running The Script

  1. Save the iControlsh.ps1 file to a directory on your system.
  2. Save the various modules to the following directory structure.
    installdir\iControlsh.ps1
    installdir\modules\gtm\wideip.ps1
    installdir\modules\ltm\pool.ps1
    installdir\modules\ltm\poolmember.ps1
    installdir\modules\ltm\virtualserver.ps1
    installdir\modules\networking\vlan.ps1
    installdir\modules\system\systeminfops1
  3. Run the script

    installdir> .\iControlsh.ps1
  4. Connect to your BIG-IP

    PLEASE CONNECT> : c bigip user pass 
    bigip> : 
  5. Navigate through the objects and issue some commands. At any level, type "h" for help.

Files

iControlsh.ps1

Code :

#----------------------------------------------------------------------------
# The contents of this file are subject to the "END USER LICENSE AGREEMENT 
# FOR F5 Software Development Kit for iControl"; you may not use this file 
# except in compliance with the License. The License is included in the 
# iControl Software Development Kit.
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is iControl Code and related documentation
# distributed by F5.
#
# The Initial Developer of the Original Code is F5 Networks,
# Inc. Seattle, WA, USA. Portions created by F5 are Copyright (C) 1996-2010 
# F5 Networks, Inc. All Rights Reserved.  iControl (TM) is a registered 
# trademark of F5 Networks, Inc.
#
# Alternatively, the contents of this file may be used under the terms
# of the GNU General Public License (the "GPL"), in which case the
# provisions of GPL are applicable instead of those above.  If you wish
# to allow use of your version of this file only under the terms of the
# GPL and not to allow others to use your version of this file under the
# License, indicate your decision by deleting the provisions above and
# replace them with the notice and other provisions required by the GPL.
# If you do not delete the provisions above, a recipient may use your
# version of this file under either the License or the GPL.
#----------------------------------------------------------------------------
param([switch]$Debug = $false);

# Global Script variables
$script:VERSION = "1.0.0";
$script:ICONTROLSH = $true;
$script:DEBUG = $Debug;

$script:BIGIP = "";
$script:Username = "";
$script:Password = "";

$script:Connected = $false;

# Current path
$script:HOSTNAME = "";
$script:CURPATH = "PLEASE CONNECT";

# Path Hashtable
$script:PATHS = @{};

#----------------------------------------------------------------------------
function Debug-Message()
#----------------------------------------------------------------------------
{
  param($msg);
  
  if ( $script:DEBUG )
  {
    Write-Host "[DEBUG] $msg";
  }
}

#-------------------------------------------------------------------------
function Initialize-Connection()
#-------------------------------------------------------------------------
{
  param($line = $null);
  
  if ( $line )
  {
    $tokens = $line.Split(" ");
    Load-Configuration;
    if ($tokens.length -eq 4 )
    {
      $script:BIGIP = $tokens[1];
      $script:Username = $tokens[2];
      $script:Password = $tokens[3];
    }

if ( ($script:BIGIP.Length -gt 0) -and
     ($script:Username.Length -gt 0) -and
     ($script:Password.Length -gt 0) )
{
    if ( (Get-PSSnapin | Where-Object { $_.Name -eq "iControlSnapIn"}) -eq $null )
    {
      Add-PSSnapIn iControlSnapIn
    }
    $script:Connected = Initialize-F5.iControl `
        -HostName $script:BIGIP -Username $script:Username -Password $script:Password;
        
    if ( $script:Connected )
    {
      $sysInfo = (Get-F5.iControl).SystemSystemInfo.get_system_information();
      $script:CURPATH = $sysInfo.host_name;
      $script:HOSTNAME = $sysInfo.host_name;
    }
}
  }
}

#----------------------------------------------------------------------------
function Exit-Console()
#----------------------------------------------------------------------------
{
  if ( $script:Connected )
  {
    Save-Configuration;
  }
  exit;
}


#----------------------------------------------------------------------------
function Validate-RegistryKey()
#----------------------------------------------------------------------------
{
  param($Name = $null);
  $keyroot = "HKCU:\Software";
  
  if ( $Null -ne $name )
  {
    $key = Get-Item "${keyroot}\$Name" -ErrorAction silentlyContinue;
    if ( $null -eq $key ) { New-Item -Path "${keyroot}\$Name"; }
  }
}

#----------------------------------------------------------------------------
function Load-Configuration()
#----------------------------------------------------------------------------
{
  $hive = Get-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" `
    -Name "BIGIP" -ErrorAction SilentlyContinue;
  
  if ( $null -ne $hive ) { $script:BIGIP = $hive.BIGIP; }
  $hive = Get-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" `
    -Name "Username" -ErrorAction SilentlyContinue;
  
  if ( $null -ne $hive ) { $script:Username = $hive.Username; }
  $hive = Get-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" `
  -Name "Password" -ErrorAction SilentlyContinue;
  
  if ( $null -ne $hive ) { $script:Password = $hive.Password; }
}

#----------------------------------------------------------------------------
function Save-Configuration()
#----------------------------------------------------------------------------
{
  Validate-Registrykey "F5 Networks";
  Validate-RegistryKey "F5 Networks\iControlsh";
  if ( $script:BIGIP.Length -gt 0 )
  {
    Set-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" `
      -Name "BIGIP" -Value $script:BIGIP;
  }
  if ( $script:Username.Length -gt 0 )
  {
    Set-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" `
      -Name "Username" -Value $script:Username;
  }
  if ( $script:Password.Length -gt 0 )
  {
    Set-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" `
      -Name "Password" -Value $script:Password;
  }
}


#----------------------------------------------------------------------------
function Get-CurrentPath()
#----------------------------------------------------------------------------
{
  return $script:CURPATH;
}

#----------------------------------------------------------------------------
function Set-CurrentPath()
#----------------------------------------------------------------------------
{
  param($path);
  $script:CURPATH = $path;
}

#----------------------------------------------------------------------------
function Add-ScriptPath()
#----------------------------------------------------------------------------
{
  param($key, $value);
  
  Debug-Message "< $($MyInvocation.MyCommand.Name) >";
  Debug-Message "Key = '$key'; Value = '$value'";
  
  $v = $script:PATHS[$key];
  if ( $null -eq $v )
  {
    Debug-Message "null -eq '$v'"
    $script:PATHS.Add($key, $value);
  }
  else
  {
    Debug-Message "null -ne $v"
    $v2 = "$v,$value";
    Debug-Message "Adding $key = '$v2'";
    $script:PATHS[$key] = $v2;
    $v3 = $script:PATHS[$key];

    Debug-Message "$key = '$v3'";
  }
}

#----------------------------------------------------------------------------
function Show-Help()
#----------------------------------------------------------------------------
{
  param([switch]$Full, $Topic = $null);

  $indent = " "*10;

if ( $Topic -and ($Topic.Length -gt 0) )
{
  $key = (Get-CurrentPath).Replace($script:HOSTNAME, "icsh");
$key += "/" + $Topic;

    Get-Help -Full $key;
}
else
{

  if ( $Full )
  {
  Write-Host @"
$indent  ================================================================
$indent               iControl Interactive Console Help
$indent  ================================================================

$indent  Global Commands
$indent  ---------------
$indent  c   - connect to LTM with args "bigip user pass"
$indent  h   - print this help message.
$indent  i   - show connection information.
$indent  q   - exit the console.
$indent  r   - reload the modules.
"@
  if ( $script:Connected )
  {
  Write-Host @"
$indent  ..  - Move up one level.
$indent  cmd - level specific command and arguments
"@
  }
}


if ( $script:Connected )
{
    
Write-Host @"

$indent  Child Objects
$indent  ----------------
"@

  $entry = (Get-HashEntry $script:PATHS)
  if ( $null -ne $entry )
  {
    $children = $entry.Split(',');
    foreach($child in $children)
    {
      Write-Host "$indent  $child";
    }
  }

Write-Host @"

$indent  Commands In this object
$indent  -----------------------
"@
  $validCmds = Get-ValidCommands;
      foreach($cmd in $validCmds)
      {
        Write-Host "$indent  $cmd";
      }
}
}
}

#----------------------------------------------------------------------------
function Show-Information()
#----------------------------------------------------------------------------
{
  Debug-Message "< $($MyInvocation.MyCommand.Name) >";
  
  Write-Host @"
Shell Version   : $($script:VERSION)
Connected State : $($script:Connected)
BIGIP           : $($script:BIGIP)
Username        : $($script:Username)
Password        : $($script:Password)
Debug           : $($script:DEBUG)
"@
}

#----------------------------------------------------------------------------
function Move-Up()
#----------------------------------------------------------------------------
{
  Debug-Message "< $($MyInvocation.MyCommand.Name) >";
  #$tokens = (Get-CurrentPath).Split(":");
  $tokens = (Get-CurrentPath).Split("/");
  if ($tokens.Length -gt 1)
  {
    $newpath = "";
    for($i=0; $i -lt $tokens.Length-1; $i++)
    {
      #if ( $i -gt 0 ) { $newpath += ":"; }
      if ( $i -gt 0 ) { $newpath += "/"; }
      $newpath += $tokens[$i];
    }
    if ( $newpath.Length -gt 0 )
    {
      Set-CurrentPath $newpath;
    }
  }
}

#----------------------------------------------------------------------------
function Move-Down()
#----------------------------------------------------------------------------
{
  param($subdir);
  Debug-Message "< $($MyInvocation.MyCommand.Name) >";

  $newpath = Get-CurrentPath;
  #$newpath += ":";
  $newpath += "/";
  $newpath += $subdir;
  Set-CurrentPath $newpath;
  
  #Show-Help;
}

#----------------------------------------------------------------------------
function Get-HashEntry()
#----------------------------------------------------------------------------
{
  param($hash, $key=(Get-CurrentPath));
  $key = $key.Replace($script:HOSTNAME, "icsh");
  Debug-Message "< $($MyInvocation.MyCommand.Name) '$key' >";
  return $hash[$key];
}

#----------------------------------------------------------------------------
function Find-HashEntry()
#----------------------------------------------------------------------------
{
  param($cmd, $hash);
  Debug-Message "< $($MyInvocation.MyCommand.Name) '$cmd' >";
  $valid = $false;
  $entry = (Get-HashEntry $hash)
  if ( $null -ne $entry )
  {
    $children = $entry.Split(',');
    foreach($child in $children)
    {
      if ( $child -eq $cmd )
      {
        $valid = $true;
        break;
      }
    }
  }
  return $valid;
}

#----------------------------------------------------------------------------
function Is-SubDirectory()
#----------------------------------------------------------------------------
{
  param($cmd);
  Debug-Message "< $($MyInvocation.MyCommand.Name) >";
  return Find-HashEntry $cmd $script:PATHS;
}

#----------------------------------------------------------------------------
function Get-ValidCommands()
#----------------------------------------------------------------------------
{
  Debug-Message "< $($MyInvocation.MyCommand.Name) >";

  $path = (Get-CurrentPath)
  $cmdPrefix = $path.Replace("$($script:HOSTNAME)", "icsh") + "/";
  
  Debug-Message "Getting valid commands from CmdPrefix: '$cmdPrefix'";
  
  $validCmds = Get-Command -CommandType Function "${cmdPrefix}*" |
    Foreach-Object -Process { $_.Name.Replace($cmdPrefix, "") }
    
  $validCmds;
}

#----------------------------------------------------------------------------
function Is-ValidCommand()
#----------------------------------------------------------------------------
{
  param($cmd);

  Debug-Message "< $($MyInvocation.MyCommand.Name) '$cmd' >";

  $bValid = $false;
  
  $validCmds = Get-ValidCommands;

  $tokens = $cmd.Split(" ");
  
  Debug-Message "Valid Commands";
  Debug-Message $validCmds;
  foreach($validCmd in $validCmds)
  {
    if ( $validCmd -eq $tokens[0] )
    {
      Debug-Message "Command '$($tokens[0])' matched '$validCmd'";
      $bValid = $true;
      break;
    }
  }
  return $bValid;
}

#----------------------------------------------------------------------------
function Gen-FunctionName()
#----------------------------------------------------------------------------
{
  param($cmd);
  Debug-Message "< $($MyInvocation.MyCommand.Name) >";
  if ( $cmd )
  {
    $path = Get-CurrentPath;
    $function = "icsh/";
    #$tokens = $path.Split(":");
    $tokens = $path.Split("/");
    for($i=1; $i -lt $tokens.length; $i++)
    {
      if ( $i -gt 1 ) { $function += "/"; }
      $function += $tokens[$i];
    }
    if ( $function -ne "icsh/" ) { $function += "/"; }
    $function += $cmd;
  }
  
  Debug-Message "Returning function '$function'";
  return $function;
}

#----------------------------------------------------------------------------
function Process-Command()
#----------------------------------------------------------------------------
{
  param($cmd);
  Debug-Message "< $($MyInvocation.MyCommand.Name) >";
  $tokens = $cmd.Split(" ");
  $command = $tokens[0];
  $args = "";
  for($i=1; $i-lt$tokens.Length; $i++)
  {
    if ( $i -gt 1 ) { $args += " "; }
    $args += $tokens[$i];
  }
  $key = $(Get-CurrentPath) + "/" + $command;
  $code = Gen-FunctionName $command;
  
  Debug-Message "Processing command: '$code' '$args'";
  if ( $args.Length -gt 0 ) { $code += " -Opts '$args'"; }
  Debug-Message "Invoking code <$code>";
  Invoke-Expression $code;
}

#----------------------------------------------------------------------------
function Get-CommandName()
#----------------------------------------------------------------------------
{
param($line);
$cmd = $line.Trim();
$idx = $cmd.IndexOf(' ');
if ( -1 -ne $idx )
{
$cmd = $cmd.SubString(0, $idx).Trim();
}
return $cmd;
}

#----------------------------------------------------------------------------
Function Get-Arguments()
#----------------------------------------------------------------------------
{
param($line);
$args = "";
$idx = $line.Trim().IndexOf(' ');
if ( -1 -ne $idx )
{
$args = $line.SubString($idx+1).Trim();
}
return $args;
}

#-------------------------------------------------------------------------
function Convert-To64Bit()
#-------------------------------------------------------------------------
{
  param($high, $low);
  return ($high*[Math]::Pow(2,32))+$low;
}


#----------------------------------------------------------------------------
# Main script logic
#----------------------------------------------------------------------------
$curdir = $MyInvocation.MyCommand.Path.Replace($MyInvocation.MyCommand.Name, "");

$LoadModStr = @"
`$script:PATHS.Clear();

# Iterate through all the modules
`$modules = Get-ChildItem `$curdir\Modules\* |
  Where-Object { `$_.GetType().Name -eq "DirectoryInfo" }
  
foreach(`$module in `$modules)
{
  `$mod = `$module.BaseName.ToLower();
  Add-ScriptPath "icsh" `$mod;
  
  # iterate through the interfaces
  `$files = Get-ChildItem `$curdir\Modules\`$mod\* |
    Where-Object { `$_.GetType().Name -eq "FileInfo" }
    
  foreach(`$file in `$files)
  {
    Add-ScriptPath "icsh/`$mod" `$file.BaseName.ToLower();
    
    Debug-Message "Invoking content for script `$(`$file.FullName)";
    . `$file.FullName;
  }
}
"@;
Invoke-Expression $LoadModStr;

while(1)
{
  $prompt = "$(Get-CurrentPath)> ";
  $i = (Read-Host $prompt).Trim();
  
  Debug-Message "< $($MyInvocation.MyCommand.Name) '$i' >";
  if ( $i.Length -gt 0 )
  {
    Debug-Message "CommandLine: '$i'...";
    switch -Wildcard ($i.ToLower())
    {
      ""   { break; }
      "c*" { Initialize-Connection $i; }
      "h*" { Show-Help -Full -Topic (Get-Arguments $i); }
      "i"  { Show-Information; }
      "q"  { Exit-Console; }
      "r"  { Invoke-Expression $LoadModStr; }
      "d"  { $script:DEBUG = -not $script:DEBUG; }
      "!*" {
        $cmd = $i.Replace("!", "").Trim();
        Debug-Message "Executing command $cmd";
        Invoke-Expression $cmd;
      }
      ".." { Move-Up; }
      default {
        if ( $script:Connected )
        {
          if ( Is-SubDirectory $i )     { Move-Down $i; }
          elseif ( Is-ValidCommand $i ) { Process-Command $i; }
          else                          { Show-Help; }
        }
        else
        {
          Show-Help;
        }
      }
    }
  }
}
Published Mar 09, 2015
Version 1.0