source: fedd/federation/emulab_segment.py @ d4946da

Last change on this file since d4946da was d4946da, checked in by Tom Carroll <thomas.carroll@…>, 8 years ago

Fixed permission problem when creating directory hierarchies.

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