blob: b3b8c165e0781aeffb5762fb9c929cb611f45ef1 [file] [log] [blame]
jadmanski1c5e3a12008-08-15 23:08:20 +00001import os, sys, subprocess
2
jadmanskia2db9412008-08-22 21:47:24 +00003from autotest_lib.client.common_lib import utils, error
4from autotest_lib.server import utils as server_utils
mbligh3b02e8b2009-02-17 15:59:54 +00005from autotest_lib.server.hosts import remote
jadmanski1c5e3a12008-08-15 23:08:20 +00006
7
mbligh3b02e8b2009-02-17 15:59:54 +00008SiteHost = utils.import_site_class(
9 __file__, "autotest_lib.server.hosts.site_host", "SiteHost",
10 remote.RemoteHost)
11
12
13class SerialHost(SiteHost):
14 DEFAULT_REBOOT_TIMEOUT = SiteHost.DEFAULT_REBOOT_TIMEOUT
jadmanskia2db9412008-08-22 21:47:24 +000015
jadmanskif6562912008-10-21 17:59:01 +000016 def _initialize(self, conmux_server=None, conmux_attach=None,
17 console_log="console.log", *args, **dargs):
18 super(SerialHost, self)._initialize(*args, **dargs)
jadmanski1c5e3a12008-08-15 23:08:20 +000019
jadmanskic533bd12008-09-03 20:48:51 +000020 self.__logger = None
21 self.__console_log = console_log
22
jadmanski1c5e3a12008-08-15 23:08:20 +000023 self.conmux_server = conmux_server
jadmanskia2db9412008-08-22 21:47:24 +000024 self.conmux_attach = self._get_conmux_attach(conmux_attach)
jadmanski1c5e3a12008-08-15 23:08:20 +000025
jadmanski1c5e3a12008-08-15 23:08:20 +000026
jadmanskia2db9412008-08-22 21:47:24 +000027 @classmethod
28 def _get_conmux_attach(cls, conmux_attach=None):
29 if conmux_attach:
30 return conmux_attach
31
32 # assume we're using the conmux-attach provided with autotest
33 server_dir = server_utils.get_server_dir()
34 path = os.path.join(server_dir, "..", "conmux", "conmux-attach")
35 path = os.path.abspath(path)
36 return path
37
38
39 @staticmethod
40 def _get_conmux_hostname(hostname, conmux_server):
41 if conmux_server:
42 return "%s/%s" % (conmux_server, hostname)
jadmanski1c5e3a12008-08-15 23:08:20 +000043 else:
jadmanskia2db9412008-08-22 21:47:24 +000044 return hostname
45
46
47 def get_conmux_hostname(self):
48 return self._get_conmux_hostname(self.hostname, self.conmux_server)
49
50
51 @classmethod
52 def host_is_supported(cls, hostname, conmux_server=None,
53 conmux_attach=None):
54 """ Returns a boolean indicating if the remote host with "hostname"
55 supports use as a SerialHost """
56 conmux_attach = cls._get_conmux_attach(conmux_attach)
57 conmux_hostname = cls._get_conmux_hostname(hostname, conmux_server)
58 cmd = "%s %s echo 2> /dev/null" % (conmux_attach, conmux_hostname)
jadmanski74394b62008-08-25 19:24:45 +000059 result = utils.run(cmd, ignore_status=True)
jadmanskia2db9412008-08-22 21:47:24 +000060 return result.exit_status == 0
jadmanski1c5e3a12008-08-15 23:08:20 +000061
62
jadmanskic533bd12008-09-03 20:48:51 +000063 def start_loggers(self):
64 super(SerialHost, self).start_loggers()
65
mblighd876f452008-12-03 15:09:17 +000066 if self.__console_log is None:
jadmanski1c5e3a12008-08-15 23:08:20 +000067 return
jadmanskic533bd12008-09-03 20:48:51 +000068
jadmanski1c5e3a12008-08-15 23:08:20 +000069 if not self.conmux_attach or not os.path.exists(self.conmux_attach):
70 return
71
72 r, w = os.pipe()
jadmanski79777f62008-09-09 22:31:38 +000073 script_path = os.path.join(self.monitordir, 'console.py')
jadmanskia2db9412008-08-22 21:47:24 +000074 cmd = [self.conmux_attach, self.get_conmux_hostname(),
jadmanski1c5e3a12008-08-15 23:08:20 +000075 '%s %s %s %d' % (sys.executable, script_path,
jadmanskic533bd12008-09-03 20:48:51 +000076 self.__console_log, w)]
jadmanski1c5e3a12008-08-15 23:08:20 +000077
jadmanskic533bd12008-09-03 20:48:51 +000078 self.__warning_stream = os.fdopen(r, 'r', 0)
jadmanski1c5e3a12008-08-15 23:08:20 +000079 if self.job:
jadmanskic533bd12008-09-03 20:48:51 +000080 self.job.warning_loggers.add(self.__warning_stream)
81
82 stdout = stderr = open(os.devnull, 'w')
83 self.__logger = subprocess.Popen(cmd, stdout=stdout, stderr=stderr)
jadmanski1c5e3a12008-08-15 23:08:20 +000084 os.close(w)
85
86
jadmanskic533bd12008-09-03 20:48:51 +000087 def stop_loggers(self):
88 super(SerialHost, self).stop_loggers()
89
90 if self.__logger:
91 utils.nuke_subprocess(self.__logger)
92 self.__logger = None
jadmanski1c5e3a12008-08-15 23:08:20 +000093 if self.job:
jadmanskic533bd12008-09-03 20:48:51 +000094 self.job.warning_loggers.discard(self.__warning_stream)
95 self.__warning_stream.close()
jadmanski1c5e3a12008-08-15 23:08:20 +000096
97
98 def run_conmux(self, cmd):
99 """
100 Send a command to the conmux session
101 """
102 if not self.conmux_attach or not os.path.exists(self.conmux_attach):
103 return False
104 cmd = '%s %s echo %s 2> /dev/null' % (self.conmux_attach,
jadmanskia2db9412008-08-22 21:47:24 +0000105 self.get_conmux_hostname(),
jadmanski1c5e3a12008-08-15 23:08:20 +0000106 cmd)
107 result = utils.system(cmd, ignore_status=True)
108 return result == 0
jadmanskia2db9412008-08-22 21:47:24 +0000109
110
111 def hardreset(self, timeout=DEFAULT_REBOOT_TIMEOUT, wait=True,
112 conmux_command='hardreset'):
113 """
114 Reach out and slap the box in the power switch.
115 Args:
116 conmux_command: The command to run via the conmux interface
117 timeout: timelimit in seconds before the machine is
118 considered unreachable
119 wait: Whether or not to wait for the machine to reboot
120
121 """
122 conmux_command = "'~$%s'" % conmux_command
123 def reboot():
124 if not self.run_conmux(conmux_command):
125 self.record("ABORT", None, "reboot.start",
126 "hard reset unavailable")
127 raise error.AutoservUnsupportedError(
128 'Hard reset unavailable')
129 self.record("GOOD", None, "reboot.start", "hard reset")
130 if wait:
131 self.wait_for_restart(timeout)
132
133 if wait:
134 self.log_reboot(reboot)
135 else:
136 reboot()