source: fedd/federation/emulab_segment.py @ 9a256f7

compt_changes
Last change on this file since 9a256f7 was 9a256f7, checked in by Ted Faber <faber@…>, 12 years ago

More neighborly permissions

  • Property mode set to 100644
File size: 5.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
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, 'chmod 0770 %s' % softdir
55        print >>scriptfile, "rm -f %s" % scriptbase
56        scriptfile.close()
57
58        # Move the script to the remote machine
59        # XXX: could collide tempfile names on the remote host
60        if self.scp_file(scriptname, user, host, scriptbase):
61            os.remove(scriptname)
62        else:
63            return False
64
65        # Execute the script (and the script's last line deletes it)
66        if not self.ssh_cmd(user, host, "sh -x %s" % scriptbase):
67            return False
68
69        for f in os.listdir(tmpdir):
70            if not os.path.isdir("%s/%s" % (tmpdir, f)):
71                if not self.scp_file("%s/%s" % (tmpdir, f), user, host,
72                        "%s/%s" % (proj_dir, f)):
73                    return False
74        if os.path.isdir(lsoftdir):
75            for f in os.listdir(lsoftdir):
76                if not os.path.isdir("%s/%s" % (lsoftdir, f)):
77                    if not self.scp_file("%s/%s" % (lsoftdir, f), 
78                            user, host, "%s/%s" % (softdir, f)):
79                        return False
80        return True
81
82
83    def __call__(self, parent, eid, pid, user, tclfile, tmpdir, timeout=0, 
84            gid=None):
85        """
86        Start a sub-experiment on a federant.
87
88        Get the current state, and terminate the experiment if it exists. The
89        group membership of the experiment is difficult to determine or change,
90        so start with a clean slate.  Create a new one and ship data
91        and configs and start the experiment.  There are small ordering
92        differences based on the initial state of the sub-experiment.
93        """
94
95        state = self.get_state(pid, eid)
96
97        if state != 'none':
98            self.terminate_exp(pid, eid)
99
100        if not self.make_null_experiment(pid, eid, tmpdir, gid):
101            return False
102
103        if not self.set_up_experiment_filespace(user, self.ops, 
104                pid, eid, tmpdir):
105            return False
106
107        # Put the file into a string to pass to emulab.
108        try:
109            tcl = "".join([ l for l in open(tclfile,"r")])
110        except EnvironmentError, e:
111            self.log.error("Can't read %s: %s" % (tclfile, e))
112            return False
113       
114        # Stage the new configuration
115        if not self.modify_exp(pid, eid, tcl):
116            self.log.error("modify failed")
117            return False
118
119        if not self.swap_exp(pid, eid, 'in'):
120            self.log.error("swap in failed")
121            return False
122        # Everything has gone OK.
123        self.get_mapping(pid,eid)
124        return True
125
126class stop_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
127    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
128            ops=None, cert=None):
129        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
130        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
131
132    def __call__(self, parent, user, pid, eid, gid=None, terminate=False):
133        """
134        Stop a sub experiment by calling swapexp on the federant
135        """
136
137        self.log.info("[stop_segment]: Stopping %s" % eid)
138        rv = False
139        try:
140            # Clean out tar files: we've gone over quota in the past
141            self.ssh_cmd(user, self.ops, 
142                    "rm -rf /proj/%s/software/%s" % (pid, eid))
143            rv = self.swap_exp(pid, eid, 'out')
144            if terminate:
145                rv = self.terminate_exp(pid, eid)
146        except self.cmd_timeout:
147            rv = False
148        return rv
149
150class info_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
151    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
152            ops=None, cert=None):
153        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
154        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
155
156    def __call__(self, parent, user, pid, eid):
157        self.log.info("[info_segment]: Getting info from %s" % eid)
158        self.get_mapping(pid,eid)
159        return True
160
161class operation_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
162    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
163            ops=None, cert=None):
164        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
165        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
166
167    def __call__(self, parent, op, targets, param, top):
168        for l, p in targets.items():
169            self.log.info("[operation_segment]: Calling op %s on %s(%s)" % \
170                    (op, l,p))
171            self.do_operation(op, l, p, param, top)
172        return True
Note: See TracBrowser for help on using the repository browser.