2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-02-26 07:11:35 +00:00

Merge pull request #96 from weragrzeda/master

i reverted NTP and Eaton, Only Geist PDUs merging
This commit is contained in:
Jarrod Johnson 2024-08-16 09:33:01 -04:00 committed by GitHub
commit e6f6919ef4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,13 +1,13 @@
# Copyright 2022 Lenovo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
@ -20,12 +20,15 @@ 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:
@ -34,7 +37,9 @@ def data_by_type(indata):
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
return databytype
@ -58,31 +63,30 @@ 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]
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')
if not isinstance(passwd, str):
@ -92,26 +96,32 @@ class GeistClient(object):
self.username = username
rsp = self.wc.grab_json_response(
'/api/auth/{0}'.format(username),
{'cmd': 'login', 'data': {'password': passwd}})
{'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']
dbt = data_by_type(rsp)
if 't3hd' in dbt:
del dbt['t3hd']
if len(dbt) != 1:
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]
return state
@ -125,12 +135,20 @@ class GeistClient(object):
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}})
{
'cmd': 'control',
'token': self.token,
'data': {'action': state, 'delay': False},
},
)
def process_measurement(keyname, name, enttype, entname, measurement, readings, category):
def process_measurement(
keyname, name, enttype, entname, measurement, readings, category
):
if measurement['type'] == 'realPower':
if category not in ('all', 'power'):
return
@ -147,6 +165,10 @@ def process_measurement(keyname, name, enttype, entname, measurement, readings,
if category not in ('all',):
return
readtype = 'Voltage'
elif measurement['type'] == 'current':
if category not in ('all',):
return
readtype = 'Current'
elif measurement['type'] == 'temperature':
readtype = 'Temperature'
elif measurement['type'] == 'dewpoint':
@ -158,23 +180,35 @@ def process_measurement(keyname, name, enttype, entname, measurement, readings,
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']
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
@ -192,10 +226,12 @@ def read_sensors(element, node, configmanager):
_sensors_by_node[node] = (adev, time.time() + 1)
sn = _sensors_by_node.get(node, None)
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)
if justnames:
@ -204,25 +240,78 @@ def read_sensors(element, node, configmanager):
else:
yield msg.SensorReadings(readings, name=node)
def get_outlet(node, configmanager, element):
def get_outlet(element, node, configmanager):
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)
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] != 'appVersion'
and elem[0] != 'build'
and elem[0] != 'version'
and elem[0] != 'apiVersion'
):
temp = elem[0]
if elem[0] == 'serialNumber':
temp = 'Serial'
elif elem[0] == 'partNumber':
temp = 'P/N'
elif elem[0] == 'modelNumber':
temp = 'Lenovo P/N and Serial'
_inventory[temp] = 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():
temp = entry[0]
if temp == 'sn':
temp = 'Serial'
_inventory[tempname + ' ' + temp] = entry[1]
inventory['information'] = _inventory
yield msg.KeyValueData({'inventory': [inventory]}, node)
def retrieve(nodes, element, configmanager, inputdata):
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':
gp = greenpool.GreenPile(pdupool)
@ -239,11 +328,20 @@ def retrieve(nodes, element, configmanager, inputdata):
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')