source: fedd/federation/ns2topdl.py @ 2c16731

Last change on this file since 2c16731 was de059e1, checked in by Ted Faber <faber@…>, 12 years ago

Chdir when doing an ns2topdl using the local tcl

  • Property mode set to 100644
File size: 5.2 KB
RevLine 
[4700b3b]1#!/usr/local/bin/python
2
3import os,sys
4import subprocess
5import tempfile
[c971895]6import logging
[6bedbdba]7from deter import topdl
[4700b3b]8
[8cb269a]9import os.path
10
[ec4fb42]11from util import *
[6bedbdba]12from deter import fedid
[9460b1e]13from remote_service import xmlrpc_handler, soap_handler
[4700b3b]14from service_error import *
[454f398]15from authorizer import authorizer, abac_authorizer
[4700b3b]16
17
18class nullHandler(logging.Handler):
19    def emit(self, record): pass
20
[2c6128f]21fl = logging.getLogger("fedd.splitter")
[4700b3b]22fl.addHandler(nullHandler())
23
[5f6929a]24class ns2topdl_local:
[3f6bc5f]25    def __init__(self, config=None, auth=None):
[4700b3b]26        """
27        Intialize the various attributes, most from the config object
28        """
[5f6929a]29        self.debug = config.getboolean("ns2topdl", "debug")
30        self.muxmax = config.getint("ns2topdl", "muxmax", 3)
31        self.tclsh = config.get("ns2topdl", "tclsh", 
[05191a6]32                "/usr/local/bin/otclsh")
[5f6929a]33        self.tcl_splitter = config.get("ns2topdl", "tcl_splitter",
[05191a6]34                "/usr/testbed/lib/ns2ir/parse.tcl")
[454f398]35        self.auth_type = config.get('ns2topdl', 'auth_type') or 'legacy'
[5f6929a]36        access_db = config.get("ns2topdl", "accessdb", None)
[454f398]37        self.allow_any = config.getboolean("ns2topdl", "allow_any", False)
38        auth_dir = config.get('ns2topdl', 'auth_dir')
[f4f4117]39
[5f6929a]40        self.log = logging.getLogger("fedd.ns2topdl")
41        set_log_level(config, "ns2topdl", self.log)
[4700b3b]42        self.trace_file = sys.stderr
43
[5f6929a]44        set_log_level(config, "ns2topdl", self.log)
[05191a6]45
46        if auth:
47            self.auth= auth
48        else:
49            self.auth = authorizer()
[5f6929a]50            self.log.warning("[ns2topdl] No authorizer passed in, " +\
[05191a6]51                    "using local one")
52
[454f398]53
54        if self.auth_type == 'legacy':
55            if access_db and self.allow_any: 
56                raise service_error(service_error.internal, 
57                        "Cannot specify both an access database and " + 
58                        "allow_any for ns2topdl")
59           
60            if access_db:
61                try:
62                    read_simple_accessdb(access_db, self.auth, 'ns2topdl')
63                except EnvironmentError, e:
64                    raise service_error(service_error.internal,
65                            "Error reading accessDB %s: %s" % (access_db, e))
66                except ValueError:
67                    raise service_error(service_error.internal, "%s" % e)
68            elif self.allow_any:
69                auth.set_global_attribute("ns2topdl")
70        elif self.auth_type == 'abac':
71            self.auth = abac_authorizer(load=auth_dir)
72        else:
[05191a6]73            raise service_error(service_error.internal, 
[454f398]74                    "Unknown auth_type: %s" % self.auth_type)
[05191a6]75
76
[4700b3b]77        # Dispatch tables
78        self.soap_services = {\
[5f6929a]79                'Ns2Topdl': soap_handler("Ns2Topdl", self.run_ns2topdl),
[4700b3b]80        }
81
82        self.xmlrpc_services = {\
[5f6929a]83                'Ns2Topdl': xmlrpc_handler('Ns2Topdl', self.run_ns2topdl),
[4700b3b]84        }
85
[5f6929a]86    def run_ns2topdl(self, req, fid):
[4700b3b]87        """
[5f6929a]88        The external interface to tcl to topdl translation.
[4700b3b]89
[5f6929a]90        Creates a working directory, translates the incoming description using
91        the tcl script.
[4700b3b]92        """
[05191a6]93
[454f398]94        if self.allow_any:
95            self.auth.set_attribute(fid, 'ns2topdl')
96
97        access_ok, proof = self.auth.check_attribute(fid, 'ns2topdl',
98            with_proof=True)
99
100        if not access_ok:
101            raise service_error(service_error.access, "Access Denied", 
102                proof=proof)
[05191a6]103
[4700b3b]104        try:
[5f6929a]105            tmpdir = tempfile.mkdtemp(prefix="ns2topdl-")
[d3c8759]106        except EnvironmentError:
[4700b3b]107            raise service_error(service_error.internal, "Cannot create tmp dir")
108
[8cb269a]109        tclfile = os.path.join(tmpdir, "experiment.tcl")
110        # save error output in case the parse fails.
111        errfile = os.path.join(tmpdir, "errfile")
[4700b3b]112        pid = "dummy"
113        gid = "dummy"
[f4f4117]114        eid = "dummy"
[5f6929a]115        master = "dummy"
[4700b3b]116
[5f6929a]117        req = req.get('Ns2TopdlRequestBody', None)
[4700b3b]118        if not req:
119            raise service_error(service_error.req,
[5f6929a]120                    "Bad request format (no Ns2TopdlRequestBody)")
[4700b3b]121        # The tcl parser needs to read a file so put the content into that file
[f4f4117]122        descr=req.get('description', None)
[4700b3b]123        if descr:
124            file_content=descr.get('ns2description', None)
125            if file_content:
126                try:
127                    f = open(tclfile, 'w')
128                    f.write(file_content)
129                    f.close()
[8cb269a]130                    ef = open(errfile, 'w')
[d3c8759]131                except EnvironmentError:
[4700b3b]132                    raise service_error(service_error.internal,
133                            "Cannot write temp experiment description")
134            else:
135                raise service_error(service_error.req, 
136                        "Only ns2descriptions supported")
137        else:
[f4f4117]138            raise service_error(service_error.req, "No description")
[4700b3b]139
140       
[3159f5d]141        tclcmd = [self.tclsh, self.tcl_splitter, '-t', '-x', 
[2c6128f]142            str(self.muxmax), '-m', master]
143        tclcmd.extend([pid, gid, eid, tclfile])
144        self.log.debug("Calling splitter %s" % " ".join(tclcmd))
[de059e1]145        # This is just fantastic.  As a side effect the parser copies
146        # tb_compat.tcl into the current directory, so that directory
147        # must be writable by the fedd user.  Doing this in the
148        # temporary subdir ensures this is the case.
149        tclparser = subprocess.Popen(tclcmd, stdout=subprocess.PIPE, 
150                stderr=ef, cwd=tmpdir)
[4700b3b]151
[8cb269a]152        try:
153            top = topdl.topology_from_xml(file=tclparser.stdout, 
154                    top="experiment")
155        except:
156            top = None
157
158        if top is None:
159            # There was an ns parsing error, gather up the error from the
160            # errfile and raise a service_error containing the error text
161            try:
162                ef = open(errfile, 'r')
163                parse_err = ef.read()
164                ef.close()
165            except EnvironmentError:
166                raise service_error(service_error.internal,
167                        "Cannot read error string")
168
169            raise service_error(service_error.req, 
170                    "Cannot parse ns file: %s" % parse_err)
[4700b3b]171
172        # Walk up tmpdir, deleting as we go
173        for path, dirs, files in os.walk(tmpdir, topdown=False):
174            for f in files:
175                os.remove(os.path.join(path, f))
176            for d in dirs:
177                os.rmdir(os.path.join(path, d))
178        os.rmdir(tmpdir)
179
[3159f5d]180        resp = { 
181                'experimentdescription':  { 
182                    'topdldescription': top.to_dict(),
[454f398]183                    },
184                'proof': proof.to_dict(),
[3159f5d]185                }
[4700b3b]186
187        return resp
188
189
Note: See TracBrowser for help on using the repository browser.