--- /dev/null
+#!/usr/bin/python
+
+# First, let's import the right kea_connector.
+# We have two versions: one for python 2.x and another for python 3.x.
+# Sadly, there's no unified way to handle http connections. The recommended
+# way is to use Requests (http://docs.python-requests.org/en/master/), but
+# that's a stand alone package that requires separate installation. One of
+# the design requirements was to not require any additional packages, so
+# the code uses standard libraries available in python. Hence two versions.
+import sys
+if (sys.version_info[0] == 2):
+ # This is Python 2.x
+ import kea_connector2 as kea_connector
+else:
+ if (sys.version_info[0] == 3):
+ # This is Python 3.x
+ import kea_connector3 as kea_connector
+ else:
+ # This is... have no idea what it is.
+ raise SystemExit("Unknown python version:" + str(sys.version_info[0]))
+
+from kea_conn import CARequest, CAResponse
+
+# Second step: Need to parse command line parameters. We will use argparse for
+# that purpose. It does great job with having default values, taking care of
+# the help and sanity checking input parameters.
+
+import argparse
+parser = argparse.ArgumentParser(description='Connects to Kea Control Agent.')
+parser.add_argument('--host', type=str, nargs=1, default='localhost',
+ help='hostname of the CA to connect to')
+parser.add_argument('--port', type=int, nargs=1, default='8000',
+ help='TCP port of the CA to connect to')
+parser.add_argument('--timeout', type=int, nargs=1, default='10000',
+ help='Timeout (in milliseconds) when attempting to connect to CA')
+parser.add_argument('command', type=str, nargs="?", default='list-commands',
+ help='command to be executed. If not specified, "list-commands" is used')
+cmd_args = parser.parse_args()
+
+# Ok, now time to put the parameters parsed into the structure to be used by the
+# connection.
+params = CARequest()
+params.command = cmd_args.command
+params.http_host = cmd_args.host[0]
+params.http_port = cmd_args.port[0]
+params.timeout = cmd_args.timeout
+
+params.generateBody()
+params.generateHeaders()
+
+conn = kea_connector.KeaConnector()
+
+try:
+ resp = conn.sendCA(params)
+except Exception as e:
+ print("Failed to run: " + str(e))
+ sys.exit(1)
+
+resp.printResp()
+
+sys.exit(0)
--- /dev/null
+#!/usr/bin/python
+
+# This file contains classes used for communication with Control Agent.
+
+# This class defines the HTTP request to be sent.
+# The supported parameters listed are:
+# - path (specifies the path on the server, CA uses only /)
+# - http_host - hostname of the CA
+# - http-port - TCP port of the CA
+# - command - specifies the command to send (e.g. list-commands)
+# - timeout - timeout (in ms)
+# - headers - extra HTTP headers may be added here
+class CARequest:
+ path = '/'
+ http_host = ''
+ http_port = 0
+ command = ''
+ timeout = 0
+ headers = {}
+
+ # Generates the content, out of specified command line
+ # and optional content.
+ # @todo: Add support for parameters
+ # this stores the output in self.content
+ def generateBody(self):
+ self.content = '{"command": "' + self.command + '"}'
+
+ # Generate HTTP headers
+ #
+ # In particular, this method generates Content-Length and its value.
+ def generateHeaders(self):
+ self.headers['Content-Type'] = 'application/json'
+ self.headers['User-Agent'] = 'Kea-shell/0.1'
+ self.headers['Accept'] = '*/*'
+ self.headers['Content-Length'] = "%d"%(len(self.content))
+
+ # This is a storage for generated command (input data to be sent over POST)
+ content = ''
+
+# This class represents the HTTP response
+class CAResponse:
+
+ # Constructor
+ #
+ # Three mandatory parameters are:
+ # status - numerical number the describe the status (e.g. 200 = OK)
+ # reason - textual explanation of what happened
+ # body - the actual body structure of the response
+ def __init__(self, status, reason, body):
+ self.status = status
+ self.reason = reason
+ self.body = body
+
+ status = 0
+ reason = ''
+ body = ''
+
+ # Used for debugging
+ #
+ # if defug is true, this prints even more information
+ def printResp(self, debug = False):
+ if (debug):
+ print(self.status)
+ print(self.reason)
+ print(self.body)
+
--- /dev/null
+#!/usr/bin/python
+
+# This is PYTHON 2.x version of HTTP connection establishment
+
+from kea_conn import CARequest, CAResponse
+
+import httplib
+
+class KeaConnector:
+ def sendCA(self, params):
+ # Estalbish HTTP connection first.
+ conn = httplib.HTTPConnection(params.http_host, params.http_port)
+ conn.connect()
+
+ # Use POST to send it
+ request = conn.putrequest('POST', params.path)
+
+ # Send the headers first
+ for k in params.headers:
+ conn.putheader(k, params.headers[k])
+ conn.endheaders()
+
+ # Send the content
+ conn.send(params.content)
+
+ # Now get the response
+ resp = conn.getresponse()
+
+ # Now get the response details, put it in CAResponse and
+ # return it
+ x = CAResponse(resp.status, resp.reason, resp.read())
+ conn.close()
+
+ return (x)
--- /dev/null
+#!/usr/bin/python
+
+from kea_conn import CARequest, CAResponse
+
+import urllib.request
+
+class KeaConnector:
+ def sendCA(self, params):
+ # Estalbish HTTP connection first.
+ url = "http://" + params.http_host + ":" + str(params.http_port) + str(params.path)
+
+ req = urllib.request.Request(url = url, data = str.encode(params.content),
+ headers = params.headers)
+ resp = urllib.request.urlopen(req)
+
+ # Now get the response details, put it in CAResponse and
+ # return it
+ x = CAResponse(resp.getcode(), resp.reason, resp.read().decode("utf-8"))
+
+ return (x)