blob: 64d9003536708a503732619a1269c4c22026da48 [file] [log] [blame]
Alex Miller885543d2014-02-04 20:51:21 -08001# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Prashanth Balasubramanian3a9b9a12014-11-13 20:05:10 -08005import contextlib
Alex Miller885543d2014-02-04 20:51:21 -08006import getpass
Alex Miller885543d2014-02-04 20:51:21 -08007import subprocess
Prashanth Balasubramanian3a9b9a12014-11-13 20:05:10 -08008import os
Alex Miller885543d2014-02-04 20:51:21 -08009
10import common
11from autotest_lib.server.hosts import ssh_host
12from autotest_lib.client.common_lib import error
13from autotest_lib.client.common_lib import global_config
Dan Shif6c65bd2014-08-29 16:15:07 -070014from autotest_lib.client.common_lib import utils
Jakob Juelich0a331872014-09-25 14:45:43 -070015from autotest_lib.server.cros.dynamic_suite import frontend_wrappers
Alex Miller885543d2014-02-04 20:51:21 -080016
17
Prashanth Balasubramanian3a9b9a12014-11-13 20:05:10 -080018@contextlib.contextmanager
19def chdir(dirname=None):
20 """A context manager to help change directories.
21
22 Will chdir into the provided dirname for the lifetime of the context and
23 return to cwd thereafter.
24
25 @param dirname: The dirname to chdir into.
26 """
27 curdir = os.getcwd()
28 try:
29 if dirname is not None:
30 os.chdir(dirname)
31 yield
32 finally:
33 os.chdir(curdir)
34
35
36def local_runner(cmd, stream_output=False):
Alex Miller885543d2014-02-04 20:51:21 -080037 """
38 Runs a command on the local system as the current user.
39
40 @param cmd: The command to run.
Prashanth Balasubramanian3a9b9a12014-11-13 20:05:10 -080041 @param stream_output: If True, streams the stdout of the process.
42
Shuqian Zhaoa482c4a2016-11-21 18:49:41 -080043 @returns: The output of cmd, will be stdout and stderr.
Alex Miller885543d2014-02-04 20:51:21 -080044 @raises CalledProcessError: If there was a non-0 return code.
45 """
Shuqian Zhaoa482c4a2016-11-21 18:49:41 -080046 print 'Running command: %s' % cmd
Shuqian Zhaoae2d0782016-11-15 16:58:47 -080047 proc = subprocess.Popen(
Shuqian Zhaoa482c4a2016-11-21 18:49:41 -080048 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
49 if stream_output:
50 output = ''
51 for newline in iter(proc.stdout.readline, ''):
52 output += newline
53 print newline.rstrip(os.linesep)
54 else:
55 output = proc.communicate()[0]
56
57 return_code = proc.wait()
58 if return_code !=0:
59 print "ERROR: '%s' failed with error:\n%s" % (cmd, output)
60 raise subprocess.CalledProcessError(return_code, cmd, output[:1024])
61 return output
Alex Miller885543d2014-02-04 20:51:21 -080062
63
64_host_objects = {}
65
Prashanth Balasubramanian3a9b9a12014-11-13 20:05:10 -080066def host_object_runner(host, **kwargs):
Alex Miller885543d2014-02-04 20:51:21 -080067 """
68 Returns a function that returns the output of running a command via a host
69 object.
70
71 @param host: The host to run a command on.
72 @returns: A function that can invoke a command remotely.
73 """
74 try:
75 host_object = _host_objects[host]
76 except KeyError:
Alex Miller792e2072014-02-18 21:00:20 -080077 username = global_config.global_config.get_config_value(
78 'CROS', 'infrastructure_user')
79 host_object = ssh_host.SSHHost(host, user=username)
Alex Miller885543d2014-02-04 20:51:21 -080080 _host_objects[host] = host_object
81
82 def runner(cmd):
83 """
84 Runs a command via a host object on the enclosed host. Translates
85 host.run errors to the subprocess equivalent to expose a common API.
86
87 @param cmd: The command to run.
88 @returns: The output of cmd.
89 @raises CalledProcessError: If there was a non-0 return code.
90 """
91 try:
Alex Miller792e2072014-02-18 21:00:20 -080092 return host_object.run(cmd).stdout
Alex Miller885543d2014-02-04 20:51:21 -080093 except error.AutotestHostRunError as e:
94 exit_status = e.result_obj.exit_status
95 command = e.result_obj.command
96 raise subprocess.CalledProcessError(exit_status, command)
97 return runner
98
99
Fang Deng51240a42015-12-17 14:52:52 -0800100def googlesh_runner(host, **kwargs):
Alex Miller885543d2014-02-04 20:51:21 -0800101 """
102 Returns a function that return the output of running a command via shelling
Fang Deng51240a42015-12-17 14:52:52 -0800103 out to `googlesh`.
Alex Miller885543d2014-02-04 20:51:21 -0800104
105 @param host: The host to run a command on
106 @returns: A function that can invoke a command remotely.
107 """
108 def runner(cmd):
109 """
Fang Deng51240a42015-12-17 14:52:52 -0800110 Runs a command via googlesh on the enclosed host.
Alex Miller885543d2014-02-04 20:51:21 -0800111
112 @param cmd: The command to run.
113 @returns: The output of cmd.
114 @raises CalledProcessError: If there was a non-0 return code.
115 """
Fang Deng51240a42015-12-17 14:52:52 -0800116 out = subprocess.check_output(['googlesh', '-s', '-uchromeos-test',
Shuqian Zhao9febd452017-01-31 15:36:40 -0800117 '-m%s' % host, '%s' % cmd],
118 stderr=subprocess.STDOUT)
Alex Miller885543d2014-02-04 20:51:21 -0800119 return out
120 return runner
121
122
Prashanth Balasubramanian3a9b9a12014-11-13 20:05:10 -0800123def execute_command(host, cmd, **kwargs):
Alex Miller885543d2014-02-04 20:51:21 -0800124 """
125 Executes a command on the host `host`. This an optimization that if
126 we're already chromeos-test, we can just ssh to the machine in question.
127 Or if we're local, we don't have to ssh at all.
128
129 @param host: The hostname to execute the command on.
130 @param cmd: The command to run. Special shell syntax (such as pipes)
131 is allowed.
Prashanth Balasubramanian3a9b9a12014-11-13 20:05:10 -0800132 @param kwargs: Key word arguments for the runner functions.
Alex Miller885543d2014-02-04 20:51:21 -0800133 @returns: The output of the command.
134 """
Dan Shif6c65bd2014-08-29 16:15:07 -0700135 if utils.is_localhost(host):
Alex Miller885543d2014-02-04 20:51:21 -0800136 runner = local_runner
137 elif getpass.getuser() == 'chromeos-test':
138 runner = host_object_runner(host)
139 else:
Fang Deng51240a42015-12-17 14:52:52 -0800140 runner = googlesh_runner(host)
Alex Miller885543d2014-02-04 20:51:21 -0800141
Prashanth Balasubramanian3a9b9a12014-11-13 20:05:10 -0800142 return runner(cmd, **kwargs)