source: fedd/federation/ssh_emulab_segment.py @ b745876

compt_changes
Last change on this file since b745876 was c7141dc, checked in by Ted Faber <faber@…>, 13 years ago

Single access works

  • Property mode set to 100644
File size: 2.9 KB
RevLine 
[37776ea]1#!/usr/local/bin/python
2
3import sys, os
4import re
5
6import tempfile
7import subprocess
8import logging 
9import time
10import signal
11
12from service_error import service_error
13
[06c1dba]14class ssh_emulab_segment:
[5bf359d]15    """
16    Base class for segment starter classes that access their underlying testebd
17    remotely using ssh.  It is promarily a code repository for commonly used
18    ssh commands for moving code and logging in.
19    """
[37776ea]20    class ssh_cmd_timeout(RuntimeError): pass
21
22    def __init__(self, log=None, keyfile=None, debug=False):
[5bf359d]23        """
24        log is the logging.log to print messages to, keyfile is the private key
25        for ssh interactions and if debug is true, commands are not executed
26        using ssh.
27        """
[c7141dc]28        self.log = log or logging.getLogger('fedd.access.ssh_emulab_segment')
[37776ea]29        self.ssh_privkey_file = keyfile
30        self.debug = debug
31        self.ssh_exec="/usr/bin/ssh"
32        self.scp_exec = "/usr/bin/scp"
[c7141dc]33        self.ssh_cmd_timeout = ssh_emulab_segment.ssh_cmd_timeout
[37776ea]34
35    def scp_file(self, file, user, host, dest=""):
36        """
37        scp a file to the remote host.  If debug is set the action is only
38        logged.
39        """
40
41        scp_cmd = [self.scp_exec, '-o', 'IdentitiesOnly yes', 
[e777dab]42                '-o', 'StrictHostKeyChecking no', '-o', 'ForwardX11 no','-i', 
[37776ea]43                self.ssh_privkey_file, file, 
44                "%s@%s:%s" % (user, host, dest)]
45        rv = 0
46
47        try:
48            dnull = open("/dev/null", "w")
[d3c8759]49        except EnvironmentError:
[37776ea]50            self.log.debug("[ssh_file]: failed to open " + \
51                    "/dev/null for redirect")
52            dnull = Null
53
54        self.log.debug("[scp_file]: %s" % " ".join(scp_cmd))
55        if not self.debug:
56            rv = subprocess.call(scp_cmd, stdout=dnull, 
57                    stderr=dnull, close_fds=True)
58
59        return rv == 0
60
61    def ssh_cmd(self, user, host, cmd, wname=None, timeout=None):
62        """
63        Run a remote command on host as user.  If debug is set, the action
64        is only logged.  Commands are run without stdin, to avoid stray
65        SIGTTINs.
66        """
67        sh_str = ("%s -n -o 'IdentitiesOnly yes' -o " + \
[e777dab]68                "'StrictHostKeyChecking no' -o 'ForwardX11 no' " +
69                "-i %s %s@%s %s") % \
[37776ea]70                (self.ssh_exec, self.ssh_privkey_file, 
71                        user, host, cmd)
72
73        try:
74            dnull = open("/dev/null", "w")
[d3c8759]75        except EnvironmentError:
[37776ea]76            self.log.debug("[ssh_cmd]: failed to open /dev/null " + \
77                    "for redirect")
78            dnull = Null
79
80        self.log.debug("[ssh_cmd]: %s" % sh_str)
81        if not self.debug:
82            if dnull:
83                sub = subprocess.Popen(sh_str, shell=True, stdout=dnull,
84                        stderr=dnull, close_fds=True)
85            else:
86                sub = subprocess.Popen(sh_str, shell=True, close_fds=True)
87            if timeout:
88                i = 0
89                rv = sub.poll()
90                while i < timeout:
91                    if rv is not None: break
92                    else:
93                        time.sleep(1)
94                        rv = sub.poll()
95                        i += 1
96                else:
97                    self.log.debug("Process exceeded runtime: %s" % sh_str)
98                    os.kill(sub.pid, signal.SIGKILL)
99                    raise self.ssh_cmd_timeout();
100                return rv == 0
101            else:
102                return sub.wait() == 0
103        else:
104            if timeout == 0:
105                self.log.debug("debug timeout raised on %s " % sh_str)
106                raise self.ssh_cmd_timeout()
107            else:
108                return True
109
Note: See TracBrowser for help on using the repository browser.