mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-22 01:22:00 +00:00
Add health/hardware resource to nodes and wire up for IPMI
This commit is contained in:
parent
6aaee681e7
commit
ca2a4ed775
4
TODO
4
TODO
@ -36,3 +36,7 @@ Traceback (most recent call last):
|
||||
passvalue = pluginmap[plugpath].__dict__[operation](
|
||||
KeyError: ''
|
||||
|
||||
|
||||
-reuse SDR to make health faster
|
||||
-have pyghmi and friends do multiprocessing pools (particularly the PBKDF stuff in auth)
|
||||
-bad password retrie
|
||||
|
@ -21,7 +21,27 @@ import confluent.exceptions as exc
|
||||
import json
|
||||
|
||||
|
||||
def _htmlify_structure(indict):
|
||||
ret = "<ul>"
|
||||
if isinstance(indict, dict):
|
||||
for key in indict.iterkeys():
|
||||
ret += "<li>{0}: ".format(key)
|
||||
if type(indict[key]) in (str, unicode):
|
||||
ret += indict[key]
|
||||
else:
|
||||
ret += _htmlify_structure(indict[key])
|
||||
elif isinstance(indict, list):
|
||||
if type(indict[0]) in (str, unicode):
|
||||
ret += ",".join(indict)
|
||||
else:
|
||||
for v in indict:
|
||||
ret += _htmlify_structure(v)
|
||||
return ret + '</ul>'
|
||||
|
||||
|
||||
|
||||
class ConfluentMessage(object):
|
||||
readonly = False
|
||||
defaultvalue = ''
|
||||
defaulttype = 'text'
|
||||
|
||||
@ -72,24 +92,31 @@ class ConfluentMessage(object):
|
||||
value = '********'
|
||||
if isinstance(val, list):
|
||||
snippet += key + ":"
|
||||
if len(val) == 0:
|
||||
if len(val) == 0 and not self.readonly:
|
||||
snippet += ('<input type="{0}" name="{1}" value="" '
|
||||
' "title="{2}">'
|
||||
).format(type, key, self.desc)
|
||||
for v in val:
|
||||
snippet += ('<input type="{0}" name="{1}" value="{2}" '
|
||||
' "title="{3}">'
|
||||
).format(type, key, v, self.desc)
|
||||
snippet += (
|
||||
'<input type="{0}" name="{1}" value="" title="{2}">'
|
||||
'<input type="checkbox" name="restexplorerhonorkey" '
|
||||
'value="{1}">').format(type, key, self.desc)
|
||||
if self.readonly:
|
||||
snippet += _htmlify_structure(v)
|
||||
else:
|
||||
snippet += ('<input type="{0}" name="{1}" value="{2}" '
|
||||
' "title="{3}">'
|
||||
).format(type, key, v, self.desc)
|
||||
if not self.readonly:
|
||||
snippet += (
|
||||
'<input type="{0}" name="{1}" value="" title="{2}">'
|
||||
'<input type="checkbox" name="restexplorerhonorkey" '
|
||||
'value="{1}">').format(type, key, self.desc)
|
||||
return snippet
|
||||
snippet += (key + ":" +
|
||||
'<input type="{0}" name="{1}" value="{2}" '
|
||||
'title="{3}"><input type="checkbox" '
|
||||
'name="restexplorerhonorkey" value="{1}">'
|
||||
).format(type, key, value, self.desc)
|
||||
if self.readonly:
|
||||
snippet += "{0}: {1}".format(key, value)
|
||||
else:
|
||||
snippet += (key + ":" +
|
||||
'<input type="{0}" name="{1}" value="{2}" '
|
||||
'title="{3}"><input type="checkbox" '
|
||||
'name="restexplorerhonorkey" value="{1}">'
|
||||
).format(type, key, value, self.desc)
|
||||
if len(notes) > 0:
|
||||
snippet += '(' + ','.join(notes) + ')'
|
||||
return snippet
|
||||
@ -325,6 +352,45 @@ class PowerState(ConfluentChoiceMessage):
|
||||
}
|
||||
|
||||
|
||||
class SensorReadings(ConfluentMessage):
|
||||
readonly = True
|
||||
|
||||
def __init__(self, sensors=[], name=None):
|
||||
readings = []
|
||||
for sensor in sensors:
|
||||
sensordict = {'name': sensor['name']}
|
||||
if 'value' in sensor:
|
||||
sensordict['value'] = sensor['value']
|
||||
if 'units' in sensor:
|
||||
sensordict['units'] = sensor['units']
|
||||
if 'states' in sensor:
|
||||
sensordict['states'] = sensor['states']
|
||||
if 'health' in sensor:
|
||||
sensordict['health'] = sensor['health']
|
||||
readings.append(sensordict)
|
||||
if name is None:
|
||||
self.kvpairs = {'sensors': readings}
|
||||
else:
|
||||
self.kvpairs = {name: {'sensors': readings}}
|
||||
|
||||
|
||||
class HealthSummary(ConfluentMessage):
|
||||
readonly = True
|
||||
valid_values = set([
|
||||
'ok',
|
||||
'warning',
|
||||
'critical',
|
||||
'failed',
|
||||
])
|
||||
|
||||
def __init__(self, health, name=None):
|
||||
if health not in self.valid_values:
|
||||
raise ValueError("%d is not a valid health state" % health)
|
||||
if name is None:
|
||||
self.kvpairs = {'health': {'value': health}}
|
||||
else:
|
||||
self.kvpairs = {name: {'health': {'value': health}}}
|
||||
|
||||
class Attributes(ConfluentMessage):
|
||||
def __init__(self, name=None, kv=None, desc=''):
|
||||
self.desc = desc
|
||||
|
@ -98,6 +98,12 @@ noderesources = {
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
},
|
||||
'health': {
|
||||
'hardware': PluginRoute({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
},
|
||||
'boot': {
|
||||
'nextdevice': PluginRoute({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
|
@ -12,7 +12,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import collections
|
||||
import confluent.exceptions as exc
|
||||
import confluent.interface.console as conapi
|
||||
import confluent.messages as msg
|
||||
@ -21,7 +20,7 @@ import eventlet.event
|
||||
import eventlet.green.threading as threading
|
||||
import eventlet.greenpool as greenpool
|
||||
import eventlet.queue
|
||||
import os
|
||||
import pyghmi.constants as pygconstants
|
||||
import pyghmi.exceptions as pygexc
|
||||
import pyghmi.ipmi.console as console
|
||||
import pyghmi.ipmi.command as ipmicommand
|
||||
@ -156,6 +155,7 @@ class IpmiConsole(conapi.Console):
|
||||
|
||||
class IpmiIterator(object):
|
||||
def __init__(self, operator, nodes, element, cfg, inputdata):
|
||||
self.currdata = None
|
||||
crypt = cfg.decrypt
|
||||
cfg.decrypt = True
|
||||
configdata = cfg.get_node_attributes(nodes, _configattributes)
|
||||
@ -168,10 +168,15 @@ class IpmiIterator(object):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
ndata = self.gpile.next()
|
||||
if self.currdata is None:
|
||||
self.currdata = self.gpile.next()
|
||||
# need to apply any translations between pyghmi and confluent
|
||||
return ndata
|
||||
|
||||
try:
|
||||
retdata = self.currdata.next()
|
||||
except AttributeError:
|
||||
retdata = self.currdata
|
||||
self.currdata = None
|
||||
return retdata
|
||||
|
||||
def perform_request(operator, node, element, configdata, inputdata):
|
||||
return IpmiHandler(operator, node, element, configdata, inputdata).handle_request()
|
||||
@ -220,6 +225,41 @@ class IpmiHandler(object):
|
||||
return self.power()
|
||||
elif self.element == [ 'boot', 'nextdevice' ]:
|
||||
return self.bootdevice()
|
||||
elif self.element == [ 'health', 'hardware' ]:
|
||||
return self.health()
|
||||
|
||||
def _str_health(self, health):
|
||||
if pygconstants.Health.Failed & health:
|
||||
health = 'failed'
|
||||
elif pygconstants.Health.Critical & health:
|
||||
health = 'critical'
|
||||
elif pygconstants.Health.Warning & health:
|
||||
health = 'warning'
|
||||
else:
|
||||
health = 'ok'
|
||||
return health
|
||||
|
||||
def _dict_sensor(self, pygreading):
|
||||
retdict = {}
|
||||
retdict['name'] = pygreading.name
|
||||
retdict['value'] = pygreading.value
|
||||
retdict['states'] = pygreading.states
|
||||
retdict['health'] = self._str_health(pygreading.health)
|
||||
return retdict
|
||||
|
||||
def health(self):
|
||||
if 'read' == self.op:
|
||||
response = self.ipmicmd.get_health()
|
||||
health = response['health']
|
||||
health = self._str_health(health)
|
||||
yield msg.HealthSummary(health, self.node)
|
||||
if 'badreadings' in response:
|
||||
badsensors = []
|
||||
for reading in response['badreadings']:
|
||||
badsensors.append(self._dict_sensor(reading))
|
||||
yield msg.SensorReadings(badsensors, name=self.node)
|
||||
else:
|
||||
raise exc.InvalidArgumentException('health is read-only')
|
||||
|
||||
def bootdevice(self):
|
||||
if 'read' == self.op:
|
||||
@ -275,4 +315,3 @@ def update(nodes, element, configmanager, inputdata):
|
||||
def retrieve(nodes, element, configmanager, inputdata):
|
||||
initthread()
|
||||
return IpmiIterator('read', nodes, element, configmanager, inputdata)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user