2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-25 19:10:10 +00:00

Merge branch 'master' of github.com:jjohnson42/confluent

This commit is contained in:
Jarrod Johnson 2017-10-26 13:31:36 -04:00
commit 45b8a18f14
5 changed files with 125 additions and 2 deletions

View File

@ -0,0 +1,62 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2015-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 optparse
import os
import signal
import sys
try:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except AttributeError:
pass
path = os.path.dirname(os.path.realpath(__file__))
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
if path.startswith('/opt'):
sys.path.append(path)
import confluent.client as client
argparser = optparse.OptionParser(usage="Usage: %prog <noderange>")
(options, args) = argparser.parse_args()
try:
noderange = args[0]
except IndexError:
argparser.print_help()
sys.exit(1)
session = client.Command()
exitcode = 0
errorNodes = set([])
success = session.simple_noderange_command(noderange, 'power/reseat', 'reseat', key='reseat', errnodes=errorNodes) # = 0 if successful
# Determine which nodes were successful and print them
allNodes = set([])
for node in session.read('/noderange/{0}/nodes/'.format(noderange)):
allNodes.add(node['item']['href'].replace("/", ""))
goodNodes = allNodes - errorNodes
for node in goodNodes:
print node + ": Reseat successful"
sys.exit(success)

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()