2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-29 13:00:03 +00:00

Confluent server side enclosure reseat

This provides ability to request reseat of nodes, and redirects it to
the enclosure manager.
This commit is contained in:
Jarrod Johnson 2017-10-26 11:45:16 -04:00
parent c86d9f3e33
commit 52673a990b
4 changed files with 63 additions and 2 deletions

View File

@ -185,6 +185,11 @@ def _init_core():
'handler': 'ssh',
}),
},
'_enclosure': {
'reseat_bay': PluginRoute(
{'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi'}),
},
'shell': {
# another special case similar to console
'sessions': PluginCollection({
@ -250,6 +255,7 @@ def _init_core():
'pluginattrs': ['hardwaremanagement.method'],
'default': 'ipmi',
}),
'reseat': PluginRoute({'handler': 'enclosure'}),
},
'sensors': {
'hardware': {

View File

@ -364,6 +364,9 @@ class ChildCollection(LinkRelation):
def get_input_message(path, operation, inputdata, nodes=None, multinode=False):
if path[0] == 'power' and path[1] == 'state' and operation != 'retrieve':
return InputPowerMessage(path, nodes, inputdata)
elif (path in (['power', 'reseat'], ['_enclosure', 'reseat_bay']) and
operation != 'retrieve'):
return InputReseatMessage(path, nodes, inputdata)
elif path == ['attributes', 'expression']:
return InputExpression(path, inputdata, nodes)
elif path[0] in ('attributes', 'users') and operation != 'retrieve':
@ -624,7 +627,7 @@ class ConfluentInputMessage(ConfluentMessage):
if self.keyname not in datum:
raise exc.InvalidArgumentException(
'missing {0} argument'.format(self.keyname))
elif datum[self.keyname] not in self.valid_values:
elif not self.is_valid_key(datum[self.keyname]):
raise exc.InvalidArgumentException(
datum[self.keyname] + ' is not one of ' +
','.join(self.valid_values))
@ -634,13 +637,15 @@ class ConfluentInputMessage(ConfluentMessage):
if self.keyname not in datum:
raise exc.InvalidArgumentException(
'missing {0} argument'.format(self.keyname))
elif datum[self.keyname] not in self.valid_values:
elif not self.is_valid_key(datum[self.keyname]):
raise exc.InvalidArgumentException(datum[self.keyname] +
' is not one of ' +
','.join(self.valid_values))
for node in nodes:
self.inputbynode[node] = datum[self.keyname]
def is_valid_key(self, key):
return key in self.valid_values
class InputIdentifyMessage(ConfluentInputMessage):
valid_values = set([
@ -664,6 +669,16 @@ class InputPowerMessage(ConfluentInputMessage):
def powerstate(self, node):
return self.inputbynode[node]
class InputReseatMessage(ConfluentInputMessage):
valid_values = set([
'reseat',
])
keyname = 'reseat'
def is_valid_key(self, key):
return key in self.valid_values or isinstance(key, int)
class InputBMCReset(ConfluentInputMessage):
valid_values = set([
@ -875,6 +890,13 @@ class IdentifyState(ConfluentChoiceMessage):
keyname = 'identify'
class ReseatResult(ConfluentChoiceMessage):
valid_values = set([
'success',
])
keyname = 'reseat'
class PowerState(ConfluentChoiceMessage):
valid_values = set([
'on',

View File

@ -0,0 +1,26 @@
# Copyright 2017 Lenovo
#
# 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,
# 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.
import confluent.core as core
def update(nodes, element, configmanager, inputdata):
emebs = configmanager.get_node_attributes(
nodes, (u'enclosure.manager', u'enclosure.bay'))
for node in nodes:
em = emebs[node]['enclosure.manager']['value']
eb = emebs[node]['enclosure.bay']['value']
for rsp in core.handle_path(
'/nodes/{0}/_enclosure/reseat_bay'.format(em),
'update', configmanager,
inputdata={'reseat': int(eb)}):
yield rsp

View File

@ -432,6 +432,8 @@ class IpmiHandler(object):
raise Exception(self.error)
if self.element == ['power', 'state']:
self.power()
elif self.element == ['_enclosure', 'reseat_bay']:
self.reseat_bay()
elif self.element == ['boot', 'nextdevice']:
self.bootdevice()
elif self.element == ['health', 'hardware']:
@ -820,6 +822,11 @@ class IpmiHandler(object):
else:
raise exc.InvalidArgumentException('health is read-only')
def reseat_bay(self):
bay = self.inputdata.inputbynode[self.node]
self.ipmicmd.reseat_bay(bay)
self.output.put(msg.ReseatResult(self.node, 'success'))
def bootdevice(self):
if 'read' == self.op:
bootdev = self.ipmicmd.get_bootdev()