2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-04-27 19:07:46 +00:00

Geit PDU nodeinvntory

Please enter the commit message for your changes. Lines starting
 with '' will be ignored, and an empty message aborts the commit.

 On branch master
 Your branch is up to date with 'origin/master'.

 Changes to be committed:
	modified:   geist.py
This commit is contained in:
weragrzeda
2023-08-25 08:27:27 +02:00
parent 6d87d11f5e
commit f633c93d0f

View File

@@ -20,23 +20,28 @@ import eventlet.green.time as time
import eventlet
import eventlet.greenpool as greenpool
def simplify_name(name):
return name.lower().replace(' ', '_').replace('/', '-').replace(
'_-_', '-')
return name.lower().replace(" ", "_").replace("/", "-").replace("_-_", "-")
pdupool = greenpool.GreenPool(128)
def data_by_type(indata):
databytype = {}
for keyname in indata:
obj = indata[keyname]
objtype = obj.get('type', None)
objtype = obj.get("type", None)
if not objtype:
continue
if objtype in databytype:
raise Exception("Multiple instances of type {} not yet supported".format(objtype))
raise Exception(
"Multiple instances of type {} not yet supported".format(objtype)
)
databytype[objtype] = obj
obj['keyname'] = keyname
obj["keyname"] = keyname
return databytype
@@ -58,173 +63,227 @@ class GeistClient(object):
def wc(self):
if self._wc:
return self._wc
targcfg = self.configmanager.get_node_attributes(self.node,
['hardwaremanagement.manager'],
decrypt=True)
targcfg = self.configmanager.get_node_attributes(
self.node, ["hardwaremanagement.manager"], decrypt=True
)
targcfg = targcfg.get(self.node, {})
target = targcfg.get(
'hardwaremanagement.manager', {}).get('value', None)
target = targcfg.get("hardwaremanagement.manager", {}).get("value", None)
if not target:
target = self.node
target = target.split('/', 1)[0]
target = target.split("/", 1)[0]
cv = util.TLSCertVerifier(
self.configmanager, self.node,
'pubkeys.tls_hardwaremanager').verify_cert
self.configmanager, self.node, "pubkeys.tls_hardwaremanager"
).verify_cert
self._wc = wc.SecureHTTPConnection(target, port=443, verifycallback=cv)
return self._wc
def login(self, configmanager):
credcfg = configmanager.get_node_attributes(self.node,
['secret.hardwaremanagementuser',
'secret.hardwaremanagementpassword'],
decrypt=True)
credcfg = configmanager.get_node_attributes(
self.node,
["secret.hardwaremanagementuser", "secret.hardwaremanagementpassword"],
decrypt=True,
)
credcfg = credcfg.get(self.node, {})
username = credcfg.get(
'secret.hardwaremanagementuser', {}).get('value', None)
passwd = credcfg.get(
'secret.hardwaremanagementpassword', {}).get('value', None)
username = credcfg.get("secret.hardwaremanagementuser", {}).get("value", None)
passwd = credcfg.get("secret.hardwaremanagementpassword", {}).get("value", None)
if not isinstance(username, str):
username = username.decode('utf8')
username = username.decode("utf8")
if not isinstance(passwd, str):
passwd = passwd.decode('utf8')
passwd = passwd.decode("utf8")
if not username or not passwd:
raise Exception('Missing username or password')
raise Exception("Missing username or password")
self.username = username
rsp = self.wc.grab_json_response(
'/api/auth/{0}'.format(username),
{'cmd': 'login', 'data': {'password': passwd}})
token = rsp['data']['token']
"/api/auth/{0}".format(username),
{"cmd": "login", "data": {"password": passwd}},
)
token = rsp["data"]["token"]
return token
def logout(self):
if self._token:
self.wc.grab_json_response('/api/auth/{0}'.format(self.username),
{'cmd': 'logout', 'token': self.token})
self.wc.grab_json_response(
"/api/auth/{0}".format(self.username),
{"cmd": "logout", "token": self.token},
)
self._token = None
def get_outlet(self, outlet):
rsp = self.wc.grab_json_response('/api/dev')
rsp = rsp['data']
rsp = self.wc.grab_json_response("/api/dev")
rsp = rsp["data"]
dbt = data_by_type(rsp)
if 't3hd' in dbt:
del dbt['t3hd']
if "t3hd" in dbt:
del dbt["t3hd"]
if len(dbt) != 1:
raise Exception('Multiple PDUs not supported per pdu')
raise Exception("Multiple PDUs not supported per pdu")
pdutype = list(dbt)[0]
outlet = dbt[pdutype]['outlet'][str(int(outlet) - 1)]
state = outlet['state'].split('2')[-1]
outlet = dbt[pdutype]["outlet"][str(int(outlet) - 1)]
state = outlet["state"].split("2")[-1]
return state
def set_outlet(self, outlet, state):
rsp = self.wc.grab_json_response('/api/dev')
dbt = data_by_type(rsp['data'])
if 't3hd' in dbt:
del dbt['t3hd']
rsp = self.wc.grab_json_response("/api/dev")
dbt = data_by_type(rsp["data"])
if "t3hd" in dbt:
del dbt["t3hd"]
if len(dbt) != 1:
self.logout()
raise Exception('Multiple PDUs per endpoint not supported')
pdu = dbt[list(dbt)[0]]['keyname']
raise Exception("Multiple PDUs per endpoint not supported")
pdu = dbt[list(dbt)[0]]["keyname"]
outlet = int(outlet) - 1
rsp = self.wc.grab_json_response(
'/api/dev/{0}/outlet/{1}'.format(pdu, outlet),
{'cmd': 'control', 'token': self.token,
'data': {'action': state, 'delay': False}})
"/api/dev/{0}/outlet/{1}".format(pdu, outlet),
{
"cmd": "control",
"token": self.token,
"data": {"action": state, "delay": False},
},
)
def process_measurement(keyname, name, enttype, entname, measurement, readings, category):
if measurement['type'] == 'realPower':
if category not in ('all', 'power'):
def process_measurement(
keyname, name, enttype, entname, measurement, readings, category
):
if measurement["type"] == "realPower":
if category not in ("all", "power"):
return
readtype = 'Real Power'
elif measurement['type'] == 'apparentPower':
if category not in ('all', 'power'):
readtype = "Real Power"
elif measurement["type"] == "apparentPower":
if category not in ("all", "power"):
return
readtype = 'Apparent Power'
elif measurement['type'] == 'energy':
if category not in ('all', 'energy'):
readtype = "Apparent Power"
elif measurement["type"] == "energy":
if category not in ("all", "energy"):
return
readtype = 'Energy'
elif measurement['type'] == 'voltage':
if category not in ('all',):
readtype = "Energy"
elif measurement["type"] == "voltage":
if category not in ("all",):
return
readtype = 'Voltage'
elif measurement['type'] == 'temperature':
readtype = 'Temperature'
elif measurement['type'] == 'dewpoint':
readtype = 'Dewpoint'
elif measurement['type'] == 'humidity':
readtype = 'Humidity'
readtype = "Voltage"
elif measurement["type"] == "temperature":
readtype = "Temperature"
elif measurement["type"] == "dewpoint":
readtype = "Dewpoint"
elif measurement["type"] == "humidity":
readtype = "Humidity"
else:
return
myname = entname + ' ' + readtype
if name != 'all' and simplify_name(myname) != name:
myname = entname + " " + readtype
if name != "all" and simplify_name(myname) != name:
return
readings.append({
'name': myname,
'value': float(measurement['value']),
'units': measurement['units'],
'type': readtype.split()[-1]
})
readings.append(
{
"name": myname,
"value": float(measurement["value"]),
"units": measurement["units"],
"type": readtype.split()[-1],
}
)
def process_measurements(name, category, measurements, enttype, readings):
for measure in util.natural_sort(list(measurements)):
measurement = measurements[measure]['measurement']
entname = measurements[measure]['name']
measurement = measurements[measure]["measurement"]
entname = measurements[measure]["name"]
for measureid in measurement:
process_measurement(measure, name, enttype, entname, measurement[measureid], readings, category)
process_measurement(
measure,
name,
enttype,
entname,
measurement[measureid],
readings,
category,
)
_sensors_by_node = {}
def read_sensors(element, node, configmanager):
category, name = element[-2:]
justnames = False
if len(element) == 3:
# just get names
category = name
name = 'all'
name = "all"
justnames = True
if category in ('leds, fans', 'temperature'):
if category in ("leds, fans", "temperature"):
return
sn = _sensors_by_node.get(node, None)
if not sn or sn[1] < time.time():
gc = GeistClient(node, configmanager)
adev = gc.wc.grab_json_response('/api/dev')
adev = gc.wc.grab_json_response("/api/dev")
_sensors_by_node[node] = (adev, time.time() + 1)
sn = _sensors_by_node.get(node, None)
dbt = data_by_type(sn[0]['data'])
dbt = data_by_type(sn[0]["data"])
readings = []
for datatype in dbt:
for datatype in dbt:
datum = dbt[datatype]
process_measurements(name, category, datum['entity'], 'entity', readings)
if 'outlet' in datum:
process_measurements(name, category, datum['outlet'], 'outlet', readings)
process_measurements(name, category, datum["entity"], "entity", readings)
if "outlet" in datum:
process_measurements(name, category, datum["outlet"], "outlet", readings)
if justnames:
for reading in readings:
yield msg.ChildCollection(simplify_name(reading['name']))
yield msg.ChildCollection(simplify_name(reading["name"]))
else:
yield msg.SensorReadings(readings, name=node)
def get_outlet(node, configmanager, element):
gc = GeistClient(node, configmanager)
state = gc.get_outlet(element[-1])
return msg.PowerState(node=node, state=state)
def read_firmware(node, configmanager):
gc = GeistClient(node, configmanager)
adev = gc.wc.grab_json_response('/api/sys')
myversion = adev['data']['version']
yield msg.Firmware([{'PDU Firmware': {'version': myversion}}], node)
adev = gc.wc.grab_json_response("/api/sys")
myversion = adev["data"]["version"]
yield msg.Firmware([{"PDU Firmware": {"version": myversion}}], node)
def read_inventory(element, node, configmanager):
_inventory = {}
inventory = {}
gc = GeistClient(node, configmanager)
adev = gc.wc.grab_json_response("/api/sys")
basedata = adev["data"]
inventory["present"] = True
inventory["name"] = "PDU"
for elem in basedata.items():
if (
elem[0] != "component"
and elem[0] != "locale"
and elem[0] != "state"
and elem[0] != "contact"
): # and elem[0] !='name':
_inventory[elem[0]] = elem[1]
elif elem[0] == "component":
tempname = ""
for component in basedata["component"].items():
for item in component:
if type(item) == str:
tempname = item
else:
for entry in item.items():
_inventory[tempname + " " + entry[0]] = entry[1]
inventory["information"] = _inventory
yield msg.KeyValueData({"inventory": [inventory]}, node)
def retrieve(nodes, element, configmanager, inputdata):
if 'outlets' in element:
if "outlets" in element:
gp = greenpool.GreenPile(pdupool)
for node in nodes:
gp.spawn(get_outlet, node, configmanager, element)
gp.spawn(get_outlet, element, node, configmanager)
for res in gp:
yield res
return
elif element[0] == 'sensors':
elif element[0] == "sensors":
gp = greenpool.GreenPile(pdupool)
for node in nodes:
gp.spawn(read_sensors, element, node, configmanager)
@@ -232,21 +291,30 @@ def retrieve(nodes, element, configmanager, inputdata):
for datum in rsp:
yield datum
return
elif '/'.join(element).startswith('inventory/firmware/all'):
elif "/".join(element).startswith("inventory/firmware/all"):
gp = greenpool.GreenPile(pdupool)
for node in nodes:
gp.spawn(read_firmware, node, configmanager)
for rsp in gp:
for datum in rsp:
yield datum
elif "/".join(element).startswith("inventory/hardware/all"):
gp = greenpool.GreenPile(pdupool)
for node in nodes:
gp.spawn(read_inventory, element, node, configmanager)
for rsp in gp:
for datum in rsp:
yield datum
else:
for node in nodes:
yield msg.ConfluentResourceUnavailable(node, 'Not implemented')
yield msg.ConfluentResourceUnavailable(node, "Not implemented")
return
def update(nodes, element, configmanager, inputdata):
if 'outlets' not in element:
yield msg.ConfluentResourceUnavailable(node, 'Not implemented')
if "outlets" not in element:
yield msg.ConfluentResourceUnavailable(node, "Not implemented")
return
for node in nodes:
gc = GeistClient(node, configmanager)