mirror of
https://github.com/xcat2/confluent.git
synced 2025-01-17 21:23:18 +00:00
Add identify support
In the course of adding identify support, also took the opportunity to address a few mistakes and refactor some code for future ease of development.
This commit is contained in:
parent
059b448932
commit
a645e256eb
@ -110,6 +110,10 @@ noderesources = {
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
},
|
||||
'identify': PluginRoute({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
'default': 'ipmi',
|
||||
}),
|
||||
'boot': {
|
||||
'nextdevice': PluginRoute({
|
||||
'pluginattrs': ['hardwaremanagement.method'],
|
||||
@ -166,6 +170,8 @@ def show_user(name, configmanager):
|
||||
|
||||
def stripnode(iterablersp, node):
|
||||
for i in iterablersp:
|
||||
if i is None:
|
||||
raise exc.NotImplementedException("Not Implemented")
|
||||
i.strip_node(node)
|
||||
yield i
|
||||
|
||||
|
@ -36,6 +36,7 @@ class TargetEndpointUnreachable(ConfluentException):
|
||||
# was unreachable. http code 504
|
||||
pass
|
||||
|
||||
|
||||
class TargetEndpointBadCredentials(ConfluentException):
|
||||
# target was reachable, but authentication/authorization
|
||||
# failed
|
||||
@ -45,3 +46,9 @@ class TargetEndpointBadCredentials(ConfluentException):
|
||||
class ForbiddenRequest(ConfluentException):
|
||||
# The client request is not allowed by authorization engine
|
||||
pass
|
||||
|
||||
|
||||
class NotImplementedException(ConfluentException):
|
||||
# The current configuration/plugin is unable to perform
|
||||
# the requested task. http code 501
|
||||
pass
|
@ -390,8 +390,9 @@ def resourcehandler_backend(env, start_response):
|
||||
except exc.TargetEndpointBadCredentials:
|
||||
start_response('502 Bad Credentials', headers)
|
||||
yield '502 - Bad Credentials'
|
||||
|
||||
|
||||
except exc.NotImplementedException:
|
||||
start_response('501 Not Implemented', headers)
|
||||
yield '501 Not Implemented'
|
||||
|
||||
def _assemble_html(responses, resource, querydict, url, extension):
|
||||
yield '<html><head><title>' \
|
||||
|
@ -171,6 +171,13 @@ class ConfluentChoiceMessage(ConfluentMessage):
|
||||
valid_values = set()
|
||||
valid_paramset = {}
|
||||
|
||||
def __init__(self, node, state):
|
||||
self.kvpairs = {
|
||||
node: {
|
||||
self.keyname: {'value': state},
|
||||
}
|
||||
}
|
||||
|
||||
def html(self, extension=''):
|
||||
snippet = ""
|
||||
for key in self.kvpairs.iterkeys():
|
||||
@ -247,6 +254,8 @@ def get_input_message(path, operation, inputdata, nodes=None):
|
||||
return InputAttributes(path, inputdata, nodes)
|
||||
elif path == ['boot', 'nextdevice'] and operation != 'retrieve':
|
||||
return InputBootDevice(path, nodes, inputdata)
|
||||
elif path == [ 'identify' ] and operation != 'retrieve':
|
||||
return InputIdentifyMessage(path, nodes, inputdata)
|
||||
elif inputdata:
|
||||
raise exc.InvalidArgumentException()
|
||||
|
||||
@ -308,7 +317,49 @@ class InputAttributes(ConfluentMessage):
|
||||
return nodeattr
|
||||
|
||||
|
||||
class InputPowerMessage(ConfluentMessage):
|
||||
class ConfluentInputMessage(ConfluentMessage):
|
||||
keyname = 'state'
|
||||
|
||||
def __init__(self, path, nodes, inputdata):
|
||||
self.inputbynode = {}
|
||||
if not inputdata:
|
||||
raise exc.InvalidArgumentException('missing input data')
|
||||
if self.keyname not in inputdata:
|
||||
#assume we have nested information
|
||||
for key in nodes:
|
||||
if key not in inputdata:
|
||||
raise exc.InvalidArgumentException(key + ' not in request')
|
||||
datum = inputdata[key]
|
||||
if self.keyname not in datum:
|
||||
raise exc.InvalidArgumentException(
|
||||
'missing {0} argument'.format(self.keyname))
|
||||
elif datum[self.keyname] not in self.valid_values:
|
||||
raise exc.InvalidArgumentException(
|
||||
datum[self.keyname] + ' is not one of ' +
|
||||
','.join(self.valid_values))
|
||||
self.inputbynode[key] = datum[self.keyname]
|
||||
else: # we have a state argument not by node
|
||||
datum = inputdata
|
||||
if self.keyname not in datum:
|
||||
raise exc.InvalidArgumentException('missing {0} argument'.format(self.keyname))
|
||||
elif datum[self.keyname] not in self.valid_values:
|
||||
raise exc.InvalidArgumentException(datum[self.keyname] +
|
||||
' is not one of ' +
|
||||
','.join(self.valid_values))
|
||||
for node in nodes:
|
||||
self.inputbynode[node] = datum[self.keyname]
|
||||
|
||||
|
||||
class InputIdentifyMessage(ConfluentInputMessage):
|
||||
valid_values = set([
|
||||
'on',
|
||||
'off',
|
||||
])
|
||||
|
||||
keyname = 'identify'
|
||||
|
||||
|
||||
class InputPowerMessage(ConfluentInputMessage):
|
||||
valid_values = set([
|
||||
'on',
|
||||
'off',
|
||||
@ -316,37 +367,8 @@ class InputPowerMessage(ConfluentMessage):
|
||||
'boot',
|
||||
])
|
||||
|
||||
def __init__(self, path, nodes, inputdata):
|
||||
self.powerbynode = {}
|
||||
if not inputdata:
|
||||
raise exc.InvalidArgumentException('missing input data')
|
||||
if 'state' not in inputdata:
|
||||
#assume we have nested information
|
||||
for key in nodes:
|
||||
if key not in inputdata:
|
||||
raise exc.InvalidArgumentException(key + ' not in request')
|
||||
datum = inputdata[key]
|
||||
if 'state' not in datum:
|
||||
raise exc.InvalidArgumentException(
|
||||
'missing state argument')
|
||||
elif datum['state'] not in self.valid_values:
|
||||
raise exc.InvalidArgumentException(
|
||||
datum['state'] + ' is not one of ' +
|
||||
','.join(self.valid_values))
|
||||
self.powerbynode[key] = datum['state']
|
||||
else: # we have a state argument not by node
|
||||
datum = inputdata
|
||||
if 'state' not in datum:
|
||||
raise exc.InvalidArgumentException('missing state argument')
|
||||
elif datum['state'] not in self.valid_values:
|
||||
raise exc.InvalidArgumentException(datum['state'] +
|
||||
' is not one of ' +
|
||||
','.join(self.valid_values))
|
||||
for node in nodes:
|
||||
self.powerbynode[node] = datum['state']
|
||||
|
||||
def powerstate(self, node):
|
||||
return self.powerbynode[node]
|
||||
return self.inputbynode[node]
|
||||
|
||||
|
||||
class BootDevice(ConfluentChoiceMessage):
|
||||
@ -428,6 +450,14 @@ class InputBootDevice(BootDevice):
|
||||
return self.bootmodebynode.get(node, 'unspecified')
|
||||
|
||||
|
||||
class IdentifyState(ConfluentChoiceMessage):
|
||||
valid_values = set([
|
||||
'on',
|
||||
'off',
|
||||
])
|
||||
keyname = 'identify'
|
||||
|
||||
|
||||
class PowerState(ConfluentChoiceMessage):
|
||||
valid_values = set([
|
||||
'on',
|
||||
@ -435,13 +465,9 @@ class PowerState(ConfluentChoiceMessage):
|
||||
'reset',
|
||||
'boot',
|
||||
])
|
||||
keyname = 'state'
|
||||
|
||||
|
||||
def __init__(self, node, state):
|
||||
self.kvpairs = {
|
||||
node: {
|
||||
'state': {'value': state},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SensorReadings(ConfluentMessage):
|
||||
|
@ -213,6 +213,8 @@ def perform_request(operator, node, element, configdata, inputdata, cfg):
|
||||
excmsg = str(ipmiexc)
|
||||
if excmsg == 'Session no longer connected':
|
||||
return msg.ConfluentTargetTimeout(node)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
persistent_ipmicmds = {}
|
||||
@ -275,6 +277,8 @@ class IpmiHandler(object):
|
||||
return self.bootdevice()
|
||||
elif self.element == ['health', 'hardware']:
|
||||
return self.health()
|
||||
elif self.element == ['identify']:
|
||||
return self.identify()
|
||||
|
||||
@staticmethod
|
||||
def _str_health(health):
|
||||
@ -331,6 +335,12 @@ class IpmiHandler(object):
|
||||
return msg.BootDevice(node=self.node,
|
||||
device=bootdev['bootdev'])
|
||||
|
||||
def identify(self):
|
||||
if 'update' == self.op:
|
||||
identifystate = self.inputdata.inputbynode[self.node] == 'on'
|
||||
self.ipmicmd.set_identify(on=identifystate)
|
||||
return msg.IdentifyState(
|
||||
node=self.node, state=self.inputdata.inputbynode[self.node])
|
||||
def power(self):
|
||||
if 'read' == self.op:
|
||||
power = self.ipmicmd.get_power()
|
||||
|
@ -112,6 +112,10 @@ def sessionhdl(connection, authname, skipauth=False):
|
||||
tlvdata.send(connection, {'errorcode': 504,
|
||||
'error': 'Unreachable Target'})
|
||||
tlvdata.send(connection, {'_requestdone': 1})
|
||||
except exc.NotImplementedException:
|
||||
tlvdata.send(connection, {'errorcode': 501,
|
||||
'error': 'Not Implemented'})
|
||||
tlvdata.send(connection, {'_requestdone': 1})
|
||||
except SystemExit:
|
||||
sys.exit(0)
|
||||
except:
|
||||
|
Loading…
x
Reference in New Issue
Block a user