Basic support for Aruba lookups
This commit is contained in:
parent
47d2f7a238
commit
3901c411f5
9
ifxtool
9
ifxtool
@ -24,7 +24,7 @@ class IFXTool():
|
|||||||
warninfo = {}
|
warninfo = {}
|
||||||
namespace = ''
|
namespace = ''
|
||||||
servicedelegates = []
|
servicedelegates = []
|
||||||
totalconfig = {}
|
totalconfig = None
|
||||||
_internal_messages = {}
|
_internal_messages = {}
|
||||||
_subjecttuples = []
|
_subjecttuples = []
|
||||||
_dnsmaps = {}
|
_dnsmaps = {}
|
||||||
@ -35,7 +35,6 @@ class IFXTool():
|
|||||||
if arglist.config :
|
if arglist.config :
|
||||||
try:
|
try:
|
||||||
self.totalconfig = yaml.safe_load(open(os.path.normpath(arglist.config)))
|
self.totalconfig = yaml.safe_load(open(os.path.normpath(arglist.config)))
|
||||||
|
|
||||||
except Exception as exception :
|
except Exception as exception :
|
||||||
self.errorinfo.update({"config": "There was a problem reading your config file, aborting."})
|
self.errorinfo.update({"config": "There was a problem reading your config file, aborting."})
|
||||||
else :
|
else :
|
||||||
@ -50,10 +49,12 @@ class IFXTool():
|
|||||||
self.errorinfo.update({'config': 'Config file ' + self.configdir + '/' + self.configfilename + ' is empty, aborting.'})
|
self.errorinfo.update({'config': 'Config file ' + self.configdir + '/' + self.configfilename + ' is empty, aborting.'})
|
||||||
else :
|
else :
|
||||||
self.errorinfo.update({"config": "There was a problem reading your config file, aborting."})
|
self.errorinfo.update({"config": "There was a problem reading your config file, aborting."})
|
||||||
|
except Exception as exception :
|
||||||
|
self.errorinfo.update({"config": "There was a problem reading your config file, aborting."})
|
||||||
if self.totalconfig == {} :
|
if self.totalconfig == {} :
|
||||||
with open(self.configdir + '/' + self.configfilename, 'w') as output :
|
with open(self.configdir + '/' + self.configfilename, 'w') as output :
|
||||||
yaml.dump(self.configtemplate, output)
|
yaml.dump(self.configtemplate, output)
|
||||||
self.errorinfo.udpate({'config': 'Config file ' + self.configdir + '/' + self.configfilename + ' is empty, populating with a template.'})
|
self.errorinfo.update({'config': 'Config file ' + self.configdir + '/' + self.configfilename + ' is empty, populating with a template.'})
|
||||||
|
|
||||||
def dispatch(self) :
|
def dispatch(self) :
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ class IFXTool():
|
|||||||
except socket.gaierror :
|
except socket.gaierror :
|
||||||
subjecttuple = [ipaddress.ip_address(item).reverse_pointer,[],[str(item)]]
|
subjecttuple = [ipaddress.ip_address(item).reverse_pointer,[],[str(item)]]
|
||||||
# Convert mutable types to immutable (to be used as dictionary keys)
|
# Convert mutable types to immutable (to be used as dictionary keys)
|
||||||
immutablesubjecttuple = tuple([subjecttuple[0],tuple(subjecttuple[1]),tuple(subjecttuple[2])])
|
immutablesubjecttuple = tuple([subjecttuple[0].lower(),tuple(subjecttuple[1]),tuple(subjecttuple[2])])
|
||||||
self._dnsmaps.update({immutablesubjecttuple:item})
|
self._dnsmaps.update({immutablesubjecttuple:item})
|
||||||
self._subjecttuples.append(immutablesubjecttuple)
|
self._subjecttuples.append(immutablesubjecttuple)
|
||||||
|
|
||||||
|
120
plugins/aruba.py
120
plugins/aruba.py
@ -1,14 +1,124 @@
|
|||||||
from servicebase import ServiceBase
|
from servicebase import ServiceBase
|
||||||
|
import requests
|
||||||
|
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
|
||||||
|
import xml.etree.ElementTree as ElementTree
|
||||||
|
|
||||||
|
|
||||||
class ServiceDelegate(ServiceBase) :
|
class ServiceDelegate(ServiceBase) :
|
||||||
|
|
||||||
|
host = None
|
||||||
|
api_session = requests.session()
|
||||||
|
session_key = None
|
||||||
|
query_page_size = 200
|
||||||
|
bigdata_fields = ['sta_mac_address', 'client_ht_phy_type', 'openflow_state', 'client_ip_address', 'client_user_name', 'client_dev_type', 'client_ap_location', 'client_conn_port', 'client_conn_type', 'client_timestamp', 'client_role_name', 'client_active_uac', 'client_standby_uac', 'ap_cluster_name', 'client_health', 'total_moves', 'successful_moves', 'steer_capability', 'ssid', 'ap_name', 'channel', 'channel_str', 'channel_busy', 'tx_time', 'rx_time', 'channel_free', 'channel_interference', 'current_channel_utilization', 'radio_band', 'bssid', 'speed', 'max_negotiated_rate', 'noise_floor', 'radio_ht_phy_type', 'snr', 'total_data_frames', 'total_data_bytes', 'avg_data_rate', 'tx_avg_data_rate', 'rx_avg_data_rate', 'tx_frames_transmitted', 'tx_frames_dropped', 'tx_bytes_transmitted', 'tx_bytes_dropped', 'tx_time_transmitted', 'tx_time_dropped', 'tx_data_transmitted', 'tx_data_dropped', 'tx_data_retried', 'tx_data_transmitted_retried', 'tx_data_bytes_transmitted', 'tx_abs_data_bytes', 'tx_data_bytes_dropped', 'tx_time_data_transmitted', 'tx_time_data_dropped', 'tx_mgmt', 'rx_frames', 'rx_bytes', 'rx_data', 'rx_data_bytes', 'rx_abs_data_bytes', 'rx_data_retried', 'tx_data_frame_rate_dist', 'rx_data_frame_rate_dist', 'tx_data_bytes_rate_dist', 'rx_data_bytes_rate_dist', 'connection_type_classification', 'total_data_throughput', 'tx_data_throughput', 'rx_data_throughput', 'client_auth_type', 'client_auth_subtype', 'client_encrypt_type', 'client_fwd_mode']
|
||||||
|
justip_fields = ['client_ip_address']
|
||||||
|
aruba_hosts = []
|
||||||
|
|
||||||
def get_arguments(cls) :
|
def get_arguments(cls) :
|
||||||
"""Returns an array of information used to construct an argumentparser argument."""
|
"""Returns an array of information used to construct an argumentparser argument."""
|
||||||
# [ <short flag>,<unix flag>,<arg type>,<description> ]
|
|
||||||
# Example return: [ '-n', '--net', 'store_true', "Return network information about the subject" ]
|
|
||||||
return ['-w', '--wifi', 'store_true', "Return wireless connection information about the subject"]
|
return ['-w', '--wifi', 'store_true', "Return wireless connection information about the subject"]
|
||||||
|
|
||||||
def get_ap_list() :
|
def startup(self) :
|
||||||
"""Returns the access points available from the aruba controllers."""
|
for requirement in ['host','username','key'] :
|
||||||
pass
|
if requirement not in self.config or (requirement in self.config and (self.config[requirement] is '' or type(self.config[requirement]) is not str)):
|
||||||
|
self.error.append('Missing required config option ' + requirement)
|
||||||
|
return
|
||||||
|
self.host = self.config['host']
|
||||||
|
self.start_session(self.config['host'],self.config['username'],self.config['key'])
|
||||||
|
listquery = 'backend-observer-sta-19'
|
||||||
|
sortfield = 'client_user_name'
|
||||||
|
self._debug("Retrieving list of Aruba hosts...",1)
|
||||||
|
self.perform_list_query(listquery,self.bigdata_fields,sortfield)
|
||||||
|
self._debug("Searching Aruba hosts...",1)
|
||||||
|
|
||||||
|
def perform_lookup(self,host_tuple) :
|
||||||
|
# Lookup by IP
|
||||||
|
for ip in host_tuple[2] :
|
||||||
|
for entry in self.aruba_hosts :
|
||||||
|
if ip in entry.values() :
|
||||||
|
return entry
|
||||||
|
# Lookup by hostname
|
||||||
|
for entry in self.aruba_hosts :
|
||||||
|
if host_tuple[0] in entry.values() :
|
||||||
|
return entry
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def start_session(self,host,username,key) :
|
||||||
|
headers = { "Content-Type": "application/x-www-form-urlencoded" }
|
||||||
|
data = "opcode=login&uid=" + username + "&passwd=" + key
|
||||||
|
self.api_session.post("https://" + host + "/screens/wms/wms.login",verify=False,headers=headers,data=data)
|
||||||
|
if 'SESSION' in self.api_session.cookies.get_dict() :
|
||||||
|
self.session_key = self.api_session.cookies.get_dict()['SESSION']
|
||||||
|
|
||||||
|
def perform_list_query(self,queryname,columnlist,sortfield) :
|
||||||
|
"""Performs a list-type XML query against the Aruba UI API"""
|
||||||
|
# So uncivilized.
|
||||||
|
# Build the basic object for our list query
|
||||||
|
sortdir = 'asc'
|
||||||
|
aruba_queries = Element('aruba_queries')
|
||||||
|
query = SubElement(aruba_queries,'query')
|
||||||
|
qname = SubElement(query,'qname')
|
||||||
|
qname.text = queryname
|
||||||
|
type = SubElement(query,'type')
|
||||||
|
type.text = 'list'
|
||||||
|
|
||||||
|
list_query = SubElement(query,'list_query')
|
||||||
|
device_type = SubElement(list_query,'device_type')
|
||||||
|
device_type.text = 'sta'
|
||||||
|
requested_columns = SubElement(list_query,'requested_columns')
|
||||||
|
requested_columns.text = ' '.join(self.bigdata_fields)
|
||||||
|
sort_by_field = SubElement(list_query,'sort_by_field')
|
||||||
|
sort_by_field.text = sortfield
|
||||||
|
sort_order = SubElement(list_query,'sort_order')
|
||||||
|
sort_order.text = sortdir
|
||||||
|
pagination = SubElement(list_query,'pagination')
|
||||||
|
start_row = SubElement(pagination,'start_row')
|
||||||
|
num_rows = SubElement(pagination,'num_rows')
|
||||||
|
|
||||||
|
filter = SubElement(query,'filter')
|
||||||
|
global_operator = SubElement(filter,'global_operator')
|
||||||
|
global_operator.text = 'and'
|
||||||
|
filter_list = SubElement(filter,'filter_list')
|
||||||
|
filter_item_entry = SubElement(filter_list,'filter_item_entry')
|
||||||
|
field_name = SubElement(filter_item_entry,'field_name')
|
||||||
|
field_name.text = 'client_conn_type'
|
||||||
|
comp_operator = SubElement(filter_item_entry,'comp_operator')
|
||||||
|
comp_operator.text = 'not_equals'
|
||||||
|
value = SubElement(filter_item_entry,'value')
|
||||||
|
value.text = '0'
|
||||||
|
|
||||||
|
# Repeat with page size on the query, aggregating results
|
||||||
|
nextstart = 0
|
||||||
|
finish = False
|
||||||
|
allitems = []
|
||||||
|
while not finish :
|
||||||
|
start_row.text = str(nextstart)
|
||||||
|
num_rows.text = str(self.query_page_size)
|
||||||
|
datapayload = "".join(['query=',tostring(aruba_queries).decode(),'&UIDARUBA=',self.session_key])
|
||||||
|
page = self.api_session.post("https://" + self.host + "/screens/cmnutil/execUiQuery.xml",verify=False,timeout=1,data=datapayload)
|
||||||
|
self._debug("Got a page of results from Aruba host...",3)
|
||||||
|
if page.status_code == 100 or page.status_code == 200 :
|
||||||
|
pagecontents = ElementTree.fromstring(page.text)
|
||||||
|
rows = pagecontents.iter('row')
|
||||||
|
for row in rows:
|
||||||
|
if row == {} :
|
||||||
|
finish = Tru
|
||||||
|
item = {}
|
||||||
|
headers = pagecontents.iter('column_name')
|
||||||
|
for value, header in zip(row,headers) :
|
||||||
|
item.update({header.text: value.text})
|
||||||
|
allitems.append(item)
|
||||||
|
# Abort when we get no more rows
|
||||||
|
try :
|
||||||
|
rows = pagecontents.iter('row')
|
||||||
|
next(rows)
|
||||||
|
except Exception :
|
||||||
|
finish = True
|
||||||
|
if page.status_code != 100 and page.status_code !=200 :
|
||||||
|
finish = True
|
||||||
|
nextstart = nextstart + self.query_page_size
|
||||||
|
else :
|
||||||
|
finish = True
|
||||||
|
self.aruba_hosts = allitems
|
||||||
|
self._debug("Retrieved " + str((len(allitems))) + " hosts from Aruba host",2)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user