iC2I: Automation - Creating Virtuals Simplified.

There are several instances where you need server or workstation command line access to your BIG-IP, automation being the primary instance. For a long time we have wanted to start providing you with automation tools that will help you do your daily job, and this article is a first start. Not only will you get the tutorial bits that iC2I is known for, but the final product of this article will be a command line system that allows you to quickly and efficiently create new Virtual Servers on your BIG-IP.

There are caveats of course, we limit the amount of information you have to pass on the command line by making assumptions about the Virtuals you're creating. We assume it will be a FAST_HTTP Virtual utilizing the FAST_HTTP profile, and we assume that ROUND_ROBIN is an acceptable load balancing technique for your Virtual. Other than that though, this is a fully functional system for creation. Since the load balancing method, Virtual Server Type, and profiles can all be changed in the Web UI or you can change assumptions in the source code presented, this should not be a massively limiting factor for you.

This application assumes that you have the iControl jar installed into a project on your desktop Java dev environment - we used Eclipse - and that you have access to a BIG-IP. Username, password, and the BIG-IP fully qualified domain name or IP address are all required. Of course you have to have a route to the BIG-IP management port also. Unlike some i2CI articles, this article is complete in-and-of itself. All of the source required to build this application is included in this article.

The program follows the following order of execution.

  1. Parse the command line parameters.
  2. Add nodes and create a pool if necessary.
  3. Check that the pool exists if the pool option was used.
  4. Create the Virtual and tie it to the pool.

That's it. There's quite a bit of code between here and there, but we'll walk through it bit by bit and dissect the harrier parts.

First up, you'll need the base class for all iControl calls. This isn't new and isn't complex, so we'll just give you the source. For a discussion of this class see The Introductory Article

 

package iC2i;

public class BigIpBase {

       protected String username_ = null;
       protected String password_ = null;
       protected String address_ = null;
       protected String fullUrl = null;

        public BigIpBase(String username, String password, String addressOrName) {
         username_ = username;
         password_ = password;
         address_ = addressOrName;
         fullUrl = "https://" + username + ":" + password + "@" + addressOrName + "/iControl/iControlPortal.cgi";

       }
       public BigIpBase() { }
    }

 

Not much to say about this source, it is the base class for all the classes we use except the main program, but it is simple.

Next up is the main program. There's a lot here, but it's well commented and we'll talk about the gotchas after the source code.

 

import iC2i.BigIpPool;
import iC2i.BigIpVirtualServer;

import java.util.Arrays;


/** MakeVirtual - main class for the iC2I sample that creates a simple Virtual from the command line.
 * Takes command line parameters to create a Virtual.
 * @author dmacvittie
 * copyright (c) 2008, F5 Networks, Inc.
 */
public class MakeVirtual {
    static String iconPath = new String("C:/F5Lib/iControl-9.4.0/sdk/samples/soap/java/apache/axis/System/images/SmallF5.jpg");
    static String poolName = null;
    static String nodes[] = new String[10];
    static int nodeCount = 0;
    static String serverName = null;
    static String serverAddress = null;
    static String serverPort = null;
    static String userName = null;
    static String password = null;
    static String fqdn = null;
   
    /**
     * @param args
     */
    public static void main(String[] args) {
       
        // Install our trust provider.
        System.setProperty("javax.net.ssl.trustStore", System.getProperty("user.home") + "/.keystore");
        XTrustProvider.install();

        // Parse the passed in arguments. If parseArgs returns false, either we cannot continue or -h/-help was specified and we should exit.
        if(parseArgs(args)) {

            try {
                BigIpPool pool = new BigIpPool(userName, password, fqdn);

                // first up, check if the Virtual the user specified exists on the BIG-IP. If so, tell them and get out.
                BigIpVirtualServer bVip = new BigIpVirtualServer(userName, password, fqdn);
                String vips[] = bVip.getList();
               
                if(Arrays.asList(vips).contains(serverName)) {
                    System.out.println("Error: Virtual Server " + serverName + " already exists on this BIG-IP.");
                    return;
                }
               
                // Next, if they specified nodes and not a pool, create a pool with default values and the specified nodes.
                if(poolName == null) {
                    poolName = serverName + "_pool";
                    pool.simpleCreate(poolName, nodes);
                } else {
                    // if they specified a pool name, validate that the pool exists. If it does not, error and get out.
                    boolean poolExists = false;
                    String pools[] = pool.getList();
                    if(!Arrays.asList(pools).contains(poolName)) {
                        System.out.println("Error - the specified pool does not exist!");
                        throw(new java.lang.Exception("Error creating VS: Specified Pool " + poolName + " does not exist."));
                    }
                       
                }
                // Create the Virtual on the BIG-IP with passed IP/name, default values and our pool.
                bVip.createSimpleVirtualServer(serverName, serverAddress, serverPort, poolName);
            // While some exceptions are handled in the classes, some will make it out here... Let's give the user what info we can.   
            } catch(Exception e) {
                System.out.println("Error creating running program: " + e.getLocalizedMessage());
                System.out.println("Parameters");
                for(int i = 0; i < args.length; i++)
                    System.out.println("\t" + args[i]);
                return;
            }
            // If you made it here, the parameters were valid, no errors were found, and no exceptions thrown... Tell the user about it!
            System.out.println("Success! Your Virtual is now active on the BIG-IP.");
        }
    }

    /**
     * usage() - display command line usage information.
     *
     */
    private static void usage() {
        System.out.println("Usage:");
        System.out.println("\tjava MakeVirtual -user=[username] -password=[password] \n\t -bigip=[ip or dns name of BIG-IP] -name=[virtualname] \n\t -ip=[ip of virtual] -pool=[pool name]");
        System.out.println("\tjava MakeVirtual -user=[username] -password=[password] \n\t -bigip=[ip or dns name of BIG-IP] -name=[virtualname] \n\t -ip=[ip of virtual] -node=[node ip[:port]]");
        System.out.println("\tjava MakeVirtual -h");
        System.out.println("\tjava MakeVirtual -help");
        System.out.println("\nWhere username is your username on the BIG-IP, password is the pass word for that username, virutal name is the name of the Virtual to create, ");
        System.out.println("pool name is the name of an existing pool on the BIG-IP, and node ip is the IP address of a node you want to service this application. -node may be repeated.");
        System.out.println("user, password, bigip, name, and ip are required. Either pool or at least one node are also required.");
        System.out.println("If one or more nodes are specified, a pool with named virtualname_pool will be created with those nodes in it.");
    }
   
    /**
     *
     * @param args The command line arguments the VM has passed to our program.
     * if one of the parameters is -H or -HELP, processing stops and usage() is called.
     * REQUIRED ARGUMENTS:
     *     USER - The username on the BIG-IP.
     *     PASSWORD - the password on the BIG-IP.
     *     BIGIP - the FQDN or IP address of the BIG-IP.
     *     NAME - the name to give the Virtual. Must follow BIG-IP naming conventions, and a Virtual with that name cannot exist on the BIG-IP.
     *     IP - the IP address to assign to this Virtual. The format is IP:Port, but if Port is left off, we will assume port 80.
     * IN ADDITION, ONE OF THE FOLLOWING (BUT NOT BOTH) IS REQUIRED:
     *     POOL - the name of the (existing) pool to service this Virtual. Program will fail if this pool does not exist on the BIG-IP.
     *     NODE - to create a new pool with specific IP addresses in it, one or more -NODE= parameters can be specified. Format is IP:Port, but
     *         we assume port 80 if port is not specified. When this option is used, a pool will be created with the name VirtualName_pool.
     *         This parameter may be repeated up to 10 times.
     *  
     * @return true if the command line arguments are as expected, false if there is insufficient data to continue.
     */
    private static boolean parseArgs(String args[]) {
       
        String label = null;
        String value = null;
        boolean retval = true;
       
        // Loop through the list and parse parameters.
        for(int i = 0; i < args.length; i++) {
            // -H and -HELP have no "=" in them, so check before building the label and value flags.
            if(args[i].indexOf('=') == -1) {
                label = args[i].toUpperCase();
                value = null;
            } else {
                label = args[i].substring(0,args[i].indexOf('=')).toUpperCase();
                value = args[i].substring(args[i].indexOf('=') + 1);
            }
            if(label.compareTo("-POOL") == 0)
                poolName = value;
            else if(label.compareTo("-NODE") == 0){
                if(value.indexOf(':') != -1)
                    nodes[nodeCount++] = value;
                else
                    // No port specified, but we need one, default to 80.
                    nodes[nodeCount++] = value + ":80";
            }
            else if(label.compareTo("-NAME") == 0)
                serverName = value;           
            else if(label.compareTo("-IP") == 0) {
                if(value.indexOf(':') >= 0) {
                    serverAddress = value.substring(0,value.indexOf(':'));
                    serverPort = value.substring(value.indexOf(":") + 1);
                }
                else {
                    // If no port specified, default to 80.
                    serverAddress = value;
                    serverPort = "80";
                }
            }
               
            else if(label.compareTo("-USER") == 0)
                userName = value;
            else if(label.compareTo("-PASSWORD") == 0)
                password = value;
            else if(label.compareTo("-BIGIP") == 0)
                fqdn = value;
            else if(label.compareTo("-H") == 0 || label.compareTo("-HELP") == 0) {
                usage();
                return false;
            } else {
                System.out.println("Unrecognized parameter: " + args[i]);
                return false;
            }
        }
        // We aren't adding nodes to pools here, so either NODE or POOL can be used, not both.
        if(nodeCount > 0 && poolName != null) {
            System.out.println("Error - you cannot specify both a pool name and nodes.");
            retval = false;
        }
        // If for some reason we got here without a port or address for the VIP, error.
        if(serverPort == null || serverAddress == null) {
            System.out.println("Error - VIP Address is required. Specify -IP= parameter and try again.");
        }
        // If they did not specify a user name, password, or BIG-IP, error.
        if(userName == null) {
            System.out.println("Error - Username required. Specify -USER= parameter and try again.");
            retval = false;
        }
        if(password == null) {
            System.out.println("Error - Password required. Specify -PASSWORD= parameter and try again.");
            retval = false;
        }
        if(fqdn == null) {
            System.out.println("Error - BIG-IP DNS Name required. Specify -BIGIP= and try again.");
            retval = false;
        }
           
        return retval;
    }

}

 

This class presents three methods - main, usage, and parseargs. Usage is easily dismissed as it is simply a printout to standard out of the possible command lines this program expects.

parseArgs() runs through the command line arguments and parses them out. Most are a simple case of split the label from the value and stash the value in the correct class-level variable. The oddities here are -h/-help, which, if found on the command line, calls usage and exits no matter what else is on the command line, and the relationship of Nodes to Pool. If you send in a pool name in -POOL, then you may not specify nodes via the -NODE parameter. This is because -POOL is "use this existing pool", whereas the existence of the -NODE parameter implies that you want the system to create a new pool for you. If one or more -NODE parameters are found on the command line, the system will create a pool with the Virtual Name concatenated with _pool for you. Should pool creation fail, the Virtual will not have a valid pool, and the system exits. If any -NODE parameters or the -IP parameter are passed in without a port, port 80 is assumed.

As always, the password must be valid for username, username must be a username on the BIG-IP, and the username must have rights to create Nodes, Pools, and Virtuals on the BIG-IP.

main() first checks to see that the Virtual Server Name passed in does not already exist on the BIG-IP. If the name has already been used on the BIG-IP it tells the user and exits the program.

Next,  if no pool name was passed in, it generates the pool name from the server name, and then creates the pool, sending the list of addresses passed in the -NODE command line parameters as the servers in the pool.

If the pool name was passed in, main simply gets a list of pools from the BIG-IP and makes certain our Pool is in it. If the pool doesn't exist, it informs the user and exits.

Finally, main creates the Virtual Server.

That's it for main, while there is a lot there, it is pretty straight-forward.

 

The next thing to look at is pool creation. We use the BigIpPool class from previous iC2I articles, but everything not used is stripped out of this class so we can focus on what this application requires (we did not clean up the imports section since we don't talk about that).

 

 

package iC2i;

import iControl.CommonIPPortDefinition;
import iControl.LocalLBPoolBindingStub;
import iControl.LocalLBPoolLocator;

import iControl.LocalLBObjectStatus;
import iControl.LocalLBLBMethod;
import iControl.CommonEnabledState;
import iControl.CommonHAAction;
import iControl.LocalLBServiceDownAction;
import iControl.LocalLBPoolPoolStatistics;
import iControl.LocalLBPoolPoolStatisticEntry;
import iControl.CommonStatistic;
import iControl.CommonStatisticType;

public class BigIpPool extends BigIpBase {
    LocalLBPoolBindingStub stub = null;
   
    public BigIpPool(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 = (LocalLBPoolBindingStub) new LocalLBPoolLocator().getLocalLBPoolPort(new java.net.URL(fullUrl));
        stub.setTimeout(6000);       
    }
   
    public String[] getList() throws java.lang.Exception {
       return stub.get_list();
    }

 
    /**
     * simpleCreate assumes that you want Round Robin load balancing. This is a safe assumption, since you can change it later.
     * @param name The name of the pool to create.
     * @param servers A one-dimensional array of servers in IP_ADDRESS:Port format.
     * @return true if successful, false if not. On exception, the text is written to stdout.
     * We parse through the servers array and put the entries into the form that iControl expects.
     */
    public boolean simpleCreate(String name, String servers[]) {
        String names[] = {name};
       
        // AXIS doesn't deal well with null elements in parameter arrays, so let's rightsize the array passed in.
        int actuallyUsed = 0;
        for(; servers[actuallyUsed] != null; actuallyUsed++)
            ;
        // Assume Round Robin - user can change it in the UI if necessary.
        LocalLBLBMethod lbmeth[] = {LocalLBLBMethod.LB_METHOD_ROUND_ROBIN};
        CommonIPPortDefinition ipPorts[][] = new CommonIPPortDefinition[1][actuallyUsed];
        BigIpNodeAddress bipNA = new BigIpNodeAddress(username_, password_, address_ );
        String addr;
        String port;
        // Make certain our nodes exist in the BIG-IP. If they don't, create them.
        for(int i = 0; i < actuallyUsed; i++) {
            if(servers[i] != null) {
                if(!bipNA.findOrCreate(servers[i])) {
                    System.out.println("Could not find or create node: " + servers[i]);
                    return false;
                }
                ipPorts[0][i] = new CommonIPPortDefinition();
                addr = servers[i].substring(0, servers[i].indexOf(':'));
                port = servers[i].substring(servers[i].indexOf(':') + 1);
                ipPorts[0][i].setAddress(addr);
                ipPorts[0][i].setPort(Long.parseLong(port));
            }
        }
        try {
            stub.create(names, lbmeth, ipPorts);
        } catch(Exception e) {
            System.out.println("Error creating pool " + name + ": " + e.getLocalizedMessage());
            return false;
        }
        return true;
    }
}

 

 

The constructor,  getList, and connect were all discussed in previous i2CI articles, so we will not cover them here.

That leaves simpleCreate(). AXIS threw exceptions if we sent the server list as an array of 10, but only three had values in them - it couldn't handle null elements - so we wrote a little loop to calculate the correct number of elements for the array.

Next, we set the load balancing method for this pool to round robin. The possible values are documented on the iControl Wiki .

We then build the list of CommonIPPortDefinition elements to represent the nodes in this pool, and call findOrCreateServers() in the BigIpNodeAddress class to make certain these nodes exist on the BIG-IP.

After that we call create to generate the pool. Easy enough!

Finally, we look at the BigIpNodeAddress class.

 

 

package iC2i;

import java.util.Vector;
import java.util.Arrays;

import iControl.CommonIPPortDefinition;
import iControl.LocalLBNodeAddressBindingStub;
import iControl.LocalLBNodeAddressLocator;

public class BigIpNodeAddress extends BigIpBase {

    private LocalLBNodeAddressBindingStub stub = null;
   
    public BigIpNodeAddress(String username, String password, String addressOrName) {
        super(username, password, addressOrName);
        try {
        connect();
        } catch(Exception e) {
            System.out.println("Error connecting to NodeAddress Interface: " + e.getLocalizedMessage());
        }
    }

    private void connect() throws Exception {
        stub = (LocalLBNodeAddressBindingStub) new LocalLBNodeAddressLocator().getLocalLBNodeAddressPort(new java.net.URL(fullUrl));
        stub.setTimeout(6000);       
    }
   
    String[] getList() throws Exception {
        return stub.get_list();
    }
   
    /**
     * create - create nodes as listed.
     * @param nodes Node list, each in the format IP:Port.
     * Assumes limits for all servers of 0 - none. User can change in the UI if unacceptable.
     */
    public void create(String nodes[]) {
        String addresses[] = new String[nodes.length];
        long limits[] = new long[nodes.length];
       
        // Build our list and send it to the create routine on the BIG-IP.
        for(int i = 0; i < nodes.length; i++) {
            // handle correctly whether port is included or not.
            if(nodes[i] != null) {
                if(nodes[i].indexOf(':') >= 0)
                    addresses[i] = nodes[i].substring(0, nodes[i].indexOf(":"));
                else
                    addresses[i] = nodes[i];
                // As mentioned above, assume there are no limits - this is iControl... NO LIMITS.
                limits[i] = 0;
            }
        }
        try{
            stub.create(addresses, limits);
        } catch(Exception e) {
            System.out.println("Error creating nodes: " + e.getLocalizedMessage());
        }
    }

    /**
     * find simply loops through the list of installed nodes and looks for ours. Note that Arrays.asList().contains(node) might be quicker.
     * @param node - the node we're looking for.
     * @return true if it exists on the BIG-IP, false if not.
     * @throws Exception just passes up exception generated in getList().
     */
    public boolean find(String node) throws Exception {
        String installed[] = getList();

        for(int i = 0; i < installed.length; i++) {
            if(installed[i].compareTo(node) == 0)
                return true;
        }
        return false;
    }
   
    /**
     * findOrCreate() validates that a node exists on the BIG-IP using find, and creates it if it does not.
     * @param node
     * @return false if the node does not exist and cannot be created.
     */
    public boolean findOrCreate(String node) {
        try {
            boolean found = find(node);
           
            if(!found) {
                String nodes[] = {node};
                    create(nodes);
                return true;
            }
            return found;   
        } catch(Exception e) {
            System.out.println("Failed to create node: " + node);
            System.out.println(e.toString());
            return false;
        }
    }
}

 

The three methods that are new here are find, create, and findOrCreate.

Find simply gets the list of nodes installed on the BIG-IP and checks to see if our node is in the list, returning true if it is, false if it is not.

Create assumes that there are no connection limits on the nodes, and if the node is passed in with the address:port format, it strips the port off (port is maintained in poolmember, no port is required to be listed as a node in the system).

And finally, we have BigIpVirtualServer. This is the class that actually creates the Virtual on the BIG-IP, all of the above classes merely insure that the environment exists (pools, nodes, connection) so that the Virtual can be created.

 

package iC2i;

import java.util.Arrays;
import java.util.Vector;
import java.util.List;

import iControl.LocalLBProfileType;
import iControl.LocalLBProfileContextType;
import iControl.LocalLBVirtualServerBindingStub;
import iControl.LocalLBVirtualServerLocator;
import iControl.LocalLBVirtualServerVirtualServerProfileAttribute;
import iControl.LocalLBVirtualServerVirtualServerRule;
import iControl.CommonVirtualServerDefinition;
import iControl.LocalLBVirtualServerVirtualServerResource;
import iControl.LocalLBVirtualServerVirtualServerProfile;
import iControl.LocalLBVirtualServerVirtualServerType;
import iControl.CommonProtocolType;
import iControl.LocalLBHardwareAccelerationMode;
import iControl.CommonULong64;
import iControl.CommonStatistic;
import iControl.CommonTimeStamp;
import iControl.LocalLBVirtualServerVirtualServerType;
import iControl.CommonEnabledState;
import iControl.CommonIPPortDefinition;
import iControl.LocalLBObjectStatus;
import iControl.LocalLBVirtualServerVirtualServerProfileAttribute;
import iControl.LocalLBVirtualServerVirtualServerRule;
import iControl.CommonVLANFilterList;
import iControl.LocalLBVirtualServerVirtualServerStatistics;
import iControl.LocalLBVirtualServerVirtualServerStatisticEntry;

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

    /** very thin wrapper that creates the virtual servers and then checks that they exist.
     * @param vsDef CommonVirtualServerDefinition as defined in the iControl Wiki
     * @param masks Netmask strings, one per element in vsDef.
     * @param vsRes LocalLBVirtualServerVirtualServerResource elements, one per element in vsDef as defined in the iControl Wiki
     * @param vsProf LocalLBVirtualServerVirtualServerProfile elements, one row per element in the vsDef array as defined in the iControl Wiki
     * @return true if successful, false if failed.
     * @throws Exception passes up exception generated in stub.create.
     */
    boolean createVirtualServers(CommonVirtualServerDefinition vsDef[], String masks[], LocalLBVirtualServerVirtualServerResource vsRes[], LocalLBVirtualServerVirtualServerProfile vsProf[][]) throws Exception {
       
        // Make the iControl call.
        stub.create(vsDef, masks, vsRes, vsProf);
       
        // Now build a list of all Virtual Servers on the BIG-IP
        List checkNames = Arrays.asList(stub.get_list());
       
        // And check it for each of the Virtuals we said to create.
        for(int i = 0; i < vsDef.length; i++)
            if(!checkNames.contains(vsDef[i].getName()))
                return false;    // At least one failed to create.
       
        return true;
    }
  
    /** createVirtualServer()
     * @param name The name of the Virtual Server you wish to create. This is the name that the UI will display, and can be used for reference later.
     * @param address The IP address you wish to assign to this Virtual Server.
     * @param port The port this Virtual Server listens on.
     * @param protocolType the type of protocol this Virtual Server cares about. Possible values include:
     *         PROTOCOL_ANY          0     Protocol is wildcard.
     *         PROTOCOL_IPV6         1     Protocol is IPv6 header.
     *         PROTOCOL_ROUTING     2     Protocol is IPv6 routing header.
     *         PROTOCOL_NONE         3     Protocol is IPv6 no next header.
     *         PROTOCOL_FRAGMENT     4     Protocol is IPv6 fragmentation header.
     *         PROTOCOL_DSTOPTS     5     Protocol is IPv6 destination options.
     *         PROTOCOL_TCP         6     Protocol is TCP.
     *         PROTOCOL_UDP         7     Protocol is UDP.
     *         PROTOCOL_ICMP         8     Protocol is ICMP.
     *         PROTOCOL_ICMPV6     9     Protocol is ICMPv6.
     *         PROTOCOL_OSPF         10     Protocol is OSPF.
     *         PROTOCOL_SCTP         11     Protocol is SCTP.
     * @param netMask The Netmask to apply to the listed IP Address.
     * @param vsType The type of Virtual Server you're creating. Note that "type" means "Function" - what will it be doing.
     *         RESOURCE_TYPE_POOL                  0     The virtual server is based on a pool.
     *         RESOURCE_TYPE_IP_FORWARDING     1     The virtual server only supports IP forwarding. There is no load balancing on this type of virtual server.
     *         RESOURCE_TYPE_L2_FORWARDING     2     The virtual server only supports L2 forwarding. There is no load balancing on this type of virtual server.
     *         RESOURCE_TYPE_REJECT             3     All connections going to this virtual server will be rejected, and resets will be sent.
     *         RESOURCE_TYPE_FAST_L4             4     The virtual server is based on the Fast L4 profile.
     *         RESOURCE_TYPE_FAST_HTTP         5     The virtual server is based on the Fast HTTP profile.
     * @param defaultPool The name of the pool this Virtual Server will utilize - where does it get its nodes.
     * @param profileContextType[] The type of each profile you're applying. This version of createVirtualServer only takes a single profile (others can be added later). Possible values:
     *         PROFILE_CONTEXT_TYPE_ALL          0     Profile applies to both client and server sides.
     *         PROFILE_CONTEXT_TYPE_CLIENT     1     Profile applies to the client side only.
     *         PROFILE_CONTEXT_TYPE_SERVER     2     Profile applies to the server side only.
     * @param profileName[] The name of the profile to utilize with the above context type. One per entry in the profileContextType array.
     * @return
     * @throws Exception
     */
    public boolean createVirtualServer(String name, String address, long port, String protocolType, String netMask, String vsType, String defaultPool, String profileContextType[], String profileName[]) throws Exception {
        CommonVirtualServerDefinition vsDefs[] = {new CommonVirtualServerDefinition()};
        String masks[] = {netMask};
        LocalLBVirtualServerVirtualServerResource vsRes[] = {new LocalLBVirtualServerVirtualServerResource() };
        LocalLBVirtualServerVirtualServerProfile vsProfs[][] = {{new LocalLBVirtualServerVirtualServerProfile()}};
       
        // Set the fields of the CommonVirtualServerDefinition instance.
        vsDefs[0].setName(name);
        vsDefs[0].setAddress(address);
        vsDefs[0].setPort(port);
        vsDefs[0].setProtocol(CommonProtocolType.fromString(protocolType));

        // And the fields of the LocalLBVirtualServerVirtualServerResource instance.
        vsRes[0].setType(LocalLBVirtualServerVirtualServerType.fromString(vsType));
        vsRes[0].setDefault_pool_name(defaultPool);
       
        // And finally the fields of the LocalLBVirtualServerVirtualServerProfile instance
        if(profileContextType.length != profileName.length)
            return false;
       
        for(int i = 0; i < profileName.length; i++) {
            vsProfs[0][0].setProfile_context(LocalLBProfileContextType.fromString(profileContextType[i]));
            vsProfs[0][0].setProfile_name(profileName[i]);
        }
       
        return createVirtualServers(vsDefs, masks, vsRes, vsProfs);
       
    }
   
    /**
     * createSimpleVirtualServer - Heavy wrapper of the VirtualServer.create() routine that assumes TCP for protocol, Fast HTTP for profile, and Fast HTTP for VS type.
     * @param name The name of the virtual server to create.
     * @param address The IP address for this virtual server.
     * @param port The port this Virtual server listens on, or zero for all ports (not recommended).
     * @param pool The pool that will service requests to this virtual server.
     * @return true on success, false on failure.
     */
    public boolean createSimpleVirtualServer(String name, String address, String port, String pool) {
        String profile[] = {"fasthttp"};
        String contextType[] = {"PROFILE_CONTEXT_TYPE_ALL"};
        try {
            return createVirtualServer(name, address, Long.parseLong(port), "PROTOCOL_TCP", "255.255.255.255", "RESOURCE_TYPE_FAST_HTTP", pool, contextType, profile);
        } catch(Exception e) {
            System.out.println("Error creating " + name + ":");
            // MIGHT WAHT TO CHANGE THIS: e.getLocalizedMessage() returns nothing for some AXIS errors because the exception class says all... So we're using this,
            //    but printing a Java stack trace is not the best thing to do if non-programmers are using this routine.
            e.printStackTrace();
            return false;
        }
    }
}

 

Again, this is pretty well documented, so we'll just talk about the bits you might want to change. First off, in createSimpleVirtualServer, we assume the fasthttp profile will be used for all streams in and out of this Virtual. You might wish to assign a different profile. Second, we default the protocol to TCP. While this is a pretty safe assumption, there are cases where you will want it to be something else. Next, we assume the VS is of type FAST_HTTP. If you want yours to be anything else, you should change it. All of these types are well documented in the iControl Wiki. Finally, some of the exceptions raised by Apache AXIS have no description. That is becuase the exception name was deemed to describe the problem well enough. Because of this, and because this particular routine was occasionally seeing some of those exceptions during our testing, we use e.printStackTrace instead of printing out e.getLocalizedMessage(). If you are going to have non-programmers using this system, it is probably best to handle all exceptions righ tin the catch and return false without printing out a stack trace.

That's it. Assuming you've got everythign configured correctly for your project and a path to the BIG-IP, you should be able to run this from the command line or Eclipse and create Virtual Servers. We tested both command line and Eclipse against a BIG-IP 9.2.3 box and all runs well, but if you have problems don't hesitate to post them to the forums!

 

Published May 23, 2008
Version 1.0

Was this article helpful?

2 Comments

  • zafer's avatar
    zafer
    Icon for Nimbostratus rankNimbostratus
    Hello

     

     

    i dont have experience about icontrol, could you please share it file format, i dont know how can i use this script

     

     

    this script usefull for F5 replacement for other laod balancers

     

     

    regards

     

     

    zafer
  • Don_MacVittie_1's avatar
    Don_MacVittie_1
    Historic F5 Account
    Hi Zafer!

     

     

    That would make a great next iC2I article... Look for it in 2 weeks. I'll put all fo the iC2I articles to date together and present the source as a lab - in source and executable formats.

     

     

    Don.