From b412695c22ccaf0f11f36b62df15eb3dfadd72f2 Mon Sep 17 00:00:00 2001 From: dejanlevaja Date: Mon, 14 Mar 2016 19:31:50 +0100 Subject: [PATCH] v3.6 Device lookup by MAC address --- inventory.cfg.sample | 1 + main.py | 97 +++++++++++++++++++++++++++++++++++++++++--- module_shared.py | 9 ++-- util_uploader.py | 17 +++++++- 4 files changed, 113 insertions(+), 11 deletions(-) diff --git a/inventory.cfg.sample b/inventory.cfg.sample index 6d71e6d..6e86820 100644 --- a/inventory.cfg.sample +++ b/inventory.cfg.sample @@ -58,6 +58,7 @@ remove_stale_ips = True add_hdd_as_device_properties= True add_hdd_as_parts = True give_hostname_precedence = True +mac_lookup = False debug = True threads = 50 dict_output = False diff --git a/main.py b/main.py index f60a18f..8f85929 100644 --- a/main.py +++ b/main.py @@ -16,16 +16,78 @@ import module_openbsd as openbsd import module_aix as aix -__version__ = "3.5" +__version__ = "3.6" # environment and other stuff lock = threading.Lock() q = Queue.Queue() +def mac_lookup_map(): + rest = uploader.Rest(base_url, username, secret, debug) + url = base_url + '/api/1.0/macs/' + response = rest.fetcher(url) + + #print json.dumps(r, indent=4, sort_keys=True) + if isinstance(response, dict): + macs = response['macaddresses'] + mac_devid_map = {} + + # single device might have multiple macs + # create dict to store dev_id:{mac_id:mac} mappings + macdb = {} + for m in macs: + try: + mid = int(m['macaddress_id']) + mac = m['macaddress'] + dev_id = m['device']['device_id'] + if dev_id not in macdb: + macdb.update({dev_id:[{mid:mac}]}) + else: + macdb[dev_id].append({mid:mac}) + except: + pass + if macdb: + for k,values in macdb.items(): + # we must discover smallest mac_id. Mac with smallest mac_id is the 'first' one and it is used for mac lookup + smallest = 99999999999999999999 + mac = None + dev_id = k + for value in values: + mid = value.keys()[0] + if mid < smallest: + smallest = mid + mac = value[mid] + # create mac:dev_id mapping + mac_devid_map.update({mac:dev_id}) + + macdb.clear() + return mac_devid_map + + +def find_devid_by_mac(data): + macs = [] + for rec in data: + if 'macaddress' in rec: + m = rec['macaddress'] + macs.append(m) + + for mac in macs: + if mac in mac_devid_map: + dev_id = mac_devid_map[mac] + return dev_id + + + def upload(data): + dev_id = None + if mac_lookup: + dev_id = find_devid_by_mac(data) + + ips = [] name = None + result = None rest = uploader.Rest(base_url, username, secret, debug) # get hdd parts if any @@ -42,16 +104,30 @@ def upload(data): devindex = data.index(rec) if devindex != None: rec = data[devindex] - if duplicate_serials: - result, scode = rest.post_multinodes(rec) + if mac_lookup and dev_id and not duplicate_serials: + rec.update({'device_id':dev_id}) + result, scode = rest.put_device(rec) if scode != 200: - print '\n[!] Error! Could not upload devices: %s\n' % str(rec) + print '\n[!] Error! Could not upload device: %s\n' % str(rec) return + elif duplicate_serials: + if mac_lookup and dev_id: + rec.update({'device_id':dev_id}) + result, scode = rest.put_device(rec) + if scode != 200: + print '\n[!] Error! Could not upload device: %s\n' % str(rec) + return + else: + result, scode = rest.post_multinodes(rec) + if scode != 200: + print '\n[!] Error! Could not upload devices: %s\n' % str(rec) + return else: result, scode = rest.post_device(rec) if scode != 200: print '\n[!] Error! Could not upload device: %s\n' % str(rec) return + try: name = result['msg'][2] except IndexError: @@ -262,6 +338,8 @@ def check_os(ip): if cred not in ('', ' ', '\n'): try: usr, pwd = cred.split(':') + usr = usr.strip() + pwd = pwd.strip() except ValueError: print '\n[!] Error. \n\tPlease check credentials formatting. It should look like user:password\n' sys.exit() @@ -337,6 +415,8 @@ def check_os(ip): def main(): + if mac_lookup: + mac_lookup_map() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(float(timeout)) msg = '\r\n[!] Running %s threads.' % THREADS @@ -389,9 +469,16 @@ def main(): if __name__ == '__main__': from module_shared import * - + if mac_lookup: + if debug: + print '\n[!] Creating MAC<->deviceID map for MAC lookup.\n' + mac_devid_map = mac_lookup_map() main() sys.exit() else: # you can use dict_output if called from external script (starter.py) from module_shared import * + if mac_lookup: + if debug: + print '\n[!] Creating MAC<->deviceID map for MAC lookup.\n' + mac_devid_map = mac_lookup_map() diff --git a/module_shared.py b/module_shared.py index ebc2b58..40fbf6a 100644 --- a/module_shared.py +++ b/module_shared.py @@ -50,6 +50,7 @@ def get_settings(): add_hdd_as_device_properties = cc.getboolean('options', 'add_hdd_as_device_properties') add_hdd_as_parts = cc.getboolean('options', 'add_hdd_as_parts') give_hostname_precedence = cc.getboolean('options', 'give_hostname_precedence') + mac_lookup = cc.getboolean('options', 'mac_lookup') debug = cc.getboolean('options', 'debug') threads = cc.get('options', 'threads') dict_output = cc.getboolean('options', 'dict_output') @@ -58,7 +59,7 @@ def get_settings(): use_key_file, key_file, credentials, ssh_port, timeout, get_serial_info, duplicate_serials,\ add_hdd_as_device_properties, add_hdd_as_parts, get_hardware_info, get_os_details, get_cpu_info,\ get_memory_info, ignore_domain, ignore_virtual_machines, upload_ipv6, debug, threads, dict_output, \ - give_hostname_precedence,remove_stale_ips + give_hostname_precedence, mac_lookup, remove_stale_ips # noinspection PyProtectedMember @@ -68,8 +69,8 @@ def get_settings(): mod_linux, mod_solaris, mod_mac, mod_bsd, mod_aix, base_url, username, secret, targets, exclude_ips, use_key_file,\ key_file, credentials, ssh_port, timeout, get_serial_info, duplicate_serials, add_hdd_as_device_properties,\ add_hdd_as_parts, get_hardware_info, get_os_details, get_cpu_info, get_memory_info, ignore_domain,\ - ignore_virtual_machines, upload_ipv6, debug, THREADS, DICT_OUTPUT, give_hostname_precedence, REMOVE_STALE_IPS \ - = get_settings() + ignore_virtual_machines, upload_ipv6, debug, THREADS, DICT_OUTPUT, give_hostname_precedence, mac_lookup, \ + REMOVE_STALE_IPS = get_settings() ssh_port = int(ssh_port) timeout = int(timeout) @@ -80,7 +81,7 @@ def get_settings(): xuse_key_file, xkey_file, xcredentials, ssh_port, timeout, get_serial_info, duplicate_serials,\ add_hdd_as_device_properties, add_hdd_as_parts, get_hardware_info, get_os_details, get_cpu_info,\ get_memory_info, ignore_domain, ignore_virtual_machines, upload_ipv6, debug, THREADS, DICT_OUTPUT, \ - give_hostname_precedence, REMOVE_STALE_IPS = get_settings() + give_hostname_precedence, mac_lookup, REMOVE_STALE_IPS = get_settings() ssh_port = int(ssh_port) timeout = int(timeout) diff --git a/util_uploader.py b/util_uploader.py index 084ecc8..01cf888 100644 --- a/util_uploader.py +++ b/util_uploader.py @@ -23,9 +23,12 @@ def __init__(self, base_url, username, secret, debug): 'Content-Type': 'application/x-www-form-urlencoded' } - def uploader(self, data, url): + def uploader(self, data, url, method=None): payload = data - r = requests.post(url, data=payload, headers=self.headers, verify=False) + if method == 'put': + r = requests.put(url, data=payload, headers=self.headers, verify=False) + else: + r = requests.post(url, data=payload, headers=self.headers, verify=False) msg = unicode(payload) if self.debug: print msg @@ -59,6 +62,16 @@ def deleter(self, url): else: return status_code + def put_device(self, data): + if not DRY_RUN: + url = self.base_url + '/api/1.0/device/' + msg = '\r\nUpdating device by mac %s ' % url + if self.debug: + print msg + method = 'put' + result, scode = self.uploader(data, url, method) + return result, scode + def post_device(self, data): if not DRY_RUN: url = self.base_url + '/api/device/'