2019-08-04 00:00:22 +02:00
|
|
|
import netbox_agent.dmidecode as dmidecode
|
2020-02-02 20:08:56 +01:00
|
|
|
from netbox_agent.config import config
|
|
|
|
from netbox_agent.config import netbox_instance as nb
|
2019-08-26 16:54:48 +02:00
|
|
|
from netbox_agent.inventory import Inventory
|
2020-07-01 18:54:58 +02:00
|
|
|
from netbox_agent.location import Datacenter, Rack, Tenant
|
|
|
|
from netbox_agent.misc import create_netbox_tags, get_device_role, get_device_type
|
2020-04-19 12:28:49 +02:00
|
|
|
from netbox_agent.network import ServerNetwork
|
2019-09-05 13:47:10 +02:00
|
|
|
from netbox_agent.power import PowerSupply
|
2022-02-25 18:43:09 +01:00
|
|
|
from pprint import pprint
|
|
|
|
import subprocess
|
|
|
|
import logging
|
|
|
|
import socket
|
|
|
|
import sys
|
2019-08-04 00:00:22 +02:00
|
|
|
|
2021-05-18 13:59:04 +02:00
|
|
|
|
2019-08-02 18:39:05 +02:00
|
|
|
class ServerBase():
|
|
|
|
def __init__(self, dmi=None):
|
|
|
|
if dmi:
|
|
|
|
self.dmi = dmi
|
|
|
|
else:
|
2019-08-03 15:46:21 +02:00
|
|
|
self.dmi = dmidecode.parse()
|
2019-09-05 15:13:36 +02:00
|
|
|
|
2020-02-02 20:08:56 +01:00
|
|
|
self.baseboard = dmidecode.get_by_type(self.dmi, 'Baseboard')
|
|
|
|
self.bios = dmidecode.get_by_type(self.dmi, 'BIOS')
|
|
|
|
self.chassis = dmidecode.get_by_type(self.dmi, 'Chassis')
|
|
|
|
self.system = dmidecode.get_by_type(self.dmi, 'System')
|
2019-08-02 18:39:05 +02:00
|
|
|
|
2019-08-09 12:08:11 +02:00
|
|
|
self.network = None
|
2019-08-02 18:39:05 +02:00
|
|
|
|
2021-05-18 13:59:04 +02:00
|
|
|
self.tags = list(set([
|
|
|
|
x.strip() for x in config.device.tags.split(',') if x.strip()
|
|
|
|
])) if config.device.tags else []
|
2021-05-11 20:42:13 +02:00
|
|
|
self.nb_tags = list(create_netbox_tags(self.tags))
|
2022-02-16 11:22:51 +01:00
|
|
|
config_cf = set([
|
|
|
|
f.strip() for f in config.device.custom_fields.split(",")
|
|
|
|
if f.strip()
|
|
|
|
])
|
|
|
|
self.custom_fields = {}
|
|
|
|
self.custom_fields.update(dict([
|
|
|
|
(k.strip(), v.strip()) for k, v in
|
|
|
|
[f.split("=", 1) for f in config_cf]
|
|
|
|
]))
|
2020-07-01 18:54:58 +02:00
|
|
|
|
|
|
|
def get_tenant(self):
|
|
|
|
tenant = Tenant()
|
|
|
|
return tenant.get()
|
|
|
|
|
|
|
|
def get_netbox_tenant(self):
|
2020-07-11 15:09:44 +02:00
|
|
|
tenant = self.get_tenant()
|
|
|
|
if tenant is None:
|
|
|
|
return None
|
|
|
|
nb_tenant = nb.tenancy.tenants.get(
|
2020-07-01 18:54:58 +02:00
|
|
|
slug=self.get_tenant()
|
|
|
|
)
|
2020-07-11 15:09:44 +02:00
|
|
|
return nb_tenant
|
2020-07-01 18:54:58 +02:00
|
|
|
|
2019-08-04 01:11:53 +02:00
|
|
|
def get_datacenter(self):
|
|
|
|
dc = Datacenter()
|
2019-08-04 19:33:09 +02:00
|
|
|
return dc.get()
|
2019-08-04 01:11:53 +02:00
|
|
|
|
|
|
|
def get_netbox_datacenter(self):
|
2020-07-01 18:51:57 +02:00
|
|
|
dc = self.get_datacenter()
|
|
|
|
if dc is None:
|
|
|
|
logging.error("Specificing a datacenter (Site) is mandatory in Netbox")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
nb_dc = nb.dcim.sites.get(
|
|
|
|
slug=dc,
|
2019-08-04 01:11:53 +02:00
|
|
|
)
|
2020-07-01 18:51:57 +02:00
|
|
|
if nb_dc is None:
|
|
|
|
logging.error("Site (slug: {}) has not been found".format(dc))
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
return nb_dc
|
2019-08-04 01:11:53 +02:00
|
|
|
|
2019-09-03 13:16:37 +02:00
|
|
|
def update_netbox_location(self, server):
|
|
|
|
dc = self.get_datacenter()
|
|
|
|
nb_rack = self.get_netbox_rack()
|
|
|
|
nb_dc = self.get_netbox_datacenter()
|
|
|
|
|
|
|
|
update = False
|
2019-09-12 17:47:41 +02:00
|
|
|
if dc and server.site and server.site.slug != nb_dc.slug:
|
2019-09-03 13:16:37 +02:00
|
|
|
logging.info('Datacenter location has changed from {} to {}, updating'.format(
|
|
|
|
server.site.slug,
|
|
|
|
nb_dc.slug,
|
|
|
|
))
|
|
|
|
update = True
|
|
|
|
server.site = nb_dc.id
|
|
|
|
|
2021-07-20 21:55:47 +02:00
|
|
|
if (
|
|
|
|
server.rack
|
|
|
|
and nb_rack
|
|
|
|
and server.rack.id != nb_rack.id
|
|
|
|
):
|
2019-09-03 13:16:37 +02:00
|
|
|
logging.info('Rack location has changed from {} to {}, updating'.format(
|
|
|
|
server.rack,
|
|
|
|
nb_rack,
|
|
|
|
))
|
|
|
|
update = True
|
|
|
|
server.rack = nb_rack
|
|
|
|
if nb_rack is None:
|
|
|
|
server.face = None
|
|
|
|
server.position = None
|
|
|
|
return update, server
|
|
|
|
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
def update_netbox_expansion_location(self, server, expansion):
|
|
|
|
update = False
|
|
|
|
if expansion.tenant != server.tenant:
|
|
|
|
expansion.tenant = server.tenant
|
|
|
|
update = True
|
|
|
|
if expansion.site != server.site:
|
|
|
|
expansion.site = server.site
|
|
|
|
update = True
|
|
|
|
if expansion.rack != server.rack:
|
|
|
|
expansion.rack = server.rack
|
|
|
|
update = True
|
|
|
|
return update
|
|
|
|
|
2019-08-05 11:54:06 +02:00
|
|
|
def get_rack(self):
|
|
|
|
rack = Rack()
|
|
|
|
return rack.get()
|
|
|
|
|
|
|
|
def get_netbox_rack(self):
|
2020-07-01 18:51:57 +02:00
|
|
|
rack = self.get_rack()
|
|
|
|
datacenter = self.get_netbox_datacenter()
|
|
|
|
if not rack:
|
|
|
|
return None
|
|
|
|
if rack and not datacenter:
|
|
|
|
logging.error("Can't get rack if no datacenter is configured or found")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
return nb.dcim.racks.get(
|
|
|
|
name=rack,
|
|
|
|
site_id=datacenter.id,
|
2019-08-05 11:54:06 +02:00
|
|
|
)
|
|
|
|
|
2019-08-02 18:39:05 +02:00
|
|
|
def get_product_name(self):
|
2019-08-04 00:00:22 +02:00
|
|
|
"""
|
2019-08-02 18:39:05 +02:00
|
|
|
Return the Chassis Name from dmidecode info
|
2019-08-04 00:00:22 +02:00
|
|
|
"""
|
2019-09-10 14:46:04 +02:00
|
|
|
return self.system[0]['Product Name'].strip()
|
2019-08-02 18:39:05 +02:00
|
|
|
|
|
|
|
def get_service_tag(self):
|
2019-08-04 00:00:22 +02:00
|
|
|
"""
|
2019-08-02 18:39:05 +02:00
|
|
|
Return the Service Tag from dmidecode info
|
2019-08-04 00:00:22 +02:00
|
|
|
"""
|
2019-08-14 11:17:24 +02:00
|
|
|
return self.system[0]['Serial Number'].strip()
|
2019-08-02 18:39:05 +02:00
|
|
|
|
2020-09-18 12:29:17 +02:00
|
|
|
def get_expansion_service_tag(self):
|
|
|
|
"""
|
|
|
|
Return the virtual Service Tag from dmidecode info host
|
|
|
|
with 'expansion'
|
|
|
|
"""
|
|
|
|
return self.system[0]['Serial Number'].strip() + " expansion"
|
|
|
|
|
2019-08-05 16:03:35 +02:00
|
|
|
def get_hostname(self):
|
2019-09-12 11:15:12 +02:00
|
|
|
if config.hostname_cmd is None:
|
|
|
|
return '{}'.format(socket.gethostname())
|
|
|
|
return subprocess.getoutput(config.hostname_cmd)
|
2019-08-05 16:03:35 +02:00
|
|
|
|
2019-08-02 18:39:05 +02:00
|
|
|
def is_blade(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def get_blade_slot(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def get_chassis(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
2019-08-08 14:37:02 +02:00
|
|
|
def get_chassis_name(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
2019-08-02 18:39:05 +02:00
|
|
|
def get_chassis_service_tag(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def get_bios_version(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def get_bios_version_attr(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
def get_bios_release_date(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
2019-09-05 13:47:10 +02:00
|
|
|
def get_power_consumption(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
2020-09-18 12:29:17 +02:00
|
|
|
def get_expansion_product(self):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
2020-07-01 18:54:58 +02:00
|
|
|
def _netbox_create_chassis(self, datacenter, tenant, rack):
|
2019-10-23 12:14:50 +02:00
|
|
|
device_type = get_device_type(self.get_chassis())
|
2020-07-01 18:54:58 +02:00
|
|
|
device_role = get_device_role(config.device.chassis_role)
|
2019-08-06 17:59:46 +02:00
|
|
|
serial = self.get_chassis_service_tag()
|
2019-08-07 10:32:23 +02:00
|
|
|
logging.info('Creating chassis blade (serial: {serial})'.format(
|
2019-08-06 17:59:46 +02:00
|
|
|
serial=serial))
|
2019-08-03 15:46:21 +02:00
|
|
|
new_chassis = nb.dcim.devices.create(
|
2019-08-08 14:37:02 +02:00
|
|
|
name=self.get_chassis_name(),
|
2019-08-03 15:46:21 +02:00
|
|
|
device_type=device_type.id,
|
2019-08-06 17:59:46 +02:00
|
|
|
serial=serial,
|
2019-08-03 15:46:21 +02:00
|
|
|
device_role=device_role.id,
|
2019-08-04 01:11:53 +02:00
|
|
|
site=datacenter.id if datacenter else None,
|
2020-07-01 18:54:58 +02:00
|
|
|
tenant=tenant.id if tenant else None,
|
2019-08-14 11:17:24 +02:00
|
|
|
rack=rack.id if rack else None,
|
2020-12-15 12:47:47 +01:00
|
|
|
tags=[{'name': x} for x in self.tags],
|
2022-02-16 11:22:51 +01:00
|
|
|
custom_fields=self.custom_fields,
|
2019-08-03 15:46:21 +02:00
|
|
|
)
|
|
|
|
return new_chassis
|
|
|
|
|
2020-07-01 18:54:58 +02:00
|
|
|
def _netbox_create_blade(self, chassis, datacenter, tenant, rack):
|
|
|
|
device_role = get_device_role(config.device.blade_role)
|
2019-10-23 12:14:50 +02:00
|
|
|
device_type = get_device_type(self.get_product_name())
|
2019-08-06 17:59:46 +02:00
|
|
|
serial = self.get_service_tag()
|
|
|
|
hostname = self.get_hostname()
|
2019-08-07 10:32:23 +02:00
|
|
|
logging.info(
|
2019-08-06 17:59:46 +02:00
|
|
|
'Creating blade (serial: {serial}) {hostname} on chassis {chassis_serial}'.format(
|
|
|
|
serial=serial, hostname=hostname, chassis_serial=chassis.serial
|
|
|
|
))
|
2019-08-03 15:46:21 +02:00
|
|
|
new_blade = nb.dcim.devices.create(
|
2019-08-06 17:59:46 +02:00
|
|
|
name=hostname,
|
|
|
|
serial=serial,
|
2019-08-03 15:46:21 +02:00
|
|
|
device_role=device_role.id,
|
|
|
|
device_type=device_type.id,
|
|
|
|
parent_device=chassis.id,
|
2019-08-04 01:11:53 +02:00
|
|
|
site=datacenter.id if datacenter else None,
|
2020-07-01 18:54:58 +02:00
|
|
|
tenant=tenant.id if tenant else None,
|
2019-08-14 11:17:24 +02:00
|
|
|
rack=rack.id if rack else None,
|
2020-12-15 12:47:47 +01:00
|
|
|
tags=[{'name': x} for x in self.tags],
|
2022-02-16 11:22:51 +01:00
|
|
|
custom_fields=self.custom_fields,
|
2019-08-03 15:46:21 +02:00
|
|
|
)
|
|
|
|
return new_blade
|
|
|
|
|
2020-09-18 12:29:17 +02:00
|
|
|
def _netbox_create_blade_expansion(self, chassis, datacenter, tenant, rack):
|
|
|
|
device_role = get_device_role(config.device.blade_role)
|
|
|
|
device_type = get_device_type(self.get_expansion_product())
|
|
|
|
serial = self.get_expansion_service_tag()
|
|
|
|
hostname = self.get_hostname() + " expansion"
|
|
|
|
logging.info(
|
|
|
|
'Creating expansion (serial: {serial}) {hostname} on chassis {chassis_serial}'.format(
|
|
|
|
serial=serial, hostname=hostname, chassis_serial=chassis.serial
|
|
|
|
))
|
|
|
|
new_blade = nb.dcim.devices.create(
|
|
|
|
name=hostname,
|
|
|
|
serial=serial,
|
|
|
|
device_role=device_role.id,
|
|
|
|
device_type=device_type.id,
|
|
|
|
parent_device=chassis.id,
|
|
|
|
site=datacenter.id if datacenter else None,
|
|
|
|
tenant=tenant.id if tenant else None,
|
|
|
|
rack=rack.id if rack else None,
|
2020-12-15 12:47:47 +01:00
|
|
|
tags=[{'name': x} for x in self.tags],
|
2020-09-18 12:29:17 +02:00
|
|
|
)
|
|
|
|
return new_blade
|
|
|
|
|
2022-02-08 18:45:44 +01:00
|
|
|
def _netbox_deduplicate_server(self):
|
|
|
|
serial = self.get_service_tag()
|
|
|
|
hostname = self.get_hostname()
|
|
|
|
server = nb.dcim.devices.get(name=hostname)
|
|
|
|
if server and server.serial != serial:
|
|
|
|
server.delete()
|
|
|
|
|
2020-07-01 18:54:58 +02:00
|
|
|
def _netbox_create_server(self, datacenter, tenant, rack):
|
|
|
|
device_role = get_device_role(config.device.server_role)
|
2019-10-23 12:14:50 +02:00
|
|
|
device_type = get_device_type(self.get_product_name())
|
2019-08-03 15:57:06 +02:00
|
|
|
if not device_type:
|
|
|
|
raise Exception('Chassis "{}" doesn\'t exist'.format(self.get_chassis()))
|
2019-08-06 17:59:46 +02:00
|
|
|
serial = self.get_service_tag()
|
|
|
|
hostname = self.get_hostname()
|
2019-08-07 10:32:23 +02:00
|
|
|
logging.info('Creating server (serial: {serial}) {hostname}'.format(
|
2019-08-06 17:59:46 +02:00
|
|
|
serial=serial, hostname=hostname))
|
2019-08-03 15:57:06 +02:00
|
|
|
new_server = nb.dcim.devices.create(
|
2019-08-06 17:59:46 +02:00
|
|
|
name=hostname,
|
|
|
|
serial=serial,
|
2019-08-03 15:57:06 +02:00
|
|
|
device_role=device_role.id,
|
|
|
|
device_type=device_type.id,
|
2019-08-04 01:11:53 +02:00
|
|
|
site=datacenter.id if datacenter else None,
|
2020-07-01 18:54:58 +02:00
|
|
|
tenant=tenant.id if tenant else None,
|
2019-08-14 11:17:24 +02:00
|
|
|
rack=rack.id if rack else None,
|
2020-12-15 12:47:47 +01:00
|
|
|
tags=[{'name': x} for x in self.tags],
|
2019-08-03 15:57:06 +02:00
|
|
|
)
|
|
|
|
return new_server
|
|
|
|
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
def get_netbox_server(self, expansion=False):
|
|
|
|
if expansion is False:
|
|
|
|
return nb.dcim.devices.get(serial=self.get_service_tag())
|
|
|
|
else:
|
|
|
|
return nb.dcim.devices.get(serial=self.get_expansion_service_tag())
|
2019-08-04 15:14:36 +02:00
|
|
|
|
2020-04-19 12:28:49 +02:00
|
|
|
def _netbox_set_or_update_blade_slot(self, server, chassis, datacenter):
|
|
|
|
# before everything check if right chassis
|
2022-02-21 18:12:16 +01:00
|
|
|
actual_device_bay = server.parent_device.device_bay \
|
|
|
|
if server.parent_device else None
|
|
|
|
actual_chassis = actual_device_bay.device \
|
|
|
|
if actual_device_bay else None
|
2020-04-19 12:28:49 +02:00
|
|
|
slot = self.get_blade_slot()
|
|
|
|
if actual_chassis and \
|
|
|
|
actual_chassis.serial == chassis.serial and \
|
|
|
|
actual_device_bay.name == slot:
|
|
|
|
return
|
2019-08-04 15:14:36 +02:00
|
|
|
|
2020-04-19 12:28:49 +02:00
|
|
|
real_device_bays = nb.dcim.device_bays.filter(
|
|
|
|
device_id=chassis.id,
|
|
|
|
name=slot,
|
2019-08-08 14:37:02 +02:00
|
|
|
)
|
2022-02-21 18:12:16 +01:00
|
|
|
real_device_bays = nb.dcim.device_bays.filter(
|
|
|
|
device_id=chassis.id,
|
|
|
|
name=slot,
|
|
|
|
)
|
|
|
|
if real_device_bays:
|
2020-04-19 12:28:49 +02:00
|
|
|
logging.info(
|
|
|
|
'Setting device ({serial}) new slot on {slot} '
|
|
|
|
'(Chassis {chassis_serial})..'.format(
|
|
|
|
serial=server.serial, slot=slot, chassis_serial=chassis.serial
|
|
|
|
))
|
|
|
|
# reset actual device bay if set
|
|
|
|
if actual_device_bay:
|
2022-02-21 18:12:16 +01:00
|
|
|
# Forces the evaluation of the installed_device attribute to
|
|
|
|
# workaround a bug probably due to lazy loading optimization
|
|
|
|
# that prevents the value change detection
|
|
|
|
actual_device_bay.installed_device
|
2020-04-19 12:28:49 +02:00
|
|
|
actual_device_bay.installed_device = None
|
|
|
|
actual_device_bay.save()
|
|
|
|
# setup new device bay
|
2022-02-21 18:12:16 +01:00
|
|
|
real_device_bay = next(real_device_bays)
|
2020-04-19 12:28:49 +02:00
|
|
|
real_device_bay.installed_device = server
|
|
|
|
real_device_bay.save()
|
|
|
|
else:
|
|
|
|
logging.error('Could not find slot {slot} for chassis'.format(
|
|
|
|
slot=slot
|
|
|
|
))
|
2020-01-25 12:03:30 +01:00
|
|
|
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
def _netbox_set_or_update_blade_expansion_slot(self, expansion, chassis, datacenter):
|
2020-09-18 12:29:17 +02:00
|
|
|
# before everything check if right chassis
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
actual_device_bay = expansion.parent_device.device_bay if expansion.parent_device else None
|
2020-09-18 12:29:17 +02:00
|
|
|
actual_chassis = actual_device_bay.device if actual_device_bay else None
|
|
|
|
slot = self.get_blade_expansion_slot()
|
|
|
|
if actual_chassis and \
|
|
|
|
actual_chassis.serial == chassis.serial and \
|
|
|
|
actual_device_bay.name == slot:
|
|
|
|
return
|
|
|
|
|
|
|
|
real_device_bays = nb.dcim.device_bays.filter(
|
|
|
|
device_id=chassis.id,
|
|
|
|
name=slot,
|
|
|
|
)
|
2022-02-21 18:12:16 +01:00
|
|
|
if not real_device_bays:
|
2020-09-18 12:29:17 +02:00
|
|
|
logging.error('Could not find slot {slot} expansion for chassis'.format(
|
|
|
|
slot=slot
|
|
|
|
))
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
return
|
|
|
|
logging.info(
|
|
|
|
'Setting device expansion ({serial}) new slot on {slot} '
|
|
|
|
'(Chassis {chassis_serial})..'.format(
|
|
|
|
serial=expansion.serial, slot=slot, chassis_serial=chassis.serial
|
|
|
|
))
|
|
|
|
# reset actual device bay if set
|
|
|
|
if actual_device_bay:
|
2022-02-21 18:12:16 +01:00
|
|
|
# Forces the evaluation of the installed_device attribute to
|
|
|
|
# workaround a bug probably due to lazy loading optimization
|
|
|
|
# that prevents the value change detection
|
|
|
|
actual_device_bay.installed_device
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
actual_device_bay.installed_device = None
|
|
|
|
actual_device_bay.save()
|
|
|
|
# setup new device bay
|
2022-02-21 18:12:16 +01:00
|
|
|
real_device_bay = next(real_device_bays)
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
real_device_bay.installed_device = expansion
|
|
|
|
real_device_bay.save()
|
2020-09-18 12:29:17 +02:00
|
|
|
|
2020-04-19 12:28:49 +02:00
|
|
|
def netbox_create_or_update(self, config):
|
|
|
|
"""
|
|
|
|
Netbox method to create or update info about our server/blade
|
2020-01-25 12:03:30 +01:00
|
|
|
|
2020-04-19 12:28:49 +02:00
|
|
|
Handle:
|
|
|
|
* new chassis for a blade
|
|
|
|
* new slot for a blade
|
|
|
|
* hostname update
|
|
|
|
* Network infos
|
|
|
|
* Inventory management
|
|
|
|
* PSU management
|
|
|
|
"""
|
|
|
|
datacenter = self.get_netbox_datacenter()
|
|
|
|
rack = self.get_netbox_rack()
|
2020-07-01 18:54:58 +02:00
|
|
|
tenant = self.get_netbox_tenant()
|
2019-08-08 14:37:02 +02:00
|
|
|
|
2022-02-08 18:45:44 +01:00
|
|
|
if config.purge_old_devices:
|
|
|
|
self._netbox_deduplicate_server()
|
|
|
|
|
2020-04-19 12:28:49 +02:00
|
|
|
if self.is_blade():
|
2019-08-08 14:37:02 +02:00
|
|
|
chassis = nb.dcim.devices.get(
|
|
|
|
serial=self.get_chassis_service_tag()
|
|
|
|
)
|
2020-04-19 12:28:49 +02:00
|
|
|
# Chassis does not exist
|
2019-08-08 14:37:02 +02:00
|
|
|
if not chassis:
|
2020-07-01 18:54:58 +02:00
|
|
|
chassis = self._netbox_create_chassis(datacenter, tenant, rack)
|
2019-08-08 14:37:02 +02:00
|
|
|
|
2020-04-19 12:28:49 +02:00
|
|
|
server = nb.dcim.devices.get(serial=self.get_service_tag())
|
|
|
|
if not server:
|
2020-07-01 18:54:58 +02:00
|
|
|
server = self._netbox_create_blade(chassis, datacenter, tenant, rack)
|
2019-08-08 14:37:02 +02:00
|
|
|
|
2020-04-19 12:28:49 +02:00
|
|
|
# Set slot for blade
|
|
|
|
self._netbox_set_or_update_blade_slot(server, chassis, datacenter)
|
|
|
|
else:
|
|
|
|
server = nb.dcim.devices.get(serial=self.get_service_tag())
|
|
|
|
if not server:
|
2020-07-29 00:45:24 +02:00
|
|
|
server = self._netbox_create_server(datacenter, tenant, rack)
|
2019-08-05 16:03:35 +02:00
|
|
|
|
2019-08-07 10:32:23 +02:00
|
|
|
logging.debug('Updating Server...')
|
2020-04-19 12:28:49 +02:00
|
|
|
# check network cards
|
|
|
|
if config.register or config.update_all or config.update_network:
|
|
|
|
self.network = ServerNetwork(server=self)
|
|
|
|
self.network.create_or_update_netbox_network_cards()
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
update_inventory = config.inventory and (config.register or
|
|
|
|
config.update_all or config.update_inventory)
|
2020-04-19 12:28:49 +02:00
|
|
|
# update inventory if feature is enabled
|
2022-02-21 18:12:16 +01:00
|
|
|
self.inventory = Inventory(server=self)
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
if update_inventory:
|
2020-04-19 12:28:49 +02:00
|
|
|
self.inventory.create_or_update()
|
|
|
|
# update psu
|
|
|
|
if config.register or config.update_all or config.update_psu:
|
|
|
|
self.power = PowerSupply(server=self)
|
|
|
|
self.power.create_or_update_power_supply()
|
|
|
|
self.power.report_power_consumption()
|
2019-09-03 13:16:37 +02:00
|
|
|
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
expansion = nb.dcim.devices.get(serial=self.get_expansion_service_tag())
|
|
|
|
if self.own_expansion_slot() and config.expansion_as_device:
|
2020-09-18 12:29:17 +02:00
|
|
|
logging.debug('Update Server expansion...')
|
|
|
|
if not expansion:
|
|
|
|
expansion = self._netbox_create_blade_expansion(chassis, datacenter, tenant, rack)
|
|
|
|
|
|
|
|
# set slot for blade expansion
|
|
|
|
self._netbox_set_or_update_blade_expansion_slot(expansion, chassis, datacenter)
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
if update_inventory:
|
|
|
|
# Updates expansion inventory
|
|
|
|
inventory = Inventory(server=self, update_expansion=True)
|
|
|
|
inventory.create_or_update()
|
|
|
|
elif self.own_expansion_slot() and expansion:
|
|
|
|
expansion.delete()
|
|
|
|
expansion = None
|
2020-09-18 12:29:17 +02:00
|
|
|
|
2019-09-03 13:16:37 +02:00
|
|
|
update = 0
|
2019-08-05 12:02:42 +02:00
|
|
|
# for every other specs
|
|
|
|
# check hostname
|
2019-08-05 16:03:35 +02:00
|
|
|
if server.name != self.get_hostname():
|
2019-09-12 11:15:12 +02:00
|
|
|
server.name = self.get_hostname()
|
2022-02-21 18:12:16 +01:00
|
|
|
update += 1
|
2019-09-03 13:16:37 +02:00
|
|
|
|
2022-03-28 14:37:21 +02:00
|
|
|
server_tags = sorted(set([x.name for x in server.tags]))
|
|
|
|
tags = sorted(set(self.tags))
|
|
|
|
if server_tags != tags:
|
|
|
|
new_tags_ids = [x.id for x in self.nb_tags]
|
|
|
|
if not config.preserve_tags:
|
|
|
|
server.tags = new_tags_ids
|
|
|
|
else:
|
|
|
|
server_tags_ids = [x.id for x in server.tags]
|
|
|
|
server.tags = sorted(set(new_tags_ids + server_tags_ids))
|
2022-02-21 18:12:16 +01:00
|
|
|
update += 1
|
2020-07-01 18:54:58 +02:00
|
|
|
|
2022-02-16 11:22:51 +01:00
|
|
|
if server.custom_fields != self.custom_fields:
|
|
|
|
server.custom_fields = self.custom_fields
|
|
|
|
update += 1
|
|
|
|
|
2019-09-03 13:16:37 +02:00
|
|
|
if config.update_all or config.update_location:
|
|
|
|
ret, server = self.update_netbox_location(server)
|
|
|
|
update += ret
|
|
|
|
|
2019-08-05 16:03:35 +02:00
|
|
|
if update:
|
|
|
|
server.save()
|
Manage blade expansions as independent devices
This patch adds the ability to detect and manage GPU and Disk expansion
bays, and either add their internal components into the device
corresponding to the blade server, or into a dedicated device.
It takes advantage of the work made by @cyrinux on GPU bays management, and
applies the same principle to the external disk bays, but harmonize the
inventory management:
- If no argument is specified on the command line, the GPU cards, RAID
controllers and their attached disks are added in the blade device,
and the device corresponding to an expansion device is deleted.
- If the `--expansion-as-device` option is specified on the command
line, a dedicated device corresponding to the expansion bay is
created, and the GPUs, RAID card and attached disks are removed from
the blade device and added to the expansion device.
2022-02-11 18:22:13 +01:00
|
|
|
|
|
|
|
if expansion:
|
|
|
|
update = 0
|
|
|
|
expansion_name = server.name + ' expansion'
|
|
|
|
if expansion.name != expansion_name:
|
|
|
|
expansion.name = expansion_name
|
|
|
|
update += 1
|
|
|
|
if self.update_netbox_expansion_location(server, expansion):
|
|
|
|
update += 1
|
|
|
|
if update:
|
|
|
|
expansion.save()
|
2019-08-07 10:32:23 +02:00
|
|
|
logging.debug('Finished updating Server!')
|
2019-08-04 15:14:36 +02:00
|
|
|
|
2019-08-04 00:00:22 +02:00
|
|
|
def print_debug(self):
|
2020-04-19 12:28:49 +02:00
|
|
|
self.network = ServerNetwork(server=self)
|
2019-08-04 00:00:22 +02:00
|
|
|
print('Datacenter:', self.get_datacenter())
|
|
|
|
print('Netbox Datacenter:', self.get_netbox_datacenter())
|
2019-08-05 11:54:06 +02:00
|
|
|
print('Rack:', self.get_rack())
|
|
|
|
print('Netbox Rack:', self.get_netbox_rack())
|
2019-08-04 00:00:22 +02:00
|
|
|
print('Is blade:', self.is_blade())
|
2020-09-18 12:29:17 +02:00
|
|
|
print('Got expansion:', self.own_expansion_slot())
|
2019-08-04 00:00:22 +02:00
|
|
|
print('Product Name:', self.get_product_name())
|
|
|
|
print('Chassis:', self.get_chassis())
|
|
|
|
print('Chassis service tag:', self.get_chassis_service_tag())
|
|
|
|
print('Service tag:', self.get_service_tag())
|
2019-08-04 14:37:51 +02:00
|
|
|
print('NIC:',)
|
|
|
|
pprint(self.network.get_network_cards())
|
|
|
|
pass
|
2022-02-21 18:12:16 +01:00
|
|
|
|
|
|
|
def own_expansion_slot(self):
|
|
|
|
"""
|
|
|
|
Indicates if the device hosts an expansion card
|
|
|
|
"""
|
|
|
|
return False
|
2022-02-25 18:43:09 +01:00
|
|
|
|
|
|
|
def own_gpu_expansion_slot(self):
|
|
|
|
"""
|
|
|
|
Indicates if the device hosts a GPU expansion card
|
|
|
|
"""
|
|
|
|
return False
|
|
|
|
|
|
|
|
def own_drive_expansion_slot(self):
|
|
|
|
"""
|
|
|
|
Indicates if the device hosts a drive expansion bay
|
|
|
|
"""
|
|
|
|
return False
|