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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user