xref: /openbmc/openbmc-tools/reboot-ping-pong/rpp (revision cf3c1e6773c0ea0346874da66a609d22cbf11ec3)
1*cf3c1e67SAndrew Jeffery#!/usr/bin/python3
2*cf3c1e67SAndrew Jeffery
3*cf3c1e67SAndrew Jefferyimport argparse
4*cf3c1e67SAndrew Jefferyimport pexpect
5*cf3c1e67SAndrew Jefferyimport sys
6*cf3c1e67SAndrew Jefferyimport time
7*cf3c1e67SAndrew Jeffery
8*cf3c1e67SAndrew Jefferyfrom collections import namedtuple
9*cf3c1e67SAndrew Jeffery
10*cf3c1e67SAndrew JefferyEndpoint = namedtuple("Endpoint", "host, port")
11*cf3c1e67SAndrew JefferyCredentials = namedtuple("Credentials", "username, password")
12*cf3c1e67SAndrew JefferyTarget = namedtuple("Target", "credentials, endpoint")
13*cf3c1e67SAndrew JefferyEntity = namedtuple("Entity", "console, ssh")
14*cf3c1e67SAndrew JefferyMachine = namedtuple("Machine", "bmc, host")
15*cf3c1e67SAndrew Jeffery
16*cf3c1e67SAndrew Jefferyclass Obmcutil(object):
17*cf3c1e67SAndrew Jeffery    BMC_READY =     "xyz.openbmc_project.State.BMC.BMCState.Ready"
18*cf3c1e67SAndrew Jeffery    BMC_NOT_READY = "xyz.openbmc_project.State.BMC.BMCState.NotReady"
19*cf3c1e67SAndrew Jeffery
20*cf3c1e67SAndrew Jeffery    HOST_OFF = "xyz.openbmc_project.State.Host.HostState.Off"
21*cf3c1e67SAndrew Jeffery    HOST_ON = "xyz.openbmc_project.State.Host.HostState.Running"
22*cf3c1e67SAndrew Jeffery    HOST_QUIESCED = "xyz.openbmc_project.State.Host.HostState.Quiesced"
23*cf3c1e67SAndrew Jeffery
24*cf3c1e67SAndrew Jeffery    def __init__(self, session, prompt):
25*cf3c1e67SAndrew Jeffery        self.session = session
26*cf3c1e67SAndrew Jeffery        self.prompt = prompt
27*cf3c1e67SAndrew Jeffery
28*cf3c1e67SAndrew Jeffery    def _clear(self):
29*cf3c1e67SAndrew Jeffery        self.session.expect([".+".encode(), pexpect.TIMEOUT], timeout=5)
30*cf3c1e67SAndrew Jeffery
31*cf3c1e67SAndrew Jeffery    def _state(self, cmd, needle):
32*cf3c1e67SAndrew Jeffery        self.session.sendline()
33*cf3c1e67SAndrew Jeffery        self._clear()
34*cf3c1e67SAndrew Jeffery        self.session.sendline("obmcutil -w {}".format(cmd).encode())
35*cf3c1e67SAndrew Jeffery        self.session.expect(needle, timeout=None)
36*cf3c1e67SAndrew Jeffery        rc = self.session.after.decode()
37*cf3c1e67SAndrew Jeffery        return rc
38*cf3c1e67SAndrew Jeffery
39*cf3c1e67SAndrew Jeffery    def hoststate(self):
40*cf3c1e67SAndrew Jeffery        return self._state("hoststate", "xyz\.openbmc_project\.State\.Host\.HostState\.(Off|Running|Quiesced)")
41*cf3c1e67SAndrew Jeffery
42*cf3c1e67SAndrew Jeffery    def bmcstate(self):
43*cf3c1e67SAndrew Jeffery        return self._state("bmcstate", "xyz\.openbmc_project\.State\.BMC\.BMCState\.(Not)?Ready")
44*cf3c1e67SAndrew Jeffery
45*cf3c1e67SAndrew Jeffery    def poweron(self):
46*cf3c1e67SAndrew Jeffery        self.session.sendline("obmcutil -w poweron")
47*cf3c1e67SAndrew Jeffery        self.session.expect(self.prompt)
48*cf3c1e67SAndrew Jeffery
49*cf3c1e67SAndrew Jeffery    def chassisoff(self):
50*cf3c1e67SAndrew Jeffery        self.session.sendline("obmcutil -w chassisoff")
51*cf3c1e67SAndrew Jeffery        self.session.expect(self.prompt)
52*cf3c1e67SAndrew Jeffery
53*cf3c1e67SAndrew Jefferyclass PexpectLogger(object):
54*cf3c1e67SAndrew Jeffery    def write(self, bstring):
55*cf3c1e67SAndrew Jeffery        try:
56*cf3c1e67SAndrew Jeffery            sys.stdout.write(bstring.decode())
57*cf3c1e67SAndrew Jeffery        except UnicodeDecodeError:
58*cf3c1e67SAndrew Jeffery            print("Dropping broken unicode line")
59*cf3c1e67SAndrew Jeffery
60*cf3c1e67SAndrew Jeffery    def flush(self):
61*cf3c1e67SAndrew Jeffery        sys.stdout.flush()
62*cf3c1e67SAndrew Jeffery
63*cf3c1e67SAndrew Jeffery
64*cf3c1e67SAndrew Jefferyclass Bmc(object):
65*cf3c1e67SAndrew Jeffery    def __init__(self, entity):
66*cf3c1e67SAndrew Jeffery        self.getty = "login: ".encode()
67*cf3c1e67SAndrew Jeffery        self.shell = "# ".encode()
68*cf3c1e67SAndrew Jeffery        self.entity = entity
69*cf3c1e67SAndrew Jeffery        fargs = (entity.console.endpoint.host, entity.console.endpoint.port)
70*cf3c1e67SAndrew Jeffery        self.session = pexpect.spawn("telnet {} {}".format(*fargs))
71*cf3c1e67SAndrew Jeffery        self.session.logfile = PexpectLogger()
72*cf3c1e67SAndrew Jeffery        self.obmcutil = Obmcutil(self.session, self.shell)
73*cf3c1e67SAndrew Jeffery        self.session.sendline()
74*cf3c1e67SAndrew Jeffery        rc = self.session.expect([self.getty, self.shell])
75*cf3c1e67SAndrew Jeffery        if rc == 0:
76*cf3c1e67SAndrew Jeffery            self.login()
77*cf3c1e67SAndrew Jeffery
78*cf3c1e67SAndrew Jeffery    def login(self):
79*cf3c1e67SAndrew Jeffery        self.session.sendline(self.entity.console.credentials.username.encode())
80*cf3c1e67SAndrew Jeffery        self.session.expect("Password: ".encode())
81*cf3c1e67SAndrew Jeffery        self.session.sendline(self.entity.console.credentials.password.encode())
82*cf3c1e67SAndrew Jeffery        self.session.expect(self.shell)
83*cf3c1e67SAndrew Jeffery
84*cf3c1e67SAndrew Jeffery    def reboot(self):
85*cf3c1e67SAndrew Jeffery        self.session.sendline("reboot")
86*cf3c1e67SAndrew Jeffery        self.session.expect("Hit any key to stop autoboot:".encode(), timeout=None)
87*cf3c1e67SAndrew Jeffery        self.session.expect(self.getty, timeout=None)
88*cf3c1e67SAndrew Jeffery        self.login()
89*cf3c1e67SAndrew Jeffery        state = self.obmcutil.bmcstate()
90*cf3c1e67SAndrew Jeffery        while state != self.obmcutil.BMC_READY:
91*cf3c1e67SAndrew Jeffery            print("Wanted state '{}', got state '{}'".format(self.obmcutil.BMC_READY, state))
92*cf3c1e67SAndrew Jeffery            time.sleep(5)
93*cf3c1e67SAndrew Jeffery            state = self.obmcutil.bmcstate()
94*cf3c1e67SAndrew Jeffery
95*cf3c1e67SAndrew Jeffery    def chassisoff(self):
96*cf3c1e67SAndrew Jeffery        self.obmcutil.chassisoff()
97*cf3c1e67SAndrew Jeffery
98*cf3c1e67SAndrew Jeffery    def poweron(self):
99*cf3c1e67SAndrew Jeffery        hs = self.obmcutil.hoststate()
100*cf3c1e67SAndrew Jeffery        print("Host state is: {}".format(hs))
101*cf3c1e67SAndrew Jeffery        if hs in (self.obmcutil.HOST_ON, self.obmcutil.HOST_QUIESCED):
102*cf3c1e67SAndrew Jeffery            self.obmcutil.chassisoff()
103*cf3c1e67SAndrew Jeffery        self.obmcutil.poweron()
104*cf3c1e67SAndrew Jeffery
105*cf3c1e67SAndrew Jefferyclass Host(object):
106*cf3c1e67SAndrew Jeffery    def __init__(self, entity, bmc):
107*cf3c1e67SAndrew Jeffery        self.shell = "/? *#".encode()
108*cf3c1e67SAndrew Jeffery        self.petitboot = "Petitboot".encode()
109*cf3c1e67SAndrew Jeffery        self.session = None
110*cf3c1e67SAndrew Jeffery        self.entity = entity
111*cf3c1e67SAndrew Jeffery        self.bmc = bmc
112*cf3c1e67SAndrew Jeffery        self.connect()
113*cf3c1e67SAndrew Jeffery
114*cf3c1e67SAndrew Jeffery    def connect(self):
115*cf3c1e67SAndrew Jeffery        fargs = (self.entity.console.endpoint.port,
116*cf3c1e67SAndrew Jeffery                self.entity.console.credentials.username,
117*cf3c1e67SAndrew Jeffery                self.entity.console.endpoint.host)
118*cf3c1e67SAndrew Jeffery        self.session = pexpect.spawn("ssh -p{} {}@{}".format(*fargs))
119*cf3c1e67SAndrew Jeffery        self.session.logfile = PexpectLogger()
120*cf3c1e67SAndrew Jeffery        self.session.expect("password:".encode())
121*cf3c1e67SAndrew Jeffery        self.session.sendline(self.entity.console.credentials.password.encode())
122*cf3c1e67SAndrew Jeffery
123*cf3c1e67SAndrew Jeffery    def poweron(self):
124*cf3c1e67SAndrew Jeffery        self.bmc.chassisoff()
125*cf3c1e67SAndrew Jeffery        self.bmc.poweron()
126*cf3c1e67SAndrew Jeffery        self.session.send('\f')
127*cf3c1e67SAndrew Jeffery        rc = self.session.expect([self.petitboot, self.shell], timeout=None)
128*cf3c1e67SAndrew Jeffery        if rc == 0:
129*cf3c1e67SAndrew Jeffery            self.session.sendline()
130*cf3c1e67SAndrew Jeffery            self.session.expect(self.shell)
131*cf3c1e67SAndrew Jeffery
132*cf3c1e67SAndrew Jeffery    def reboot(self):
133*cf3c1e67SAndrew Jeffery        self.session.send('\f')
134*cf3c1e67SAndrew Jeffery        rc = self.session.expect([self.petitboot, self.shell], timeout=None)
135*cf3c1e67SAndrew Jeffery        if rc == 0:
136*cf3c1e67SAndrew Jeffery            self.session.sendline()
137*cf3c1e67SAndrew Jeffery            self.session.expect(self.shell)
138*cf3c1e67SAndrew Jeffery        self.session.sendline("reboot".encode())
139*cf3c1e67SAndrew Jeffery        self.session.expect("INIT: Waiting for kernel...".encode(), timeout=None)
140*cf3c1e67SAndrew Jeffery        self.session.expect("Petitboot".encode(), timeout=None)
141*cf3c1e67SAndrew Jeffery        self.session.sendline()
142*cf3c1e67SAndrew Jeffery        self.session.expect(self.shell)
143*cf3c1e67SAndrew Jeffery
144*cf3c1e67SAndrew Jefferydef rpp(machine):
145*cf3c1e67SAndrew Jeffery    bmc = Bmc(machine.bmc)
146*cf3c1e67SAndrew Jeffery    host = Host(machine.host, bmc)
147*cf3c1e67SAndrew Jeffery    host.poweron()
148*cf3c1e67SAndrew Jeffery    while True:
149*cf3c1e67SAndrew Jeffery        bmc.reboot()
150*cf3c1e67SAndrew Jeffery        host.connect()
151*cf3c1e67SAndrew Jeffery        host.reboot()
152*cf3c1e67SAndrew Jeffery
153*cf3c1e67SAndrew Jefferydef main():
154*cf3c1e67SAndrew Jeffery    bmccreds = Credentials("root", "0penBmc")
155*cf3c1e67SAndrew Jeffery    b = Entity(Target(bmccreds, Endpoint("serial.concentrator.somewhere.com", 1234)),
156*cf3c1e67SAndrew Jeffery            Target(bmccreds, Endpoint("bmc.somewhere.com", 22)))
157*cf3c1e67SAndrew Jeffery    h = Entity(Target(bmccreds, Endpoint("bmc.somewhere.com", 2200)),
158*cf3c1e67SAndrew Jeffery            Target(Credentials("user", "password"), Endpoint("host.somewhere.com", 22)))
159*cf3c1e67SAndrew Jeffery    m = Machine(b, h)
160*cf3c1e67SAndrew Jeffery    return rpp(m)
161*cf3c1e67SAndrew Jeffery
162*cf3c1e67SAndrew Jefferyif __name__ == "__main__":
163*cf3c1e67SAndrew Jeffery    main()
164