add cpu,interfaces,disks,motherboard and uses lshw

This commit is contained in:
Thomas Davis 2019-09-03 13:03:04 -07:00
commit abdc2d9036
2 changed files with 181 additions and 121 deletions

View file

@ -8,11 +8,14 @@ from netbox_agent.raid.hp import HPRaid
from netbox_agent.raid.storcli import StorcliRaid from netbox_agent.raid.storcli import StorcliRaid
from netbox_agent.lshw import LSHW from netbox_agent.lshw import LSHW
from pprint import pprint
INVENTORY_TAG = { INVENTORY_TAG = {
'cpu': {'name': 'hw:cpu', 'slug': 'hw-cpu'}, 'cpu': {'name': 'hw:cpu', 'slug': 'hw-cpu'},
'disk': {'name': 'hw:disk', 'slug': 'hw-disk'}, 'disk': {'name': 'hw:disk', 'slug': 'hw-disk'},
'interface':{'name': 'hw:interface', 'slug':'hw-interface'},
'memory': {'name': 'hw:memory', 'slug': 'hw-memory'}, 'memory': {'name': 'hw:memory', 'slug': 'hw-memory'},
'network':{'name': 'hw:network', 'slug':'hw-network'}, 'motherboard':{'name': 'hw:motherboard', 'slug':'hw-motherboard'},
'raid_card': {'name': 'hw:raid_card', 'slug': 'hw-raid-card'}, 'raid_card': {'name': 'hw:raid_card', 'slug': 'hw-raid-card'},
} }
@ -67,16 +70,119 @@ class Inventory():
name=name, name=name,
) )
"""
No spaces in the slug allowed.
"""
if not manufacturer: if not manufacturer:
logging.info('Creating missing manufacturer {name}'.format(name=name)) logging.info('Creating missing manufacturer {name}'.format(name=name))
manufacturer = nb.dcim.manufacturers.create( manufacturer = nb.dcim.manufacturers.create(
name=name, name=name,
slug=name.replace(' ','-').lower(), slug=name.replace(' ','-').lower(),
) )
logging.info('Creating missing manufacturer {name}'.format(name=name)) logging.info('Creating missing manufacturer {name}'.format(name=name))
return manufacturer return manufacturer
def get_netbox_inventory(self, device_id, tag):
try:
items = nb.dcim.inventory_items.filter(
device_id=device_id,
tag=tag
)
except:
logging.info('Tag {tag} is missing, returning empty array.'.format(tag=tag))
items = []
return items
def create_netbox_inventory_item(self, device_id, tags, vendor, name, serial, description):
manufacturer = self.find_or_create_manufacturer(vendor)
_ = nb.dcim.inventory_items.create(
device=device_id,
manufacturer = manufacturer.id,
discovered=True,
tags=tags,
name='{}'.format(name),
serial='{}'.format(serial),
description=description
)
logging.info('Creating inventory item {} {}/{} {} '.format(vendor, name, serial, description))
def get_hw_motherboards(self):
motherboards = []
m = {}
m['serial'] = self.lshw.motherboard_serial
m['vendor'] = self.lshw.vendor
m['name'] = '{} {}'.format(self.lshw.vendor, self.lshw.motherboard)
m['description'] = '{} Motherboard'.format(self.lshw.motherboard)
motherboards.append(m)
return motherboards
def do_netbox_motherboard(self):
motherboards = self.get_hw_motherboards()
nb_motherboards = self.get_netbox_inventory(
device_id=self.device_id,
tag=INVENTORY_TAG['motherboard']['slug'])
for nb_motherboard in nb_motherboards:
if nb_motherboard.serial not in [x['serial'] for x in motherboards]:
logging.info('Deleting unknown motherboard {vendor} {motherboard}/{serial}'.format(
motherboard=self.lshw.motherboard,
serial=nb_motherboard.serial,
))
nb_motherboard.delete()
# create interfaces that are not in netbox
for motherboard in motherboards:
if motherboard.get('serial') not in [x.serial for x in nb_motherboards]:
self.create_netbox_inventory_item(
device_id = self.device_id,
tags=[INVENTORY_TAG['motherboard']['slug']],
vendor='{}'.format(motherboard.get('vendor', 'N/A')),
serial='{}'.format(motherboard.get('serial', '000000')),
name='{}'.format(motherboard.get('name')),
description='{}'.format(motherboard.get('description'))
)
def create_netbox_interface(self, iface):
manufacturer = self.find_or_create_manufacturer(iface["vendor"])
_ = nb.dcim.inventory_items.create(
device=self.device_id,
manufacturer = manufacturer.id,
discovered=True,
tags=[INVENTORY_TAG['interface']['name']],
name="{}".format(iface['product']),
serial='{}'.format(iface['serial']),
description='{} {}'.format(iface['description'], iface['name'])
)
def do_netbox_interfaces(self):
nb_interfaces = self.get_netbox_inventory(
device_id=self.device_id,
tag=INVENTORY_TAG['interface']['slug'])
interfaces = self.lshw.interfaces
# delete interfaces that are in netbox but not locally
# use the serial_number has the comparison element
for nb_interface in nb_interfaces:
if nb_interface.serial not in [x['serial'] for x in interfaces]:
logging.info('Deleting unknown interface {serial}'.format(
serial=nb_interface.serial,
))
nb_interface.delete()
# create interfaces that are not in netbox
for iface in interfaces:
if iface.get('serial') not in [x.serial for x in nb_interfaces]:
self.create_netbox_interface(iface)
def create_netbox_cpus(self): def create_netbox_cpus(self):
for cpu in self.lshw.get_hw_linux('cpu'): for cpu in self.lshw.get_hw_linux('cpu'):
manufacturer = self.find_or_create_manufacturer(cpu["vendor"]) manufacturer = self.find_or_create_manufacturer(cpu["vendor"])
@ -86,15 +192,15 @@ class Inventory():
discovered=True, discovered=True,
tags=[INVENTORY_TAG['cpu']['name']], tags=[INVENTORY_TAG['cpu']['name']],
name=cpu['product'], name=cpu['product'],
description='{}'.format(cpu['location']), description='CPU {}'.format(cpu['location']),
asset_tag=cpu['location'] # asset_tag=cpu['location']
) )
logging.info('Creating CPU model {}'.format(cpu['product'])) logging.info('Creating CPU model {}'.format(cpu['product']))
def update_netbox_cpus(self): def do_netbox_cpus(self):
cpus = self.lshw.get_hw_linux('cpu') cpus = self.lshw.get_hw_linux('cpu')
nb_cpus = nb.dcim.inventory_items.filter( nb_cpus = self.get_netbox_inventory(
device_id=self.device_id, device_id=self.device_id,
tag=INVENTORY_TAG['cpu']['slug'], tag=INVENTORY_TAG['cpu']['slug'],
) )
@ -103,7 +209,8 @@ class Inventory():
len(nb_cpus) and len(cpus) != len(nb_cpus): len(nb_cpus) and len(cpus) != len(nb_cpus):
for x in nb_cpus: for x in nb_cpus:
x.delete() x.delete()
self.create_netbox_cpus()
self.create_netbox_cpus()
def get_raid_cards(self): def get_raid_cards(self):
if self.server.manufacturer == 'Dell': if self.server.manufacturer == 'Dell':
@ -120,17 +227,11 @@ class Inventory():
if len(self.raid.get_controllers()): if len(self.raid.get_controllers()):
return controllers return controllers
def get_netbox_raid_cards(self):
raid_cards = nb.dcim.inventory_items.filter(
device_id=self.device_id,
tag=INVENTORY_TAG['raid_card']['slug'],
)
return raid_cards
def create_netbox_raid_card(self, raid_card): def create_netbox_raid_card(self, raid_card):
manufacturer = self.find_or_create_manufacturer( manufacturer = self.find_or_create_manufacturer(
raid_card.get_manufacturer() raid_card.get_manufacturer()
) )
name = raid_card.get_product_name() name = raid_card.get_product_name()
serial = raid_card.get_serial_number() serial = raid_card.get_serial_number()
nb_raid_card = nb.dcim.inventory_items.create( nb_raid_card = nb.dcim.inventory_items.create(
@ -149,7 +250,10 @@ class Inventory():
return nb_raid_card return nb_raid_card
def create_netbox_raid_cards(self): def create_netbox_raid_cards(self):
for raid_card in self.get_raid_cards(): for raid_card in self.get_netbox_inventory(
device_id=self.device_id,
tag=[INVENTORY_TAG['raid_card']['name']]
):
self.create_netbox_raid_card(raid_card) self.create_netbox_raid_card(raid_card)
def update_netbox_raid_cards(self): def update_netbox_raid_cards(self):
@ -163,7 +267,10 @@ class Inventory():
We only need to handle destroy and new cards We only need to handle destroy and new cards
""" """
nb_raid_cards = self.get_netbox_raid_cards() nb_raid_cards = self.self.get_netbox_inventory(
device_id=self.device_id,
tag=[INVENTORY_TAG['raid_card']['name']]
)
raid_cards = self.get_raid_cards() raid_cards = self.get_raid_cards()
# delete cards that are in netbox but not locally # delete cards that are in netbox but not locally
@ -180,20 +287,17 @@ class Inventory():
if raid_card.get_serial_number() not in [x.serial for x in nb_raid_cards]: if raid_card.get_serial_number() not in [x.serial for x in nb_raid_cards]:
self.create_netbox_raid_card(raid_card) self.create_netbox_raid_card(raid_card)
def get_disks(self): def get_hw_disks(self):
disks = [] disks = []
for disk in self.lshw.get_hw_linux("storage"): for disk in self.lshw.get_hw_linux("storage"):
print(disk)
d = {} d = {}
d["name"] = "" d["name"] = ""
d['Size'] = '{} GB'.format(int(disk['size']/1024/1024/1024)) d['size'] = '{} GB'.format(int(disk['size']/1024/1024/1024))
d['Model'] = disk['product'] d['model'] = disk['product']
d['logicalname'] = disk['logicalname'] d['logicalname'] = disk['logicalname']
d['description'] = disk['description'] d['description'] = disk['description']
d['serial'] = disk['serial']
if 'serial' in disk:
d['SN'] = disk['serial']
if 'vendor' in disk: if 'vendor' in disk:
d['vendor'] = disk['vendor'] d['vendor'] = disk['vendor']
@ -204,6 +308,9 @@ class Inventory():
if disk['product'].startswith('Crucial'): if disk['product'].startswith('Crucial'):
d['vendor'] = 'Crucial' d['vendor'] = 'Crucial'
if disk['product'].startswith('Micron'):
d['vendor'] = 'Micron'
if disk['product'].startswith('INTEL'): if disk['product'].startswith('INTEL'):
d['vendor'] = 'Intel' d['vendor'] = 'Intel'
@ -217,47 +324,40 @@ class Inventory():
return disks return disks
def get_netbox_disks(self): def create_netbox_disk(self, disk):
disks = nb.dcim.inventory_items.filter(
device_id=self.device_id,
tag=INVENTORY_TAG['disk']['slug'],
)
return disks
def create_netbox_disks(self):
for disk in self.get_disks():
m_id = 0
if "vendor" in disk: if "vendor" in disk:
manufacturer = self.find_or_create_manufacturer(disk["vendor"]) manufacturer = self.find_or_create_manufacturer(disk["vendor"])
m_id = manufacturer.id
print("inserting disk")
print(disk)
_ = nb.dcim.inventory_items.create( _ = nb.dcim.inventory_items.create(
device=self.device_id, device=self.device_id,
discovered=True, discovered=True,
tags=[INVENTORY_TAG['disk']['name']], tags=[INVENTORY_TAG['disk']['name']],
name='{} - {} ({})'.format(disk.get('description', 'Unknown'), disk.get('logicalname', 'Unknown'), disk.get('Size', 0)), name='{} - {} ({})'.format(
serial=disk['SN'], disk.get('description', 'Unknown'),
part_id=disk['Model'], disk.get('logicalname', 'Unknown'),
description='{}'.format(disk.get('logicalname', 'Unknown')), disk.get('size', 0)
# asset_tag=disk['logicalname'], ),
manufacturer=m_id serial=disk['serial'],
part_id=disk['model'],
description='Device {}'.format(disk.get('logicalname', 'Unknown')),
manufacturer=manufacturer.id
) )
logging.info('Creating Disk {model} {serial}'.format( logging.info('Creating Disk {model} {serial}'.format(
model=disk['Model'], model=disk['model'],
serial=disk['SN'], serial=disk['serial'],
)) ))
def update_netbox_disks(self): def do_netbox_disks(self):
nb_disks = self.get_netbox_disks() nb_disks = self.get_netbox_inventory(
disks = self.get_disks() device_id=self.device_id,
tag=INVENTORY_TAG['disk']['slug'])
disks = self.get_hw_disks()
# delete disks that are in netbox but not locally # delete disks that are in netbox but not locally
# use the serial_number has the comparison element # use the serial_number has the comparison element
for nb_disk in nb_disks: for nb_disk in nb_disks:
if nb_disk.serial not in [x['SN'] for x in disks]: if nb_disk.serial not in [x['serial'] for x in disks]:
logging.info('Deleting unknown locally Disk {serial}'.format( logging.info('Deleting unknown locally Disk {serial}'.format(
serial=nb_disk.serial, serial=nb_disk.serial,
)) ))
@ -265,105 +365,67 @@ class Inventory():
# create disks that are not in netbox # create disks that are not in netbox
for disk in disks: for disk in disks:
if disk['SN'] not in [x.serial for x in nb_disks]: if disk.get('serial') not in [x.serial for x in nb_disks]:
nb_disk = nb.dcim.inventory_items.create( self.create_netbox_disk(disk)
device=self.device_id,
discovered=True,
tags=[INVENTORY_TAG['disk']['name']],
name='{} ({})'.format(disk['Model'], disk['Size']),
serial=disk['SN'],
description=disk.get('Type', ''),
)
logging.info('Creating Disk {model} {serial}'.format(
model=disk['Model'],
serial=disk['SN'],
))
def get_memory(self):
memories = []
for _, value in self.server.dmi.parse().items():
if value['DMIName'] == 'Memory Device' and \
value['Size'] != 'No Module Installed':
memories.append({
'Manufacturer': value['Manufacturer'].strip(),
'Size': value['Size'].strip(),
'PN': value['Part Number'].strip(),
'SN': value['Serial Number'].strip(),
'Locator': value['Locator'].strip(),
'Type': value['Type'].strip(),
})
return memories
def get_memory_total_size(self):
total_size = 0
for memory in self.get_memory():
total_size += int(memory['Size'].split()[0])
return total_size
def get_netbox_memory(self):
memories = nb.dcim.inventory_items.filter(
device_id=self.device_id,
tag=INVENTORY_TAG['memory']['slug'],
)
return memories
def create_netbox_memory(self, memory): def create_netbox_memory(self, memory):
manufacturer = nb.dcim.manufacturers.get( manufacturer = self.find_or_create_manufacturer(memory['vendor'])
name=memory['Manufacturer']
)
if not manufacturer:
manufacturer = nb.dcim.manufacturers.create(
name=memory['Manufacturer'],
slug=memory['Manufacturer'].lower(),
)
nb_memory = nb.dcim.inventory_items.create( nb_memory = nb.dcim.inventory_items.create(
device=self.device_id, device=self.device_id,
discovered=True, discovered=True,
manufacturer=manufacturer.id, manufacturer=manufacturer.id,
tags=[INVENTORY_TAG['memory']['name']], tags=[INVENTORY_TAG['memory']['name']],
name='{} ({} {})'.format(memory['Locator'], memory['Size'], memory['Type']), name='{} ({}GB)'.format(memory['description'], memory['size']),
part_id=memory['PN'], part_id=memory['product'],
serial=memory['SN'], serial=memory['serial'],
description='RAM', description='Slot {}'.format(memory['slot']),
) )
logging.info('Creating Memory {type} {size}'.format(
type=memory['Type'], logging.info('Creating Memory {location} {type} {size}GB'.format(
size=memory['Size'], location=memory['slot'],
type=memory['product'],
size=memory['size'],
)) ))
return nb_memory return nb_memory
def create_netbox_memories(self): def do_netbox_memories(self):
for memory in self.get_memory(): memories = self.lshw.memories
self.create_netbox_memory(memory) nb_memories = self.get_netbox_inventory(
device_id=self.device_id,
def update_netbox_memories(self): tag=INVENTORY_TAG['memory']['slug']
memories = self.get_memory() )
nb_memories = self.get_netbox_memory()
for nb_memory in nb_memories: for nb_memory in nb_memories:
if nb_memory.serial not in [x['SN'] for x in memories]: if nb_memory.serial not in [x['serial'] for x in memories]:
logging.info('Deleting unknown locally Memory {serial}'.format( logging.info('Deleting unknown locally Memory {serial}'.format(
serial=nb_memory.serial, serial=nb_memory.serial,
)) ))
nb_memory.delete() nb_memory.delete()
for memory in memories: for memory in memories:
if memory['SN'] not in [x.serial for x in nb_memories]: if memory.get('serial') not in [x.serial for x in nb_memories]:
self.create_netbox_memory(memory) self.create_netbox_memory(memory)
def create(self): def create(self):
if not INVENTORY_ENABLED: if not INVENTORY_ENABLED:
return False return False
self.create_netbox_cpus() self.do_netbox_cpus()
self.create_netbox_memories() self.do_netbox_memories()
self.create_netbox_raid_cards() self.create_netbox_raid_cards()
self.create_netbox_disks() self.do_netbox_disks()
self.do_netbox_interfaces()
self.do_netbox_motherboard()
return True return True
def update(self): def update(self):
if not INVENTORY_ENABLED: if not INVENTORY_ENABLED:
return False return False
self.update_netbox_cpus() self.do_netbox_cpus()
self.update_netbox_memories() self.do_netbox_memories()
self.update_netbox_raid_cards() self.update_netbox_raid_cards()
self.update_netbox_disks() self.do_netbox_disks()
self.do_netbox_interfaces()
self.do_netbox_motherboard()
return True return True

View file

@ -96,7 +96,6 @@ class LSHW():
self.disks.append(d) self.disks.append(d)
def find_cpus(self, obj): def find_cpus(self, obj):
pprint(obj)
c = {} c = {}
c["product"] = obj["product"] c["product"] = obj["product"]
c["vendor"] = obj["vendor"] c["vendor"] = obj["vendor"]
@ -107,7 +106,6 @@ class LSHW():
def find_memories(self, obj): def find_memories(self, obj):
if "children" not in obj: if "children" not in obj:
print("not a DIMM memory.")
return return
for dimm in obj["children"]: for dimm in obj["children"]: