Managing Ramcache Entries with Pycontrol

A DevCentral user posted a question in the forums asking for verification of an attribute on the RamCacheKey structure. The maximum_responses attribute should be a long integer. With his C# code, the maximum_responses returned from his iControl call is always double the setting. I fired up pycontrol to see if this was a bug, and in my pycontrol code, I received the expected responses. While he’s taking a look at his code and the .Net library he’s using, I took an interest in the ramcache methods as I have not messed with the Ramcache module much. In this article, I’ll build out a pycontrol script that will enable users to query/evict ramcache entries.

The Interface

The iControl interface for querying/evicting Ramcache entries is RAMCacheInformation. The methods I’ll handle in the script are:

There are two more methods defined:

Preparing the BIG-IP

Beginning in v11, the ramcache configuration was removed from the http profile and moved into its own under Local Traffic->Profiles->Services->Web Acceleration. I created a profile called lcache with a parent profile of optimized-caching, increasing the cache size to 25 MB and decreasing the max age to 3600 seconds for testing. I left all the other settings default.

Apply this profile to an http virtual and a pool member with some content and I’m ready to move to the iControl work.

Building the Script

Because there are multiple actions in this interface I want to address, I’ll use command line options to control the script flow:

  • Host – (-H) Required
  • Username (-u) Required
  • Get Entries (-g) Profile Required 
  • Get Exact Entry (-x) Profile, Host and URI required (as a white-space separated list in quotes. Ex. “lcache 10.10.20.60 /images/img1.png”
  • Evict Entry (-E) Profile, Host and partial URI required
  • Evict Exact Entry (-X)  Profile, Host and URI required
  • Evict All Entries (-A) No arguments necessary, empties the ramcache

With that plan in place, I can configure the parser options, shown in the following code snippet:

  1:  from optparse import OptionParser
  2:   
  3:  parser = OptionParser()
  4:  parser.add_option("-H", "--host", action="store", type="string", dest="host")
  5:  parser.add_option("-u", "--user", action="store", type="string", dest="uname")
  6:  parser.add_option("-g", "--get", action="store", type="string", dest="get", help="Supply profile name")
  7:  parser.add_option("-x", "--get_exact", action="store", type="string", dest="get_exact", help="Supply profile name, host, and URI")
  8:  parser.add_option("-E", "--evict", action="store", type="string", dest="evict_entry")
  9:  parser.add_option("-X", "--evict_exact", action="store", type="string", dest="evict_exact")
 10:  parser.add_option("-A", "--evict_all", action="store_false", default=False, dest="evict_all")
 11:  (options, args) = parser.parse_args()
 12: 
 13:  if (options.host is None) or (options.uname is None):
 14:   print "\n\tHost (-H) and username (-u) must be supplied, exiting..."
 15:   sys.exit()

Now that the options are in place, we need to act based on the options provided

  1:  if options.get is not None:
  2:   rce = getRAMCacheEntries(rc, options.get)
  3:   print rce
  4: 
  5:  elif options.get_exact is not None:
  6:   rce = getRAMCacheExactEntry(rc, options.get_exact)
  7:   print rce
  8: 
  9:  elif options.evict_entry is not None:
 10:   rce = evictRAMCacheEntry(rc, options.evict_entry)
 11:   print rce
 12: 
 13:  elif options.evict_exact is not None:
 14:   rce = evictRAMCacheExactEntry(rc, options.evict_exact)
 15:   print rce
 16: 
 17:  elif options.evict_all is not None:
 18:   rce = evictRAMCacheAllEntries(rc)
 19:   print rce
 20: 
 21:  else:
 22:   print "No options selected!"
 23:   sys.exit()

In this code, I’m checking for the options and if none are set, I’m exiting. For each option, I’m calling a function to operate on that particular action. I’m passing the iControl object (see code below) and the argument list (“profile host uri”) as necessary to each function.

  1:  b = pc.BIGIP(
  2:   hostname = options.host,
  3:   username = options.uname,
  4:   password = upass,
  5:   fromurl = True,
  6:   wsdls = ['LocalLB.RAMCacheInformation']
  7:  )
  8: 
  9:  rc = b.LocalLB.RAMCacheInformation
 

For all the functions except the one to handle evicting all ramcache entries, I need to create an object for the RamCacheKey structure. This is done in pycontrol with the typefactory. Once the structure is created, I just need to add the appropriate attributes as defined in the API: profile_name, host_name, uri, and maximum_responses. The first three are strings, the last is a long integer. So the code is very similar in each function:

  1:  rc_key=obj.typefactory.create('LocalLB.RAMCacheInformation.RAMCacheKey')
  2: 
  3:  key_attr = rc_info.split(' ')
  4:  rc_key.profile_name = key_attr[0]
  5:  rc_key.host_name = ''
  6:  rc_key.uri = ''
  7:  rc_key.maximum_responses = 100L

I split the arguments to get each attribute isolated, then assign as appropriate. For a general get, I only need the profile name so I set the host and uri to an empty string. I chose 100 as a max response just to pick something. Now that the structure is defined, I can make an iControl call, in this case, to get all ramcache entries, then I return those values from the function to the variable making the function call above.

  1:  rc_entry = obj.get_ramcache_entry(keys=[rc_key])
  2:  return rc_entry

So if I put all this together, I can issue this command at the command line, with the data below returned:

C:\Users\jrahm\PycharmProjects\pyControl_Scripts>python ramcache_manager.py -H 10.10.20.5 -u admin -g lcache
Please enter the password for user admin
Password:
[[(LocalLB.RAMCacheInformation.RAMCacheEntry){
   profile_name = "lcache"
   host_name = "10.10.20.60"
   uri = "/images/gnome-64.png"
   vary_type = "RAM_CACHE_VARY_NONE"
   vary_count = 1
   hits = 0
   received = 1326237864
   last_sent = 1326237864
   expiration = 1326241060
   size = 4677
 }, (LocalLB.RAMCacheInformation.RAMCacheEntry){
   profile_name = "lcache"
   host_name = "10.10.20.60"
   uri = "/images/ad_remoteauth_ssh_1.png"
   vary_type = "RAM_CACHE_VARY_NONE"
   vary_count = 1
   hits = 0
   received = 1326237873
   last_sent = 1326237873
   expiration = 1326241069
   size = 16304
 }, (LocalLB.RAMCacheInformation.RAMCacheEntry){
   profile_name = "lcache"
   host_name = "10.10.20.60"
   uri = "/images/ad_descr.png"
   vary_type = "RAM_CACHE_VARY_NONE"
   vary_count = 1
   hits = 0
   received = 1326237818
   last_sent = 1326237818
   expiration = 1326241014
   size = 17942
 }]]

Now, if I want to evict one of those, I can change my options a little and try again, then do another query:

C:\Users\jrahm\PycharmProjects\pyControl_Scripts>python ramcache_manager.py -H 10.10.20.5 -u admin -E "lcache 10.10.20.60 /images/ad_descr.png"
Please enter the password for user admin
Password:
None

C:\Users\jrahm\PycharmProjects\pyControl_Scripts>python ramcache_manager.py -H 10.10.20.5 -u admin -g lcache
Please enter the password for user admin
Password:
[[(LocalLB.RAMCacheInformation.RAMCacheEntry){
   profile_name = "lcache"
   host_name = "10.10.20.60"
   uri = "/images/gnome-64.png"
   vary_type = "RAM_CACHE_VARY_NONE"
   vary_count = 1
   hits = 0
   received = 1326237864
   last_sent = 1326237864
   expiration = 1326241060
   size = 4677
 }, (LocalLB.RAMCacheInformation.RAMCacheEntry){
   profile_name = "lcache"
   host_name = "10.10.20.60"
   uri = "/images/ad_remoteauth_ssh_1.png"
   vary_type = "RAM_CACHE_VARY_NONE"
   vary_count = 1
   hits = 0
   received = 1326237873
   last_sent = 1326237873
   expiration = 1326241069
   size = 16304
 }]]

You can see that the entry is now gone. And finally, If I evict all:

C:\Users\jrahm\PycharmProjects\pyControl_Scripts>python ramcache_manager.py -H 10.10.20.5 -u admin -A
Please enter the password for user admin
Password:
None

C:\Users\jrahm\PycharmProjects\pyControl_Scripts>python ramcache_manager.py -H 10.10.20.5 -u admin -g lcache
Please enter the password for user admin
Password:
[[]]

Conclusion

There is access to great power via the iControl interface of your BIG-IP. With just a few lines of code, you can manage the ramcache from the CLI. For the full script, please check out the RAMCache Manager wiki page in the iControl codeshare. Happy Coding!

Published Jan 10, 2012
Version 1.0
No CommentsBe the first to comment