diff --git a/netbox_agent/cli.py b/netbox_agent/cli.py index 6b29d80..d7ee2bb 100644 --- a/netbox_agent/cli.py +++ b/netbox_agent/cli.py @@ -3,6 +3,7 @@ import argparse from netbox_agent.dell.dell import DellHost import netbox_agent.dmidecode as dmidecode from netbox_agent.hp.hp import HPHost +from netbox_agent.logging import logging # NOQA MANUFACTURERS = { 'Dell Inc.': DellHost, diff --git a/netbox_agent/config.py b/netbox_agent/config.py index e2b4230..6d24c48 100644 --- a/netbox_agent/config.py +++ b/netbox_agent/config.py @@ -10,6 +10,8 @@ netbox_instance = pynetbox.api( token=config['netbox']['token'] ) +LOG_LEVEL = config.get('log_level', 'debug') + DATACENTER_LOCATION_DRIVER_FILE = None DATACENTER_LOCATION = None DATACENTER_LOCATION_REGEX = None diff --git a/netbox_agent/ethtool.py b/netbox_agent/ethtool.py index 91522c9..312df95 100644 --- a/netbox_agent/ethtool.py +++ b/netbox_agent/ethtool.py @@ -61,7 +61,7 @@ class Ethtool(): if status != 0: return {} r = re.search(r'Identifier.*\((\w+)\)', output) - if r and r.groups() > 0: + if r and len(r.groups()) > 0: return {'form_factor': r.groups()[0]} def parse(self): diff --git a/netbox_agent/logging.py b/netbox_agent/logging.py new file mode 100644 index 0000000..4a21dc3 --- /dev/null +++ b/netbox_agent/logging.py @@ -0,0 +1,11 @@ +import logging + +from netbox_agent.config import LOG_LEVEL + + +logger = logging.getLogger() + +if LOG_LEVEL == 'debug': + logger.setLevel(logging.DEBUG) +else: + logger.setLevel(logging.INFO) diff --git a/netbox_agent/network.py b/netbox_agent/network.py index a2ac399..07ec6c0 100644 --- a/netbox_agent/network.py +++ b/netbox_agent/network.py @@ -1,4 +1,5 @@ from itertools import chain +import logging import os import re @@ -80,14 +81,18 @@ class Network(): def create_netbox_nic(self, device, nic): # TODO: add Optic Vendor, PN and Serial + type = self.get_netbox_type_for_nic(nic) + logging.info('Creating NIC {name} ({mac}) on {device}'.format( + name=nic['name'], mac=nic['mac'], device=device.name)) return nb.dcim.interfaces.create( device=device.id, name=nic['name'], mac_address=nic['mac'], - type=self.get_netbox_type_for_nic(nic), + type=type, ) def create_netbox_network_cards(self): + logging.debug('Creating NIC...') device = self.server.get_netbox_server() for nic in self.nics: interface = nb.dcim.interfaces.get( @@ -105,16 +110,22 @@ class Network(): address=ip, ) if netbox_ip: + logging.info('Assigning existing IP {ip} to {interface}'.format( + ip=ip, interface=new_interface)) netbox_ip.interface = new_interface netbox_ip.save() else: + logging.info('Create new IP {ip} on {interface}'.format( + ip=ip, interface=new_interface)) netbox_ip = nb.ipam.ip_addresses.create( address=ip, interface=new_interface.id, status=1, ) + logging.debug('Finished creating NIC!') def update_netbox_network_cards(self): + logging.debug('Updating NIC...') device = self.server.get_netbox_server() # delete IP on netbox that are not known on this server @@ -126,6 +137,8 @@ class Network(): ])) for netbox_ip in netbox_ips: if netbox_ip.address not in all_local_ips: + logging.info('Unassigning IP {ip} from {interface}'.format( + ip=netbox_ip.address, interface=netbox_ip.interface)) netbox_ip.interface = None netbox_ip.save() @@ -134,10 +147,17 @@ class Network(): interface = nb.dcim.interfaces.get( mac_address=nic['mac'], ) + if not interface: + logging.info('Interface {} not found, creating..'.format( + mac_address=nic['mac']) + ) + interface = self.create_netbox_nic(device, nic) nic_update = False if nic['name'] != interface.name: nic_update = True + logging.info('Updating interface {interface} name to: {name}'.format( + interface=interface, name=nic['name'])) interface.name = nic['name'] if nic['ip']: @@ -153,9 +173,19 @@ class Network(): interface=interface.id, status=1, ) + logging.info('Created new IP {ip} on {interface}'.format( + ip=ip, interface=interface)) else: - if netbox_ip.interface != interface: + if netbox_ip.interface.id != interface.id: + logging.info( + 'Detected interface change: old interface is {old_interface} ' + '(id: {old_id}), new interface is {new_interface} (id: {new_id})' + .format( + old_interface=netbox_ip.interface, new_interface=interface, + old_id=netbox_ip.id, new_id=interface.id + )) netbox_ip.interface = interface netbox_ip.save() if nic_update: interface.save() + logging.debug('Finished updating NIC!') diff --git a/netbox_agent/server.py b/netbox_agent/server.py index b445664..636fdde 100644 --- a/netbox_agent/server.py +++ b/netbox_agent/server.py @@ -1,8 +1,8 @@ +import logging from pprint import pprint import socket from netbox_agent.config import netbox_instance as nb - import netbox_agent.dmidecode as dmidecode from netbox_agent.location import Datacenter, Rack from netbox_agent.network import Network @@ -81,14 +81,19 @@ class ServerBase(): model=self.get_chassis(), ) if not device_type: - raise Exception('Chassis "{}" doesn\'t exist'.format(self.get_chassis())) + error_msg = 'Chassis "{}" doesn\'t exist'.format(self.get_chassis()) + logging.error(error_msg) + raise Exception(error_msg) device_role = nb.dcim.device_roles.get( name='Server Chassis', ) + serial = self.get_chassis_service_tag() + logging.info('Creating chassis blade (serial: {serial})'.format( + serial=serial)) new_chassis = nb.dcim.devices.create( name=''.format(), device_type=device_type.id, - serial=self.get_chassis_service_tag(), + serial=serial, device_role=device_role.id, site=datacenter.id if datacenter else None, ) @@ -101,9 +106,15 @@ class ServerBase(): device_type = nb.dcim.device_types.get( model=self.get_product_name(), ) + serial = self.get_service_tag() + hostname = self.get_hostname() + logging.info( + 'Creating blade (serial: {serial}) {hostname} on chassis {chassis_serial}'.format( + serial=serial, hostname=hostname, chassis_serial=chassis.serial + )) new_blade = nb.dcim.devices.create( - name=self.get_hostname(), - serial=self.get_service_tag(), + name=hostname, + serial=serial, device_role=device_role.id, device_type=device_type.id, parent_device=chassis.id, @@ -120,9 +131,13 @@ class ServerBase(): ) if not device_type: raise Exception('Chassis "{}" doesn\'t exist'.format(self.get_chassis())) + serial = self.get_service_tag() + hostname = self.get_hostname() + logging.info('Creating server (serial: {serial}) {hostname}'.format( + serial=serial, hostname=hostname)) new_server = nb.dcim.devices.create( - name=self.get_hostname(), - serial=self.get_service_tag(), + name=hostname, + serial=serial, device_role=device_role.id, device_type=device_type.id, site=datacenter.id if datacenter else None, @@ -133,10 +148,12 @@ class ServerBase(): return nb.dcim.devices.get(serial=self.get_service_tag()) def netbox_create(self): + logging.debug('Creating Server..') datacenter = self.get_netbox_datacenter() if self.is_blade(): # let's find the blade - blade = nb.dcim.devices.get(serial=self.get_service_tag()) + serial = self.get_service_tag() + blade = nb.dcim.devices.get(serial=serial) chassis = nb.dcim.devices.get(serial=self.get_chassis_service_tag()) # if it doesn't exist, create it if not blade: @@ -151,20 +168,24 @@ class ServerBase(): blade = self._netbox_create_blade(chassis, datacenter) # Find the slot and update it with our blade + slot = self.get_blade_slot() device_bays = nb.dcim.device_bays.filter( device_id=chassis.id, - name='Blade {}'.format(self.get_blade_slot()), + name='Blade {}'.format(slot), ) if len(device_bays) > 0: + logging.info('Updating blade ({serial}) slot on: Blade {slot}'.format( + serial=serial, slot=slot)) device_bay = device_bays[0] device_bay.installed_device = blade device_bay.save() else: server = nb.dcim.devices.get(serial=self.get_service_tag()) if not server: - self._netbox_create_server() + self._netbox_create_server(datacenter) self.network.create_netbox_network_cards() + logging.debug('Server created!') def netbox_update(self): """ @@ -176,6 +197,7 @@ class ServerBase(): * hostname update * new network infos """ + logging.debug('Updating Server...') server = nb.dcim.devices.get(serial=self.get_service_tag()) if not server: raise Exception("The server (Serial: {}) isn't yet registered in Netbox, register" @@ -203,14 +225,23 @@ class ServerBase(): chassis = self._netbox_create_blade_chassis(datacenter) if move_device_bay or device_bay.name != 'Blade {}'.format(self.get_blade_slot()): + logging.info('Device ({serial}) seems to have moved, reseting old slot..'.format( + serial=server.serial)) device_bay.installed_device = None device_bay.save() + + slot = self.get_blade_slot() # Find the slot and update it with our blade device_bays = nb.dcim.device_bays.filter( device_id=chassis.id, - name='Blade {}'.format(self.get_blade_slot()), + name='Blade {}'.format(slot), ) if len(device_bays) > 0: + logging.info( + 'Setting device ({serial}) new slot on Blade {slot} ' + '(Chassis {chassis_serial})..'.format( + serial=server.serial, slot=slot, chassis_serial=chassis.serial + )) device_bay = device_bays[0] device_bay.installed_device = server device_bay.save() @@ -224,6 +255,7 @@ class ServerBase(): self.network.update_netbox_network_cards() if update: server.save() + logging.debug('Finished updating Server!') def print_debug(self): # FIXME: do something more generic by looping on every get_* methods