Merge branch 'master' into fix/chriss/purge_remaining_devices
This commit is contained in:
commit
5d9602402b
6 changed files with 195 additions and 175 deletions
|
@ -30,6 +30,8 @@ def get_config():
|
||||||
p.add_argument('--update-psu', action='store_true', help='Update PSU')
|
p.add_argument('--update-psu', action='store_true', help='Update PSU')
|
||||||
p.add_argument('--purge-old-devices', action='store_true',
|
p.add_argument('--purge-old-devices', action='store_true',
|
||||||
help='Purge existing (old ?) devices having same name but different serial')
|
help='Purge existing (old ?) devices having same name but different serial')
|
||||||
|
p.add_argument('--expansion-as-device', action='store_true',
|
||||||
|
help='Manage blade expansions as external devices')
|
||||||
|
|
||||||
p.add_argument('--log_level', default='debug')
|
p.add_argument('--log_level', default='debug')
|
||||||
p.add_argument('--netbox.url', help='Netbox URL')
|
p.add_argument('--netbox.url', help='Netbox URL')
|
||||||
|
|
|
@ -46,10 +46,11 @@ class Inventory():
|
||||||
- no scan of NVMe devices
|
- no scan of NVMe devices
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, server):
|
def __init__(self, server, update_expansion=False):
|
||||||
self.create_netbox_tags()
|
self.create_netbox_tags()
|
||||||
self.server = server
|
self.server = server
|
||||||
netbox_server = self.server.get_netbox_server()
|
self.update_expansion = update_expansion
|
||||||
|
netbox_server = self.server.get_netbox_server(update_expansion)
|
||||||
|
|
||||||
self.device_id = netbox_server.id if netbox_server else None
|
self.device_id = netbox_server.id if netbox_server else None
|
||||||
self.raid = None
|
self.raid = None
|
||||||
|
@ -220,7 +221,7 @@ class Inventory():
|
||||||
|
|
||||||
self.create_netbox_cpus()
|
self.create_netbox_cpus()
|
||||||
|
|
||||||
def get_raid_cards(self):
|
def get_raid_cards(self, filter_cards=False):
|
||||||
raid_class = None
|
raid_class = None
|
||||||
if self.server.manufacturer == 'Dell':
|
if self.server.manufacturer == 'Dell':
|
||||||
if is_tool('omreport'):
|
if is_tool('omreport'):
|
||||||
|
@ -235,9 +236,15 @@ class Inventory():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
self.raid = raid_class()
|
self.raid = raid_class()
|
||||||
controllers = self.raid.get_controllers()
|
|
||||||
if len(self.raid.get_controllers()):
|
if filter_cards and config.expansion_as_device \
|
||||||
return controllers
|
and self.server.own_expansion_slot():
|
||||||
|
return [
|
||||||
|
c for c in self.raid.get_controllers()
|
||||||
|
if c.is_external() is self.update_expansion
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
return self.raid.get_controllers()
|
||||||
|
|
||||||
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(
|
||||||
|
@ -276,7 +283,7 @@ class Inventory():
|
||||||
device_id=self.device_id,
|
device_id=self.device_id,
|
||||||
tag=[INVENTORY_TAG['raid_card']['slug']]
|
tag=[INVENTORY_TAG['raid_card']['slug']]
|
||||||
)
|
)
|
||||||
raid_cards = self.get_raid_cards()
|
raid_cards = self.get_raid_cards(filter_cards=True)
|
||||||
|
|
||||||
# delete cards that are in netbox but not locally
|
# delete cards that are in netbox but not locally
|
||||||
# use the serial_number has the comparison element
|
# use the serial_number has the comparison element
|
||||||
|
@ -336,7 +343,7 @@ class Inventory():
|
||||||
d['Vendor'] = get_vendor(disk['product'])
|
d['Vendor'] = get_vendor(disk['product'])
|
||||||
disks.append(d)
|
disks.append(d)
|
||||||
|
|
||||||
for raid_card in self.get_raid_cards():
|
for raid_card in self.get_raid_cards(filter_cards=True):
|
||||||
disks += raid_card.get_physical_disks()
|
disks += raid_card.get_physical_disks()
|
||||||
|
|
||||||
# remove duplicate serials
|
# remove duplicate serials
|
||||||
|
@ -463,21 +470,24 @@ class Inventory():
|
||||||
tag=INVENTORY_TAG['gpu']['slug'],
|
tag=INVENTORY_TAG['gpu']['slug'],
|
||||||
)
|
)
|
||||||
|
|
||||||
if not len(nb_gpus) or \
|
if config.expansion_as_device and len(nb_gpus):
|
||||||
|
for x in nb_gpus:
|
||||||
|
x.delete()
|
||||||
|
elif not len(nb_gpus) or \
|
||||||
len(nb_gpus) and len(gpus) != len(nb_gpus):
|
len(nb_gpus) and len(gpus) != len(nb_gpus):
|
||||||
for x in nb_gpus:
|
for x in nb_gpus:
|
||||||
x.delete()
|
x.delete()
|
||||||
|
|
||||||
self.create_netbox_gpus()
|
self.create_netbox_gpus()
|
||||||
|
|
||||||
def create_or_update(self):
|
def create_or_update(self):
|
||||||
if config.inventory is None or config.update_inventory is None:
|
if config.inventory is None or config.update_inventory is None:
|
||||||
return False
|
return False
|
||||||
self.do_netbox_cpus()
|
if self.update_expansion is False:
|
||||||
self.do_netbox_memories()
|
self.do_netbox_cpus()
|
||||||
self.do_netbox_raid_cards()
|
self.do_netbox_memories()
|
||||||
self.do_netbox_disks()
|
self.do_netbox_interfaces()
|
||||||
self.do_netbox_interfaces()
|
self.do_netbox_motherboard()
|
||||||
self.do_netbox_motherboard()
|
|
||||||
self.do_netbox_gpus()
|
self.do_netbox_gpus()
|
||||||
|
self.do_netbox_disks()
|
||||||
|
self.do_netbox_raid_cards()
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -15,6 +15,9 @@ class RaidController():
|
||||||
def get_physical_disks(self):
|
def get_physical_disks(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def is_external(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class Raid():
|
class Raid():
|
||||||
def get_controllers(self):
|
def get_controllers(self):
|
||||||
|
|
|
@ -1,106 +1,65 @@
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from netbox_agent.config import config
|
||||||
from netbox_agent.misc import get_vendor
|
from netbox_agent.misc import get_vendor
|
||||||
from netbox_agent.raid.base import Raid, RaidController
|
from netbox_agent.raid.base import Raid, RaidController
|
||||||
|
|
||||||
REGEXP_CONTROLLER_HP = re.compile(r'Smart Array ([a-zA-Z0-9- ]+) in Slot ([0-9]+)')
|
REGEXP_CONTROLLER_HP = re.compile(r'Smart Array ([a-zA-Z0-9- ]+) in Slot ([0-9]+)')
|
||||||
|
|
||||||
|
|
||||||
def _get_indentation(string):
|
def _parse_ctrl_output(lines):
|
||||||
"""Return the number of spaces before the current line."""
|
controllers = {}
|
||||||
return len(string) - len(string.lstrip(' '))
|
current_ctrl = None
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
def _get_key_value(string):
|
if not line or line.startswith('Note:'):
|
||||||
"""Return the (key, value) as a tuple from a string."""
|
|
||||||
# Normally all properties look like this:
|
|
||||||
# Unique Identifier: 600508B1001CE4ACF473EE9C826230FF
|
|
||||||
# Disk Name: /dev/sda
|
|
||||||
# Mount Points: None
|
|
||||||
key = ''
|
|
||||||
value = ''
|
|
||||||
try:
|
|
||||||
key, value = string.split(':')
|
|
||||||
except ValueError:
|
|
||||||
# This handles the case when the property of a logical drive
|
|
||||||
# returned is as follows. Here we cannot split by ':' because
|
|
||||||
# the disk id has colon in it. So if this is about disk,
|
|
||||||
# then strip it accordingly.
|
|
||||||
# Mirror Group 0: physicaldrive 6I:1:5
|
|
||||||
string = string.lstrip(' ')
|
|
||||||
if string.startswith('physicaldrive'):
|
|
||||||
fields = string.split(' ')
|
|
||||||
key = fields[0]
|
|
||||||
value = fields[1]
|
|
||||||
else:
|
|
||||||
# TODO(rameshg87): Check if this ever occurs.
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
return key.lstrip(' ').rstrip(' '), value.lstrip(' ').rstrip(' ')
|
|
||||||
|
|
||||||
|
|
||||||
def _get_dict(lines, start_index, indentation):
|
|
||||||
"""Recursive function for parsing hpssacli/ssacli output."""
|
|
||||||
|
|
||||||
info = {}
|
|
||||||
current_item = None
|
|
||||||
|
|
||||||
i = start_index
|
|
||||||
while i < len(lines):
|
|
||||||
current_line = lines[i]
|
|
||||||
if current_line.startswith('Note:'):
|
|
||||||
i = i + 1
|
|
||||||
continue
|
continue
|
||||||
|
ctrl = REGEXP_CONTROLLER_HP.search(line)
|
||||||
current_line_indentation = _get_indentation(current_line)
|
if ctrl is not None:
|
||||||
# This check ignore some useless information that make
|
current_ctrl = ctrl.group(1)
|
||||||
# crash the parsing
|
controllers[current_ctrl] = {"Slot": ctrl.group(2)}
|
||||||
product_name = REGEXP_CONTROLLER_HP.search(current_line)
|
if "Embedded" not in line:
|
||||||
if current_line_indentation == 0 and not product_name:
|
controllers[current_ctrl]["External"] = True
|
||||||
i = i + 1
|
|
||||||
continue
|
continue
|
||||||
|
attr, val = line.split(": ", 1)
|
||||||
|
attr = attr.strip()
|
||||||
|
val = val.strip()
|
||||||
|
controllers[current_ctrl][attr] = val
|
||||||
|
return controllers
|
||||||
|
|
||||||
if current_line_indentation == indentation:
|
|
||||||
current_item = current_line.lstrip(' ')
|
|
||||||
|
|
||||||
info[current_item] = {}
|
def _parse_pd_output(lines):
|
||||||
i = i + 1
|
drives = {}
|
||||||
|
current_array = None
|
||||||
|
current_drv = None
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('Note:'):
|
||||||
continue
|
continue
|
||||||
|
# Parses the Array the drives are in
|
||||||
if i >= len(lines) - 1:
|
if line.startswith("Array"):
|
||||||
key, value = _get_key_value(current_line)
|
current_array = line.split(None, 1)[1]
|
||||||
# If this is some unparsable information, then
|
# Detects new physical drive
|
||||||
# just skip it.
|
if line.startswith("physicaldrive"):
|
||||||
if key:
|
current_drv = line.split(None, 1)[1]
|
||||||
info[current_item][key] = value
|
drives[current_drv] = {}
|
||||||
return info, i
|
if current_array is not None:
|
||||||
|
drives[current_drv]["Array"] = current_array
|
||||||
next_line = lines[i + 1]
|
continue
|
||||||
next_line_indentation = _get_indentation(next_line)
|
if ": " not in line:
|
||||||
|
continue
|
||||||
if current_line_indentation == next_line_indentation:
|
attr, val = line.split(": ", 1)
|
||||||
key, value = _get_key_value(current_line)
|
drives.setdefault(current_drv, {})[attr] = val
|
||||||
if key:
|
return drives
|
||||||
info[current_item][key] = value
|
|
||||||
i = i + 1
|
|
||||||
elif next_line_indentation > current_line_indentation:
|
|
||||||
ret_dict, j = _get_dict(lines, i, current_line_indentation)
|
|
||||||
info[current_item].update(ret_dict)
|
|
||||||
i = j + 1
|
|
||||||
elif next_line_indentation < current_line_indentation:
|
|
||||||
key, value = _get_key_value(current_line)
|
|
||||||
if key:
|
|
||||||
info[current_item][key] = value
|
|
||||||
return info, i
|
|
||||||
|
|
||||||
return info, i
|
|
||||||
|
|
||||||
|
|
||||||
class HPRaidController(RaidController):
|
class HPRaidController(RaidController):
|
||||||
def __init__(self, controller_name, data):
|
def __init__(self, controller_name, data):
|
||||||
self.controller_name = controller_name
|
self.controller_name = controller_name
|
||||||
self.data = data
|
self.data = data
|
||||||
|
self.drives = self._get_physical_disks()
|
||||||
|
|
||||||
def get_product_name(self):
|
def get_product_name(self):
|
||||||
return self.controller_name
|
return self.controller_name
|
||||||
|
@ -114,40 +73,42 @@ class HPRaidController(RaidController):
|
||||||
def get_firmware_version(self):
|
def get_firmware_version(self):
|
||||||
return self.data['Firmware Version']
|
return self.data['Firmware Version']
|
||||||
|
|
||||||
def get_physical_disks(self):
|
def is_external(self):
|
||||||
ret = []
|
return self.data.get('External', False)
|
||||||
|
|
||||||
|
def _get_physical_disks(self):
|
||||||
output = subprocess.getoutput(
|
output = subprocess.getoutput(
|
||||||
'ssacli ctrl slot={slot} pd all show detail'.format(slot=self.data['Slot'])
|
'ssacli ctrl slot={slot} pd all show detail'.format(slot=self.data['Slot'])
|
||||||
)
|
)
|
||||||
lines = output.split('\n')
|
lines = output.split('\n')
|
||||||
lines = list(filter(None, lines))
|
lines = list(filter(None, lines))
|
||||||
j = -1
|
drives = _parse_pd_output(lines)
|
||||||
while j < len(lines):
|
ret = []
|
||||||
info_dict, j = _get_dict(lines, j + 1, 0)
|
|
||||||
|
|
||||||
key = next(iter(info_dict))
|
for name, attrs in drives.items():
|
||||||
for array, physical_disk in info_dict[key].items():
|
model = attrs.get('Model', '').strip()
|
||||||
for _, pd_attr in physical_disk.items():
|
vendor = None
|
||||||
model = pd_attr.get('Model', '').strip()
|
if model.startswith('HP'):
|
||||||
vendor = None
|
vendor = 'HP'
|
||||||
if model.startswith('HP'):
|
elif len(model.split()) > 1:
|
||||||
vendor = 'HP'
|
vendor = get_vendor(model.split()[1])
|
||||||
elif len(model.split()) > 1:
|
else:
|
||||||
vendor = get_vendor(model.split()[1])
|
vendor = get_vendor(model)
|
||||||
else:
|
|
||||||
vendor = get_vendor(model)
|
|
||||||
|
|
||||||
ret.append({
|
ret.append({
|
||||||
'Model': model,
|
'Model': model,
|
||||||
'Vendor': vendor,
|
'Vendor': vendor,
|
||||||
'SN': pd_attr.get('Serial Number', '').strip(),
|
'SN': attrs.get('Serial Number', '').strip(),
|
||||||
'Size': pd_attr.get('Size', '').strip(),
|
'Size': attrs.get('Size', '').strip(),
|
||||||
'Type': 'SSD' if pd_attr.get('Interface Type') == 'Solid State SATA'
|
'Type': 'SSD' if attrs.get('Interface Type') == 'Solid State SATA'
|
||||||
else 'HDD',
|
else 'HDD',
|
||||||
'_src': self.__class__.__name__,
|
'_src': self.__class__.__name__,
|
||||||
})
|
})
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def get_physical_disks(self):
|
||||||
|
return self.drives
|
||||||
|
|
||||||
|
|
||||||
class HPRaid(Raid):
|
class HPRaid(Raid):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -158,16 +119,11 @@ class HPRaid(Raid):
|
||||||
def convert_to_dict(self):
|
def convert_to_dict(self):
|
||||||
lines = self.output.split('\n')
|
lines = self.output.split('\n')
|
||||||
lines = list(filter(None, lines))
|
lines = list(filter(None, lines))
|
||||||
j = -1
|
controllers = _parse_ctrl_output(lines)
|
||||||
while j < len(lines):
|
for controller, attrs in controllers.items():
|
||||||
info_dict, j = _get_dict(lines, j + 1, 0)
|
self.controllers.append(
|
||||||
if len(info_dict.keys()):
|
HPRaidController(controller, attrs)
|
||||||
_product_name = list(info_dict.keys())[0]
|
)
|
||||||
product_name = REGEXP_CONTROLLER_HP.search(_product_name)
|
|
||||||
if product_name:
|
|
||||||
self.controllers.append(
|
|
||||||
HPRaidController(product_name.group(1), info_dict[_product_name])
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_controllers(self):
|
def get_controllers(self):
|
||||||
return self.controllers
|
return self.controllers
|
||||||
|
|
|
@ -25,6 +25,7 @@ class ServerBase():
|
||||||
self.bios = dmidecode.get_by_type(self.dmi, 'BIOS')
|
self.bios = dmidecode.get_by_type(self.dmi, 'BIOS')
|
||||||
self.chassis = dmidecode.get_by_type(self.dmi, 'Chassis')
|
self.chassis = dmidecode.get_by_type(self.dmi, 'Chassis')
|
||||||
self.system = dmidecode.get_by_type(self.dmi, 'System')
|
self.system = dmidecode.get_by_type(self.dmi, 'System')
|
||||||
|
self.inventory = Inventory(server=self)
|
||||||
|
|
||||||
self.network = None
|
self.network = None
|
||||||
|
|
||||||
|
@ -94,6 +95,19 @@ class ServerBase():
|
||||||
server.position = None
|
server.position = None
|
||||||
return update, server
|
return update, server
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
def get_rack(self):
|
def get_rack(self):
|
||||||
rack = Rack()
|
rack = Rack()
|
||||||
return rack.get()
|
return rack.get()
|
||||||
|
@ -256,8 +270,11 @@ class ServerBase():
|
||||||
)
|
)
|
||||||
return new_server
|
return new_server
|
||||||
|
|
||||||
def get_netbox_server(self):
|
def get_netbox_server(self, expansion=False):
|
||||||
return nb.dcim.devices.get(serial=self.get_service_tag())
|
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())
|
||||||
|
|
||||||
def _netbox_set_or_update_blade_slot(self, server, chassis, datacenter):
|
def _netbox_set_or_update_blade_slot(self, server, chassis, datacenter):
|
||||||
# before everything check if right chassis
|
# before everything check if right chassis
|
||||||
|
@ -292,9 +309,9 @@ class ServerBase():
|
||||||
slot=slot
|
slot=slot
|
||||||
))
|
))
|
||||||
|
|
||||||
def _netbox_set_or_update_blade_expansion_slot(self, server, chassis, datacenter):
|
def _netbox_set_or_update_blade_expansion_slot(self, expansion, chassis, datacenter):
|
||||||
# before everything check if right chassis
|
# before everything check if right chassis
|
||||||
actual_device_bay = server.parent_device.device_bay if server.parent_device else None
|
actual_device_bay = expansion.parent_device.device_bay if expansion.parent_device else None
|
||||||
actual_chassis = actual_device_bay.device if actual_device_bay else None
|
actual_chassis = actual_device_bay.device if actual_device_bay else None
|
||||||
slot = self.get_blade_expansion_slot()
|
slot = self.get_blade_expansion_slot()
|
||||||
if actual_chassis and \
|
if actual_chassis and \
|
||||||
|
@ -302,30 +319,28 @@ class ServerBase():
|
||||||
actual_device_bay.name == slot:
|
actual_device_bay.name == slot:
|
||||||
return
|
return
|
||||||
|
|
||||||
server.name += " expansion"
|
|
||||||
|
|
||||||
real_device_bays = nb.dcim.device_bays.filter(
|
real_device_bays = nb.dcim.device_bays.filter(
|
||||||
device_id=chassis.id,
|
device_id=chassis.id,
|
||||||
name=slot,
|
name=slot,
|
||||||
)
|
)
|
||||||
if len(real_device_bays) > 0:
|
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(
|
logging.error('Could not find slot {slot} expansion for chassis'.format(
|
||||||
slot=slot
|
slot=slot
|
||||||
))
|
))
|
||||||
|
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:
|
||||||
|
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 = expansion
|
||||||
|
real_device_bay.save()
|
||||||
|
|
||||||
def netbox_create_or_update(self, config):
|
def netbox_create_or_update(self, config):
|
||||||
"""
|
"""
|
||||||
|
@ -370,9 +385,10 @@ class ServerBase():
|
||||||
if config.register or config.update_all or config.update_network:
|
if config.register or config.update_all or config.update_network:
|
||||||
self.network = ServerNetwork(server=self)
|
self.network = ServerNetwork(server=self)
|
||||||
self.network.create_or_update_netbox_network_cards()
|
self.network.create_or_update_netbox_network_cards()
|
||||||
|
update_inventory = config.inventory and (config.register or
|
||||||
|
config.update_all or config.update_inventory)
|
||||||
# update inventory if feature is enabled
|
# update inventory if feature is enabled
|
||||||
if config.inventory and (config.register or config.update_all or config.update_inventory):
|
if update_inventory:
|
||||||
self.inventory = Inventory(server=self)
|
|
||||||
self.inventory.create_or_update()
|
self.inventory.create_or_update()
|
||||||
# update psu
|
# update psu
|
||||||
if config.register or config.update_all or config.update_psu:
|
if config.register or config.update_all or config.update_psu:
|
||||||
|
@ -380,14 +396,21 @@ 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():
|
expansion = nb.dcim.devices.get(serial=self.get_expansion_service_tag())
|
||||||
|
if self.own_expansion_slot() and config.expansion_as_device:
|
||||||
logging.debug('Update Server expansion...')
|
logging.debug('Update Server expansion...')
|
||||||
expansion = nb.dcim.devices.get(serial=self.get_expansion_service_tag())
|
|
||||||
if not expansion:
|
if not expansion:
|
||||||
expansion = self._netbox_create_blade_expansion(chassis, datacenter, tenant, rack)
|
expansion = self._netbox_create_blade_expansion(chassis, datacenter, tenant, rack)
|
||||||
|
|
||||||
# set slot for blade expansion
|
# set slot for blade expansion
|
||||||
self._netbox_set_or_update_blade_expansion_slot(expansion, chassis, datacenter)
|
self._netbox_set_or_update_blade_expansion_slot(expansion, chassis, datacenter)
|
||||||
|
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
|
||||||
|
|
||||||
update = 0
|
update = 0
|
||||||
# for every other specs
|
# for every other specs
|
||||||
|
@ -396,6 +419,7 @@ class ServerBase():
|
||||||
update += 1
|
update += 1
|
||||||
server.name = self.get_hostname()
|
server.name = self.get_hostname()
|
||||||
|
|
||||||
|
|
||||||
if sorted(set(server.tags)) != sorted(set(self.tags)):
|
if sorted(set(server.tags)) != sorted(set(self.tags)):
|
||||||
server.tags = self.tags
|
server.tags = self.tags
|
||||||
update += 1
|
update += 1
|
||||||
|
@ -406,6 +430,17 @@ class ServerBase():
|
||||||
|
|
||||||
if update:
|
if update:
|
||||||
server.save()
|
server.save()
|
||||||
|
|
||||||
|
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()
|
||||||
logging.debug('Finished updating Server!')
|
logging.debug('Finished updating Server!')
|
||||||
|
|
||||||
def print_debug(self):
|
def print_debug(self):
|
||||||
|
|
48
netbox_agent/vendors/hp.py
vendored
48
netbox_agent/vendors/hp.py
vendored
|
@ -67,35 +67,49 @@ class HPHost(ServerBase):
|
||||||
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_blade_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Expansion slot are always the compute bay number + 1
|
||||||
|
"""
|
||||||
|
if self.is_blade() and self.own_gpu_expansion_slot() or \
|
||||||
|
self.own_disk_expansion_slot() or True:
|
||||||
|
return 'Bay {}'.format(
|
||||||
|
str(int(self.hp_rack_locator['Server Bay'].strip()) + 1)
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
def get_expansion_product(self):
|
def get_expansion_product(self):
|
||||||
"""
|
"""
|
||||||
Get the extension slot that is on a pair slot number
|
Get the extension slot that is on a pair slot number
|
||||||
next to the compute slot that is on an odd 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.
|
I only know on model of slot GPU extension card that.
|
||||||
"""
|
"""
|
||||||
if self.own_expansion_slot():
|
if self.own_gpu_expansion_slot():
|
||||||
return "ProLiant BL460c Graphics Expansion Blade"
|
return "ProLiant BL460c Graphics Expansion Blade"
|
||||||
return None
|
elif self.own_disk_expansion_slot():
|
||||||
|
return "ProLiant BL460c Disk Expansion Blade"
|
||||||
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
|
return None
|
||||||
|
|
||||||
def own_expansion_slot(self):
|
def own_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Say if the device can host an extension card based
|
||||||
|
on the product name
|
||||||
|
"""
|
||||||
|
return self.own_gpu_expansion_slot() or self.own_disk_expansion_slot()
|
||||||
|
|
||||||
|
def own_gpu_expansion_slot(self):
|
||||||
"""
|
"""
|
||||||
Say if the device can host an extension card based
|
Say if the device can host an extension card based
|
||||||
on the product name
|
on the product name
|
||||||
"""
|
"""
|
||||||
return self.get_product_name().endswith('Graphics Exp')
|
return self.get_product_name().endswith('Graphics Exp')
|
||||||
|
|
||||||
|
def own_disk_expansion_slot(self):
|
||||||
|
"""
|
||||||
|
Say if the device can host an extension card based
|
||||||
|
on the product name
|
||||||
|
"""
|
||||||
|
for raid_card in self.inventory.get_raid_cards():
|
||||||
|
if self.is_blade() and raid_card.is_external():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
Loading…
Reference in a new issue