Open niecore opened 4 years ago
My current pattern for soft-resets is this:
with contexlib.ExitStack() as cx:
b = cx.enter_context(tbot.acquire_board(lh))
lnx = cx.enter_context(tbot.acquire_linux(b))
...
ch = lnx.open_channel("systemctl", "reboot")
# Stuff the channel back into the board-machine ...
b.ch = ch
# Reinitialize the linux-machine which will wait for the reboot to
# reach the login-prompt again.
lnx = cx.enter_context(tbot.acquire_linux(b))
...
I know, this isn't the pretties way to do it and I was also thinking that maybe it would be useful to have a way for doing soft-resets with a single method call. But I'm not really sure how to model this without making a lot of assumptions about the user, so we'll have to see ...
For now, this explicit re-initialization is the pattern I would suggest you use.
I wasn't able to get the example to work. It would hang once Linux would shutdown, but wouldn't power cycle. This does seem to work for me
re_poweroff = re.compile(b'reboot: Power down\s{0,10}')
shutdown_cmd = ("sudo", "systemctl", "poweroff")
with tbot.ctx.request(tbot.role.BoardLinux) as serial:
with serial.run(*shutdown_cmd) as shutdown:
shutdown.read_until_prompt(prompt=re_poweroff, timeout=60)
shutdown._pre_terminate()
shutdown._proxy_alive = False
I would prefer not to use private attributes, but I couldn't get it to work cleanly otherwise. I tried running serial.ch.read_until_prompt()
, but it just hung like before.
Any advice on achieving something similar without accessing private attributes?
I am not 100% sure what you are trying to do... You want to first power-off the system and then have tbot power-cycle it, is that correct? In that case, try something like this:
with tbot.ctx.request(tbot.role.BoardLinux, exclusive=True) as lnx:
# Do something before reboot
lnx.exec0("uname", "-a")
# Power-down the system
ch = lnx.open_channel("systemctl", "poweroff")
ev = tbot.log.EventIO(["powerdown"], "System powering down...")
with ch.with_stream(ev):
ev.prefix = " <> "
ch.expect(["reboot: Power down", "reboot: System halted"])
with tbot.ctx.request(tbot.role.BoardLinux, reset=True) as lnx:
# Do something after reboot
lnx.exec0("uname", "-a")
FWIW, this issue was originally about performing a soft-reset without power-cycling the system. For that, things work a bit differently...
Thanks! Using Channel.expect()
is much cleaner.
For my use case, either a reboot or a shutdown will work. I just need the OS to shutdown cleanly and not just power cycle. The issue I had with the reboot is it just hung. Perhaps it also needs Channel.expect()
?
Turns out I do need to reboot. I tried to implement what you have in https://github.com/Rahix/tbot/issues/26#issuecomment-663580867. It works if I'm just running additional commands on the serial console within that same context block, but, if I call other code after this that requests the LinuxBoard
role and uses the channel, I'll get a ChannelTakenException
. I'm guessing the global context is sharing the original machine object and not the second one?
I would also need to do a reboot without a power cylcle in between. How can this be done cleanly?
It would be great to trigger a soft reset with
reboot
for some testcases. Unfortunatelyexec0 reboot
will not terminate because the prompt will not be shown again. Thesoftreset
function could handle the relogin as well.