diff --git a/netbox_agent.yaml.example b/netbox_agent.yaml.example new file mode 100644 index 0000000..f6e10c7 --- /dev/null +++ b/netbox_agent.yaml.example @@ -0,0 +1,9 @@ +netbox: + url: 'http://netbox.internal.company.com' + token: supersecrettoken + +datacenter_location: + driver: file:/etc/qualification + regex: "datacenter: (?P[A-Za-z0-9]+)" +# driver: 'cmd:lldpctl' +# regex = 'SysName: .*\.(?P[A-Za-z0-9]+)' diff --git a/netbox_agent/config.py b/netbox_agent/config.py new file mode 100644 index 0000000..007b303 --- /dev/null +++ b/netbox_agent/config.py @@ -0,0 +1,15 @@ +import pynetbox +import yaml + +with open('/etc/netbox_agent.yaml', 'r') as ymlfile: + # FIXME: validate configuration file + config = yaml.load(ymlfile) + +netbox_instance = pynetbox.api( + url=config['netbox']['url'], + token=config['netbox']['token'] +) + + +DATACENTER_LOCATION = config['datacenter_location']['driver'] +DATACENTER_LOCATION_REGEX = config['datacenter_location']['regex'] diff --git a/netbox_agent/datacenter.py b/netbox_agent/datacenter.py new file mode 100644 index 0000000..53aa3cc --- /dev/null +++ b/netbox_agent/datacenter.py @@ -0,0 +1,20 @@ +import importlib + +from netbox_agent.config import DATACENTER_LOCATION, \ + DATACENTER_LOCATION_REGEX + + +class Datacenter(): + """ + """ + def __init__(self, *args, **kwargs): + self.driver = DATACENTER_LOCATION.split(':')[0] + self.driver_value = DATACENTER_LOCATION.split(':')[1] + + try: + self.driver = importlib.import_module('netbox_agent.drivers.datacenter_' + self.driver) + except ImportError: + raise ImportError("Driver {} doesn't exists".format(self.driver)) + + def get(self): + return getattr(self.driver, 'get')(self.driver_value, DATACENTER_LOCATION_REGEX) diff --git a/netbox_agent/drivers/__init__.py b/netbox_agent/drivers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/netbox_agent/drivers/datacenter_cmd.py b/netbox_agent/drivers/datacenter_cmd.py new file mode 100644 index 0000000..ea559bc --- /dev/null +++ b/netbox_agent/drivers/datacenter_cmd.py @@ -0,0 +1,11 @@ +import re +import subprocess + + +def get(value, regex): + output = subprocess.getoutput(value) + r = re.search(regex, output) + if r: + result = r.group('datacenter') + return result + return None diff --git a/netbox_agent/drivers/datacenter_file.py b/netbox_agent/drivers/datacenter_file.py new file mode 100644 index 0000000..b9083e0 --- /dev/null +++ b/netbox_agent/drivers/datacenter_file.py @@ -0,0 +1,9 @@ +import re + + +def get(value, regex): + for line in open(value, 'r'): + r = re.search(regex, line) + if r: + return r.group('datacenter') + return None diff --git a/netbox_agent/server.py b/netbox_agent/server.py index 3677ca1..c61f7b9 100644 --- a/netbox_agent/server.py +++ b/netbox_agent/server.py @@ -3,6 +3,7 @@ import re import socket from netbox_agent.config import netbox_instance as nb +from netbox_agent.datacenter import Datacenter import netbox_agent.dmidecode as dmidecode # Regex to match base interface name @@ -21,6 +22,16 @@ class ServerBase(): self.network_cards = [] + def get_datacenter(self): + dc = Datacenter() + return dc.get().upper() + + def get_netbox_datacenter(self): + datacenter = nb.dcim.sites.get( + name=self.get_datacenter() + ) + return datacenter + def get_product_name(self): """ Return the Chassis Name from dmidecode info @@ -66,7 +77,7 @@ class ServerBase(): nics.append(nic) return nics - def _netbox_create_blade_chassis(self): + def _netbox_create_blade_chassis(self, datacenter): device_type = nb.dcim.device_types.get( model=self.get_chassis(), ) @@ -75,39 +86,33 @@ class ServerBase(): device_role = nb.dcim.device_roles.get( name='Server Chassis', ) - datacenter = nb.dcim.sites.get( - name='DC3', # FIXME: datacenter support - ) new_chassis = nb.dcim.devices.create( name=''.format(), device_type=device_type.id, serial=self.get_chassis_service_tag(), device_role=device_role.id, - site=datacenter.id, + site=datacenter.id if datacenter else None, ) return new_chassis - def _netbox_create_blade(self, chassis): + def _netbox_create_blade(self, chassis, datacenter): device_role = nb.dcim.device_roles.get( name='Blade', ) device_type = nb.dcim.device_types.get( model=self.get_product_name(), ) - datacenter = nb.dcim.sites.get( - name='DC3', # FIXME: datacenter support - ) new_blade = nb.dcim.devices.create( name='{}'.format(socket.gethostname()), serial=self.get_service_tag(), device_role=device_role.id, device_type=device_type.id, parent_device=chassis.id, - site=datacenter.id, + site=datacenter.id if datacenter else None, ) return new_blade - def _netbox_create_server(self): + def _netbox_create_server(self, datacenter): device_role = nb.dcim.device_roles.get( name='Server', ) @@ -116,19 +121,17 @@ class ServerBase(): ) if not device_type: raise Exception('Chassis "{}" doesn\'t exist'.format(self.get_chassis())) - datacenter = nb.dcim.sites.get( - name='DC3' # FIXME: datacenter support - ) new_server = nb.dcim.devices.create( name='{}'.format(socket.gethostname()), serial=self.get_service_tag(), device_role=device_role.id, device_type=device_type.id, - site=datacenter.id, + site=datacenter.id if datacenter else None, ) return new_server def netbox_create(self): + datacenter = self.get_netbox_datacenter() if self.is_blade(): # let's find the blade blade = nb.dcim.devices.get(serial=self.get_service_tag()) @@ -138,9 +141,9 @@ class ServerBase(): # check if the chassis exist before # if it doesn't exist, create it if not chassis: - chassis = self._netbox_create_blade_chassis() + chassis = self._netbox_create_blade_chassis(datacenter) - blade = self._netbox_create_blade(chassis) + blade = self._netbox_create_blade(chassis, datacenter) # Find the slot and update it with our blade device_bays = nb.dcim.device_bays.filter( @@ -152,7 +155,6 @@ class ServerBase(): device_bay.installed_device = blade device_bay.save() else: - # FIXME : handle pizza box server = nb.dcim.devices.get(serial=self.get_service_tag()) if not server: self._netbox_create_server()