diff options
author | Stefan Stanacar <stefanx.stanacar@intel.com> | 2013-06-28 11:04:06 +0300 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2013-07-09 10:53:44 +0100 |
commit | ac341af8fafc5ea6e3f937ea6ad078ab0812b2bc (patch) | |
tree | 6809fecffc6d785115f1e0093872e371a072b6b2 /meta/lib/oeqa | |
parent | 12bf6262f674a6301332cc5fdc10b2757793cfc5 (diff) | |
download | poky-ac341af8fafc5ea6e3f937ea6ad078ab0812b2bc.tar.gz |
lib/oeqa/utils/sshcontrol.py: helper module for running remote commands
Provides a class for setting up ssh connections,
running commands and copying files to/from a target.
(From OE-Core rev: 683cac9768e0d38fa15ddc5451e6b2333f184033)
Signed-off-by: Stefan Stanacar <stefanx.stanacar@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa')
-rw-r--r-- | meta/lib/oeqa/utils/__init__.py | 0 | ||||
-rw-r--r-- | meta/lib/oeqa/utils/sshcontrol.py | 100 |
2 files changed, 100 insertions, 0 deletions
diff --git a/meta/lib/oeqa/utils/__init__.py b/meta/lib/oeqa/utils/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/meta/lib/oeqa/utils/__init__.py | |||
diff --git a/meta/lib/oeqa/utils/sshcontrol.py b/meta/lib/oeqa/utils/sshcontrol.py new file mode 100644 index 0000000000..85a09a026f --- /dev/null +++ b/meta/lib/oeqa/utils/sshcontrol.py | |||
@@ -0,0 +1,100 @@ | |||
1 | import subprocess | ||
2 | import time | ||
3 | import os | ||
4 | import shlex | ||
5 | |||
6 | class SSHControl(object): | ||
7 | |||
8 | def __init__(self, host=None, timeout=200, logfile=None): | ||
9 | self.host = host | ||
10 | self.timeout = timeout | ||
11 | self._out = '' | ||
12 | self._ret = 126 | ||
13 | self.logfile = logfile | ||
14 | |||
15 | def log(self, msg): | ||
16 | if self.logfile: | ||
17 | with open(self.logfile, "a") as f: | ||
18 | f.write("%s\n" % msg) | ||
19 | |||
20 | def _internal_run(self, cmd): | ||
21 | # ssh hangs without os.setsid | ||
22 | proc = subprocess.Popen(shlex.split(cmd), shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setsid) | ||
23 | return proc | ||
24 | |||
25 | def run(self, cmd, timeout=None): | ||
26 | """Run cmd and get it's return code and output. | ||
27 | Let it run for timeout seconds and then terminate/kill it, | ||
28 | if time is 0 will let cmd run until it finishes. | ||
29 | Time can be passed to here or can be set per class instance.""" | ||
30 | |||
31 | |||
32 | |||
33 | actualcmd = "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l root %s '%s'" % (self.host, cmd) | ||
34 | if self.host: | ||
35 | sshconn = self._internal_run(actualcmd) | ||
36 | else: | ||
37 | raise Exception("Remote IP hasn't been set: '%s'" % actualcmd) | ||
38 | |||
39 | if timeout == 0: | ||
40 | self.log("[SSH run without timeout]$ %s" % actualcmd) | ||
41 | self.log(" # %s" % cmd) | ||
42 | self._out = sshconn.communicate()[0] | ||
43 | self._ret = sshconn.poll() | ||
44 | else: | ||
45 | if timeout is None: | ||
46 | endtime = time.time() + self.timeout | ||
47 | else: | ||
48 | endtime = time.time() + timeout | ||
49 | while sshconn.poll() is None and time.time() < endtime: | ||
50 | time.sleep(1) | ||
51 | self.log("[SSH run with timeout]$ %s" % actualcmd) | ||
52 | self.log(" # %s" % cmd) | ||
53 | # process hasn't returned yet | ||
54 | if sshconn.poll() is None: | ||
55 | self._ret = 255 | ||
56 | sshconn.terminate() | ||
57 | sshconn.kill() | ||
58 | self._out = sshconn.stdout.read() | ||
59 | sshconn.stdout.close() | ||
60 | self.log("[!!! process killed]") | ||
61 | else: | ||
62 | self._out = sshconn.stdout.read() | ||
63 | self._ret = sshconn.poll() | ||
64 | # remove first line from output which is always smth like (unless return code is 255 - which is a ssh error): | ||
65 | # Warning: Permanently added '192.168.7.2' (RSA) to the list of known hosts. | ||
66 | if self._ret != 255: | ||
67 | self._out = '\n'.join(self._out.splitlines()[1:]) | ||
68 | self.log("%s" % self._out) | ||
69 | self.log("[SSH command returned]: %s" % self._ret) | ||
70 | return (self._ret, self._out) | ||
71 | |||
72 | def _internal_scp(self, cmd): | ||
73 | self.log("[SCP]$ %s" % cmd) | ||
74 | scpconn = self._internal_run(cmd) | ||
75 | try: | ||
76 | self._out = scpconn.communicate()[0] | ||
77 | self._ret = scpconn.poll() | ||
78 | if self._ret != 0: | ||
79 | self.log("%s" % self._out) | ||
80 | raise Exception("Error copying file") | ||
81 | except Exception as e: | ||
82 | print("Execution failed: %s :" % cmd) | ||
83 | print e | ||
84 | self.log("%s" % self._out) | ||
85 | return (self._ret, self._out) | ||
86 | |||
87 | def copy_to(self, localpath, remotepath): | ||
88 | actualcmd = "scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no %s root@%s:%s" % (localpath, self.host, remotepath) | ||
89 | return self._internal_scp(actualcmd) | ||
90 | |||
91 | |||
92 | def copy_from(self, remotepath, localpath): | ||
93 | actualcmd = "scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@%s:%s %s" % (self.host, remotepath, localpath) | ||
94 | return self._internal_scp(actualcmd) | ||
95 | |||
96 | def get_status(self): | ||
97 | return self._ret | ||
98 | |||
99 | def get_output(self): | ||
100 | return self._out | ||