KX Connect (Python) appendix
Code below will work with both Python2 and Python3.
Python dependencies
// Core dependencies
pip
requests
uuid
sys
hashlib
datetime
json
base64
Crypto.Hash
argparse
// Below are additionally required for CSV export and plotting
csv
matplotlib
numpy
pandas
connectSample.py
# Import dependencies
import requests
import uuid
import sys
import hashlib
from datetime import datetime
import json
from base64 import b64encode
from Crypto.Hash import HMAC
from Crypto.Hash import SHA
import argparse
## Add below if you wish to call optional functions (CSV and plot export)
# import exportPlot
# Get input parameters
parser = argparse.ArgumentParser()
parser.add_argument("--hp", help="enter host:port", nargs='?', const="localhost:8080", default="localhost:8080")
parser.add_argument("--user", help="enter username", nargs='?', const="Administrator", default="Administrator")
parser.add_argument("--pw", help="enter password", nargs='?', const="password", default="password")
parser.add_argument("--method", help="enter method name", nargs='?', const="getMem", default="getMem")
args = vars(parser.parse_args())
## Define variables
HTTP_HOST = "http://" + args["hp"]
BASE_URL = HTTP_HOST + "/connect/api"
USERNAME = args["user"]
PASSWORD = args["pw"]
METHOD_NAME = args["method"]
METHOD_GROUP = "monPublic" # See Resource Information of Endpoint
METHOD_REQUEST = METHOD_NAME + "Req" # See Endoint Request
PARAMS = {}
ID = str(uuid.uuid4())
dateStr = datetime.now().strftime("%a, %d %b %Y %H:%M:%S ") + "GMT"
# Define login info
LOGIN_URL = BASE_URL + "/auth/login"
LOGIN_DATA = {
"msg" : [{
"username" : USERNAME,
"password" : PASSWORD
}],
"type" : "LoginReq",
"id": ID,
"date" : dateStr
}
# All users accessing Connect API must login before sending further requests
# Call login API
print("Making a login request to " + LOGIN_URL + " with user " + USERNAME)
response = requests.post(url = LOGIN_URL, verify = False, data = json.dumps(LOGIN_DATA))
if response.status_code != 200:
print("Login failed. Received response: " + str(response.status_code))
print("Data" + response.text)
quit()
# Got successful login
responseData = json.loads(response.text)
# Build REST request string
requestPath = BASE_URL + "/" + METHOD_GROUP + "/" + METHOD_NAME
# Auth is a subset of this
authPath = "/connect/api/" + METHOD_GROUP + "/" + METHOD_NAME
QUERY_DATA = {
"type" : METHOD_REQUEST,
"msg" : [
PARAMS
],
"id" : ID,
"date" : dateStr
}
# Content message must be hashed using MD5
queryMd5Str = hashlib.md5(json.dumps(QUERY_DATA).encode("UTF-8")).hexdigest()
mimeHeader = "application/json"
# Get session ID from login response
if sys.hexversion >= 0x3000000:
sessionId = responseData["msg"][0]["sessionId"]
else:
sessionId = responseData["msg"][0]["sessionId"].encode("utf-8")
# Create signed input string
stringToSign = "POST\n" + authPath + "\n" + USERNAME + "\n" + queryMd5Str + \
"\n" + mimeHeader + "\n" + dateStr + "\n" + sessionId
print("Data: " + stringToSign) # Can be compared to server logs (connect.log) to confirm it matches
# Create signature
if sys.hexversion >= 0x3000000:
hmacEncStr = HMAC.new(sessionId.encode("UTF-8"), (stringToSign.encode("UTF-8")), SHA).digest()
signature = b64encode(hmacEncStr).decode()
else:
hmacEncStr = HMAC.new(sessionId, stringToSign.encode("utf-8"), SHA).digest()
signature = b64encode(hmacEncStr)
print("HMAC:" + str(hmacEncStr)) # Can be compared to server logs (connect.log) to confirm it matches
# Authorization HTTP header = username + last 5 characters of the session Id : signature value
authorization = USERNAME + sessionId[len(sessionId)-5:len(sessionId)] + ":" + signature
print("Auth:" + authorization) # Can be compared to server logs (connect.log) to confirm it matches
headers = {
"Content-Type" : mimeHeader,
"Authorization" : authorization
}
# Send REST API request
queryResp = requests.post(url=requestPath, verify=False, data=json.dumps(QUERY_DATA), headers=headers)
print(queryResp.text) # This should contain results
# OPTIONAL
## Checks if data is a valid JSON, then exports as CSV and plots
def optFunc(data, method):
try:
json_object = json.loads(data.text)
except ValueError as e:
print("Cannot export: data is not a valid JSON")
return
else:
date = datetime.today().strftime("%Y-%m-%d")
# Column to plot
col = "virtual";
exportPlot.csvExport(data, method, date)
exportPlot.plotExport(method, date, col)
## Call below if you wish to export CSV or line graph
# optFunc(queryResp, METHOD_NAME)
exportPlot.py
# This file contains optional functionalities:
## export data to CSV
## export line graph as png
# Import this file to ConnectSample.py if you wish to use these functionalities.
# Import dependencies
import csv
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import pandas as pd
# Export to CSV
def csvExport(queryResp, METHOD_NAME, date):
## Create filepath to tmp directory
filepath = "/tmp/" + METHOD_NAME + "_" + date + ".csv";
## Get the response message
resp_json = queryResp.json()
resp_data = resp_json["msg"]
## Open a file for reading and writing
response_data = open(filepath, "w")
## Create the csv writer object
csvwriter = csv.writer(response_data)
## Write to CSV
count = 0
for resp in resp_data:
if count == 0:
header = resp.keys()
csvwriter.writerow(header)
count += 1
csvwriter.writerow(resp.values())
response_data.close()
print("CSV export complete")
# Export line graph as image
def plotExport(METHOD_NAME, date, aggc):
## Create CSV and image filepaths
csvFP = "/tmp/" + METHOD_NAME + "_" + date + ".csv";
imgFP = "/tmp/" + METHOD_NAME + "_" + date + ".png";
## Plot size
fig, ax = plt.subplots(figsize = (20,10))
## Create dataframe
df = pd.read_csv(csvFP, parse_dates=True)
df.time = pd.to_datetime(df.time, format = "%Y-%m-%d %H:%M:%S.%f")
df.set_index("time", inplace=True)
df.groupby("sym")[aggc].plot()
ax.legend(loc="best")
ax.set_ylabel(aggc + " usage(%)")
ax.set_ylim(ymin=0,ymax=100)
plt.title(METHOD_NAME)
## Save image to disk
fig.savefig(imgFP)
print("Image export complete")
# Show on console. This needs to be below savefig()
# plt.show()