cancel
Showing results for 
Search instead for 
Did you mean: 
Login & Join the DevCentral Connects Group to watch the Recorded LiveStream (May 12) on Basic iControl Security - show notes included.
Mark_Lloyd
F5 Employee
F5 Employee

Problem this snippet solves:

TMSH has the ability to create tcl scripts that can be used to run multiple commands and transactions. It is rare that you will want to create on with TMSH but there are a few cases where this may be desirable. One of these is to restart HTTPD, which is difficult to do from iControl REST because the REST API is running over HTTPD and the restart will not be clean. See K13292945.


This Python script creates a tmsh script, and then runs it to restart HTTPD.

How to use this snippet:

Syntax is <program_name.py> host user password


Sample output:

./rest_script_example.py 10.155.117.12 admin admin
Before
httpd (pid 3186) is running...

After
httpd (pid 3289) is running...


Code :

#!/usr/bin/python

#m.lloyd@f5.com
#Makes tmsh script to restart HTTP 

#Syntax:  host username password

import json

#allow python 2 and python 3 by loading  the correct libraries.
try:
    from http.client import BadStatusLine
    from urllib.parse import urlparse, urlencode
    from urllib.request import urlopen, Request
    from urllib.error import HTTPError
except ImportError:
    from httplib import BadStatusLine
    from urlparse import urlparse
    from urllib import urlencode
    from urllib2 import urlopen, Request, HTTPError

import ssl
import sys
import time

#Internal calls will not verify certs so disable cert verification.
ssl._create_default_https_context = ssl._create_unverified_context

#Create request for token based authentication. This is in Bigip 12 and later:
url = 'https://'+sys.argv[1]+'/mgmt/shared/authn/login'
values = {'username' : sys.argv[2],
          'password' : sys.argv[3],
          'loginProviderName' : 'tmos'}
values = json.dumps(values).encode('utf-8')
Request(url,data=values)
req = Request(url,data=values)
req.add_header('Content-Type' , 'application/json')

#Request authentication token.
response = urlopen(req)

#auth=result will be a json data structure.
auth_result = response.read()
#print (auth_result)

#Json.loads makes an internal python data structure that is easier to extract auth token from json.
#Now construct icontrol rest query for device-groups info.
auth=json.loads(auth_result)
token=(auth['token']['token'])
#print(token)

#Get current PID of HTTPD
url = 'https://'+sys.argv[1]+'/mgmt/tm/sys/service/httpd/stats'
req = Request(url)
req.add_header('X-F5-Auth-Token',auth['token']['token'])
response = urlopen(req,data=None)

json_response=(response.read())
python_response=json.loads(json_response)
print("Before")
print(python_response["apiRawValues"]["apiAnonymous"])


#look for script with name to make sure that the script does not already exist

url = 'https://'+sys.argv[1]+'/mgmt/tm/cli/script/example.tcl'

#urllib2 raises an  exception with an HTTP 404

req = Request(url)
req.add_header('X-F5-Auth-Token',auth['token']['token'])

try:
    response = urlopen(req,data=None)
except HTTPError as err:
    if err.code==404:
       
        #print (err.code)
        #print("\nCreate cli script\n")
        #request create here
        url = 'https://'+sys.argv[1]+'/mgmt/tm/cli/script'
        req = Request(url)
        req.add_header('X-F5-Auth-Token',auth['token']['token'])
        req.add_header('Content-Type' , 'application/json')

        values = {"name":"example.tcl",
                  "apiAnonymous": "proc script::init {} {\n}\n\nproc script::run {} {\n tmsh::run util bash -c 'killall -9 httpd' \n tmsh::start sys service httpd\n} \n\nproc script::help {} {\n}\n\nproc script::tabc {} {\n}\n"}
                                 
        values = json.dumps(values)

        response = urlopen(req,data=values)
        response_py=(json.load(response))
        #print(json.dumps(response_py,sort_keys=True,indent=4))

#Now run script
url = 'https://'+sys.argv[1]+'/mgmt/tm/cli/script/example.tcl'
req = Request(url)
req.add_header('X-F5-Auth-Token',auth['token']['token'])
req.add_header('Content-Type' , 'application/json')
values = {"kind":"tm:cli:script:runstate","command":"run"}
values = json.dumps(values).encode('utf-8')

# Killing HTTPD will abort the connection so catch the exception.


try:
    urlopen(req,data=values)
except BadStatusLine:
     pass 
     
#Wait for httpd to restart so you can query.
time.sleep(5)
#Get current PID of HTTPD after restart
url = 'https://'+sys.argv[1]+'/mgmt/tm/sys/service/httpd/stats'
req = Request(url)
req.add_header('X-F5-Auth-Token',auth['token']['token'])
response = urlopen(req,data=None)

json_response=(response.read())
python_response=json.loads(json_response)
print("After")
print(python_response["apiRawValues"]["apiAnonymous"])

Tested this on version:

13.0
Version history
Last update:
‎29-Dec-2020 12:02
Updated by:
Contributors