mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-22 09:32:21 +00:00
Refactor plugin code to better assure all things happen in one greenthread
Additionally, begin work to make ipmi.py start doing non-console things
This commit is contained in:
parent
1c2341e1eb
commit
5e80407bc5
127
plugins/ipmi.py
127
plugins/ipmi.py
@ -3,6 +3,7 @@ import eventlet
|
||||
import eventlet.event
|
||||
import os
|
||||
import pyghmi.ipmi.console as console
|
||||
import pyghmi.ipmi.command as ipmicommand
|
||||
console.session.select = eventlet.green.select
|
||||
|
||||
_ipmithread = None
|
||||
@ -12,6 +13,13 @@ chainpulled = False
|
||||
tmptimeout = None
|
||||
ipmiq = collections.deque([])
|
||||
ipmiwaiters = collections.deque([])
|
||||
ipmisessions = {}
|
||||
|
||||
|
||||
def wait_on_ipmi():
|
||||
waitevt = eventlet.event.Event()
|
||||
ipmiwaiters.append(waitevt)
|
||||
waitevt.wait()
|
||||
|
||||
|
||||
def _ipmi_evtloop():
|
||||
@ -30,13 +38,22 @@ def _ipmi_evtloop():
|
||||
waiter.send()
|
||||
|
||||
def _process_chgs(intline):
|
||||
#here we receive functions to run in our thread
|
||||
#the tuples on the deque consist of:
|
||||
#function, arg tuple, and optionally a callback
|
||||
#to send the return value back to the requester
|
||||
global chainpulled
|
||||
os.read(intline,1) # answer the bell
|
||||
chainpulled = False
|
||||
while ipmiq:
|
||||
cval = ipmiq.popleft()
|
||||
if hasattr(cval[0], '__call__'):
|
||||
cval[0](*cval[1])
|
||||
if isinstance(cval[1], tuple):
|
||||
rv = cval[0](*cval[1])
|
||||
elif isinstance(cval[1], dict):
|
||||
rv = cval[0](**cval[1])
|
||||
if len(cval) > 2:
|
||||
cval[2](rv)
|
||||
|
||||
|
||||
|
||||
@ -91,16 +108,35 @@ class Console(object):
|
||||
def connect(self,callback):
|
||||
global _ipmithread
|
||||
global pullchain
|
||||
self.solconnection = console.Console(bmc=self.bmc,
|
||||
port=self.port,
|
||||
userid=self.username,
|
||||
password=self.password,
|
||||
kg=self.kg,
|
||||
force=True,
|
||||
iohandler=callback)
|
||||
global ipmisessions
|
||||
global chainpulled
|
||||
try:
|
||||
ipmisession = ipmisessions[(self.bmc, self.port)]
|
||||
except KeyError:
|
||||
ipmisession = None
|
||||
if _ipmithread is None:
|
||||
pullchain = os.pipe()
|
||||
_ipmithread = eventlet.spawn(_ipmi_evtloop)
|
||||
self.solconnection = None
|
||||
ipmiq.append((console.Console,{'bmc': self.bmc,
|
||||
'port': self.port,
|
||||
'userid': self.username,
|
||||
'password': self.password,
|
||||
'kg': self.kg,
|
||||
'force': True,
|
||||
'ipmisession': ipmisession,
|
||||
'iohandler': callback}, self.got_consobject))
|
||||
if not chainpulled:
|
||||
chainpulled = True
|
||||
os.write(pullchain[1],'1')
|
||||
while self.solconnection is None:
|
||||
wait_on_ipmi()
|
||||
if ipmisession is None:
|
||||
ipmisessions[(self.bmc, self.port)] = \
|
||||
self.solconnection.ipmi_session
|
||||
|
||||
def got_consobject(self, solconnection):
|
||||
self.solconnection = solconnection
|
||||
|
||||
def write(self, data):
|
||||
global chainpulled
|
||||
@ -130,15 +166,81 @@ class Console(object):
|
||||
chainpulled=True
|
||||
os.write(pullchain[1],'1')
|
||||
eventlet.sleep(0.001)
|
||||
waitevt = eventlet.event.Event()
|
||||
ipmiwaiters.append(waitevt)
|
||||
waitevt.wait()
|
||||
wait_on_ipmi()
|
||||
#TODO: a channel for the ipmithread to tug back instead of busy wait
|
||||
#while tmptimeout is not None:
|
||||
# eventlet.sleep(0)
|
||||
#console.session.Session.wait_for_rsp(timeout=timeout)
|
||||
|
||||
|
||||
class IpmiIterator(object):
|
||||
def __init__(self, operator, nodes, element, cfg):
|
||||
configdata = cfg.get_node_attributes(nodes,
|
||||
['secret.ipmiuser', 'secret.ipmipassphrase',
|
||||
'secret.managementuser', 'secret.managementpassphrase',
|
||||
'hardwaremanagement.manager'])
|
||||
for node in nodes:
|
||||
IpmiHandler(operator, node, element, configdata)
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class IpmiHandler(object):
|
||||
def __iter__():
|
||||
return self
|
||||
|
||||
def __init__(self, operation, node, element, cfd):
|
||||
self.cfg = cfd[node]
|
||||
self.node = node
|
||||
self.element = element
|
||||
self.op = operation
|
||||
connparams = get_conn_params(node, self.cfg)
|
||||
self.ipmicmd = None
|
||||
try:
|
||||
ipmisession = ipmisessions[(self.bmc, self.port)]
|
||||
except KeyError:
|
||||
ipmisession = None
|
||||
ipmiq.append((ipmicommand.Command,{'bmc': connparams['bmc'],
|
||||
'userid': connparams['username'],
|
||||
'password': connparams['passphrase'],
|
||||
'kg': connparams['kg'],
|
||||
'port': connparams['port'],
|
||||
'onlogon': self.handle_request,
|
||||
'ipmisession': ipmisession},
|
||||
got_ipmicmd))
|
||||
while self.ipmicmd == None:
|
||||
wait_on_ipmi()
|
||||
if ipmisession is None:
|
||||
ipmisessions[(self.bmc, self.port)] = self.ipmicmd.ipmi_session
|
||||
|
||||
def got_ipmicmd(self, ipmicmd):
|
||||
self.ipmicmd = ipmicmd
|
||||
|
||||
def call_ipmicmd(self, function, *args):
|
||||
self.lastrsp = None
|
||||
ipmiq.append((function, args, self.got_rsp))
|
||||
while self.lastrsp is None:
|
||||
wait_on_ipmi()
|
||||
return self.lastrsp
|
||||
|
||||
def got_rsp(self, response):
|
||||
self.lastrsp = response
|
||||
|
||||
def handle_request(self, response):
|
||||
if 'error' in response:
|
||||
raise Exception(response['error'])
|
||||
if self.element == 'power/state':
|
||||
if 'read' == self.op:
|
||||
rsp = self.call_ipmi(self.ipmicmd.get_power)
|
||||
print(rsp)
|
||||
|
||||
def create(nodes, element, configmanager):
|
||||
if element == '_console/session':
|
||||
if len(nodes) > 1:
|
||||
@ -149,5 +251,6 @@ def create(nodes, element, configmanager):
|
||||
"TODO(jbjohnso): ipmi api implementation of %s" % element)
|
||||
|
||||
|
||||
|
||||
def retrieve(nodes, element, configmanager):
|
||||
raise Exception("TODO(jbjohnso): ipmi get implementation of %s" % element)
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user