aos/tools/harness/machines/msrc.py
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

147 lines
5.2 KiB
Python

##########################################################################
# Copyright (c) 2009, ETH Zurich.
# All rights reserved.
#
# This file is distributed under the terms in the attached LICENSE file.
# If you do not find this file, copies can be found by writing to:
# ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
##########################################################################
import sys, os, signal, time, getpass, subprocess, socket, pty
import debug, machines, msrc_machinedata
from machines import Machine, MachineLockedError, MachineFactory
TFTP_PATH='/tftpboot'
TOOLS_PATH='/home/netos/tools/bin'
RACKBOOT=os.path.join(TOOLS_PATH, 'rackboot.sh')
RACKPOWER=os.path.join(TOOLS_PATH, 'rackpower')
class MSRCMachine(Machine):
_msrc_machines = msrc_machinedata.machines
def __init__(self, options):
super(MSRCMachine, self).__init__(options)
self.lockprocess = None
def get_bootarch(self):
b = self._msrc_machines[self.name]['bootarch']
assert(b in self.get_buildarchs())
return b
def get_machine_name(self):
return self._msrc_machines[self.name]['machine_name']
def get_buildarchs(self):
return self._msrc_machines[self.name]['buildarchs']
def get_ncores(self):
return self._msrc_machines[self.name]['ncores']
def get_cores_per_socket(self):
return self._msrc_machines[self.name]['cores_per_socket']
def get_tickrate(self):
return self._msrc_machines[self.name]['tickrate']
def get_perfcount_type(self):
return self._msrc_machines[self.name]['perfcount_type']
def get_hostname(self):
return self.get_machine_name()
def get_ip(self):
return socket.gethostbyname(self.get_hostname())
def get_tftp_dir(self):
user = getpass.getuser()
return os.path.join(TFTP_PATH, user, self.name + "_harness")
def _write_menu_lst(self, data, path):
debug.verbose('writing %s' % path)
debug.debug(data)
f = open(path, 'w')
f.write(data)
f.close()
def _set_menu_lst(self, relpath):
ip_menu_name = os.path.join(TFTP_PATH, "menu.lst." + self.get_ip())
debug.verbose('relinking %s to %s' % (ip_menu_name, relpath))
os.remove(ip_menu_name)
os.symlink(relpath, ip_menu_name)
def set_bootmodules(self, modules):
fullpath = os.path.join(self.get_tftp_dir(), 'menu.lst')
relpath = os.path.relpath(fullpath, TFTP_PATH)
tftppath = '/' + os.path.relpath(self.get_tftp_dir(), TFTP_PATH)
self._write_menu_lst(modules.get_menu_data(tftppath), fullpath)
self._set_menu_lst(relpath)
def lock(self):
"""Use conserver to lock the machine."""
# find out current status of console
debug.verbose('executing "console -i %s" to check state' %
self.get_machine_name())
proc = subprocess.Popen(["console", "-i", self.get_machine_name()],
stdout=subprocess.PIPE)
line = proc.communicate()[0]
assert(proc.returncode == 0)
# check that nobody else has it open for writing
myuser = getpass.getuser()
parts = line.strip().split(':')
conname, child, contype, details, users, state = parts[:6]
if users:
for userinfo in users.split(','):
mode, username, host, port = userinfo.split('@')[:4]
if 'w' in mode and username != myuser:
raise MachineLockedError # Machine is not free
# run a console in the background to 'hold' the lock and read output
debug.verbose('starting "console %s"' % self.get_machine_name())
# run on a PTY to work around terminal mangling code in console
(masterfd, slavefd) = pty.openpty()
self.lockprocess = subprocess.Popen(["console", self.get_machine_name()],
close_fds=True,
stdout=slavefd, stdin=slavefd)
os.close(slavefd)
# XXX: open in binary mode with no buffering
# otherwise select.select() may block when there is data in the buffer
self.console_out = os.fdopen(masterfd, 'rb', 0)
def unlock(self):
if self.lockprocess is None:
return # noop
debug.verbose('terminating console process (%d)' % self.lockprocess.pid)
os.kill(self.lockprocess.pid, signal.SIGTERM)
self.lockprocess.wait()
self.lockprocess = None
def __rackboot(self, args):
debug.checkcmd([RACKBOOT] + args + [self.get_machine_name()])
def setup(self):
self.__rackboot(["-b", "-n"])
def __rackpower(self, arg):
try:
debug.checkcmd([RACKPOWER, arg, self.get_machine_name()])
except subprocess.CalledProcessError:
debug.warning("rackpower %s %s failed" %
(arg, self.get_machine_name()))
def reboot(self):
self.__rackpower('-r')
def shutdown(self):
self.__rackpower('-d')
def get_output(self):
return self.console_out
for n in sorted(MSRCMachine._msrc_machines.keys()):
class TmpMachine(MSRCMachine):
name = n
MachineFactory.addMachine(n, TmpMachine)