local_host.py revision 81de1f4c64c466e2e3f2a2eee1747dff52c80412
1# Copyright 2009 Google Inc. Released under the GPL v2 2 3""" 4This file contains the implementation of a host object for the local machine. 5""" 6 7import httplib, glob, logging, os, platform, socket, urlparse 8from autotest_lib.client.bin import utils 9from autotest_lib.client.common_lib import error, hosts 10 11 12STATEFULDEV_UPDATER='/usr/local/bin/stateful_update' 13UPDATER_BIN='/opt/google/memento_updater/memento_updater.sh' 14UPDATER_CONFIG='/etc/lsb-release' 15 16class LocalHost(hosts.Host): 17 def _initialize(self, hostname=None, bootloader=None, *args, **dargs): 18 super(LocalHost, self)._initialize(*args, **dargs) 19 20 # hostname will be an actual hostname when this client was created 21 # by an autoserv process 22 if not hostname: 23 hostname = platform.node() 24 self.hostname = hostname 25 self.bootloader = bootloader 26 27 28 def wait_up(self, timeout=None): 29 # a local host is always up 30 return True 31 32 33 def run(self, command, timeout=3600, ignore_status=False, 34 stdout_tee=utils.TEE_TO_LOGS, stderr_tee=utils.TEE_TO_LOGS, 35 stdin=None, args=()): 36 """ 37 @see common_lib.hosts.Host.run() 38 """ 39 try: 40 result = utils.run( 41 command, timeout=timeout, ignore_status=True, 42 stdout_tee=stdout_tee, stderr_tee=stderr_tee, stdin=stdin, 43 args=args) 44 except error.CmdError, e: 45 # this indicates a timeout exception 46 raise error.AutotestHostRunError('command timed out', e.result_obj) 47 48 if not ignore_status and result.exit_status > 0: 49 raise error.AutotestHostRunError('command execution error', result) 50 51 return result 52 53 54 def list_files_glob(self, path_glob): 55 """ 56 Get a list of files on a remote host given a glob pattern path. 57 """ 58 return glob.glob(path_glob) 59 60 61 def machine_install(self, update_url=None): 62 if not update_url: 63 return False 64 65 # Check that devserver is accepting connections (from autoserv's host) 66 # If we can't talk to it, the machine host probably can't either. 67 auserver_host = urlparse.urlparse(update_url)[1] 68 try: 69 httplib.HTTPConnection(auserver_host).connect() 70 except socket.error: 71 raise error.InstallError('Update server at %s not available' % 72 auserver_host) 73 74 logging.info('Installing from %s to: %s' % (update_url, self.hostname)) 75 76 self.run('echo "CHROMEOS_DEVSERVER=http://chromeosbuild_server" >> ' 77 '/mnt/stateful_partition/etc/lsb-release') 78 79 # First, attempt dev & test tools update (which don't live on 80 # the rootfs). This must succeed so that the newly installed 81 # host is testable after we run the autoupdater. 82 statefuldev_cmd = ' '.join([STATEFULDEV_UPDATER, update_url]) 83 logging.info(statefuldev_cmd) 84 try: 85 self.run(statefuldev_cmd, timeout=1200) 86 except error.AutoservRunError, e: 87 raise error.InstallError('stateful_update failed on %s', 88 self.hostname) 89 90 # Run autoupdate command. This tells the autoupdate process on 91 # the host to look for an update at a specific URL and version 92 # string. 93 autoupdate_cmd = ' '.join([UPDATER_BIN, '--omaha_url=%s' % update_url, 94 '--force_update']) 95 logging.info(autoupdate_cmd) 96 try: 97 self.run('rm -f /tmp/mememto_complete') # Ignore previous updates. 98 self.run(autoupdate_cmd, timeout=1200) 99 except error.AutoservRunError, e: 100 raise error.InstallError('OS Updater failed on %s', self.hostname) 101 102 # Check that the installer completed as expected. 103 # TODO(seano) verify installer completed in logs. 104 105 106 def symlink_closure(self, paths): 107 """ 108 Given a sequence of path strings, return the set of all paths that 109 can be reached from the initial set by following symlinks. 110 111 @param paths: sequence of path strings. 112 @return: a sequence of path strings that are all the unique paths that 113 can be reached from the given ones after following symlinks. 114 """ 115 paths = set(paths) 116 closure = set() 117 118 while paths: 119 path = paths.pop() 120 if not os.path.exists(path): 121 continue 122 closure.add(path) 123 if os.path.islink(path): 124 link_to = os.path.join(os.path.dirname(path), 125 os.readlink(path)) 126 if link_to not in closure: 127 paths.add(link_to) 128 129 return closure 130