Pull a ton of methods out of SSHHost and into RemoteHost, since most
of them have nothing to do with SSH and it will make it a lot easier
for me to implement a new host object.
Risk: Medium
Visibility: Should be code changes only.
Signed-off-by: John Admanski <jadmanski@google.com>
git-svn-id: http://test.kernel.org/svn/autotest/trunk@2307 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/server/hosts/remote.py b/server/hosts/remote.py
index a712199..eabfbb2 100644
--- a/server/hosts/remote.py
+++ b/server/hosts/remote.py
@@ -1,7 +1,10 @@
"""This class defines the Remote host class, mixing in the SiteHost class
if it is available."""
-from autotest_lib.server.hosts import base_classes
+import os, time
+from autotest_lib.client.common_lib import error
+from autotest_lib.server import utils
+from autotest_lib.server.hosts import base_classes, bootloader
class RemoteHost(base_classes.Host):
@@ -18,11 +21,195 @@
must not instantiate this class but should instantiate one of those
leaf subclasses."""
- def __init__(self, hostname, *args, **dargs):
+ DEFAULT_REBOOT_TIMEOUT = base_classes.Host.DEFAULT_REBOOT_TIMEOUT
+ LAST_BOOT_TAG = object()
+
+ def __init__(self, hostname, autodir=None, *args, **dargs):
super(RemoteHost, self).__init__(*args, **dargs)
self.hostname = hostname
+ self.autodir = autodir
+ self.tmp_dirs = []
def __del__(self):
- pass
+ self.stop_loggers()
+
+ if hasattr(self, 'tmp_dirs'):
+ for dir in self.tmp_dirs:
+ try:
+ self.run('rm -rf "%s"' % (utils.sh_escape(dir)))
+ except error.AutoservRunError:
+ pass
+
+
+ def get_autodir(self):
+ return self.autodir
+
+
+ def set_autodir(self, autodir):
+ '''
+ This method is called to make the host object aware of the
+ where autotest is installed. Called in server/autotest.py
+ after a successful install
+ '''
+ self.autodir = autodir
+
+
+ def sysrq_reboot(self):
+ self.run('echo b > /proc/sysrq-trigger &')
+
+
+ def reboot(self, timeout=DEFAULT_REBOOT_TIMEOUT, label=LAST_BOOT_TAG,
+ kernel_args=None, wait=True, **dargs):
+ """
+ Reboot the remote host.
+
+ Args:
+ timeout - How long to wait for the reboot.
+ label - The label we should boot into. If None, we will
+ boot into the default kernel. If it's LAST_BOOT_TAG,
+ we'll boot into whichever kernel was .boot'ed last
+ (or the default kernel if we haven't .boot'ed in this
+ job). If it's None, we'll boot into the default kernel.
+ If it's something else, we'll boot into that.
+ wait - Should we wait to see if the machine comes back up.
+ """
+ if self.job:
+ if label == self.LAST_BOOT_TAG:
+ label = self.job.last_boot_tag
+ else:
+ self.job.last_boot_tag = label
+
+ self.reboot_setup(label=label, kernel_args=kernel_args, **dargs)
+
+ if label or kernel_args:
+ self.bootloader.install_boottool()
+ if not label:
+ default = int(self.bootloader.get_default())
+ label = self.bootloader.get_titles()[default]
+ self.bootloader.boot_once(label)
+ if kernel_args:
+ self.bootloader.add_args(label, kernel_args)
+
+ # define a function for the reboot and run it in a group
+ print "Reboot: initiating reboot"
+ def reboot():
+ self.record("GOOD", None, "reboot.start")
+ try:
+ self.run('(sleep 5; reboot) '
+ '</dev/null >/dev/null 2>&1 &')
+ except error.AutoservRunError:
+ self.record("ABORT", None, "reboot.start",
+ "reboot command failed")
+ raise
+ if wait:
+ self.wait_for_restart(timeout)
+ self.reboot_followup(**dargs)
+
+ # if this is a full reboot-and-wait, run the reboot inside a group
+ if wait:
+ self.log_reboot(reboot)
+ else:
+ reboot()
+
+
+ def wait_for_restart(self, timeout=DEFAULT_REBOOT_TIMEOUT):
+ """ Wait for the host to come back from a reboot. This wraps the
+ generic wait_for_restart implementation in a reboot group. """
+ def reboot_func():
+ super(RemoteHost, self).wait_for_restart(timeout=timeout)
+ self.log_reboot(reboot_func)
+
+
+ def get_tmp_dir(self):
+ """
+ Return the pathname of a directory on the host suitable
+ for temporary file storage.
+
+ The directory and its content will be deleted automatically
+ on the destruction of the Host object that was used to obtain
+ it.
+ """
+ dir_name= self.run("mktemp -d /tmp/autoserv-XXXXXX").stdout.rstrip()
+ self.tmp_dirs.append(dir_name)
+ return dir_name
+
+
+ def ping(self):
+ """
+ Ping the remote system, and return whether it's available
+ """
+ fpingcmd = "%s -q %s" % ('/usr/bin/fping', self.hostname)
+ rc = utils.system(fpingcmd, ignore_status = 1)
+ return (rc == 0)
+
+
+ def check_uptime(self):
+ """
+ Check that uptime is available and monotonically increasing.
+ """
+ if not self.ping():
+ raise error.AutoservHostError('Client is not pingable')
+ result = self.run("/bin/cat /proc/uptime", 30)
+ return result.stdout.strip().split()[0]
+
+
+ def get_crashinfo(self, test_start_time):
+ print "Collecting crash information..."
+ super(RemoteHost, self).get_crashinfo(test_start_time)
+
+ # wait for four hours, to see if the machine comes back up
+ current_time = time.strftime("%b %d %H:%M:%S", time.localtime())
+ print "Waiting four hours for %s to come up (%s)" % (self.hostname,
+ current_time)
+ if not self.wait_up(timeout=4*60*60):
+ print "%s down, unable to collect crash info" % self.hostname
+ return
+ else:
+ print "%s is back up, collecting crash info" % self.hostname
+
+ # find a directory to put the crashinfo into
+ if self.job:
+ infodir = self.job.resultdir
+ else:
+ infodir = os.path.abspath(os.getcwd())
+ infodir = os.path.join(infodir, "crashinfo.%s" % self.hostname)
+ if not os.path.exists(infodir):
+ os.mkdir(infodir)
+
+ # collect various log files
+ log_files = ["/var/log/messages", "/var/log/monitor-ssh-reboots"]
+ for log in log_files:
+ print "Collecting %s..." % log
+ try:
+ self.get_file(log, infodir)
+ except Exception, e:
+ print "crashinfo collection of %s failed with:\n%s" % (log, e)
+
+ # collect dmesg
+ print "Collecting dmesg..."
+ try:
+ result = self.run("dmesg").stdout
+ file(os.path.join(infodir, "dmesg"), "w").write(result)
+ except Exception, e:
+ print "crashinfo collection of dmesg failed with:\n%s" % e
+
+
+ def are_wait_up_process_up(self):
+ """
+ Checks if any HOSTS waitup processes are running yet on the
+ remote host.
+
+ Returns True if any the waitup processes are running, False
+ otherwise.
+ """
+ processes = self.get_wait_up_processes()
+ if len(processes) == 0:
+ return True # wait up processes aren't being used
+ for procname in processes:
+ exit_status = self.run("{ ps -e || ps; } | grep '%s'" % procname,
+ ignore_status=True).exit_status
+ if exit_status == 0:
+ return True
+ return False