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