source: fedd/federation/emulab_segment.py @ 06c1dba

compt_changesinfo-ops
Last change on this file since 06c1dba was 06c1dba, checked in by Ted Faber <faber@…>, 12 years ago

Fisrt step to multi-user - checkpoint

  • Property mode set to 100644
File size: 5.2 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            cert=None):
21        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
22        xmlrpc_emulab_segment.__init__(self, boss=boss, 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(pid, eid, tmpdir):
103            return False
104
105        # Put the file into a string to pass to emulab.
106        try:
107            tcl = "".join([ l for l in open(tclfile,"r")])
108        except EnvironmentError, e:
109            self.log.error("Can't read %s: %s" % (tclfile, e))
110            return False
111       
112        # Stage the new configuration
113        if not self.modify_exp(pid, eid, tcl):
114            self.log.error("modify failed")
115            return False
116
117        if not self.swap_exp(pid, eid, 'in'):
118            self.log.error("swap in failed")
119            return False
120        # Everything has gone OK.
121        self.get_mapping(pid,eid)
122        return True
123
124class stop_segment(local_segment, emulab_segment):
125    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
126            cert=None):
127        local_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
128        emulab_segment.__init__(self, boss=boss, cert=cert)
129
130    def __call__(self, parent, user, pid, eid, gid=None, terminate=False):
131        """
132        Stop a sub experiment by calling swapexp on the federant
133        """
134
135        self.log.info("[stop_segment]: Stopping %s" % eid)
136        rv = False
137        try:
138            # Clean out tar files: we've gone over quota in the past
139            self.ssh_cmd("rm -rf /proj/%s/software/%s" % (pid, eid))
140            rv = self.swap_exp(pid, eid, 'out')
141            if terminate:
142                rv = self.terminate_exp(pid, eid)
143        except self.cmd_timeout:
144            rv = False
145        return rv
146
147class info_segment(local_segment, emulab_segment):
148    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
149            cert=None):
150        local_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
151        emulab_segment.__init__(self, boss=boss, cert=cert)
152
153    def __call__(self, parent, user, pid, eid):
154        self.log.info("[info_segment]: Getting info from %s" % eid)
155        self.get_mapping(pid,eid)
156        return True
157
158class operation_segment(local_segment, emulab_segment):
159    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
160            cert=None):
161        local_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
162        emulab_segment.__init__(self, boss=boss, cert=cert)
163
164    def __call__(self, parent, op, targets, param, top):
165        for l, p in targets.items():
166            self.log.info("[operation_segment]: Calling op %s on %s(%s)" % \
167                    (op, l,p))
168            self.do_operation(op, l, p, param, top)
169        return True
Note: See TracBrowser for help on using the repository browser.