mirror of
https://github.com/xcat2/confluent.git
synced 2026-09-21 16:39:32 +00:00
Finish the server side SOL and cleanup paths
The console awaits its output handler, but both sample BMCs supplied a plain function, and both dropped the send_data coroutine. virshbmc additionally receives its stream callback on a libvirt thread, so the send goes through run_coroutine_threadsafe against the loop captured at activation, called asyncloop because the class already has a loop method it uses as a thread target. ServerConsole asked the session layer to retry, which a ServerSession cannot do: it never runs Session.__init__, so it has no timeout, and its _timedout does nothing. IpmiServer.logout was synchronous and an argument short while _cleanup awaits logout(False). The boot options handler answered, then read an unbound name and answered again with 0xff.
This commit is contained in:
@@ -73,10 +73,10 @@ class FakeBmc(bmc.Bmc):
|
||||
def is_active(self):
|
||||
return self.powerstate == 'on'
|
||||
|
||||
def iohandler(self, data):
|
||||
async def iohandler(self, data):
|
||||
print(data)
|
||||
if self.sol:
|
||||
self.sol.send_data(data)
|
||||
await self.sol.send_data(data)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -39,8 +39,11 @@ def stream_callback(stream, events, console):
|
||||
data = console.stream.recv(1024)
|
||||
except Exception:
|
||||
return
|
||||
if console.sol:
|
||||
console.sol.send_data(data)
|
||||
if console.sol and console.asyncloop:
|
||||
# libvirt calls this from its own event thread, and asyncio objects
|
||||
# are not thread safe, so hand the send to the loop that owns them.
|
||||
asyncio.run_coroutine_threadsafe(console.sol.send_data(data),
|
||||
console.asyncloop)
|
||||
|
||||
|
||||
class LibvirtBmc(bmc.Bmc):
|
||||
@@ -54,6 +57,7 @@ class LibvirtBmc(bmc.Bmc):
|
||||
self.domain = self.conn.lookupByName(domain)
|
||||
self.state = self.domain.state(0)
|
||||
self.stream = None
|
||||
self.asyncloop = None
|
||||
self.run_console = False
|
||||
self.conn.domainEventRegister(lifecycle_callback, self)
|
||||
self.sol_thread = None
|
||||
@@ -108,6 +112,8 @@ class LibvirtBmc(bmc.Bmc):
|
||||
return self.run_console
|
||||
|
||||
async def activate_payload(self, request, session):
|
||||
# captured for stream_callback, which runs on a libvirt thread
|
||||
self.asyncloop = asyncio.get_running_loop()
|
||||
await super(LibvirtBmc, self).activate_payload(request, session)
|
||||
self.run_console = True
|
||||
self.sol_thread = threading.Thread(target=self.loop)
|
||||
@@ -118,7 +124,7 @@ class LibvirtBmc(bmc.Bmc):
|
||||
self.sol_thread.join()
|
||||
await super(LibvirtBmc, self).deactivate_payload(request, session)
|
||||
|
||||
def iohandler(self, data):
|
||||
async def iohandler(self, data):
|
||||
if self.stream:
|
||||
self.stream.send(data)
|
||||
|
||||
|
||||
@@ -132,7 +132,9 @@ class Bmc(serversession.IpmiServer):
|
||||
try:
|
||||
bootdevice = self.get_boot_device()
|
||||
except NotImplementedError:
|
||||
await session.send_ipmi_response(data=[1, 5, 0, 0, 0, 0, 0])
|
||||
# nothing more to say, and bootdevice below would be unbound
|
||||
return await session.send_ipmi_response(
|
||||
data=[1, 5, 0, 0, 0, 0, 0])
|
||||
if (type(bootdevice) != int
|
||||
and bootdevice in ipmicommand.boot_devices):
|
||||
bootdevice = ipmicommand.boot_devices[bootdevice]
|
||||
|
||||
@@ -541,9 +541,12 @@ class ServerConsole(Console):
|
||||
needskeepalive=False):
|
||||
while not (self.connected or self.broken):
|
||||
await session.Session.wait_for_rsp(timeout=10)
|
||||
# retry is not passed on: a ServerSession has no retry timer, it
|
||||
# never runs Session.__init__ and its _timedout does nothing, so
|
||||
# asking for one only reaches for a timeout attribute it lacks.
|
||||
await self.ipmi_session.send_payload(payload,
|
||||
payload_type=payload_type,
|
||||
retry=retry,
|
||||
retry=False,
|
||||
needskeepalive=needskeepalive)
|
||||
|
||||
def close(self):
|
||||
|
||||
@@ -412,5 +412,5 @@ class IpmiServer(object):
|
||||
# per table 5-2, completion code 0xc1 is 'unrecognized'
|
||||
await session.send_ipmi_response(code=0xc1)
|
||||
|
||||
def logout(self):
|
||||
async def logout(self, sessionok=True):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user