#!/usr/local/bin/python import os,sys import subprocess import tempfile import logging from util import * from fedid import fedid from remote_service import xmlrpc_handler, soap_handler from service_error import * from authorizer import authorizer class nullHandler(logging.Handler): def emit(self, record): pass fl = logging.getLogger("fedd.splitter") fl.addHandler(nullHandler()) class split_local: def __init__(self, config=None, auth=None): """ Intialize the various attributes, most from the config object """ self.debug = config.getboolean("splitter", "debug") self.muxmax = config.getint("splitter", "muxmax", 3) self.tclsh = config.get("splitter", "tclsh", "/usr/local/bin/otclsh") self.tcl_splitter = config.get("splitter", "tcl_splitter", "/usr/testbed/lib/ns2ir/parse.tcl") access_db = config.get("splitter", "access_db", None) allow_any = config.getboolean("splitter", "allow_any", False) self.log = logging.getLogger("fedd.splitter") set_log_level(config, "splitter", self.log) self.trace_file = sys.stderr set_log_level(config, "splitter", self.log) if auth: self.auth= auth else: self.auth = authorizer() self.log.warning("[splitter] No authorizer passed in, " +\ "using local one") if access_db and allow_any: raise service_error(service_error.internal, "Cannot specify both an access database and allow_any " +\ "for splitter") if access_db: try: read_simple_accessdb(access_db, self.auth, 'split') except IOError, e: raise service_error(service_error.internal, "Error reading accessDB %s: %s" % (access_db, e)) except ValueError: raise service_error(service_error.internal, "%s" % e) elif allow_any: auth.set_global_attribute("split") # Dispatch tables self.soap_services = {\ 'Ns2Split': soap_handler("Ns2Split", self.run_splitter), } self.xmlrpc_services = {\ 'Ns2Split': xmlrpc_handler('Ns2Split', self.run_splitter), } def run_splitter(self, req, fid): """ The external interface to experiment creation called from the dispatcher. Creates a working directory, splits the incoming description using the splitter script and parses out the avrious subsections using the lcasses above. Once each sub-experiment is created, use pooled threads to instantiate them and start it all up. """ if not self.auth.check_attribute(fid, 'split'): raise service_error(service_error.access, "Access Denied") try: tmpdir = tempfile.mkdtemp(prefix="split-") except IOError: raise service_error(service_error.internal, "Cannot create tmp dir") tclfile = tmpdir + "/experiment.tcl" pid = "dummy" gid = "dummy" eid = "dummy" req = req.get('Ns2SplitRequestBody', None) if not req: raise service_error(service_error.req, "Bad request format (no Ns2SplitRequestBody)") # The tcl parser needs to read a file so put the content into that file descr=req.get('description', None) if descr: file_content=descr.get('ns2description', None) if file_content: try: f = open(tclfile, 'w') f.write(file_content) f.close() except IOError: raise service_error(service_error.internal, "Cannot write temp experiment description") else: raise service_error(service_error.req, "Only ns2descriptions supported") else: raise service_error(service_error.req, "No description") master = req.get('master', None) if master == None: raise service_error(service_error.req, "No master testbed label") include_fedkit = req.get('include_fedkit', None) if include_fedkit == None: raise service_error(service_error.req, "No federation kit inclusion directive") tclcmd = [self.tclsh, self.tcl_splitter, '-s', '-x', str(self.muxmax), '-m', master] if include_fedkit: tclcmd.append('-k') tclcmd.extend([pid, gid, eid, tclfile]) self.log.debug("Calling splitter %s" % " ".join(tclcmd)) tclparser = subprocess.Popen(tclcmd, stdout=subprocess.PIPE) out = "" # Package up the split data for line in tclparser.stdout: out += line # Walk up tmpdir, deleting as we go for path, dirs, files in os.walk(tmpdir, topdown=False): for f in files: os.remove(os.path.join(path, f)) for d in dirs: os.rmdir(os.path.join(path, d)) os.rmdir(tmpdir) resp = { 'output' : out } return resp