Demystifying iControl REST: Merging BIG-IP Config Files

A coworker/friend of mine here at F5 was working last week on some super secret project I hope I’ll get to see soon and reached out on the best approach for merging config files via iControl REST. The command in tmsh

tmsh load sys config merge file “file”
is simple enough, but there are a few things we need to solve for this to work remotely. First, we need to get the file to the BIG-IP. Second, we need to run the merge command. Finally, we need to clean up that file so we don’t leave unnecessary remnants. So let’s address these one by one.

Uploading the File

This is the easy part! I’ve already written stolen this code from another coworker and shared that with the community in part 5 of this Demystifying iControl REST series. Bottom line, there is a file worker that you can use to upload files. That’s the good news. The bad news is that you cannot direct that file to a destination of your choosing, it’ll go to /var/config/rest/downloads or /shared/images, depending on the URL you specify in your transfer. More on that when we address the third problem below.

Merging the File

As shown in the introduction, the tmsh command is simple. But what does that look like in the REST call? Here’s the breakdown:

The URL sets the tmsh path (tmsh sys config,) and the tmsh command is established in the payload, with those command line options following. In python, that makes for a simple function.

def _merge_config(host, creds, file):
    requests.packages.urllib3.disable_warnings()
 
    b_url = 'https://%s/mgmt/tm/sys/config' % host
    b = requests.session()
    b.auth = creds
    b.verify = False
    b.headers.update({'Content-Type': 'application/json'})
 
 
    options = {}
    options['file'] = '/var/config/rest/downloads/%s' % file
    options['merge'] = True
 
    payload = {}
    payload['command'] = 'load'
    payload['options'] = [options]
 
    try:
        merge = b.post(b_url, json.dumps(payload))
        if merge.status_code is not 200:
            print "Merge failed, check rest log file"
            exit()
    except Exception, e:
        print e

Cleaning up the File

Now that the merge has occurred, we no longer need the file taking up space on the filesystem. Because the upload directory is /var/config/rest/downloads, the space on the /var partition is not nearly as large (a tenth on my VE image) as /shared, depending on the frequency/size of your file uploads it could become a precarious situation if you fill up the /var partition. So the point is…clean up your merge files!

And this takes us to another thing we can demystify about iControl REST: how do we move/remove files on the file system, or run cli utilities?  Remember that iControl REST is essentially a wrapper for tmsh, so the method needs to be defined there. If you execute run util ? you’ll see a list of commands made available from the system to tmsh. Here is the interesting one for this application:

unix-rm Remove files or directories

So we can remove system files from tmsh and thus iControl REST…huzzah! But what does that look like in the REST call? Another breakdown:

And in python code, that function looks like this:

def _cleanup_mergefile(host, creds, file):
    requests.packages.urllib3.disable_warnings()
 
    b_url = 'https://%s/mgmt/tm/util/unix-rm' % host
    b = requests.session()
    b.auth = creds
    b.verify = False
    b.headers.update({'Content-Type': 'application/json'})
 
    payload = {}
    payload['command'] = 'run'
    payload['utilCmdArgs'] = '/var/config/rest/downloads/%s' % file
 
    try:
        cleanup = b.post(b_url, json.dumps(payload))
        if cleanup.status_code is not 200:
            print "Cleanup failed, please check system."
    except Exception, e:
        print e

Wrapping Up

So there you have it: a simple python script utilizing iControl REST to upload and merge BIG-IP config files! The full script is available here in the codeshare. What else about iControl REST do you need demystified? Post down in the comments!

Updated Jun 06, 2023
Version 2.0
  • I'm trying to adapt this script to work with an LDAP account that we are using to post config files to the F5. I've authenticated with the F5 and received a token and tacked the X-F5-Auth-Token header on to all of these requests. For the most part, this works pretty well. Couple of issues/questions: 1. The service account appears to need full Administrator privileges to upload a file to the F5. Is that right? 2. Even with full admin access and terminal access, I cannot seem to get the cleanup to work. The post to /mgmt/tm/util/unix-rm returns a 200 but the file isn't deleted and the response says Permission Denied. Any idea what permissions I'm missing? Thanks!