source: fedd/federation/ssh_emulab_segment.py @ 8fbef04

Last change on this file since 8fbef04 was 8fbef04, checked in by Ted Faber <faber@…>, 5 years ago

Shared NAT integrated

  • Property mode set to 100644
File size: 3.5 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 ssh_emulab_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.ssh_emulab_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 = ssh_emulab_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 scp_file_from(self, file, user, host, dest=""):
62        """
63        scp a file to the remote host.  If debug is set the action is only
64        logged.
65        """
66
67        scp_cmd = [self.scp_exec, '-o', 'IdentitiesOnly yes',
68                '-o', 'StrictHostKeyChecking no', '-o', 'ForwardX11 no','-i',
69                self.ssh_privkey_file, "%s@%s:%s" % (user, host, file), dest]
70        rv = 0
71
72        try:
73            dnull = open("/dev/null", "w")
74        except EnvironmentError:
75            self.log.debug("[ssh_file]: failed to open " + \
76                    "/dev/null for redirect")
77            dnull = Null
78
79        self.log.debug("[scp_file]: %s" % " ".join(scp_cmd))
80        if not self.debug:
81            rv = subprocess.call(scp_cmd, stdout=dnull,
82                    stderr=dnull, close_fds=True)
83
84        return rv == 0
85
86    def ssh_cmd(self, user, host, cmd, wname=None, timeout=None):
87        """
88        Run a remote command on host as user.  If debug is set, the action
89        is only logged.  Commands are run without stdin, to avoid stray
90        SIGTTINs.
91        """
92        sh_str = ("%s -n -o 'IdentitiesOnly yes' -o " + \
93                "'StrictHostKeyChecking no' -o 'ForwardX11 no' " +
94                "-i %s %s@%s %s") % \
95                (self.ssh_exec, self.ssh_privkey_file, 
96                        user, host, cmd)
97
98        try:
99            dnull = open("/dev/null", "w")
100        except EnvironmentError:
101            self.log.debug("[ssh_cmd]: failed to open /dev/null " + \
102                    "for redirect")
103            dnull = Null
104
105        self.log.debug("[ssh_cmd]: %s" % sh_str)
106        if not self.debug:
107            if dnull:
108                sub = subprocess.Popen(sh_str, shell=True, stdout=dnull,
109                        stderr=dnull, close_fds=True)
110            else:
111                sub = subprocess.Popen(sh_str, shell=True, close_fds=True)
112            if timeout:
113                i = 0
114                rv = sub.poll()
115                while i < timeout:
116                    if rv is not None: break
117                    else:
118                        time.sleep(1)
119                        rv = sub.poll()
120                        i += 1
121                else:
122                    self.log.debug("Process exceeded runtime: %s" % sh_str)
123                    os.kill(sub.pid, signal.SIGKILL)
124                    raise self.ssh_cmd_timeout();
125                return rv == 0
126            else:
127                return sub.wait() == 0
128        else:
129            if timeout == 0:
130                self.log.debug("debug timeout raised on %s " % sh_str)
131                raise self.ssh_cmd_timeout()
132            else:
133                return True
134
Note: See TracBrowser for help on using the repository browser.