source: fedd/federation/proxy_segment.py @ e91c492

axis_examplecompt_changesinfo-opsversion-3.01version-3.02
Last change on this file since e91c492 was 5bf359d, checked in by Ted Faber <faber@…>, 15 years ago

More refactoring. Neaten up the code for creating segments in emulab and make the local and proxy class structures parallel. The code is more readable this way, I hope.

  • Property mode set to 100644
File size: 2.9 KB
Line 
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
14class proxy_segment:
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    """
20    class ssh_cmd_timeout(RuntimeError): pass
21
22    def __init__(self, log=None, keyfile=None, debug=False):
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        """
28        self.log = log or logging.getLogger('fedd.access.proxy_segment')
29        self.ssh_privkey_file = keyfile
30        self.debug = debug
31        self.ssh_exec="/usr/bin/ssh"
32        self.scp_exec = "/usr/bin/scp"
33        self.ssh_cmd_timeout = proxy_segment.ssh_cmd_timeout
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', 
42                '-o', 'StrictHostKeyChecking no', '-o', 'ForwardX11 no','-i', 
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")
49        except EnvironmentError:
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 " + \
68                "'StrictHostKeyChecking no' -o 'ForwardX11 no' " +
69                "-i %s %s@%s %s") % \
70                (self.ssh_exec, self.ssh_privkey_file, 
71                        user, host, cmd)
72
73        try:
74            dnull = open("/dev/null", "w")
75        except EnvironmentError:
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.