This is the second article in the “Java iControl Objects” series in which I define a set of software objects that implement the iControl methods in various iControl interfaces.  In my last article, I defined the LocalLB Pool class where you could define your application pools of servers and control attributes on any given pool.  In that article I mentioned that I couldn’t do the PoolMember class without having a Pool defined first.  So, since the Pool is there, this article will focus on the PoolMember.

The PoolMember represents a server in your application pool.  If you have a server farm of dozens of servers, those servers will be represented in the LTM configuration as a PoolMember within a given pool.  Most iControl-based automation tasks surrounding application server management revolve around the PoolMember interface.  Typical uses involve enabling and gracefully disabling servers from provisioning and querying statistics.  With the LTM PoolMember Java Object, you will be able to create an instance of that PoolMember and do all that and everything else the iControl PoolMember interface provides.

Prerequisites

The code in this article, relies on the iControl library for Java that can be downloaded in it’s DevCentral labs project.  If you haven’t watched it already, check out my previous article on Configuring Eclipse for iControl development with Java.

The Class

The package I will be using is “iControl.Objects” with the various classes being in sub-packages for the related products (LTM, GTM, etc) and the class names will be the same as their corresponding iControl interfaces.  For the PoolMember class, we will need the underlying iControl.Interfaces object defined in the iControl Library for Java.  We will also need the containing Pool class as well as the address and port defining that pool member.

   1: package iControl.Objects.LTM;
   2:  
   3: public class PoolMember
   4: {
   5:   private iControl.Interfaces _interfaces = null;
   6:  
   7:   private Pool _pool = null;
   8:   private String _address = null;
   9:   private long _port = 0;
  10:  
  11:   //-----------------------------------------------------------------------
  12:   // Member Accessors
  13:   //-----------------------------------------------------------------------
  14:   public iControl.Interfaces getInterfaces() { return _interfaces; }
  15:   public void setInterfaces(iControl.Interfaces interfaces) { _interfaces = interfaces; }
  16:  
  17:   public String getAddress() { return _address;  }
  18:   public void setAddress(String address) { _address = address; }
  19:   
  20:   public Pool getPool() { return _pool;  }
  21:   public void setPool(Pool pool) { _pool = pool; }
  22:   
  23:   public long getPort() { return _port;  }
  24:   public void setPort(long port) { _port = port; }
  25:   
  26:   //-----------------------------------------------------------------------
  27:   // Constructors
  28:   //-----------------------------------------------------------------------
  29:   public PoolMember(iControl.Interfaces interfaces, Pool pool, String address, long port)
  30:   {
  31:     _interfaces = interfaces;
  32:     _pool = pool;
  33:     _address = address;
  34:     _port = port;
  35:   }

Object Attribute Accessors

For each of the attribute methods in the iControl PoolMember interface, we will define associated methods in the class definition.  The iControl API was meant for bulk method calls – meaning you can change attributes on as many like-objects at a time with a single method call.  Since this doesn’t make sense in an object model, I’ve masked all the arrays with scalar values to make it easier to code from the client side.  There are still some arrays floating around, but they are only used when necessary within the single object instance.

The following section of code shows the wrappers around the iControl LocalLB.PoolMember.set_connection_limit() and get_connection_limit() methods.

   1: // connection_limit
   2: public void setConnectionLimit(long value) throws Exception
   3: {
   4:   validateMembers();
   5:  
   6:   String [] pool_names = { _pool.getName() };
   7:  
   8:   iControl.LocalLBPoolMemberMemberConnectionLimit memberConnLimit =
   9:     new iControl.LocalLBPoolMemberMemberConnectionLimit();
  10:   memberConnLimit.setMember(new iControl.CommonIPPortDefinition());
  11:   memberConnLimit.getMember().setAddress(_address);
  12:   memberConnLimit.getMember().setPort(_port);
  13:   memberConnLimit.setConnection_limit(value);
  14:   
  15:   iControl.LocalLBPoolMemberMemberConnectionLimit [] memberConnLimitA = 
  16:     { memberConnLimit };
  17:   iControl.LocalLBPoolMemberMemberConnectionLimit [][] memberConnLimitAofA = 
  18:     { memberConnLimitA };
  19:   
  20:   _interfaces.getLocalLBPoolMember().set_connection_limit(
  21:     pool_names, memberConnLimitAofA);
  22: }
  23: public long getConnectionLimit() throws Exception
  24: {
  25:   validateMembers();
  26:   long value = 0;
  27:  
  28:   String [] pool_names = { _pool.getName() };
  29:   
  30:   iControl.LocalLBPoolMemberMemberConnectionLimit [][] memberConnLimitAofA =
  31:     _interfaces.getLocalLBPoolMember().get_connection_limit(pool_names);
  32:  
  33:   iControl.LocalLBPoolMemberMemberConnectionLimit [] memberConnLimitA =
  34:     memberConnLimitAofA[0];
  35:   
  36:   for(int i=0; i<memberConnLimitA.length; i++)
  37:   {
  38:     iControl.CommonIPPortDefinition member = memberConnLimitA[i].getMember();
  39:     if ( member.getAddress().equals(_address) && (member.getPort() == _port) )
  40:     {
  41:       value = memberConnLimitA[i].getConnection_limit();
  42:       break;
  43:     }
  44:   }
  45:   return value;
  46: }

Action Methods

In addition to attribute accessor methods, there are a set of actions you can take on the objects.  Enabling and disabling are probably the most popular methods as they aid in the automation of server provisioning.  Questions about gracefully disabling servers come up all the time in the DevCentral forums, so I chose to include that logic in the disable method.  This method will disable any new connections to the PoolMember, query the statistics and wait for the current connections to drop to zero, and then force down the PoolMember.  This logic is illustrated below.

   1: public void disable() throws Exception
   2: {
   3:   validateMembers();
   4:   
   5:   String [] pool_list = { _pool.getName() };
   6:   
   7:   //System.out.println("Disabling Session Enabled State...");
   8:   
   9:   iControl.LocalLBPoolMemberMemberSessionState memberSessionState = 
  10:     new iControl.LocalLBPoolMemberMemberSessionState();
  11:   memberSessionState.setMember(new iControl.CommonIPPortDefinition(_address, _port));
  12:   memberSessionState.setSession_state(iControl.CommonEnabledState.STATE_DISABLED);
  13:   
  14:   iControl.LocalLBPoolMemberMemberSessionState [] sessionStateA = { memberSessionState };
  15:   iControl.LocalLBPoolMemberMemberSessionState [][] sessionStateAofA = { sessionStateA };
  16:   
  17:   _interfaces.getLocalLBPoolMember().set_session_enabled_state(pool_list, sessionStateAofA);
  18:   
  19:   //System.out.println("Waiting for current connections to drop to zero...");
  20:   
  21:   iControl.CommonIPPortDefinition memberDef = 
  22:     new iControl.CommonIPPortDefinition(_address, _port);
  23:   
  24:   iControl.CommonIPPortDefinition [] memberDefA = { memberDef };
  25:   iControl.CommonIPPortDefinition [][] memberDefAofA = { memberDefA };
  26:   
  27:   long cur_connections = 1;
  28:   
  29:   while ( cur_connections > 0 )
  30:   {
  31:     iControl.LocalLBPoolMemberMemberStatistics [] memberStatsA = 
  32:       _interfaces.getLocalLBPoolMember().get_statistics(pool_list, memberDefAofA);
  33:     
  34:     iControl.LocalLBPoolMemberMemberStatistics memberStats = memberStatsA[0];
  35:     
  36:     iControl.LocalLBPoolMemberMemberStatisticEntry [] statsEntryA = 
  37:       memberStats.getStatistics();
  38:     iControl.LocalLBPoolMemberMemberStatisticEntry  statsEntry = statsEntryA[0];
  39:     
  40:     iControl.CommonStatistic [] statsA = statsEntry.getStatistics();
  41:     
  42:     for(int i=0; i<statsA.length; i++)
  43:     {
  44:       iControl.CommonStatisticType type = statsA[i].getType();
  45:       iControl.CommonULong64 value64 = statsA[i].getValue();
  46:  
  47:       if ( type == iControl.CommonStatisticType.STATISTIC_SERVER_SIDE_CURRENT_CONNECTIONS )
  48:       {
  49:         cur_connections = value64.getLow();
  50:         //System.out.println("Current Connections: " + cur_connections);
  51:       }
  52:     }
  53:     Thread.currentThread();
  54:     Thread.sleep(1000);
  55:   }
  56:   
  57:   //System.out.println("Disabling Monitor State...");
  58:   
  59:   iControl.LocalLBPoolMemberMemberMonitorState memberMonitorState = 
  60:     new iControl.LocalLBPoolMemberMemberMonitorState();
  61:   memberMonitorState.setMember(new iControl.CommonIPPortDefinition(_address, _port));
  62:   memberMonitorState.setMonitor_state(iControl.CommonEnabledState.STATE_DISABLED);
  63:   
  64:   iControl.LocalLBPoolMemberMemberMonitorState [] monStateA = { memberMonitorState };
  65:   iControl.LocalLBPoolMemberMemberMonitorState [][] monStateAofA = { monStateA };
  66:   
  67:   _interfaces.getLocalLBPoolMember().set_monitor_state(pool_list, monStateAofA);
  68: }

Static Methods

Static methods are ones that you can call on a class without having to create an instance of that class. For the PoolMember, I created an “exists” method that allows you to query whether a specified pool member exists in the running configuration.  This is done by creating a temporary Pool and PoolMember class and then calling the “exists” action method in the PoolMember class.

   1: public static boolean exists(iControl.Interfaces interfaces, String poolname, String address, long port) throws Exception
   2: {
   3:   Pool pool = new Pool(interfaces, poolname);
   4:   PoolMember poolMember = new PoolMember(interfaces, pool, address, port);
   5:   return poolMember.exists();
   6: }

An Example Usage

Below is a sample routine that illustrates how to use the PoolMember object.  An iControl.Interfaces object is created and inialized with the supplied input arguments.  For this example, I hard coded in a few temporary variables for the pool name and member definition.

The code then instantiates a Pool and a PoolMember object.  An empty pool is created, the member is added, the members are queried, and then the dynamic_ration and connection_limit accessor methods are tested.  When all is done, the Pool is then removed from the configuration.

   1: public void testPoolMember(String [] args)
   2: {
   3:   if ( args.length >= 2)
   4:   {
   5:     try
   6:     {
   7:       iControl.Interfaces interfaces = new iControl.Interfaces();
   8:       interfaces.initialize(args[0], args[1], args[2]);
   9:  
  10:       String poolName = "dummyPool";
  11:       String memberAddr = "99.99.99.99";
  12:       long memberPort = 80;
  13:       
  14:       iControl.Objects.LTM.Pool pool = new iControl.Objects.LTM.Pool(interfaces, poolName);
  15:       iControl.Objects.LTM.PoolMember poolMember = new iControl.Objects.LTM.PoolMember(interfaces, pool, memberAddr, memberPort);
  16:       
  17:       System.out.println("> Creating pool " + pool.getName());
  18:       iControl.CommonIPPortDefinition[] members = null;
  19:       pool.create(LocalLBLBMethod.LB_METHOD_ROUND_ROBIN, members);
  20:       
  21:       System.out.println("> Creating pool member " + pool.getName() + "/" + poolMember.getAddress() + ":" + poolMember.getPort() + "...");
  22:       poolMember.create();
  23:       
  24:       members = pool.getMembers();
  25:       System.out.println("Pool '" + pool.getName() + "' members:");
  26:       for(int i=0; i<members.length; i++)
  27:       {
  28:         System.out.println("  " + members[i].getAddress() + ":" + members[i].getPort());
  29:       }
  30:       
  31:       long dynRatio = poolMember.getDynamicRatio();
  32:       System.out.println("Dynamic Ratio -> " + dynRatio);
  33:       
  34:       long connLimit = poolMember.getConnectionLimit();
  35:       System.out.println("Connection Limit -> " + connLimit);
  36:       
  37:       System.out.println("> Setting connection limit to 1000...");
  38:       poolMember.setConnectionLimit(1000);
  39:       
  40:       connLimit = poolMember.getConnectionLimit();
  41:       System.out.println("Connection Limit -> " + connLimit);
  42:       
  43:       iControl.LocalLBObjectStatus objStatus = poolMember.getObjectStatus();
  44:       System.out.println("Object Status :");
  45:       System.out.println("  Availability -> " + objStatus.getAvailability_status());
  46:       System.out.println("  Enabled      -> " + objStatus.getEnabled_status());
  47:       System.out.println("  Description  -> " + objStatus.getStatus_description());
  48:  
  49:       iControl.CommonEnabledState sessionState = poolMember.getSessionEnabledState();
  50:       System.out.println("Session Enabled State -> " + sessionState);
  51:       
  52:       System.out.println("> Gracefully Disabling pool member...");
  53:       poolMember.disable();
  54:  
  55:       objStatus = poolMember.getObjectStatus();
  56:       System.out.println("Object Status :");
  57:       System.out.println("  Availability -> " + objStatus.getAvailability_status());
  58:       System.out.println("  Enabled      -> " + objStatus.getEnabled_status());
  59:       System.out.println("  Description  -> " + objStatus.getStatus_description());
  60:       
  61:       System.out.println("> Enabling pool member...");
  62:       poolMember.enable();
  63:  
  64:       objStatus = poolMember.getObjectStatus();
  65:       System.out.println("Object Status :");
  66:       System.out.println("  Availability -> " + objStatus.getAvailability_status());
  67:       System.out.println("  Enabled      -> " + objStatus.getEnabled_status());
  68:       System.out.println("  Description  -> " + objStatus.getStatus_description());
  69:       
  70:       System.out.println("Deleting pool member...");
  71:       poolMember.remove();
  72:  
  73:       System.out.println("Deleting pool...");
  74:       pool.remove();
  75:     
  76:     }
  77:     catch(Exception ex)
  78:     {
  79:       ex.printStackTrace(System.out);
  80:     }
  81:   }
  82: }

View The Source

The source code can be found in the iControl CodeShare under JavaObjectLtmPoolMember.

Related Articles on DevCentral

Technorati Tags: Java, PoolMember, Joe Pruitt