source: fedd/federation/emulab_segment.py @ a11eda5

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

Single access works

  • Property mode set to 100644
File size: 5.4 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
12import util
13
14from ssh_emulab_segment import ssh_emulab_segment
15from xmlrpc_emulab_segment import xmlrpc_emulab_segment
16
17
18class start_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
19    def __init__(self, log=None, keyfile=None, debug=False, boss=None,
20            ops=None, cert=None):
21        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
22        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
23
24    def set_up_experiment_filespace(self, user, host, pid, eid, tmpdir):
25        """
26        Send all the software and configuration files into the experiment's
27        file space.  To reduce the number of ssh connections, we script many
28        changes and execute the script.
29        """
30        # Configuration directories on the remote machine
31        proj_dir = "/proj/%s/exp/%s/tmp" % (pid, eid)
32        softdir = "/proj/%s/software/%s" % (pid, eid)
33        # Local software dir
34        lsoftdir = "%s/software" % tmpdir
35
36        # Open up a temporary file to contain a script for setting up the
37        # filespace for the new experiment.
38        self.log.info("[start_segment]: creating script file")
39        try:
40            sf, scriptname = tempfile.mkstemp()
41            scriptfile = os.fdopen(sf, 'w')
42        except EnvironmentError:
43            return False
44
45        scriptbase = os.path.basename(scriptname)
46
47        # Script the filesystem changes
48        print >>scriptfile, "/bin/rm -rf %s" % proj_dir
49        # Clear and create the software directory
50        print >>scriptfile, "/bin/rm -rf %s/*" % softdir
51        print >>scriptfile, 'mkdir -p %s' % proj_dir
52        if os.path.isdir(lsoftdir):
53            print >>scriptfile, 'mkdir -p %s' % softdir
54        print >>scriptfile, "rm -f %s" % scriptbase
55        scriptfile.close()
56
57        # Move the script to the remote machine
58        # XXX: could collide tempfile names on the remote host
59        if self.scp_file(scriptname, user, host, scriptbase):
60            os.remove(scriptname)
61        else:
62            return False
63
64        # Execute the script (and the script's last line deletes it)
65        if not self.ssh_cmd(user, host, "sh -x %s" % scriptbase):
66            return False
67
68        for f in os.listdir(tmpdir):
69            if not os.path.isdir("%s/%s" % (tmpdir, f)):
70                if not self.scp_file("%s/%s" % (tmpdir, f), user, host,
71                        "%s/%s" % (proj_dir, f)):
72                    return False
73        if os.path.isdir(lsoftdir):
74            for f in os.listdir(lsoftdir):
75                if not os.path.isdir("%s/%s" % (lsoftdir, f)):
76                    if not self.scp_file("%s/%s" % (lsoftdir, f), 
77                            user, host, "%s/%s" % (softdir, f)):
78                        return False
79        return True
80
81
82    def __call__(self, parent, eid, pid, user, tclfile, tmpdir, timeout=0, 
83            gid=None):
84        """
85        Start a sub-experiment on a federant.
86
87        Get the current state, and terminate the experiment if it exists. The
88        group membership of the experiment is difficult to determine or change,
89        so start with a clean slate.  Create a new one and ship data
90        and configs and start the experiment.  There are small ordering
91        differences based on the initial state of the sub-experiment.
92        """
93
94        state = self.get_state(pid, eid)
95
96        if state != 'none':
97            self.terminate_exp(pid, eid)
98
99        if not self.make_null_experiment(pid, eid, tmpdir, gid):
100            return False
101
102        if not self.set_up_experiment_filespace(user, self.ops, 
103                pid, eid, tmpdir):
104            return False
105
106        # Put the file into a string to pass to emulab.
107        try:
108            tcl = "".join([ l for l in open(tclfile,"r")])
109        except EnvironmentError, e:
110            self.log.error("Can't read %s: %s" % (tclfile, e))
111            return False
112       
113        # Stage the new configuration
114        if not self.modify_exp(pid, eid, tcl):
115            self.log.error("modify failed")
116            return False
117
118        if not self.swap_exp(pid, eid, 'in'):
119            self.log.error("swap in failed")
120            return False
121        # Everything has gone OK.
122        self.get_mapping(pid,eid)
123        return True
124
125class stop_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
126    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
127            ops=None, cert=None):
128        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
129        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
130
131    def __call__(self, parent, user, pid, eid, gid=None, terminate=False):
132        """
133        Stop a sub experiment by calling swapexp on the federant
134        """
135
136        self.log.info("[stop_segment]: Stopping %s" % eid)
137        rv = False
138        try:
139            # Clean out tar files: we've gone over quota in the past
140            self.ssh_cmd(user, self.ops, 
141                    "rm -rf /proj/%s/software/%s" % (pid, eid))
142            rv = self.swap_exp(pid, eid, 'out')
143            if terminate:
144                rv = self.terminate_exp(pid, eid)
145        except self.cmd_timeout:
146            rv = False
147        return rv
148
149class info_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
150    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
151            ops=None, cert=None):
152        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
153        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
154
155    def __call__(self, parent, user, pid, eid):
156        self.log.info("[info_segment]: Getting info from %s" % eid)
157        self.get_mapping(pid,eid)
158        return True
159
160class operation_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
161    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
162            ops=None, cert=None):
163        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
164        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
165
166    def __call__(self, parent, op, targets, param, top):
167        for l, p in targets.items():
168            self.log.info("[operation_segment]: Calling op %s on %s(%s)" % \
169                    (op, l,p))
170            self.do_operation(op, l, p, param, top)
171        return True
Note: See TracBrowser for help on using the repository browser.