summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/utils/sshcontrol.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/utils/sshcontrol.py')
-rw-r--r--meta/lib/oeqa/utils/sshcontrol.py109
1 files changed, 109 insertions, 0 deletions
diff --git a/meta/lib/oeqa/utils/sshcontrol.py b/meta/lib/oeqa/utils/sshcontrol.py
new file mode 100644
index 0000000000..1539ff2a37
--- /dev/null
+++ b/meta/lib/oeqa/utils/sshcontrol.py
@@ -0,0 +1,109 @@
1# Copyright (C) 2013 Intel Corporation
2#
3# Released under the MIT license (see COPYING.MIT)
4
5# Provides a class for setting up ssh connections,
6# running commands and copying files to/from a target.
7# It's used by testimage.bbclass and tests in lib/oeqa/runtime.
8
9import subprocess
10import time
11import os
12
13class SSHControl(object):
14
15 def __init__(self, host=None, timeout=300, logfile=None):
16 self.host = host
17 self.timeout = timeout
18 self._starttime = None
19 self._out = ''
20 self._ret = 126
21 self.logfile = logfile
22 self.ssh_options = [
23 '-o', 'UserKnownHostsFile=/dev/null',
24 '-o', 'StrictHostKeyChecking=no',
25 '-o', 'LogLevel=ERROR'
26 ]
27 self.ssh = ['ssh', '-l', 'root'] + self.ssh_options
28
29 def log(self, msg):
30 if self.logfile:
31 with open(self.logfile, "a") as f:
32 f.write("%s\n" % msg)
33
34 def _internal_run(self, cmd):
35 # We need this for a proper PATH
36 cmd = ". /etc/profile; " + cmd
37 command = self.ssh + [self.host, cmd]
38 self.log("[Running]$ %s" % " ".join(command))
39 self._starttime = time.time()
40 # ssh hangs without os.setsid
41 proc = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setsid)
42 return proc
43
44 def run(self, cmd, timeout=None):
45 """Run cmd and get it's return code and output.
46 Let it run for timeout seconds and then terminate/kill it,
47 if time is 0 will let cmd run until it finishes.
48 Time can be passed to here or can be set per class instance."""
49
50 if self.host:
51 sshconn = self._internal_run(cmd)
52 else:
53 raise Exception("Remote IP hasn't been set: '%s'" % actualcmd)
54
55 if timeout == 0:
56 self._out = sshconn.communicate()[0]
57 self._ret = sshconn.poll()
58 else:
59 if timeout is None:
60 tdelta = self.timeout
61 else:
62 tdelta = timeout
63 endtime = self._starttime + tdelta
64 while sshconn.poll() is None and time.time() < endtime:
65 time.sleep(1)
66 # process hasn't returned yet
67 if sshconn.poll() is None:
68 self._ret = 255
69 sshconn.terminate()
70 sshconn.kill()
71 self._out = sshconn.stdout.read()
72 sshconn.stdout.close()
73 self._out += "\n[!!! SSH command timed out after %d seconds and it was killed]" % tdelta
74 else:
75 self._out = sshconn.stdout.read()
76 self._ret = sshconn.poll()
77 # strip the last LF so we can test the output
78 self._out = self._out.rstrip()
79 self.log("%s" % self._out)
80 self.log("[SSH command returned after %d seconds]: %s" % (time.time() - self._starttime, self._ret))
81 return (self._ret, self._out)
82
83 def _internal_scp(self, cmd):
84 cmd = ['scp'] + self.ssh_options + cmd
85 self.log("[Running SCP]$ %s" % " ".join(cmd))
86 self._starttime = time.time()
87 scpconn = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setsid)
88 out = scpconn.communicate()[0]
89 ret = scpconn.poll()
90 self.log("%s" % out)
91 self.log("[SCP command returned after %d seconds]: %s" % (time.time() - self._starttime, ret))
92 if ret != 0:
93 # we raise an exception so that tests fail in setUp and setUpClass without a need for an assert
94 raise Exception("Error running %s, output: %s" % ( " ".join(cmd), out))
95 return (ret, out)
96
97 def copy_to(self, localpath, remotepath):
98 actualcmd = [localpath, 'root@%s:%s' % (self.host, remotepath)]
99 return self._internal_scp(actualcmd)
100
101 def copy_from(self, remotepath, localpath):
102 actualcmd = ['root@%s:%s' % (self.host, remotepath), localpath]
103 return self._internal_scp(actualcmd)
104
105 def get_status(self):
106 return self._ret
107
108 def get_output(self):
109 return self._out