source: fedd/federation/benito_segment.py @ 6a50b78

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

Initial benito plug in. Fixed bug pickling topdl as well

  • Property mode set to 100644
File size: 6.0 KB
Line 
1#!/usr/local/bin/python
2
3import sys, os
4import re
5import os.path
6
7import tempfile
8import subprocess
9import logging 
10import time
11import signal
12
13import util
14
15from deter import topdl
16
17from ssh_emulab_segment import ssh_emulab_segment
18from xmlrpc_emulab_segment import xmlrpc_emulab_segment
19
20
21class start_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
22    def __init__(self, log=None, keyfile=None, debug=False, boss=None,
23            ops=None, cert=None):
24        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
25        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
26        self.start_mixed = '/share/benito/start_mixed %s %s %s'
27        self.start_qemu =  '/share/benito/start_qemu %s %s %s'
28
29    def get_mapping(self, pid, eid):
30        """
31        Benito's info reporting is not sufficient to support this yet
32        """
33        pass
34
35    def set_up_experiment_filespace(self, user, host, pid, eid, tmpdir):
36        """
37        Send all the software and configuration files into the experiment's
38        file space.  To reduce the number of ssh connections, we script many
39        changes and execute the script.
40        """
41        # Configuration directories on the remote machine
42        proj_dir = "/proj/%s/exp/%s/tmp" % (pid, eid)
43        softdir = "/proj/%s/software/%s" % (pid, eid)
44        # Local software dir
45        lsoftdir = "%s/software" % tmpdir
46
47        # Open up a temporary file to contain a script for setting up the
48        # filespace for the new experiment.
49        self.log.info("[start_segment]: creating script file")
50        try:
51            sf, scriptname = tempfile.mkstemp()
52            scriptfile = os.fdopen(sf, 'w')
53        except EnvironmentError:
54            return False
55
56        scriptbase = os.path.basename(scriptname)
57
58        # Script the filesystem changes
59        print >>scriptfile, "/bin/rm -rf %s" % proj_dir
60        # Clear and create the software directory
61        print >>scriptfile, "/bin/rm -rf %s/*" % softdir
62        print >>scriptfile, 'mkdir -p %s' % proj_dir
63        if os.path.isdir(lsoftdir):
64            print >>scriptfile, 'mkdir -p %s' % softdir
65        print >>scriptfile, "rm -f %s" % scriptbase
66        scriptfile.close()
67
68        # Move the script to the remote machine
69        # XXX: could collide tempfile names on the remote host
70        if self.scp_file(scriptname, user, host, scriptbase):
71            os.remove(scriptname)
72        else:
73            return False
74
75        # Execute the script (and the script's last line deletes it)
76        if not self.ssh_cmd(user, host, "sh -x %s" % scriptbase):
77            return False
78
79        for f in os.listdir(tmpdir):
80            if not os.path.isdir("%s/%s" % (tmpdir, f)):
81                if not self.scp_file("%s/%s" % (tmpdir, f), user, host,
82                        "%s/%s" % (proj_dir, f)):
83                    return False
84        if os.path.isdir(lsoftdir):
85            for f in os.listdir(lsoftdir):
86                if not os.path.isdir("%s/%s" % (lsoftdir, f)):
87                    if not self.scp_file("%s/%s" % (lsoftdir, f), 
88                            user, host, "%s/%s" % (softdir, f)):
89                        return False
90        return True
91
92
93    def __call__(self, parent, eid, pid, user, tclfile, tmpdir, timeout=0, 
94            gid=None):
95        """
96        Start a sub-experiment on a federant.
97
98        Get the current state, and terminate the experiment if it exists. The
99        group membership of the experiment is difficult to determine or change,
100        so start with a clean slate.  Create a new one and ship data
101        and configs and start the experiment.  There are small ordering
102        differences based on the initial state of the sub-experiment.
103        """
104
105        # benito listens to the filename extension.  tclfile here is really
106        # topdl, but we'll move it to a different filename.
107        if tclfile.endswith('.tcl'):
108            topdlfile = os.path.join(tmpdir, 'experiment.xml')
109            os.rename(tclfile, topdlfile)
110        else:
111            topdlfile = tclfile
112
113
114        state = self.get_state(pid, eid)
115
116        if state != 'none':
117            self.terminate_exp(pid, eid)
118
119        top = topdl.topology_from_xml(filename=topdlfile, top='experiment')
120        embedded = False
121        for e in top.elements:
122            if isinstance(e, topdl.Computer) and \
123                    e.get_attribute('partition') is not None:
124                embedded = True
125                break
126        # on the for
127        else:
128            embedded = False
129
130        if embedded:
131            cmd = self.start_mixed  %  (pid, eid, topdlfile)
132        else:
133            cmd = self.start_qemu % (pid, eid, topdlfile, 20)
134
135        if not self.ssh_cmd(user, self.ops, cmd):
136            self.log.error("Cannot create benito experiment")
137            return False
138
139        if not self.swap_exp(pid, eid, 'in'):
140            self.log.error("swap in failed")
141            return False
142        # Everything has gone OK.
143        self.get_mapping(pid,eid)
144        return True
145
146class stop_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
147    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
148            ops=None, cert=None):
149        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
150        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
151
152    def __call__(self, parent, user, pid, eid, gid=None, terminate=False):
153        """
154        Stop a sub experiment by calling swapexp on the federant
155        """
156
157        self.log.info("[stop_segment]: Stopping %s" % eid)
158        rv = False
159        try:
160            # Clean out tar files: we've gone over quota in the past
161            self.ssh_cmd(user, self.ops, 
162                    "rm -rf /proj/%s/software/%s" % (pid, eid))
163            rv = self.swap_exp(pid, eid, 'out')
164            if terminate:
165                rv = self.terminate_exp(pid, eid)
166        except self.cmd_timeout:
167            rv = False
168        return rv
169
170class info_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
171    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
172            ops=None, cert=None):
173        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
174        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
175
176    def get_mapping(self, pid, eid):
177        """
178        Benito's info reporting is not sufficient to support this yet
179        """
180        pass
181
182    def __call__(self, parent, user, pid, eid):
183        self.log.info("[info_segment]: Getting info from %s" % eid)
184        self.get_mapping(pid,eid)
185        return True
186
187class operation_segment(ssh_emulab_segment, xmlrpc_emulab_segment):
188    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
189            ops=None, cert=None):
190        ssh_emulab_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
191        xmlrpc_emulab_segment.__init__(self, boss=boss, ops=ops, cert=cert)
192
193    def __call__(self, parent, op, targets, param, top):
194        self.status.append('operations not yet supported')
195        return True
Note: See TracBrowser for help on using the repository browser.