Have you heard of iControl? That’s important, so we should start there.


iControl Background

iControl is F5’s API that allows for programmatic access to pretty much every system that F5 has put out for quite some time now. This API is based on SOAP/XML. It is robust, granular, and allows a huge range of functionality. Whether you’re looking to tweak a feature buried under 4 sub menus or spin up 1,000 new pool members, iControl is up to the task. Anything you can do via the command line or GUI, you can accomplish via iControl. What’s more, you can do it programmatically so you don’t have to enter in every single command in the chain, or have an admin up at 3am for the change control window just to bleed the servers off a pool and toggle it, etc. This has proved extremely powerful and useful over the years, with many F5 users leveraging iControl to great success.There has been, however, a burning need to continue to build on this tried and true technology. Namely by adding a different, lighter weight means of accessing the BIG-IP remotely.

Enter iControl REST (iCR for short). iCR is simpler, leaner, and easier to pick up with minimal additional programming or API specific knowledge. It’s built on, as the name suggests, REST (Representational State Transfer), which is a simple, stateless architecture delivered over HTTP(S). It is a simpler approach to passing data to and from an endpoint than the well-known SOAP architecture. Where SOAP is near bullet-proof due to its robust definitions and structure, REST is nimble and fleet of foot. Making use of JSON (JavaScript Object Notation), which is rapidly becoming the most commonly used format for transferring data pairs, allows iCR to require very little structure at all. Combine this with the fact that iControl REST is effectively an extension of tmsh, and you have an extremely low overhead solution, both in terms of operational expense, as well as time to learn.


More Methods to learn?

If you have any exposure to the SOAP based iControl API you’re no doubt aware of how extensive the list of available methods, or commands, is. There are thousands of possible commands, each unique to iControl SOAP. This is amazingly powerful, in that it is highly granular and allows you to perform the specific action in the precise manner that you need. That’s powerful, and there is definitely a place for that. For many tasks, however, such as something simple like creating a virtual server, it isn’t really necessary.

Rather than introduce an entirely new set of methods to learn, iCR acts as effectively an interpreter layer that lives on top of the already powerful tmsh infrastructure on all F5 devices. This means that anything you can do via tmsh, you can do via iCR. And what’s more, you do it the same way. No more learning how to add a virtual via the command line and re-learning how to do it in your code. Once you’ve learned it in tmsh, you’ve learned it in iControl REST.


So…it’s just remote tmsh?

Well, sort of. It’s not quite as simple as that, but nearly. You still have to connect to the system, properly format your desired arguments into JSON so that the server side can understand what you’re instructing it to do, and send those commands. Other than that, though…yes, it really does act a heck of a lot like remote tmsh. This is a good thing, trust me. Not only does this make for excellent command and code re-use, which we love, but it also means a couple other important things. First, it means command and feature parity. The fact that iControl REST rides on top of tmsh means that any command, for any module that ever gets added to tmsh is immediately available to iControl REST. By collapsing the development needs from tmsh plus iControl to only tmsh, we’re not just reducing the workload on our internal devs, which means more goodness for you. We’re also eliminating any delay or feature gaps between command line and API, and that seems like a very good thing indeed.

Second, and just as importantly, there is less to learn. If you already know how to manipulate your device via the command line, it’s going to be conceptually very simple to step into doing so remotely via iCR. For instance, in SOAP iControl, if you want to add a virtual server, it might look something like:


   1: #!/bin/env python
   3: import sys
   4: import pycontrol.pycontrol as pc
   5: import time
   7: if pc.__version__ == '2.0':
   8:     pass
   9: else:
  10:     print "Requires pycontrol version 2.x!"
  11:     sys.exit()
  13: if len(sys.argv) < 4:
  14:     print "Usage %s ip_address username password" % sys.argv[0]
  15:     sys.exit()
  17: a = sys.argv[1:]
  19: b = pc.BIGIP(
  20:         hostname = a[0],
  21:         username = a[1],
  22:         password = a[2],
  23:         fromurl = True,
  24:         wsdls = ['LocalLB.VirtualServer'])
  27: # Setup a shortcut
  28: v = b.LocalLB.VirtualServer
  30: # create() takes four params:
  31: # definitions, a Common.VirtualServerSequence,
  32: # wildmasks, a Common.IPAddressSequence,
  33: # resources, a LocalLB.VirtualServer.VirtualServerResourceSequence,
  34: # profiles, a LocalLB.VirtualServer.VirtualServerProfileSequenceSequence
  36: name = 'PC2' + str(int(time.time())) # the name of our vs.ww
  38: # Setup types.
  39: vs_def = v.typefactory.create('Common.VirtualServerDefinition')
  41: vs_def.name = name
  42: vs_def.address = ''
  43: vs_def.port = 8888
  45: proto = v.typefactory.create('Common.ProtocolType')
  46: vs_def.protocol = proto.PROTOCOL_TCP
  48: vs_def_seq = v.typefactory.create('Common.VirtualServerSequence')
  49: vs_def_seq.item = [vs_def]
  53: # Resource has a 'type' attribute, which must point to a 'VirtualServerType'
  54: # object, so let's create that.
  55: vs_type = v.typefactory.create('LocalLB.VirtualServer.VirtualServerType')
  56: resource = v.typefactory.create('LocalLB.VirtualServer.VirtualServerResource')
  58: resource.type = vs_type.RESOURCE_TYPE_POOL
  59: resource.default_pool_name = 'dummyServer' # Change to whatever pool you want 
  61: # A resource sequence we can add the resource to.
  62: resource_seq = v.typefactory.create(
  63:         'LocalLB.VirtualServer.VirtualServerResourceSequence'
  64:         )
  65: resource_seq.item = [resource]
  68: context = v.typefactory.create('LocalLB.ProfileContextType')
  69: prof = v.typefactory.create('LocalLB.VirtualServer.VirtualServerProfile')
  70: prof.profile_context = context.PROFILE_CONTEXT_TYPE_ALL
  71: prof.profile_name = 'tcp'
  73: prof_http = v.typefactory.create('LocalLB.VirtualServer.VirtualServerProfile')
  74: prof_http.profile_name = 'http'
  76: prof_oneconn = v.typefactory.create('LocalLB.VirtualServer.VirtualServerProfile')
  77: prof_oneconn.profile_name = 'oneconnect'
  79: # We need to create a 'profile sequence' to add this profile to...
  80: prof_seq = v.typefactory.create(
  81:         'LocalLB.VirtualServer.VirtualServerProfileSequence'
  82:         )
  84: prof_seq.item = [prof, prof_http, prof_oneconn]
  85: try:
  86:     v.create(
  87:             definitions = vs_def_seq,
  88:             wildmasks=[''],
  89:             resources=resource_seq,
  90:             profiles=[prof_seq]
  91:             )
  92: except Exception, e:
  93:     print "Error creating virtual server %s" % name
  94:     print e



Not horrible, but not exactly light on its feet, either. Shall we see what doing effectively the same thing in iControl REST looks like?


   1: # create virtual
   2: create_http_virtual(bigip, VS_NAME, VS_ADDRESS, VS_PORT, POOL_NAME)
   3: print "created virtual server \"%s\" with destination %s:%s..." % (VS_NAME, VS_ADDRESS, VS_PORT)
   6: def create_http_virtual(bigip, name, address, port, pool):
   7:     payload = {}
   9:     # define test virtual
  10:     payload['kind'] = 'tm:ltm:virtual:virtualstate'
  11:     payload['name'] = name
  12:     payload['description'] = 'A Python REST client test virtual server'
  13:     payload['destination'] = '%s:%s' % (address, port)
  14:     payload['mask'] = ''
  15:     payload['ipProtocol'] = 'tcp'
  16:     payload['sourceAddressTranslation'] = { 'type' : 'automap' }
  17:     payload['profiles'] = [ 
  18:         { 'kind' : 'ltm:virtual:profile', 'name' : 'http' }, 
  19:         { 'kind' : 'ltm:virtual:profile', 'name' : 'tcp' }
  20:     ]
  21:     payload['pool'] = pool
  23:     bigip.post('%s/ltm/virtual' % BIGIP_URL_BASE, data=json.dumps(payload))



I don’t know about you, but that looks decidedly shorter to me. And not just shorter, but more legible. If you’ve used tmsh before you can almost certainly understand what’s going on here, and that’s the beauty of it.


Where are all the commands?

Remember how this runs off tmsh? That means there isn’t a huge laundry list of extra commands. There is not, and will not be a command by command iterative list of documentation on DevCentral that steps through every possible iControl REST command. That’s because you’re pretty much running tmsh commands, packaged in a JSON format and sent over HTTP. Because of this, if you’re looking for specific commands to execute in your scripts I recommend checking out the tmsh section on DevCentral. If what you’re looking for is how to format and send commands, that will be covered in the next couple installments of this series, so stay tuned!


So who is this for?

The entire idea is to make scripting more accessible to everyone. Whether you’re a seasoned programmer that’s been hankering for a more modern approach to API access, or you have extensive BIG-IP knowledge and have been hoping to dabble a bit in scripting, iCR is definitely for you.

For the programming types: Let’s face it, REST is in. The trend for most APIs is to head towards REST as opposed to other available architectures. So much so that if you aren’t running on REST, your API probably isn’t going to get much traction amongst the coding types of today. It’s easier to use, faster, and is generally what is expected when approaching a device to automate or manage via code.

For the networking types: iCR presents way less of a programming hurdle than the SOAP based architecture. There is hugely less setup to begin actually executing commands, and the commands you’re using are mostly the commands you already know, if you’re familiar with BIG-IP. You can learn the formatting requirements, how to set up and tear down connections in your code, and you’re off. It really is a short jump from command line guru to iControl REST writing wizard, and that’s very much by design.


What now?

You go check it out! Go to DevCentral, check out the wiki, the examples, and start poking around. Read through the user’s guide, and if you’ve got them, start asking questions. The community will no doubt be eager to help wherever it can. If your needs go beyond that, or if you’re experiencing difficulties, there is always product support to save the day. Also, make sure to keep a look out for more iControl REST information coming your way, and check back next week for the next installment, iControl REST 101: Getting Started – which will walk you through just what it will take to make the leap to iCR coding yourself, if you haven’t already gotten there.

Again, if you’re looking for specific commands to use within your iControl REST scripts, check out the tmsh section on DevCentral. In that section there is a list of tmsh commands, as well as a mapping of old school b commands to tmsh, if that’s what you’re more familiar with.