I feel like I'm writing more bugs than features
This commit is contained in:
parent
3530dc965c
commit
d233a12a5e
29
ifxtool
29
ifxtool
@ -61,15 +61,22 @@ class IFXTool():
|
||||
# Resolve subject names
|
||||
for item in self.namespace.subjects :
|
||||
try:
|
||||
quicklookup = socket.gethostbyname(item)
|
||||
if quicklookup != item:
|
||||
quicklookup = ipaddress.ip_address(item)
|
||||
subjecttuple = socket.gethostbyname_ex(item)
|
||||
# Can't make an IP out of item
|
||||
except ValueError :
|
||||
try :
|
||||
# Lookup with system
|
||||
subjecttuple = socket.gethostbyname_ex(item)
|
||||
else :
|
||||
subjecttuple = socket.gethostbyaddr(item)
|
||||
except (socket.gaierror,socket.herror) :
|
||||
self.warninfo.append("Unable to resolve " + item)
|
||||
self.namespace.subjects.remove(item)
|
||||
continue
|
||||
except socket.gaierror :
|
||||
# Not a valid host or IP
|
||||
self.warninfo.append("Unable to resolve " + item)
|
||||
#self.namespace.subjects.remove(item)
|
||||
#continue
|
||||
subjecttuple = [item,[],['']]
|
||||
# Can't make IPv4 out of it
|
||||
except socket.gaierror :
|
||||
subjecttuple = [ipaddress.ip_address(item).reverse_pointer,[],[str(item)]]
|
||||
# Convert mutable types to immutable (to be used as dictionary keys)
|
||||
immutablesubjecttuple = tuple([subjecttuple[0],tuple(subjecttuple[1]),tuple(subjecttuple[2])])
|
||||
self._dnsmaps.update({immutablesubjecttuple:item})
|
||||
@ -109,10 +116,6 @@ class IFXTool():
|
||||
else :
|
||||
return ''
|
||||
|
||||
def get_dc_from_ip(self,ip) :
|
||||
"""Given an IP, return the datacenter the IP resides in."""
|
||||
pass
|
||||
|
||||
def print_results(self,dataset) :
|
||||
"""Returns the submitted dataset"""
|
||||
finalresult = {}
|
||||
@ -125,7 +128,6 @@ class IFXTool():
|
||||
for subject in self._subjecttuples :
|
||||
subjectname = self._dnsmaps[subject]
|
||||
subjectdataset = {}
|
||||
# for plugin in [x for x in dataset if x != 'status'] :
|
||||
for plugin in [x for x in dataset if x != 'error' and x != 'warn'] :
|
||||
subjectdataset.update({plugin:dataset[plugin][subject]})
|
||||
finalresult.update({subjectname:subjectdataset})
|
||||
@ -141,6 +143,7 @@ if __name__ == "__main__":
|
||||
# Load Plugins
|
||||
plugindir="plugins"
|
||||
pluginfiles = [x for x in os.listdir(plugindir) if x != "servicebase.py" and x.endswith('.py')]
|
||||
pluginfiles = sorted(pluginfiles)
|
||||
importlib.import_module(plugindir)
|
||||
delegates = []
|
||||
for pluginfile in pluginfiles :
|
||||
|
@ -20,13 +20,20 @@ class ServiceDelegate(ServiceBase) :
|
||||
self.current_auth_header = self.get_bc_auth_header(self.config['host'],self.config['username'],self.config['key'])
|
||||
|
||||
def perform_lookup(self,host_tuple) :
|
||||
error = None
|
||||
if self.return_payload and 'error' in self.return_payload :
|
||||
error = self.return_payload['error']
|
||||
self.return_payload = {}
|
||||
if error :
|
||||
self.return_payload.update({'error':error})
|
||||
if self.current_auth_header :
|
||||
object = self.search_bc_object(host_tuple)
|
||||
self.return_payload.update({'object':object})
|
||||
parent = self.search_bc_parent_object(host_tuple)
|
||||
self.return_payload.update({'parent':parent})
|
||||
return self.return_payload
|
||||
else :
|
||||
return self.return_payload
|
||||
|
||||
def shutdown(self) :
|
||||
if self.host and self.current_auth_header :
|
||||
@ -49,7 +56,7 @@ class ServiceDelegate(ServiceBase) :
|
||||
|
||||
def search_bc_parent_object(self,host_tuple) :
|
||||
"""Search for and return information about the objects parent, if any"""
|
||||
if 'object' in self.return_payload and 'id' in self.return_payload['object'] :
|
||||
if 'object' in self.return_payload and type(self.return_payload['object']) is dict and 'id' in self.return_payload['object'] :
|
||||
response = requests.get("https://" + self.host + "/Services/REST/v1/getParent?entityId=" + str(self.return_payload['object']['id']), headers=self.current_auth_header)
|
||||
return self.clean_response(response)
|
||||
|
||||
|
114
plugins/f5.py
114
plugins/f5.py
@ -1,18 +1,108 @@
|
||||
from servicebase import ServiceBase
|
||||
import requests
|
||||
import re
|
||||
import json
|
||||
|
||||
class ServiceDelegate(ServiceBase) :
|
||||
|
||||
current_auth_header = None
|
||||
return_payload = {}
|
||||
hosts = None
|
||||
|
||||
def get_arguments(cls) :
|
||||
"""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 ['-cg', '--vip', 'store_true', "Return VIP information about the subject"]
|
||||
|
||||
def get_f5_auth_header(host,username,password,authprovider) :
|
||||
"""Given authentication information, return the authenticated header for use in REST requests to an F5 device."""
|
||||
pass
|
||||
def get_f5_for_dc(dc) :
|
||||
"""Given a datacenter, return the next F5 device for that datacenter."""
|
||||
pass
|
||||
def get_vip_cg(ip) :
|
||||
"""Given an IP, return all VIPs that the IP is a member of."""
|
||||
pass
|
||||
def startup(self) :
|
||||
for requirement in ['hosts','username','key'] :
|
||||
if requirement not in self.config or (requirement in self.config and self.config[requirement] is ''):
|
||||
self.return_payload.update({'error':'Missing required config option ' + requirement})
|
||||
return
|
||||
self.hosts = self.config['hosts']
|
||||
#self.current_auth_header = self.get_bc_auth_header(self.config['host'],self.config['username'],self.config['key'])
|
||||
|
||||
def perform_lookup(self,host_tuple) :
|
||||
error = None
|
||||
if self.return_payload and 'error' in self.return_payload :
|
||||
error = self.return_payload['error']
|
||||
self.return_payload = {}
|
||||
if error :
|
||||
self.return_payload.update({'error':error})
|
||||
self.return_payload.update({'lookupcandidates':self.choose_host(host_tuple)})
|
||||
|
||||
|
||||
return self.return_payload
|
||||
if self.current_auth_header :
|
||||
object = self.search_bc_object(host_tuple)
|
||||
self.return_payload.update({'object':object})
|
||||
parent = self.search_bc_parent_object(host_tuple)
|
||||
self.return_payload.update({'parent':parent})
|
||||
return self.return_payload
|
||||
|
||||
def shutdown(self) :
|
||||
return
|
||||
if self.host and self.current_auth_header :
|
||||
logout = requests.get("https://" + self.host + "/Services/REST/v1/logout",headers=self.current_auth_header)
|
||||
if not logout.text.endswith("successfully logged out.\"") :
|
||||
self.return_payload.update({'error':'Unable to log out of BlueCat API session'})
|
||||
|
||||
|
||||
def get_bc_auth_header(self,host,username,password) :
|
||||
auth_token = requests.get("https://" + host + "/Services/REST/v1/login?username=" + username + "&password=" + password).text[17:71]
|
||||
if auth_token.startswith('BAMAuthToken') :
|
||||
return { "Authorization" : auth_token }
|
||||
else :
|
||||
return None
|
||||
|
||||
def search_bc_object(self,host_tuple) :
|
||||
"""Searches BC for the subject."""
|
||||
response = requests.get("https://" + self.host + "/Services/REST/v1/searchByObjectTypes?keyword=" + host_tuple[2][0] + "&types=IP4Address,IP6Address&start=0&count=10",headers=self.current_auth_header)
|
||||
return self.clean_response(response)
|
||||
|
||||
def search_bc_parent_object(self,host_tuple) :
|
||||
"""Search for and return information about the objects parent, if any"""
|
||||
if 'object' in self.return_payload and 'id' in self.return_payload['object'] :
|
||||
response = requests.get("https://" + self.host + "/Services/REST/v1/getParent?entityId=" + str(self.return_payload['object']['id']), headers=self.current_auth_header)
|
||||
return self.clean_response(response)
|
||||
|
||||
def choose_host(self,host_tuple) :
|
||||
"""Given a host_tuple, return the host that we suspect is responsible for the VIP resides in."""
|
||||
hosts = {}
|
||||
# Guess based on hostname
|
||||
dcmatch = re.search('^[a-zA-Z]*-([a-zA-Z0-9]*)(-.*)*$',host_tuple[0])
|
||||
if dcmatch :
|
||||
potentialdc = dcmatch.group(1)
|
||||
else :
|
||||
potentialdc = None
|
||||
if potentialdc :
|
||||
for host in self.hosts.keys() :
|
||||
if potentialdc.lower() in host.lower() :
|
||||
hosts.update({host:self.hosts[host]})
|
||||
if hosts != {} :
|
||||
return hosts
|
||||
# No hostname match, maybe we have info from bluecat?
|
||||
if 'bluecat' in self.data and host_tuple in self.data['bluecat'] and self.data['bluecat'][host_tuple]['object'] :
|
||||
potentialdc = self.data['bluecat'][host_tuple]['object']['locationCode'].split(' ')[-1]
|
||||
for host in self.hosts.keys() :
|
||||
if potentialdc.lower() in host.lower() :
|
||||
hosts.update({host:self.hosts[host]})
|
||||
return hosts
|
||||
return hosts
|
||||
|
||||
def clean_response(self,response) :
|
||||
parsed = {}
|
||||
try :
|
||||
parsed = json.loads(response.text)
|
||||
except Exception :
|
||||
return parsed
|
||||
if type(parsed) is list and len(parsed) > 0 :
|
||||
parsed = parsed[0]
|
||||
if type(parsed) is dict :
|
||||
if 'properties' in parsed :
|
||||
parsed["properties"] = parsed["properties"][:-1]
|
||||
bad_delim_props = [x for x in parsed["properties"].split("|") if x.count('=') > 1]
|
||||
if len(bad_delim_props) > 0 :
|
||||
parsed.update({"unknown":bad_delim_props})
|
||||
attributes = dict(x.split("=") for x in parsed["properties"].split("|") if x.count('=') == 1)
|
||||
parsed.pop("properties", None)
|
||||
parsed.update(attributes)
|
||||
return parsed
|
||||
|
Loading…
Reference in New Issue
Block a user