commit
3a802cb4a6
6 changed files with 106 additions and 52 deletions
|
|
@ -70,15 +70,21 @@ class LSHW():
|
||||||
return self.memories
|
return self.memories
|
||||||
|
|
||||||
def find_network(self, obj):
|
def find_network(self, obj):
|
||||||
d = {}
|
# Some interfaces do not have device (logical) name (eth0, for
|
||||||
d["name"] = obj["logicalname"]
|
# instance), such as not connected network mezzanine cards in blade
|
||||||
d["macaddress"] = obj["serial"]
|
# servers. In such situations, the card will be named `unknown[0-9]`.
|
||||||
d["serial"] = obj["serial"]
|
unkn_intfs = [
|
||||||
d["product"] = obj["product"]
|
i for i in self.interfaces if i["name"].startswith("unknown")
|
||||||
d["vendor"] = obj["vendor"]
|
]
|
||||||
d["description"] = obj["description"]
|
unkn_name = "unknown{}".format(len(unkn_intfs))
|
||||||
|
self.interfaces.append({
|
||||||
self.interfaces.append(d)
|
"name": obj.get("logicalname", unkn_name),
|
||||||
|
"macaddress": obj.get("serial", ""),
|
||||||
|
"serial": obj.get("serial", ""),
|
||||||
|
"product": obj["product"],
|
||||||
|
"vendor": obj["vendor"],
|
||||||
|
"description": obj["description"],
|
||||||
|
})
|
||||||
|
|
||||||
def find_storage(self, obj):
|
def find_storage(self, obj):
|
||||||
if "children" in obj:
|
if "children" in obj:
|
||||||
|
|
@ -121,13 +127,12 @@ class LSHW():
|
||||||
|
|
||||||
def find_cpus(self, obj):
|
def find_cpus(self, obj):
|
||||||
if "product" in obj:
|
if "product" in obj:
|
||||||
c = {}
|
self.cpus.append({
|
||||||
c["product"] = obj["product"]
|
"product": obj["product"],
|
||||||
c["vendor"] = obj["vendor"]
|
"vendor": obj["vendor"],
|
||||||
c["description"] = obj["description"]
|
"description": obj["description"],
|
||||||
c["location"] = obj["slot"]
|
"location": obj["slot"],
|
||||||
|
})
|
||||||
self.cpus.append(c)
|
|
||||||
|
|
||||||
def find_memories(self, obj):
|
def find_memories(self, obj):
|
||||||
if "children" not in obj:
|
if "children" not in obj:
|
||||||
|
|
@ -138,25 +143,23 @@ class LSHW():
|
||||||
if "empty" in dimm["description"]:
|
if "empty" in dimm["description"]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
d = {}
|
self.memories.append({
|
||||||
d["slot"] = dimm.get("slot")
|
"slot": dimm.get("slot"),
|
||||||
d["description"] = dimm.get("description")
|
"description": dimm.get("description"),
|
||||||
d["id"] = dimm.get("id")
|
"id": dimm.get("id"),
|
||||||
d["serial"] = dimm.get("serial", 'N/A')
|
"serial": dimm.get("serial", 'N/A'),
|
||||||
d["vendor"] = dimm.get("vendor", 'N/A')
|
"vendor": dimm.get("vendor", 'N/A'),
|
||||||
d["product"] = dimm.get("product", 'N/A')
|
"product": dimm.get("product", 'N/A'),
|
||||||
d["size"] = dimm.get("size", 0) / 2 ** 20 / 1024
|
"size": dimm.get("size", 0) / 2 ** 20 / 1024,
|
||||||
|
})
|
||||||
self.memories.append(d)
|
|
||||||
|
|
||||||
def find_gpus(self, obj):
|
def find_gpus(self, obj):
|
||||||
if "product" in obj:
|
if "product" in obj:
|
||||||
c = {}
|
self.gpus.append({
|
||||||
c["product"] = obj["product"]
|
"product": obj["product"],
|
||||||
c["vendor"] = obj["vendor"]
|
"vendor": obj["vendor"],
|
||||||
c["description"] = obj["description"]
|
"description": obj["description"],
|
||||||
|
})
|
||||||
self.gpus.append(c)
|
|
||||||
|
|
||||||
def walk_bridge(self, obj):
|
def walk_bridge(self, obj):
|
||||||
if "children" not in obj:
|
if "children" not in obj:
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ class Network(object):
|
||||||
|
|
||||||
def create_netbox_nic(self, nic, mgmt=False):
|
def create_netbox_nic(self, nic, mgmt=False):
|
||||||
# TODO: add Optic Vendor, PN and Serial
|
# TODO: add Optic Vendor, PN and Serial
|
||||||
type = self.get_netbox_type_for_nic(nic)
|
nic_type = self.get_netbox_type_for_nic(nic)
|
||||||
logging.info('Creating NIC {name} ({mac}) on {device}'.format(
|
logging.info('Creating NIC {name} ({mac}) on {device}'.format(
|
||||||
name=nic['name'], mac=nic['mac'], device=self.device.name))
|
name=nic['name'], mac=nic['mac'], device=self.device.name))
|
||||||
|
|
||||||
|
|
@ -270,11 +270,10 @@ class Network(object):
|
||||||
params = dict(self.custom_arg)
|
params = dict(self.custom_arg)
|
||||||
params.update({
|
params.update({
|
||||||
'name': nic['name'],
|
'name': nic['name'],
|
||||||
'type': type,
|
'type': nic_type,
|
||||||
'mgmt_only': mgmt,
|
'mgmt_only': mgmt,
|
||||||
})
|
})
|
||||||
|
if nic['mac']:
|
||||||
if not nic.get('virtual', False):
|
|
||||||
params['mac_address'] = nic['mac']
|
params['mac_address'] = nic['mac']
|
||||||
|
|
||||||
interface = self.nb_net.interfaces.create(**params)
|
interface = self.nb_net.interfaces.create(**params)
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,26 @@ import re
|
||||||
|
|
||||||
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]+)')
|
||||||
|
|
||||||
|
class HPRaidControllerError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
def ssacli(command):
|
|
||||||
output = subprocess.getoutput('ssacli {}'.format(command) )
|
def ssacli(sub_command):
|
||||||
lines = output.split('\n')
|
command = ["ssacli"]
|
||||||
|
command.extend(sub_command.split())
|
||||||
|
p = subprocess.Popen(
|
||||||
|
command,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
p.wait()
|
||||||
|
stdout = p.stdout.read().decode("utf-8")
|
||||||
|
if p.returncode != 0:
|
||||||
|
mesg = "Failed to execute command '{}':\n{}".format(
|
||||||
|
" ".join(command), stdout
|
||||||
|
)
|
||||||
|
raise HPRaidControllerError(mesg)
|
||||||
|
lines = stdout.split('\n')
|
||||||
lines = list(filter(None, lines))
|
lines = list(filter(None, lines))
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
@ -92,8 +108,10 @@ class HPRaidController(RaidController):
|
||||||
self.controller_name = controller_name
|
self.controller_name = controller_name
|
||||||
self.data = data
|
self.data = data
|
||||||
self.pdrives = self._get_physical_disks()
|
self.pdrives = self._get_physical_disks()
|
||||||
self.ldrives = self._get_logical_drives()
|
arrays = [d['Array'] for d in self.pdrives.values() if d.get('Array')]
|
||||||
self._get_virtual_drives_map()
|
if arrays:
|
||||||
|
self.ldrives = self._get_logical_drives()
|
||||||
|
self._get_virtual_drives_map()
|
||||||
|
|
||||||
def get_product_name(self):
|
def get_product_name(self):
|
||||||
return self.controller_name
|
return self.controller_name
|
||||||
|
|
@ -135,6 +153,7 @@ class HPRaidController(RaidController):
|
||||||
'Type': 'SSD' if attrs.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__,
|
||||||
|
'custom_fields': {'pd_identifier': name}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
@ -164,8 +183,7 @@ class HPRaidController(RaidController):
|
||||||
" Ignoring.".format(name)
|
" Ignoring.".format(name)
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
attrs['custom_fields'] = ld
|
attrs['custom_fields'].update(ld)
|
||||||
attrs['custom_fields']['pd_identifier'] = name
|
|
||||||
|
|
||||||
def get_physical_disks(self):
|
def get_physical_disks(self):
|
||||||
return list(self.pdrives.values())
|
return list(self.pdrives.values())
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,32 @@ import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class OmreportControllerError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def omreport(sub_command):
|
def omreport(sub_command):
|
||||||
command = 'omreport {}'.format(sub_command)
|
command = ["omreport"]
|
||||||
output = subprocess.getoutput(command)
|
command.extend(sub_command.split())
|
||||||
|
p = subprocess.Popen(
|
||||||
|
command,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
p.wait()
|
||||||
|
stdout = p.stdout.read().decode("utf-8")
|
||||||
|
if p.returncode != 0:
|
||||||
|
mesg = "Failed to execute command '{}':\n{}".format(
|
||||||
|
" ".join(command), stdout
|
||||||
|
)
|
||||||
|
raise OmreportControllerError(mesg)
|
||||||
|
|
||||||
res = {}
|
res = {}
|
||||||
section_re = re.compile('^[A-Z]')
|
section_re = re.compile('^[A-Z]')
|
||||||
current_section = None
|
current_section = None
|
||||||
current_obj = None
|
current_obj = None
|
||||||
|
|
||||||
for line in output.split('\n'):
|
for line in stdout.split('\n'):
|
||||||
if ': ' in line:
|
if ': ' in line:
|
||||||
attr, value = line.split(': ', 1)
|
attr, value = line.split(': ', 1)
|
||||||
attr = attr.strip()
|
attr = attr.strip()
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,27 @@ import re
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class StorcliControllerError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def storecli(sub_command):
|
def storecli(sub_command):
|
||||||
command = 'storcli {} J'.format(sub_command)
|
command = ["storcli"]
|
||||||
output = subprocess.getoutput(command)
|
command.extend(sub_command.split())
|
||||||
data = json.loads(output)
|
command.append("J")
|
||||||
|
p = subprocess.Popen(
|
||||||
|
command,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
p.wait()
|
||||||
|
stdout = p.stdout.read().decode("utf-8")
|
||||||
|
if p.returncode != 0:
|
||||||
|
mesg = "Failed to execute command '{}':\n{}".format(
|
||||||
|
" ".join(command), stdout
|
||||||
|
)
|
||||||
|
raise StorcliControllerError(mesg)
|
||||||
|
data = json.loads(stdout)
|
||||||
controllers = dict([
|
controllers = dict([
|
||||||
(
|
(
|
||||||
c['Command Status']['Controller'],
|
c['Command Status']['Controller'],
|
||||||
|
|
@ -22,7 +39,7 @@ def storecli(sub_command):
|
||||||
if not controllers:
|
if not controllers:
|
||||||
logging.error(
|
logging.error(
|
||||||
"Failed to execute command '{}'. "
|
"Failed to execute command '{}'. "
|
||||||
"Ignoring data.".format(command)
|
"Ignoring data.".format(" ".join(command))
|
||||||
)
|
)
|
||||||
return {}
|
return {}
|
||||||
return controllers
|
return controllers
|
||||||
|
|
|
||||||
2
setup.py
2
setup.py
|
|
@ -16,7 +16,7 @@ def get_requirements():
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='netbox_agent',
|
name='netbox_agent',
|
||||||
version='0.7.0',
|
version='0.7.1',
|
||||||
description='NetBox agent for server',
|
description='NetBox agent for server',
|
||||||
long_description=open('README.md', encoding="utf-8").read(),
|
long_description=open('README.md', encoding="utf-8").read(),
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
|
|
|
||||||
Loading…
Add table
editor.link_modal.header
Reference in a new issue