From cd97fe4d3a07c84f23e1ff9ed9e3e3b1991b963d Mon Sep 17 00:00:00 2001 From: Solvik Blum Date: Mon, 5 Aug 2019 12:02:42 +0200 Subject: [PATCH 1/5] wip --- netbox_agent/server.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/netbox_agent/server.py b/netbox_agent/server.py index b8b8f07..3e8709d 100644 --- a/netbox_agent/server.py +++ b/netbox_agent/server.py @@ -148,6 +148,14 @@ class ServerBase(): self.network.update_netbox_network_cards() + def netbox_update(self): + server = nb.dcim.devices.get(serial=self.get_service_tag()) + if self.is_blade(): + # check if the slot/chassis is the same + # for every other specs + # check hostname + # check network cards + def print_debug(self): # FIXME: do something more generic by looping on every get_* methods print('Datacenter:', self.get_datacenter()) From e80d8b941c9cb4d55af48574a6b57dad76b6c9f1 Mon Sep 17 00:00:00 2001 From: Solvik Blum Date: Mon, 5 Aug 2019 16:03:35 +0200 Subject: [PATCH 2/5] wip - update in progress, working for blades/hostname --- netbox_agent/cli.py | 8 ++++-- netbox_agent/server.py | 65 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/netbox_agent/cli.py b/netbox_agent/cli.py index c0498bf..6b29d80 100644 --- a/netbox_agent/cli.py +++ b/netbox_agent/cli.py @@ -18,14 +18,18 @@ def run(args): server.print_debug() if args.register: server.netbox_create() + if args.update: + server.netbox_update() return True def main(): parser = argparse.ArgumentParser(description='Netbox agent command line') - parser.add_argument('--register', action='store_true', + parser.add_argument('-r', '--register', action='store_true', help='Register server in Netbox') - parser.add_argument('--debug', action='store_true', + parser.add_argument('-u', '--update', action='store_true', + help='Update server in Netbox') + parser.add_argument('-d', '--debug', action='store_true', help='Print debug informations') args = parser.parse_args() diff --git a/netbox_agent/server.py b/netbox_agent/server.py index 3e8709d..d7b0626 100644 --- a/netbox_agent/server.py +++ b/netbox_agent/server.py @@ -2,7 +2,7 @@ from pprint import pprint import socket from netbox_agent.config import netbox_instance as nb -from netbox_agent.datacenter import Datacenter +from netbox_agent.location import Datacenter import netbox_agent.dmidecode as dmidecode from netbox_agent.network import Network @@ -40,6 +40,9 @@ class ServerBase(): """ return self.system[0]['Serial Number'] + def get_hostname(self): + return '{}'.format(socket.gethostname()) + def is_blade(self): raise NotImplementedError @@ -87,7 +90,7 @@ class ServerBase(): model=self.get_product_name(), ) new_blade = nb.dcim.devices.create( - name='{}'.format(socket.gethostname()), + name=self.get_hostname(), serial=self.get_service_tag(), device_role=device_role.id, device_type=device_type.id, @@ -106,7 +109,7 @@ class ServerBase(): if not device_type: raise Exception('Chassis "{}" doesn\'t exist'.format(self.get_chassis())) new_server = nb.dcim.devices.create( - name='{}'.format(socket.gethostname()), + name=self.get_hostname(), serial=self.get_service_tag(), device_role=device_role.id, device_type=device_type.id, @@ -127,6 +130,9 @@ class ServerBase(): if not blade: # check if the chassis exist before # if it doesn't exist, create it + chassis = nb.dcim.devices.get( + serial=self.get_chassis_service_tag() + ) if not chassis: chassis = self._netbox_create_blade_chassis(datacenter) @@ -149,12 +155,63 @@ class ServerBase(): self.network.update_netbox_network_cards() def netbox_update(self): + """ + Netbox method to update info about our server/blade + + Handle: + * new chasis for a blade + * new slot for a bblade + * hostname update + * new network infos + """ 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" + "it before updating it".format(self.get_service_tag())) + update = False if self.is_blade(): - # check if the slot/chassis is the same + # get current chassis device bay + device_bay = nb.dcim.device_bays.get( + server.parent_device.device_bay.id + ) + netbox_chassis_serial = server.parent_device.device_bay.device.serial + chassis = server.parent_device.device_bay.device + move_device_bay = False + + # check chassis serial with dmidecode + if netbox_chassis_serial != self.get_chassis_service_tag(): + move_device_bay = True + # try to find the new netbox chassis + chassis = nb.dcim.devices.get( + serial=self.get_chassis_service_tag() + ) + # create the new chassis if it doesn't exist + if not chassis: + chassis = self._netbox_create_blade_chassis(datacenter) + + if move_device_bay or device_bay.name != 'Blade {}'.format(self.get_blade_slot()): + device_bay.installed_device = None + device_bay.save() + + # 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()), + ) + if len(device_bays) > 0: + device_bay = device_bays[0] + device_bay.installed_device = server + device_bay.save() + # for every other specs # check hostname + if server.name != self.get_hostname(): + update = True + server.hostname = self.get_hostname() # check network cards + #self.network.update_netbox_network_cards() + if update: + server.save() def print_debug(self): # FIXME: do something more generic by looping on every get_* methods From 165f911631904cb3f1717e6c555ebe21b263ba78 Mon Sep 17 00:00:00 2001 From: Solvik Blum Date: Mon, 5 Aug 2019 16:51:01 +0200 Subject: [PATCH 3/5] handle network update --- netbox_agent/network.py | 53 +++++++++++++++++++++++++++++++++++------ netbox_agent/server.py | 5 ++-- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/netbox_agent/network.py b/netbox_agent/network.py index 38855ca..984e5df 100644 --- a/netbox_agent/network.py +++ b/netbox_agent/network.py @@ -1,5 +1,6 @@ import os import re +from itertools import chain from netaddr import IPAddress import netifaces @@ -86,7 +87,7 @@ class Network(): type=self.get_netbox_type_for_nic(nic), ) - def update_netbox_network_cards(self): + def create_netbox_network_cards(self): device = self.server.get_netbox_server() for nic in self.nics: interface = nb.dcim.interfaces.get( @@ -112,9 +113,47 @@ class Network(): interface=new_interface.id, status=1, ) - # or we check if it needs update - else: - # FIXME: implement update - # update name or ip - # see https://github.com/Solvik/netbox_agent/issues/9 - pass + + def update_netbox_network_cards(self): + device = self.server.get_netbox_server() + + # delete IP on netbox that are not known on this server + netbox_ips = nb.ipam.ip_addresses.filter( + device=device + ) + all_local_ips = list(chain.from_iterable([x['ip'] for x in self.nics if x['ip'] != None])) + for netbox_ip in netbox_ips: + if netbox_ip.address not in all_local_ips: + netbox_ip.interface = None + netbox_ip.save() + + # update each nic + for nic in self.nics: + interface = nb.dcim.interfaces.get( + mac_address=nic['mac'], + ) + + nic_update = False + if nic['name'] != interface.name: + nic_update = True + interface.name = nic['name'] + + if nic['ip']: + # sync local IPs + for ip in nic['ip']: + netbox_ip = nb.ipam.ip_addresses.get( + address=ip, + ) + if not netbox_ip: + # create netbbox_ip on device + netbox_ip = nb.ipam.ip_addresses.create( + address=ip, + interface=interface.id, + status=1, + ) + else: + if netbox_ip.device != device: + netbox_ip.device = device + netbox_ip.save() + if nic_update: + interface.save() diff --git a/netbox_agent/server.py b/netbox_agent/server.py index d7b0626..bfd27e0 100644 --- a/netbox_agent/server.py +++ b/netbox_agent/server.py @@ -152,7 +152,7 @@ class ServerBase(): if not server: self._netbox_create_server() - self.network.update_netbox_network_cards() + self.network.create_netbox_network_cards() def netbox_update(self): """ @@ -192,7 +192,6 @@ class ServerBase(): if move_device_bay or device_bay.name != 'Blade {}'.format(self.get_blade_slot()): device_bay.installed_device = None device_bay.save() - # Find the slot and update it with our blade device_bays = nb.dcim.device_bays.filter( device_id=chassis.id, @@ -209,7 +208,7 @@ class ServerBase(): update = True server.hostname = self.get_hostname() # check network cards - #self.network.update_netbox_network_cards() + self.network.update_netbox_network_cards() if update: server.save() From bea1bf8614edf1256931c010ae889b619bd55317 Mon Sep 17 00:00:00 2001 From: Solvik Blum Date: Mon, 5 Aug 2019 16:55:22 +0200 Subject: [PATCH 4/5] flake8 fixes --- netbox_agent/server.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/netbox_agent/server.py b/netbox_agent/server.py index bfd27e0..01ddc3c 100644 --- a/netbox_agent/server.py +++ b/netbox_agent/server.py @@ -167,7 +167,7 @@ class ServerBase(): 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" - "it before updating it".format(self.get_service_tag())) + 'it before updating it'.format(self.get_service_tag())) update = False if self.is_blade(): # get current chassis device bay @@ -187,6 +187,7 @@ class ServerBase(): ) # create the new chassis if it doesn't exist if not chassis: + datacenter = self.get_netbox_datacenter() chassis = self._netbox_create_blade_chassis(datacenter) if move_device_bay or device_bay.name != 'Blade {}'.format(self.get_blade_slot()): From 69a9327b18de06899037547923268feef7b7685b Mon Sep 17 00:00:00 2001 From: Solvik Blum Date: Mon, 5 Aug 2019 16:55:37 +0200 Subject: [PATCH 5/5] flake8 fixes --- netbox_agent/network.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/netbox_agent/network.py b/netbox_agent/network.py index 984e5df..44e6efc 100644 --- a/netbox_agent/network.py +++ b/netbox_agent/network.py @@ -1,6 +1,6 @@ +from itertools import chain import os import re -from itertools import chain from netaddr import IPAddress import netifaces @@ -121,7 +121,9 @@ class Network(): netbox_ips = nb.ipam.ip_addresses.filter( device=device ) - all_local_ips = list(chain.from_iterable([x['ip'] for x in self.nics if x['ip'] != None])) + all_local_ips = list(chain.from_iterable([ + x['ip'] for x in self.nics if x['ip'] is not None + ])) for netbox_ip in netbox_ips: if netbox_ip.address not in all_local_ips: netbox_ip.interface = None