NETWORK ENGINEER BLOG

Tips and Reviews for Engineers

Windows PowerShell で BIG-IP LTM を制御

F5の iControl を使って Windows PowerShell と BIG-IP を連携させることが可能です。
詳細はマイクロソフトの PowerShell と iControl の連携をご参照ください。

検証環境
  • BIGIP-10.1.0.3341.1084
  • Windows Server 2008R2 Datacenter
  • VMware Workstation 9.0.1 build-894247
iControlSnapIn のダウンロード

Installer をDevCentralからダウンロードし Windows PowerShell を実行するサーバーへインストールします。

実行ポリシーの変更

iControlSnapIn をインストール完了後、PowerShell スクリプトの実行ポリシーを変更します。

PS C:\Users\Administrator> Set-ExecutionPolicy RemoteSigned

実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリ
のヘルプ トピックで説明されているセキュリティ上の危険にさらされる可能性があ
[Y] はい(Y)  [N] いいえ(N)  [S] 中断(S)  [?] ヘルプ (既定値は "Y"): y

Set-ExecutionPolicy コマンドレットを使用すると、Windows PowerShell スクリプトがあるときに、コンピュータで実行できるスクリプトを決定できます。Windows PowerShell には 4 つの異なる実行ポリシーがあります。
特定のポリシーを割り当てるには、Set-ExecutionPolicy に適切なポリシー名を続けます。

Restricted

実行できるスクリプトはありません。Windows PowerShell は対話型モードでのみ使用できます。

AllSigned

信頼できる発行元が署名したスクリプトのみを実行できます。

RemoteSigned

ダウンロードしたスクリプトは信頼できる発行元が署名した場合にのみ実行できます。

Unrestricted

制限なし。すべての Windows PowerShell スクリプトを実行できます。
参考:Set-ExecutionPolicy コマンドレットの使用

SnapIn のインストール

setupSnapIn.ps1 を実行します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> .\setupSnapIn.ps1

SnapIn をインストール後、SnapIn インスタンスを生成します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> Add-PSSnapin -Name iControlSnapin

SnapIn のロード完了後、iControl を呼び出す事が可能です。CmdLets の一覧は下記コマンドで確認します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> Get-F5.iControlCommands
BIG-IP の制御

BIG-IP へ iControl コネクションを確立します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> Initialize-F5.iControl -HostName 10.10.10.10 -Username admin -Password admin

コネクション確立後、BIG-IP の設定及び確認を PowerShell 経由で行えます。

Virtual Server の状態を確認します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> Get-F5.LTMVirtualServer

Name                                           Availability                       Enabled Status
----                                           ------------                       ------- ------
vs_http                           AVAILABILITY_STATUS_GREEN        ENABLED_STATUS_ENABLED The virtual server is avai...

Pool の状態を確認します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> Get-F5.LTMPool

MemberCount  : 2
Name         : http_pool
Availability : AVAILABILITY_STATUS_GREEN
Enabled      : ENABLED_STATUS_ENABLED
Status       : The pool is available

Pool に所属するメンバーの状態を確認します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> Get-F5.LTMPoolMember http_pool

Pool         : http_pool
Address      : 192.168.1.101
Port         : 80
Name         : 192.168.1.101:80
Availability : AVAILABILITY_STATUS_GREEN
Enabled      : ENABLED_STATUS_ENABLED
Status       : Pool member is available

Pool         : http_pool
Address      : 192.168.1.102
Port         : 80
Name         : 192.168.1.102:80
Availability : AVAILABILITY_STATUS_GREEN
Enabled      : ENABLED_STATUS_ENABLED
Status       : Pool member is available

Pool に所属するメンバーを無効化します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> Disable-F5.LTMPoolMember -Pool http_pool -Member 192.168.1.101:80

Pool         : http_pool
Address      : 192.168.1.101
Port         : 80
Name         : 192.168.1.101:80
Availability : AVAILABILITY_STATUS_NONE
Enabled      : ENABLED_STATUS_DISABLED
Status       :

Pool に所属するメンバーを有効化します。

PS C:\Program Files (x86)\F5 Networks\iControlSnapIn> Enable-F5.LTMPoolMember -Pool http_pool -Member 192.168.1.101:80

Pool         : http_pool
Address      : 192.168.1.101
Port         : 80
Name         : 192.168.1.101:80
Availability : AVAILABILITY_STATUS_NONE
Enabled      : ENABLED_STATUS_ENABLED
Status       :
タスクスケジューラによる自動化

こちらからダウンロード可能な下記のスクリプトと、タスクスケジューラを使用して、Pool に所属するメンバーの有効化/無効化を自動化する事が可能です。

タスクスケジューラを起動し[基本タスクの作成]をクリックします。
f:id:FriendsNow:20130123234337p:plain

タスク名を設定し[次へ]をクリックします。
f:id:FriendsNow:20130123234338p:plain

タスクトリガを指定し[次へ]をクリックします。
f:id:FriendsNow:20130123234344p:plain

開始時間、間隔を指定し[次へ]をクリックします。
f:id:FriendsNow:20130123234355p:plain

プログラムの開始を指定し[次へ]をクリックします。
f:id:FriendsNow:20130123234401p:plain

プログラム/スクリプトと引数を下記のとおり指定し[次へ]をクリックします。
f:id:FriendsNow:20130123234408p:plain

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

-file "C:\Program Files (x86)\F5 Networks\iControlSnapIn\LocalLBPool.ps1" 192.168.1.1 admin password http_pool 192.168.1.100:80 enable

内容を確認し[完了]をクリックします。
f:id:FriendsNow:20130123234415p:plain

なお、ログオフしている状況でタスクを実行する際は、下記のオプションを有効にする必要があります。
f:id:FriendsNow:20130124182123p:plain

  • ユーザーがログオンしているかどうかにかかわらず実行する
  • 最上位の特権で実行する。

ダウンロードしたスクリプトの内容は下記のとおりです。

#----------------------------------------------------------------------------
# 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-2009 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 (
  $bigip = $null,
  $user = $null,
  $pass = $null,
  $object = $null,
  $state = $null
);

Set-PSDebug -strict;

$MONITOR_STATE_HASH = @{};
$MONITOR_STATE_HASH.Add("enabled", "STATE_ENABLED");
$MONITOR_STATE_HASH.Add("disabled", "STATE_ENABLED");
$MONITOR_STATE_HASH.Add("offline", "STATE_DISABLED");

$SESSION_STATE_HASH = @{};
$SESSION_STATE_HASH.Add("enabled", "STATE_ENABLED");
$SESSION_STATE_HASH.Add("disabled", "STATE_DISABLED");
$SESSION_STATE_HASH.Add("offline", "STATE_DISABLED");

#-------------------------------------------------------------------------
# function Write-Usage
#-------------------------------------------------------------------------
function Write-Usage()
{
  Write-Host "Usage: ServerControl.ps1 host uid pwd [object [state]]";
  Write-Host "   object: address (Node) | address:port (Pool Member)";
  Write-Host "    state: enabled | disabled | offline";
  exit;
}


#-------------------------------------------------------------------------
# function Get-AllObjects
#-------------------------------------------------------------------------
function Get-AllObjects()
{
  # Build objects with Pool Members and Node Addresses
  $pool_list = (Get-F5.iControl).LocalLBPool.get_list();
  $memberDefAofA = (Get-F5.iControl).LocalLBPool.get_member($pool_list);
  
  foreach ($memberDefA in $MemberDefAofA)
  {
    foreach ($memberDef in $MemberDefA)
    {
      $addr = $memberDef.address;
      $port = $memberDef.port;
      $objects += ,"${addr}:${port}"
    }
  }
  
  $node_list = (Get-F5.iControl).LocalLBNodeAddress.get_list();
  foreach ($node in $node_list)
  {
    $objects += ,$node;
  }
  
  $objects | Sort-Object;
}

#-------------------------------------------------------------------------
# function Get-ToggleState
#-------------------------------------------------------------------------
function Get-ToggleState()
{
  param(
    [string]$monitor_state = $null,
    [string]$session_enabled_state = $null
  );
  $state = $null;
  if ( $monitor_state -and $session_enabled_state )
  {
    if ( ($monitor_state -eq "STATE_ENABLED") -and ($session_enabled_state -eq "STATE_ENABLED") )
    {
      $state = "enabled";
    }
    elseif ( ($monitor_state -eq "STATE_ENABLED") -and ($session_enabled_state -eq "STATE_DISABLED") )
    {
      $state = "disabled";
    }
    elseif ( ($monitor_state -eq "STATE_DISABLED") -and ($session_enabled_state -eq "STATE_DISABLED") )
    {
      $state = "offline";
    }
  }
  $state;
}

#-------------------------------------------------------------------------
# function New-ObjectStatus
#-------------------------------------------------------------------------
function New-ObjectStatus()
{
  param(
    [string]$object = $null,
    [string]$parent = $null,
    [string]$state = $null
  );
  $o = $null;
  if ( $object -and $state )
  {
    $o = 1 | select "Object", "Parent", "State";
    $o.Object = $object;
    $o.State = $state;
    if ($parent) { $o.Parent = $parent; }
  }
  $o;
}

#-------------------------------------------------------------------------
# function Get-NodeAddressState
#-------------------------------------------------------------------------
function Get-NodeAddressState()
{
  param([string]$address = $null);
  
  $state = $null;
  if ( $address )
  {
    $MonitorStatusA = (Get-F5.iControl).LocalLBNodeAddress.get_monitor_status( (,$address));
    $monitor_state = "STATE_ENABLED";
    if ( $MonitorStatusA[0] -eq "MONITOR_STATUS_FORCED_DOWN" )
    {
      $monitor_state = "STATE_DISABLED";
    }

    $EnabledStateA = (Get-F5.iControl).LocalLBNodeAddress.get_session_enabled_state( (,$address));
    $session_enabled_state = $EnabledStateA[0];
    
    $state = Get-ToggleState -monitor_state $monitor_state -session_enabled_state $session_enabled_state;
    New-ObjectStatus -object $address -state $state;
  }
}

#-------------------------------------------------------------------------
# function Get-PoolMemberState
#-------------------------------------------------------------------------
function Get-PoolMemberState()
{
  param([string]$address = $null, [string]$pool = $null, [string]$port = $null);
  if ( $address -and $port )
  {
    $state = $null;
    $pool_list = (Get-F5.iControl).LocalLBPool.get_list();
    $memberSessionStateAofA = (Get-F5.iControl).LocalLBPoolMember.get_session_enabled_state($pool_list);
    $monitorStatusAofA = (Get-F5.iControl).LocalLBPoolMember.get_monitor_status($pool_list);
    
    for ($i=0; $i-lt$pool_list.Length; $i++)
    {
      if ( !$pool -or ($pool_list[$i] -eq $pool) )
      {
        for($j=0; $j-lt$memberSessionStateAofA[$i].Length; $j++)
        {
          $memberSessionState = $memberSessionStateAofA[$i][$j];
          $monitorStatus = $monitorStatusAofA[$i][$j];
          
          if ( ($monitorStatus.member.address -eq $address) -and
               ($monitorStatus.member.port -eq $port) )
          {
            # found a match
            $session_enabled_state = $memberSessionState.session_state;
            $monitor_state = "STATE_ENABLED";
            if ( $monitorStatus.monitor_status -eq "MONITOR_STATUS_FORCED_DOWN" )
            {
              $monitor_state = "STATE_DISABLED";
            }
            
            $state = Get-ToggleState -monitor_state $monitor_state -session_enabled_state $session_enabled_state;
            New-ObjectStatus -object "${address}:${port}" -parent "$($pool_list[$i])" -state $state;
          }
        }
      }
    }
  }
}

#-------------------------------------------------------------------------
# function Get-ObjectState
#-------------------------------------------------------------------------
function Get-ObjectState()
{
  param([string[]]$objects = $null);
  
  if ( ! $objects )
  {
    $objects = Get-AllObjects;
  }
  foreach ($object in $objects)
  {
    $tokens = $object.Split((, ":"));
    if ( $tokens.Length -eq 1 )
    {
      # Node Address
      Get-NodeAddressState -address $tokens[0];
    }
    elseif ( $tokens.Length -eq 2 )
    {
      # Pool Member
      Get-PoolMemberState -address $tokens[0] -port $tokens[1];
    }
    else
    {
      Write-Host "Invalid object '$object'";
    }
  }
}

#-------------------------------------------------------------------------
# function Set-NodeAddressState
#-------------------------------------------------------------------------
function Set-NodeAddressState()
{
  param(
    [string]$address = $null,
    [string]$state = $null
  );
  
  if ( $address -and $state )
  {
    $monitor_state = $MONITOR_STATE_HASH[$state];
    $session_state = $SESSION_STATE_HASH[$state];
    if ( $monitor_state -and $session_state )
    {
      (Get-F5.iControl).LocalLBNodeAddress.set_monitor_state( (,$address), (,$monitor_state));
      (Get-F5.iControl).LocalLBNodeAddress.set_session_enabled_state( (,$address), (,$session_state));
      Get-NodeAddressState -address $address;
    }
  }
}

#-------------------------------------------------------------------------
# function Set-NodeAddressState
#-------------------------------------------------------------------------
function Set-PoolMemberState()
{
  param(
    [string]$address = $null,
    [string]$port = $null,
    [string]$state = $null
  );
  if ( $address -and $port -and $state )
  {
    $pool_list = (Get-F5.iControl).LocalLBPool.get_list();
    $memberDefAofA = (Get-F5.iControl).LocalLBPool.get_member($pool_list);

    $monitor_state = $MONITOR_STATE_HASH[$state];
    $session_state = $SESSION_STATE_HASH[$state];

    for ($i=0; $i-lt$pool_list.Length; $i++)
    {
      for($j=0; $j-lt$memberDefAofA[$i].Length; $j++)
      {
        $member = $memberDefAofA[$i][$j];
        
        if ( ($member.address -eq $address) -and ($member.port -eq $port) )
        {
          # found a match
          $memberMonitorState = New-Object -TypeName iControl.LocalLBPoolMemberMemberMonitorState;
          $memberMonitorState.member = $member;
          $memberMonitorState.monitor_state = $monitor_state;
          (Get-F5.iControl).LocalLBPoolMember.set_monitor_state(
            (,$pool_list[$i]),
            (,(,$memberMonitorState))
          );
            
          $memberSessionState = New-Object -TypeName iControl.LocalLBPoolMemberMemberSessionState;
          $memberSessionState.member = $member;
          $memberSessionState.session_state = $session_state;
          (Get-F5.iControl).LocalLBPoolMember.set_session_enabled_state(
            (,$pool_list[$i]),
            (,(,$memberSessionState))
          )
          
          Get-PoolMemberState -address $address -pool $pool_list[$i] -port $port;
        }
      }
    }
  }
}

#-------------------------------------------------------------------------
# function Set-ObjectState
#-------------------------------------------------------------------------
function Set-ObjectState()
{
  param(
    [string]$object = $null,
    [string]$state = $null
  );
  if ( $object -and $state )
  {
    $tokens = $object.Split((,":"));
    if ( $tokens.Length -eq 1 )
    {
      Set-NodeAddressState -address $tokens[0] -state $state;
    }
    elseif ( $tokens.Length -eq 2 )
    {
      Set-PoolMemberState -address $tokens[0] -port $tokens[1] -state $state;
    }
  }
}

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

#-------------------------------------------------------------------------
# Main Application Logic
#-------------------------------------------------------------------------
if ( ($bigip -eq $null) -or ($user -eq $null) -or ($pass -eq $null) )
{
  Write-Usage;
}

if ( Do-Initialize )
{
  if ( ! $object )
  {
    # List all Node Addresses and Pool Members
    Get-ObjectState -objects $null;
  }
  elseif ( ! $state )
  {
    # List toggle state of provided object
    Get-ObjectState -objects (,$object);
  }
  else
  {
    if ( ($state -eq "enabled") -or ($state -eq "disabled") -or ($state -eq "offline") )
    {
      # Set the specified object's toggle state
      Set-ObjectState -object $object -state $state;
    }
    else
    {
        Write-Usage;
    }
  }
}
else
{
  Write-Error "ERROR: iControl subsystem not initialized"
}

参考書籍

以上