Last time we delved into how to find all of the pools on the system that rely upon a given IP address. This is useful, but not generally exactly what we're looking for. When determining the effect upon your data center, you are much more likely to want to know which virtual nodes are going to be impacted by changes to this server than which pools. The point here is to make it very easy for you to manage your systems, so we want to take that extra step and determine which virtual nodes would be impacted. And that is what we do here.

This installment adds a method to the BigIpNodeAddress class that will return a list of Virtual Nodes that rely upon the IP Address passed in. This is the meat of the problem, but let's break it down a bit. We have (from the last installment) a list of Pools that are dependent upon this node, all we need to correlate that list of pools to Virtuals is a way to find out what the default pool for a given virtual node is, and a list of all of the virtual nodes on the BIG-IP. The it is a trivial task to compare the list of pools dependent upon the IP to the default pool for each Virtual and build a list of Virtual Nodes that are dependent (through pools) on the IP address in question.

To do this, we need a new class to represent Virtual Nodes, since we've not touched on them in this series yet, we'll need to modify BigIpNodeAddress to give it a method called getVirtualList() that takes a String representing an IP address (again, for simplicity we are not doing NSlookups to make it usable with DNS names, though you will likely want to in your code) and returns a Vector that is a list of Virtual Nodes that rely on that IP address. Finally, we'll need to add a call to our main routine to call out the getVirtualList method.

Simple, if you know where to look. And that's what this series is all about, helping you find what you want, while offering you working code that shows you how it's used.

First, let's look at the new class BigIpVirtualServer.

package iC2i;

import iControl.LocalLBVirtualServerBindingStub;
import iControl.LocalLBVirtualServerLocator;


public class BigIpVirtualServer extends BigIpBase {
 LocalLBVirtualServerBindingStub stub = null;
 
 public BigIpVirtualServer(String username, String password, String addressOrName) throws Exception {
 super(username, password, addressOrName);
 
 // Get a connection to the BIG-IP for this instance (yeah, could get big if you're not careful)
 connect();
 }
 
 private void connect() throws Exception {
 stub = (LocalLBVirtualServerBindingStub) new LocalLBVirtualServerLocator().getLocalLBVirtualServerPort(new java.net.URL(fullUrl));
 stub.setTimeout(6000); 
 }
 
 public String[] getList() throws java.lang.Exception {
 return stub.get_list();
 }

 public String[] getDefaultPools(String virtualNames[]) throws java.lang.Exception {
 return stub.get_default_pool_name(virtualNames);
 }
 
 public String getDefaultPool(String virtualName) throws java.lang.Exception{
 String vNames[] = {virtualName};
 String retval[] = getDefaultPools(vNames);
 return retval[0];
 }
}



It should look rather familiar in the connect() method, just notice that we're connecting to the VirtualServer stub in this case. The constructor is exactly the same as we built for Pool and NodeAddress, and that's by design. The getList() method is also exactly the same as in the BigIpPool class. This is because iControl has a get_list() interface for most classes that we are utilizing, and it is implemented the same everywhere, so we're just wrapping it.

That leaves the only interesting methods to be getDefaultPools - which is a direct wrapper for an API call - and getDefaultPool, which is simply a call to the core API version that sends in a single virtual and returns the default pool for that virtual. I'm lazy, what can I say. I'd rather do this once here and have a slight overlap of methods than write this code every time I only cared about a single Virtual.

That's it. The class (at this point anyway) is really rather simple. That's the power of iControl though, the tough work is done for you, it's only a question of wrapping it on the client side so that it's a little easier to use.

So, we've got access to the default pool for any given Virtual defined on the system, and a method to get a list of all virtuals defined on the system, now we can look at the changes to BigIpNodeAddress.

Since the last iC2I article developed BigIpNodeAddress, and we don't want this to run forever, we'll just list and talk about the single new method in that class - getVirtualList, which takes an IP address (not a DNS name, that's outside the scope of this article and trivial for you to implement) and returns a Vector that contains all of the Virtual Nodes that rely on this IP address. It throws Exception - note that in all of these methods you could improve exception handling if you liked by actually listing the exceptions that could be thrown, but again, that's outside the scope of this article so I use the generic java.lang.Exception to handle everything.

At the end of the BigIpNodeAddress class defined in the last installment, just insert this method:

 public Vector getVirtualList(String ipAddress) throws java.lang.Exception {
 // Make a place to hold our return value.
 Vector retVal = new Vector();
 
 // Get a list of all the pools used by this node.
 Vector poolVector = getPoolList(ipAddress);
 // Create an instance of VirtualServer to get the list of virtual servers and their pools.
 BigIpVirtualServer bipVS = new BigIpVirtualServer(username_, address_, password_);
 // Get the virtual server list
 String vsList[] = bipVS.getList();
 String currentPool = null;
 // Now loop through the list of virtual servers,
 // get each one's default pool,
 // and if that default pool is in the list of pools
 // this node is a member of, then add the virtual server
 // to the return value.
 for(int i = 0; i < vsList.length; i++) {
 currentPool = bipVS.getDefaultPool(vsList[i]);
 if(poolVector.contains(currentPool))
 retVal.add(vsList[i]);
 }
 
 return retVal;
 }



All this does is get the list of pools that are dependent upon this node (using the methods defined last time), then gets a list of all Virtual Servers on this BIG-IP, then walks through the list of Virtual Servers and calls the BigIpVirtualServer.getDefaultPoolName() method we defined above, checking the list of pools that rely on this server to see if there's a match. If the name of this Virtual Servers' pool is in the list of pools that rely on this IP address, then we add the Virtual Server name to the return list.

Simple, it takes more lines of comments to explain clearly than it takes lines of code.

Finally, we can call this from within the simple main routine we wrote last time, just adding another set of ifs to the last ones.

As the last block of statements inside the try{} brackets, add the following:

 Vector virtuals = bIpNode.getVirtualList("NodeIpAddress");
 if(virtuals.isEmpty())
 System.out.println("No Virtual Server uses this node.");
 else
 System.out.println("The following Virtual Nodes rely on this IP: " + virtuals);


Just like when asking which pools rely on this server, you have to replace "NodeIpAddress" with a reference to a string representation of an IP address. We recommend you set it up to pass this in args[], but again, that is beyond the scope of this article, and any good Java reference will tell you how to parse command line arguments. For our testing, we just hard-coded node addresses into this space.

There you have it! In two articles we have offered you a set of routines to help you better understand your data center without having to paw through several layers of the UI - we've done it, it's painful.

We haven't settled on next week's topic yet, there are several options we're considering, most likely is manipulating statistics data, but implementing a non-thread safe method of connection sharing in iControl is a strong contender also - largely because it would change the look of all implemented classes, so now while there are only three i2CI classes is a good time to introduce it.

If you have an idea you'd like to see us cover in the i2CI series, let us know! We're happy to insert your problems into our publishing schedule. Contact Don if you've got an idea, or call the DevCentral Skype mailbox and leave us a message - Skype username "F5 recorder".

Get the Flash Player to see this player.