DevProvisioningLaptopIntroduction

So, you've probably read all about the BIG-IP LTM VE.  You've gone through the download process and got the thing configured and running in VMWare.  You've even gone through the initial configuration steps to get the management port configured and got the thing licensed up.  Now what?  Well, we've got a bunch of examples of firing up separate VM instances of host operating systems so that you can test creating pools of servers with those other VM instances.  The problem there is that running those VM's is costly in RAM and CPU.

Being a developer, my first thought was how I could make use of my existing development environment with Visual Studio and IIS on the laptop that is hosting the LTM VE virtual machine.  Why should I have to create a new VM instance of Windows and incur the overhead of running that extra VM?  Well, you don't! 

In this article, I'm going to show you how to build a full client-server environment utilizing only the laptop's host operating system and a single LTM VE instance.

Configuring IIS

The first step is to configure a web application.  You could use any web server you desire (apache, tomcat, etc) but I'll use IIS since I'm already using it to debug applications I've written with Microsoft Visual Studio .NET.  Below is the IIS 7 admin console running under Windows 7.  The main trick here, is to make sure that the site bindings for your app will accept all ip addresses.  That way requests coming from the internal VMWare interface will be able to handle the requests.

DevProvisioningIIS

The Web Application

For this example, I'm going to go old school and write a simple .asp (HTML) page with no server side processing.  Requests to the Default Web Site in IIS will return the contents of this file.

DevProvisioningWebpage

Creating your VM

I'm going to assume for this article, that you already have VMWare Workstation or Server installed and that you have got your BIG-IP LTM-VE fired up and licensed.  If you don't, there are several walkthroughs here on DevCentral that will help you get going.

VMWare sets up several network adapters.  We are going to make use of two of those interfaces to act as the external and internal networks for the LTM.  By configuring IIS to handle requests from all addresses, this means we can create a pool member pointing to the internal network here.  In this example 192.168.239.1 is my external network and 192.168.41.1 is my internal network address that will act as a pool member.

DevProvisioningIPConfig

Provisioning your LTM-VE

Now, I could go and document all of the steps needed to create the objects on the LTM needed to successfully deploy the application but that wouldn't be any fun, plus it wouldn't let me show off my iControl PowerShell integration.

I've written a deployment iControl PowerShell script that will go through the process of configuring VLANs and SelfIPs, creating a pool with the internal host NIC as a pool member with it's associated health monitors, creating the Virtual Server, and, just for fun, an iRule that will modify the response content from IIS back to the browser.

Here's the output of the script.  I'll describe the pieces below.

DevProvisioningPowerShell

Create VLANs

A default LTM-VE configuration has no objects created so the first step is configuring VLAN for the external and internal networks.  The code below can be used to create the "external" and "internal" VLANs.  In my example the external VLAN is configured with the 1.1 interface as untagged (corresponding to the external VMWare NIC) and the internal VLAN using interface 1.2 (corresponding to the internal VMWare NIC).

   1: function Create-VLAN()
   2: {
   3:   param([string]$name, [long]$id, [string]$member_name);
   4:   
   5:   # Create VLAN
   6:   $vlans = (, $name);
   7:   $vlan_ids = (, $id);
   8:   $member = New-Object -TypeName iControl.NetworkingVLANMemberEntry;
   9:   $member.member_name = $member_name
  10:   $member.member_type = "MEMBER_INTERFACE";
  11:   $member.tag_state = "MEMBER_UNTAGGED"
  12:   $memberA = (, $member);
  13:   $memberAofA = (, $memberA);
  14:   $failsafe_states = (, "STATE_DISABLED");
  15:   $timeouts = (, 1500);
  16:   $mac_masquerade = (, "");
  17:   
  18:   (Get-F5.iControl).NetworkingVLAN.create(
  19:     $vlans, $vlan_ids, $memberAofA,
  20:     $failsafe_states, $timeouts, $mac_masquerade);
  21: }

Looking in the BIG-IP GUI, the following VLANs were created.

DevProvisioningVlans

Create SelfIPs

Now that the VLANs have been created, Self IP Addresses must be configured for those VLANs so that the LTM can communicate with the laptop network interfaces.  The following code is used to create two SelfIPs (192.168.42.2 for the internal VLAN, and 192.168.239.2 for the external VLAN).

   1: function Create-SelfIP()
   2: {
   3:   param([string]$address, [string]$vlan);
   4:     
   5:   $self_ips = (, $address);
   6:   $vlan_names = (, $vlan);
   7:   $netmasks = (, "255.255.255.0");
   8:   $unit_ids = (, 0);
   9:   $floating_states = (, "STATE_DISABLED");
  10:   (Get-F5.iControl).NetworkingSelfIP.create(
  11:     $self_ips, $vlan_names, $netmasks,
  12:     $unit_ids, $floating_states
  13:   );
  14: }

And again, the BIG-IP GUI shows the two Self IPs for the two VLANs.

DevProvisioningSelfIPs

Create Pool

The previous two steps were to ensure the lower networking layer was in place to allow connections from the upcoming generated Virtual Server as well as the defined pool members.  The next step is to create a pool with a pool member of the internal VMWare NIC address (192.168.41.1).  In this code, the pool is created and I've associated two health check monitors on the pool member.  In this case I'm using the standard http and gateway_icmp monitors.  You can modify these to suit your taste.

   1: function Create-Pool()
   2: {
   3:   param([string]$name, [string]$member_ip, [long]$member_port);
   4:   
   5:   $pool_list = (Get-F5.iControl).LocalLBPool.get_list();
   6:   if ( -not (Is-InList -search $name -list $pool_list) )
   7:   {
   8:     $pool_names = (, $name);
   9:     $lb_methods = (, "LB_METHOD_ROUND_ROBIN");
  10:     $member = New-Object -TypeName iControl.CommonIPPortDefinition;
  11:     $member.address = $member_ip;
  12:     $member.port = $member_port;
  13:     $memberA = (, $member);
  14:     $memberAofA = (, $memberA);
  15:     
  16:     Write-Host "Creating Pool `"$name`"...";
  17:     (Get-F5.iControl).LocalLBPool.create($pool_names, $lb_methods, $memberAofA);
  18:     
  19:     $monitor_association = New-Object -TypeName iControl.LocalLBPoolMonitorAssociation;
  20:     $monitor_association.pool_name = $name;
  21:     $monitor_association.monitor_rule = New-Object -TypeName iControl.LocalLBMonitorRule;
  22:     $monitor_association.monitor_rule.type = "MONITOR_RULE_TYPE_AND_LIST";
  23:     $monitor_association.monitor_rule.quorum = 1;
  24:     $monitor_association.monitor_rule.monitor_templates = ("http", "gateway_icmp");
  25:     $monitor_associations = (, $monitor_association);
  26:  
  27:     Write-Host "Assigning monitors to Pool `"$name`"...";
  28:     (Get-F5.iControl).LocalLBPool.set_monitor_association($monitor_associations);
  29:   }
  30: }

And again, the BIG-IP GUI shows the generated Pool with the single defined member.  Oh, and as a bonus, we have a Green Circle status which means the health checks succeeded and we're ready to go!

DevProvisioningPool

Create Virtual Server

Now that the application pool is created, the virtual server is configured to give an IP address you can use to test the IIS application.  The Virtual Server creation process involves specifying virtual server configuration as well as a list of profiles to associate with the virtual.  In this example, I'm using the stock "http" profile and as an added bonus, I've added in the "stream" profile so that my upcoming iRule will be able to do some content replacement.

   1: function Create-Virtual()
   2: {
   3:   param([string]$name, [string]$ip, [long]$port, [string]$pool);
   4:   $vs_list = (Get-F5.iControl).LocalLBVirtualServer.get_list();
   5:   if ( -not (Is-InList -search $name -list $vs_list) )
   6:   {
   7:     $definition = New-Object -TypeName iControl.CommonVirtualServerDefinition;
   8:     $definition.name = $name;
   9:     $definition.address = $ip;
  10:     $definition.port = $port;
  11:     $definition.protocol = "PROTOCOL_TCP";
  12:     $definitions = (, $definition);
  13:     $wildmasks = (, "255.255.255.255");
  14:     $resource = New-Object -TypeName iControl.LocalLBVirtualServerVirtualServerResource;
  15:     $resource.type = "RESOURCE_TYPE_POOL";
  16:     $resource.default_pool_name = $pool;
  17:     $resources = (, $resource);
  18:     $profile = New-Object -TypeName iControl.LocalLBVirtualServerVirtualServerProfile;
  19:     $profile.profile_context = "PROFILE_CONTEXT_TYPE_ALL";
  20:     $profile.profile_name = "http";
  21:     $profile2 = New-Object -TypeName iControl.LocalLBVirtualServerVirtualServerProfile;
  22:     $profile2.profile_context = "PROFILE_CONTEXT_TYPE_ALL";
  23:     $profile2.profile_name = "stream";
  24:     $profileA = ($profile2, $profile);
  25:     $profileAofA = (, $profileA);
  26:  
  27:     Write-Host "Creating Virtual Server `"$name`"...";
  28:     
  29:     (Get-F5.iControl).LocalLBVirtualServer.create($definitions, $wildmasks, $resources, $profileAofA);
  30:     
  31:     Write-Host "Enabling SNAT Automap on Virtual Server `"$name`"...";
  32:     (Get-F5.iControl).LocalLBVirtualServer.set_snat_automap( (, $name) );
  33:   }
  34: }

You'll see the Virtual Server has been created with a destination address of 192.168.239.3 which coincides with the "external" VLAN and external VMWare NIC.

DevProvisioningVirtualServer

Create iRules

Now, this isn't necessarily needed for this deployment but I figured I'd throw something in to prove that traffic is actually going through the LTM and get you an iRule to start with.  The follow code will create an iRule that does a stream replacement in the HTTP response from IIS.  It converts all occurrences of "Test" with "Test (Modified by iRule)".  This way we can tell from our client testing that the iRule is getting processed.

After the iRule is created, it is assigned to the Virtual Server with the LocalLB.VirtualServer.add_rule method.

   1: function Create-iRule()
   2: {
   3:   param([string]$virtual, [string]$rule_name);
   4:   
   5:   $rule_list = (Get-F5.iControl).LocalLBRule.get_list();
   6:   if ( -not (Is-InList -search $rule_name -list $rule_list) )
   7:   {
   8:     $rule = New-Object -TypeName iControl.LocalLBRuleRuleDefinition;
   9:     $rule.rule_name = $rule_name;
  10:     $rule.rule_definition = @"
  11: when HTTP_REQUEST {
  12:   log local0. "Request for URI: [HTTP::uri]";
  13: }
  14: when HTTP_RESPONSE {
  15:   log local0. "Response [HTTP::status]";
  16:   STREAM::expression "@Test@Test (Modified by iRule)@";
  17:   STREAM::enable;
  18: }
  19: "@;
  20:     Write-Host "Creating iRule `"$rule_name`"...";
  21:     (Get-F5.iControl).LocalLBRule.create( (, $rule) );
  22:   }
  23:   
  24:   # Assign iRule to Virtual Server
  25:   $vs_rules = (Get-F5.iControl).LocalLBVirtualServer.get_rule( (, $virtual) );
  26:   $found = $false;
  27:   foreach ($vs_rule in $vs_rules[0])
  28:   {
  29:     if ( $rule_name.Equals($vs_rule.rule_name) ) { $found = $true; }
  30:   }
  31:   if ( -not $found )
  32:   {
  33:     $virtual_servers = (, $virtual);
  34:     $rule = New-Object -TypeName iControl.LocalLBVirtualServerVirtualServerRule;
  35:     $rule.rule_name = $rule_name;
  36:     $rule.priority = 500;
  37:     $rules = (, $rule);
  38:     Write-Host "Assigning iRule `"$rule_name`" to virtual `"$virtual`"...";
  39:     (Get-F5.iControl).LocalLBVirtualServer.add_rule($virtual_servers, $rules);
  40:   }
  41: }

And there is the iRule in the BIG-IP GUI.

DevProvisioningiRule

Testing Your Application

Now that the VLANs, SelfIPs, Pool, and VirtualServer are configured and functioning, it's time to test out the application.  Here, I opened up a browser and typed in the address of the new Virtual Server (192.168.239.3) and you'll see the response came back.  And, you'll also notice that the iRule did it's magic and modified the response content from the IIS application.

DevProvisioningClientBrowser If a browser is too much work for you, curl works just as well.

DevProvisioningClientCurl

 

 

 

 

 

 

 

 

 

 

 

Conclusion

I've shown in this example how you can build and test a fully functional web application with a single host operating system (in my case Windows 7) and a single instance of BIG-IP LTM VE.  This will greatly reduce the complexity for developers who want to test applications they are currently debugging in the host operating system.

Downloads

The provisioning script used in this article can be found in the iControl CodeShare under PsProvisionVEForLocalDev