Add GPU expansion support for HP_ProLiant_BL460c_Gen10_Graphics_Exp
This commit is contained in:
parent
c1a847a177
commit
00c778d3bf
7 changed files with 2006 additions and 6 deletions
|
@ -121,6 +121,13 @@ class ServerBase():
|
||||||
"""
|
"""
|
||||||
return self.system[0]['Serial Number'].strip()
|
return self.system[0]['Serial Number'].strip()
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
def get_hostname(self):
|
def get_hostname(self):
|
||||||
if config.hostname_cmd is None:
|
if config.hostname_cmd is None:
|
||||||
return '{}'.format(socket.gethostname())
|
return '{}'.format(socket.gethostname())
|
||||||
|
@ -153,6 +160,9 @@ class ServerBase():
|
||||||
def get_power_consumption(self):
|
def get_power_consumption(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_expansion_product(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def _netbox_create_chassis(self, datacenter, tenant, rack):
|
def _netbox_create_chassis(self, datacenter, tenant, rack):
|
||||||
device_type = get_device_type(self.get_chassis())
|
device_type = get_device_type(self.get_chassis())
|
||||||
device_role = get_device_role(config.device.chassis_role)
|
device_role = get_device_role(config.device.chassis_role)
|
||||||
|
@ -193,6 +203,28 @@ class ServerBase():
|
||||||
)
|
)
|
||||||
return new_blade
|
return new_blade
|
||||||
|
|
||||||
|
def _netbox_create_blade_expansion(self, chassis, datacenter, tenant, rack):
|
||||||
|
device_role = get_device_role(config.device.bkade_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,
|
||||||
|
tags=self.tags,
|
||||||
|
)
|
||||||
|
return new_blade
|
||||||
|
|
||||||
def _netbox_create_server(self, datacenter, tenant, rack):
|
def _netbox_create_server(self, datacenter, tenant, rack):
|
||||||
device_role = get_device_role(config.device.server_role)
|
device_role = get_device_role(config.device.server_role)
|
||||||
device_type = get_device_type(self.get_product_name())
|
device_type = get_device_type(self.get_product_name())
|
||||||
|
@ -250,6 +282,41 @@ class ServerBase():
|
||||||
slot=slot
|
slot=slot
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def _netbox_set_or_update_blade_expansion_slot(self, server, chassis, datacenter):
|
||||||
|
# before everything check if right chassis
|
||||||
|
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
|
||||||
|
slot = self.get_blade_expansion_slot()
|
||||||
|
if actual_chassis and \
|
||||||
|
actual_chassis.serial == chassis.serial and \
|
||||||
|
actual_device_bay.name == slot:
|
||||||
|
return
|
||||||
|
|
||||||
|
server.name += " expansion"
|
||||||
|
|
||||||
|
real_device_bays = nb.dcim.device_bays.filter(
|
||||||
|
device_id=chassis.id,
|
||||||
|
name=slot,
|
||||||
|
)
|
||||||
|
if len(real_device_bays) > 0:
|
||||||
|
logging.info(
|
||||||
|
'Setting device expansion ({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:
|
||||||
|
actual_device_bay.installed_device = None
|
||||||
|
actual_device_bay.save()
|
||||||
|
# setup new device bay
|
||||||
|
real_device_bay = real_device_bays[0]
|
||||||
|
real_device_bay.installed_device = server
|
||||||
|
real_device_bay.save()
|
||||||
|
else:
|
||||||
|
logging.error('Could not find slot {slot} expansion for chassis'.format(
|
||||||
|
slot=slot
|
||||||
|
))
|
||||||
|
|
||||||
def netbox_create_or_update(self, config):
|
def netbox_create_or_update(self, config):
|
||||||
"""
|
"""
|
||||||
Netbox method to create or update info about our server/blade
|
Netbox method to create or update info about our server/blade
|
||||||
|
@ -300,6 +367,15 @@ class ServerBase():
|
||||||
self.power.create_or_update_power_supply()
|
self.power.create_or_update_power_supply()
|
||||||
self.power.report_power_consumption()
|
self.power.report_power_consumption()
|
||||||
|
|
||||||
|
if self.own_expansion_slot():
|
||||||
|
logging.debug('Update Server expansion...')
|
||||||
|
expansion = nb.dcim.devices.get(serial=self.get_expansion_service_tag())
|
||||||
|
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)
|
||||||
|
|
||||||
update = 0
|
update = 0
|
||||||
# for every other specs
|
# for every other specs
|
||||||
# check hostname
|
# check hostname
|
||||||
|
@ -326,6 +402,7 @@ class ServerBase():
|
||||||
print('Rack:', self.get_rack())
|
print('Rack:', self.get_rack())
|
||||||
print('Netbox Rack:', self.get_netbox_rack())
|
print('Netbox Rack:', self.get_netbox_rack())
|
||||||
print('Is blade:', self.is_blade())
|
print('Is blade:', self.is_blade())
|
||||||
|
print('Got expansion:', self.own_expansion_slot())
|
||||||
print('Product Name:', self.get_product_name())
|
print('Product Name:', self.get_product_name())
|
||||||
print('Chassis:', self.get_chassis())
|
print('Chassis:', self.get_chassis())
|
||||||
print('Chassis service tag:', self.get_chassis_service_tag())
|
print('Chassis service tag:', self.get_chassis_service_tag())
|
||||||
|
|
26
netbox_agent/vendors/dell.py
vendored
26
netbox_agent/vendors/dell.py
vendored
|
@ -67,3 +67,29 @@ class DellHost(ServerBase):
|
||||||
break
|
break
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def get_expansion_product(self):
|
||||||
|
"""
|
||||||
|
Get the extension slot that is on a pair slot number
|
||||||
|
next to the compute slot that is on an odd slot number
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def is_expansion_slot(self, server):
|
||||||
|
"""
|
||||||
|
Return True if its an extension slot
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_blade_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Expansion slot are always the compute bay number + 1
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def own_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Say if the device can host an extension card based
|
||||||
|
on the product name
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
26
netbox_agent/vendors/generic.py
vendored
26
netbox_agent/vendors/generic.py
vendored
|
@ -21,3 +21,29 @@ class GenericHost(ServerBase):
|
||||||
|
|
||||||
def get_chassis_service_tag(self):
|
def get_chassis_service_tag(self):
|
||||||
return self.get_service_tag()
|
return self.get_service_tag()
|
||||||
|
|
||||||
|
def get_expansion_product(self):
|
||||||
|
"""
|
||||||
|
Get the extension slot that is on a pair slot number
|
||||||
|
next to the compute slot that is on an odd slot number
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def is_expansion_slot(self, server):
|
||||||
|
"""
|
||||||
|
Return True if its an extension slot
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_blade_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Expansion slot are always the compute bay number + 1
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def own_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Say if the device can host an extension card based
|
||||||
|
on the product name
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
42
netbox_agent/vendors/hp.py
vendored
42
netbox_agent/vendors/hp.py
vendored
|
@ -11,12 +11,9 @@ class HPHost(ServerBase):
|
||||||
self.hp_rack_locator = self._find_rack_locator()
|
self.hp_rack_locator = self._find_rack_locator()
|
||||||
|
|
||||||
def is_blade(self):
|
def is_blade(self):
|
||||||
if self.product.startswith("ProLiant BL"):
|
blade = self.product.startswith("ProLiant BL")
|
||||||
return True
|
blade |= self.product.startswith("ProLiant m") and self.product.endswith("Server Cartridge")
|
||||||
elif self.product.startswith("ProLiant m") and self.product.endswith("Server Cartridge"):
|
return blade
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _find_rack_locator(self):
|
def _find_rack_locator(self):
|
||||||
"""
|
"""
|
||||||
|
@ -68,3 +65,36 @@ class HPHost(ServerBase):
|
||||||
if self.is_blade():
|
if self.is_blade():
|
||||||
return self.hp_rack_locator["Enclosure Serial"].strip()
|
return self.hp_rack_locator["Enclosure Serial"].strip()
|
||||||
return self.get_service_tag()
|
return self.get_service_tag()
|
||||||
|
|
||||||
|
def get_expansion_product(self):
|
||||||
|
"""
|
||||||
|
Get the extension slot that is on a pair slot number
|
||||||
|
next to the compute slot that is on an odd slot number
|
||||||
|
I only know on model of slot GPU extension card that.
|
||||||
|
"""
|
||||||
|
if self.own_expansion_slot():
|
||||||
|
return "ProLiant BL460c Graphics Expansion Blade"
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_expansion_slot(self, server):
|
||||||
|
"""
|
||||||
|
Return True if its an extension slot, based on the name
|
||||||
|
"""
|
||||||
|
return server.name.endswith(" expansion")
|
||||||
|
|
||||||
|
def get_blade_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Expansion slot are always the compute bay number + 1
|
||||||
|
"""
|
||||||
|
if self.is_blade() and self.own_expansion_slot():
|
||||||
|
return 'Bay {}'.format(
|
||||||
|
str(int(self.hp_rack_locator['Server Bay'].strip()) + 1)
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def own_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Say if the device can host an extension card based
|
||||||
|
on the product name
|
||||||
|
"""
|
||||||
|
return self.get_product_name().endswith('Graphics Exp')
|
||||||
|
|
27
netbox_agent/vendors/supermicro.py
vendored
27
netbox_agent/vendors/supermicro.py
vendored
|
@ -63,3 +63,30 @@ class SupermicroHost(ServerBase):
|
||||||
if not self.is_blade():
|
if not self.is_blade():
|
||||||
return None
|
return None
|
||||||
return 'Chassis {}'.format(self.get_chassis_service_tag())
|
return 'Chassis {}'.format(self.get_chassis_service_tag())
|
||||||
|
|
||||||
|
def get_expansion_product(self):
|
||||||
|
"""
|
||||||
|
Get the extension slot that is on a pair slot number
|
||||||
|
next to the compute slot that is on an odd slot number
|
||||||
|
I only know on model of slot GPU extension card that.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def is_expansion_slot(self, server):
|
||||||
|
"""
|
||||||
|
Return True if its an extension slot, based on the name
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_blade_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Expansion slot are always the compute bay number + 1
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def own_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Say if the device can host an extension card based
|
||||||
|
on the product name
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
1798
tests/fixtures/dmidecode/HP_ProLiant_BL460c_Gen10_Graphics_Exp
vendored
Normal file
1798
tests/fixtures/dmidecode/HP_ProLiant_BL460c_Gen10_Graphics_Exp
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -19,6 +19,7 @@ def test_init(fixture):
|
||||||
'HP_BL460c_Gen9',
|
'HP_BL460c_Gen9',
|
||||||
'HP_DL380p_Gen8',
|
'HP_DL380p_Gen8',
|
||||||
'HP_SL4540_Gen8'
|
'HP_SL4540_Gen8'
|
||||||
|
'HP_ProLiant_BL460c_Gen10_Graphics_Exp'
|
||||||
])
|
])
|
||||||
def test_hp_service_tag(fixture):
|
def test_hp_service_tag(fixture):
|
||||||
dmi = parse(fixture)
|
dmi = parse(fixture)
|
||||||
|
@ -36,6 +37,7 @@ def test_moonshot_blade(fixture):
|
||||||
assert server.get_service_tag() == 'CN66480BLA'
|
assert server.get_service_tag() == 'CN66480BLA'
|
||||||
assert server.get_chassis_service_tag() == 'CZ3702MD5K'
|
assert server.get_chassis_service_tag() == 'CZ3702MD5K'
|
||||||
assert server.is_blade() is True
|
assert server.is_blade() is True
|
||||||
|
assert server.own_expansion_slot() is False
|
||||||
|
|
||||||
|
|
||||||
@parametrize_with_fixtures(
|
@parametrize_with_fixtures(
|
||||||
|
@ -89,3 +91,17 @@ def test_generic_host_product_name(fixture):
|
||||||
dmi = parse(fixture)
|
dmi = parse(fixture)
|
||||||
server = ServerBase(dmi)
|
server = ServerBase(dmi)
|
||||||
assert server.get_product_name() == 'SR'
|
assert server.get_product_name() == 'SR'
|
||||||
|
|
||||||
|
|
||||||
|
@parametrize_with_fixtures(
|
||||||
|
'dmidecode/', only_filenames=[
|
||||||
|
'HP_ProLiant_BL460c_Gen10_Graphics_Exp'
|
||||||
|
])
|
||||||
|
def test_hp_blade_with_gpu_expansion(fixture):
|
||||||
|
dmi = parse(fixture)
|
||||||
|
server = HPHost(dmi)
|
||||||
|
assert server.get_service_tag() == '4242'
|
||||||
|
assert server.get_chassis_service_tag() == '4343'
|
||||||
|
assert server.is_blade() is True
|
||||||
|
assert server.own_expansion_slot() is True
|
||||||
|
assert server.get_expansion_service_tag() == '4242 expansion'
|
||||||
|
|
Loading…
Reference in a new issue