The BIG-IP has the ability to partition off different "slots" for multiple software installs. This allows for installing a second version of the software on the system without overwriting the existing configuration to allow for an easy rollback in the case you prefer to roll back to your previous version. The System.SoftwareManagement interface contains the methods to manage the software on the system and hidden in there are the methods for getting and setting the current "boot locations". This article will illustrate the use of those methods.

 Usage

The following code samples will build a PowerShell command line application allowing control over system boot locations.  This program takes as input the bigip, username, and password as well as a subcommand and optional parameters.  Usage is displayed with the Write-Usage function.

param (
  $g_bigip = $null,
  $g_uid = $null,
  $g_pwd = $null,
  $g_cmd = $null,
  $g_arg = $null
);

Set-PSDebug -strict;

function Write-Usage()
{
  Write-Host "Usage: BootImage.ps1 host uid pwd [options]";
  Write-Host "      options";
  Write-Host "      -------";
  Write-Host "      get          - Get the name of the active boot location";
  Write-Host "      set location - Set the active boot location";
  Write-Host "      getinfo      - Get the contents of the active boot location";
  exit;
}

Initialization

As is with all of my iControl PowerShell scripts, validation is made as to whether the iControlSnapin is loaded into the current powershell context.  The Initialize-F5.iControl cmdlet is then called to setup the connection to the BIG-IP for subsequent calls.

The main application logic checks for the passed in command and then passes control to either the Get-BootLocation, Set-BootLocation, or Get-BootImageInfo local functions which I will talk about below.

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;
}

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

if ( Do-Initialize )
{
  switch ($g_cmd.ToLower())
  {
    "getinfo" {
      Get-BootImageInfo;
    }
    "get" {
      Get-BootLocation;
    }
    "set" {
      if ( $g_arg -eq $null )
      {
        Write-Usage;
      }
      else
      {
        Set-BootLocation $g_arg;
      }
    }
    default {
      Write-Usage;
    }
  }
}
else
{
  Write-Error "ERROR: iControl subsystem not initialized"
}

Querying the boot location

The Get-BootLocation local function is just a wrapper for the iControl get_boot_location method.  This method takes as input no parameters and returns the current user friendly name for the current boot location.  This value is displayed to the console.

function Get-BootLocation()
{
  $location = (Get-F5.iControl).SystemSoftwareManagement.get_boot_location();
  Write-Host "Boot Location: $location";
}

Setting the boot location

The Set-BootLocation function passes calls the iControl set_boot_location iControl method with the passed in boot location user friend name.  It then sets the boot location with this value so next time a system reboot occurs, it will load in this location.

function Set-BootLocation()
{
  param($location);
  (Get-F5.iControl).SystemSoftwareManagement.set_boot_location($location);
  Get-BootLocation;
}

Querying all boot image information

There is no iControl method to return just the possible boot locations but we do expose a method that returns all of the boot image information.  Contained in here is the boot locations (or slots) along with a bunch of other fun stuff.  The Get-BootImageInfo function will call this get_boot_image_information() iControl method.  The returned value is the raw configuration file base64 encoded in a byte array.  We take this array and then ASCII encode it with the System.Text.ASCIIEncoding's GetString() method.  This decoded string is then passed to the Parse-BootLocationData function for further processing.

function Get-BootImageInfo()
{
  $rawdata = (Get-F5.iControl).SystemSoftwareManagement.get_boot_image_information($false);
  Write-Host "Boot Information";
  $ASCII = New-Object -TypeName System.Text.ASCIIEncoding
  $formatted = $ASCII.GetString($rawdata)
  
  Parse-BootLocationData $formatted;
}

The Parse-BootLocationData function takes the decoded data and then reads it line by line with a System.IO.StringReader object.  The format of the file is a bunch of name=value pairs grouped into sections delimited with a header line starting and ending with a slash.  This function loops line after line looking for a start of a section.  It then passes the StringReader to the Parse-BootLocationSection function to extract the name=value pairs for that section.

function Parse-BootLocationData()
{
  param($data);
  $sr = New-Object System.IO.StringReader($data);
  $line = $sr.ReadLine();
  while($null -ne $line)
  {
    if ( $line.StartsWith("/") )
    {
      # Beginning of section
      Parse-BootLocationSection $line $sr;
    }
    else
    {
      Write-Host $line;
    }
    $line = $sr.ReadLine();
  }
}

The Parse-BootLocationSection function extracts data from the section header and displays the component to the console.  Sections include Network, Disk, Slot, Hardware, Installation, and License information.  Each subsequent line is extracted until a end of section is reached.  Each of the name=value pairs are split apart and put into a hash that is finally displayed to the console in a nice tabular fashion.

function Parse-BootLocationSection()
{
  param($header, $sr);
  
  $headertxt = $header.Replace("/", '').Trim();
  $tokens = $headertxt.Split( (, ' '));
  $comp = $tokens[0];
  $desc = $headertxt.Replace("$comp ", "");
  
  $hash = @{};
  
  Write-Host "==========================================================="
  Write-Host "Component: $comp"
  Write-Host "     Desc: $desc";
  Write-Host "==========================================================="
  $line = $sr.ReadLine();
  while ($null -ne $line)
  {
    if ( $line.Trim().Length -eq 0 )
    {
      #end of section
      break;
    }
    $tokens = $line.Trim().Split( (, '='));
    $hash.Add($tokens[0], $tokens[1]);
    $line = $sr.ReadLine();
  }
  $hash.GetEnumerator() | Sort-Object -Property Name | Format-Table -autosize;
}

 Usage

The following commands will get and set the current boot location from HD1.1 to HD1.2 and back. 

PS C:\> .\bootimage.ps1 bigip_address username password get
Boot Location: HD1.1
PS C:\> .\bootimage.ps1 bigip_address username password set HD1.2
Boot Location: HD1.2
PS C:\> .\bootimage.ps1 bigip_address username password set HD1.1
Boot Location: HD1.1

 And this example will query the entire boot information, parse the contents and return the results to the console.  There is a lot of information in here with dependencies back and forth but what you'll be looking for is the "visible_name" attribute under the Slots.  This will be the value you can pass into the get and set subcommands.  I'm sure more interesting things can be gleaming from this information but I'll leave that for another tech tip.

PS C:\> .\bootimage.ps1 bigip_address username password getinfo
Boot Information
===========================================================
Component: Network
     Desc: audit_network
===========================================================
Name        Value
----        -----
address     172.27.230.170
gateway     172.27.230.254
hostname    theboss.dev.net
interface   eth0
nameservers 172.27.1.1,172.27.2.1
netmask     255.255.255.0

===========================================================
Component: Network
     Desc: audit_network_persist
===========================================================
Name        Value
----        -----
address     172.27.230.170
gateway     172.27.230.254
interface   eth0
nameservers 172.27.1.1,172.27.2.1
netmask     255.255.255.0

===========================================================
Component: Disk
     Desc: iDisk_0 audit_disks[0]
===========================================================
Name            Value
----            -----
boot_part_index 2
boot_size_kb    5040
boot_stat       0
capacity_mb     509
i1_size_kib     504000
name            hda
serial_num      095VT194S0454DC08070

===========================================================
Component: Disk
     Desc: iDisk_1 audit_disks[1]
===========================================================
Name            Value
----            -----
boot_part_index 2
boot_size_kb    803250
boot_stat       0
capacity_mb     80418
i1_size_kib     31760505
i2_size_kib     31760505
name            hdc
serial_num      PFD202S2UT1RBJ
share_size_kb   16081065
share_stat      0

===========================================================
Component: Slot
     Desc: iSlot_hda.1 audit_slots[0]
===========================================================
Name             Value
----             -----
boot_mem         1024M
boot_quiet       false
disk_description SILICONSYSTEMS
disk_index       0
disk_part        2
integrity_status 0
is_CF            true
slot_key         hda.1
visible_name     CF1.1

===========================================================
Component: Slot
     Desc: iSlot_hdc.1 audit_slots[1]
===========================================================
Name             Value
----             -----
boot_mem         1152M
boot_quiet       true
disk_description HDS728080PLAT20
disk_index       1
disk_part        2
integrity_status 0
is_active        true
slot_key         hdc.1
visible_name     HD1.1

===========================================================
Component: Slot
     Desc: iSlot_hdc.2 audit_slots[2]
===========================================================
Name             Value
----             -----
boot_mem         1152M
boot_quiet       true
disk_description HDS728080PLAT20
disk_index       1
disk_part        3
integrity_status 0
slot_key         hdc.2
visible_name     HD1.2

===========================================================
Component: Hardware
     Desc: audit_hardware
===========================================================
Name                 Value
----                 -----
boot_slot_key        hdc.1
bootdisk_id          hda
nics                 3
platform_family      BUFFALO_JUMP
platform_id          D63
ram_mb               2010
serial_console_speed 19200
sharedisk_id         hdc

===========================================================
Component: Installation
     Desc: iInstallation_0 audit_installations[0]
===========================================================
Name        Value
----        -----
build       119.0
product     BIG-IP
slot_key    hda.1
UTC_delta   -0800
UTC_hwclock true
version     9.2.0

===========================================================
Component: Configuration
     Desc: iConfiguration_0 audit_configurations[0]
===========================================================
Name     Value
----     -----
filename /mnt/tmp/install/slot/hdc.1/var/auto-ucs/config.ucs
mod_date 2008-12-10
mod_time 08:37:31.000000000
mod_tz   -0800
slot_key hdc.1
version  9.4.5

===========================================================
Component: License
     Desc: iLicense_0 audit_licenses[0]
===========================================================
Name               Value
----               -----
Licensed_Date      20070206
regkey             J9742-63173-86271-91277-3682254
Service_Check_Date 20081120
slot_key           hdc.1

===========================================================
Component: Installation
     Desc: iInstallation_1 audit_installations[1]
===========================================================
Name        Value
----        -----
build       1049.10
product     BIG-IP
slot_key    hdc.1
UTC_delta   -0800
UTC_hwclock true
version     9.4.5

===========================================================
Component: Configuration
     Desc: iConfiguration_1 audit_configurations[1]
===========================================================
Name     Value
----     -----
filename /mnt/tmp/install/slot/hdc.2/config.ucs
mod_date 2008-10-09
mod_time 09:30:29.000000000
mod_tz   -0700
slot_key hdc.2
version  9.4.2

===========================================================
Component: License
     Desc: iLicense_1 audit_licenses[1]
===========================================================
Name               Value
----               -----
Licensed_Date      20070206
regkey             J9742-63173-86271-91277-3682254
Service_Check_Date 20080716
slot_key           hdc.2

===========================================================
Component: Installation
     Desc: iInstallation_2 audit_installations[2]
===========================================================
Name        Value
----        -----
build       228.13
product     BIG-IP
slot_key    hdc.2
UTC_delta   -0800
UTC_hwclock true
version     9.4.2

 Conclusion

The boot location methods in the System.SoftwareManagement interface can give you access to remotely configure which boot slots your system will load into.  You can use the System.Services.reboot_system to switch the system back and forth between running software versions programmatically.

 

Get the Flash Player to see this player.