Index: fedd/fedd.py
===================================================================
--- fedd/fedd.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
+++ fedd/fedd.py	(revision f4f4117545ada5ee8f261126922327b95a54f83b)
@@ -16,4 +16,5 @@
 from fedd_util import fedd_ssl_context, fedid
 from fedd_deter_impl import new_feddservice
+from fedd_services import ns0
 from service_error import *
 
@@ -35,4 +36,12 @@
     A SafeConfig parser with a more forgiving get attribute
     """
+
+    def safe_get(self, sect, opt, method, default=None):
+	"""
+	If the option is present, return it, otherwise the default.
+	"""
+	if self.has_option(sect, opt): return method(self, sect, opt)
+	else: return default
+
     def get(self, sect, opt, default=None):
 	"""
@@ -41,8 +50,27 @@
 	It's more like getattr than get.
 	"""
-	if self.has_option(sect, opt):
-	    return SafeConfigParser.get(self, sect, opt)
-	else:
-	    return default
+
+	return self.safe_get(sect, opt, SafeConfigParser.get, default)
+
+    def getint(self, sect, opt, default=0):
+	"""
+	Returns the selected option as an int or a default.
+	"""
+
+	return self.safe_get(sect, opt, SafeConfigParser.getint, default)
+
+    def getfloat(self, sect, opt, default=0.0):
+	"""
+	Returns the selected option as an int or a default.
+	"""
+
+	return self.safe_get(sect, opt, SafeConfigParser.getfloat, default)
+
+    def getboolean(self, sect, opt, default=False):
+	"""
+	Returns the selected option as a boolean or a default.
+	"""
+
+	return self.safe_get(sect, opt, SafeConfigParser.getboolean, default)
 
 class fedd_server(ThreadingSSLServer):
Index: fedd/fedd_client.py
===================================================================
--- fedd/fedd_client.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
+++ fedd/fedd_client.py	(revision f4f4117545ada5ee8f261126922327b95a54f83b)
@@ -6,4 +6,5 @@
 
 from fedd_services import *
+from fedd_internal_services import *
 
 from M2Crypto import SSL, X509
@@ -259,4 +260,15 @@
 		    transdict={ 'ssl_context' : context },
 		    tracefile=tracefile)
+	    method_call = getattr(port, self.method, None)
+
+	    if not method_call:
+		loc = feddInternalServiceLocator();
+		port = loc.getfeddInternalPortType(url,
+			transport=M2Crypto.httpslib.HTTPSConnection, 
+			transdict={ 'ssl_context' : context },
+			tracefile=tracefile)
+		method_call = getattr(port, self.method, None)
+		if not method_call:
+		    raise RuntimeError("Can't find method: %s" % self.method)
 
 	    req = self.RequestMessage()
@@ -587,4 +599,77 @@
 		    else: print "%s: %s" % (k, id[k])
 
+class split(fedd_rpc):
+    def __init__(self): 
+	fedd_rpc.__init__(self, "Ns2Split")
+    def __call__(self):
+	access_keys = []
+	# Process the options using the customized option parser defined above
+	parser = fedd_create_opts(access_keys, self.add_ssh_key,
+		self.add_x509_cert)
+
+	(opts, args) = parser.parse_args()
+
+	if opts.trusted != None:
+	    if ( not os.access(opts.trusted, os.R_OK) ) :
+		sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
+	else:
+	    parser.error("--trusted is required")
+
+	if opts.debug > 0: opts.tracefile=sys.stderr
+
+	if opts.cert != None: cert = opts.cert
+
+	if cert == None:
+	    sys.exit("No certificate given (--cert) or found")
+
+	if os.access(cert, os.R_OK):
+	    fid = fedid(file=cert)
+	    if opts.use_fedid == True:
+		user = fid
+	else:
+	    sys.exit("Cannot read certificate (%s)" % cert)
+
+	if opts.file:
+	    exp_desc = ""
+	    try:
+		f = open(opts.file, 'r')
+		for line in f:
+		    exp_desc += line
+		f.close()
+	    except IOError:
+		sys.exit("Cannot read description file (%s)" %opts.file)
+	else:
+	    sys.exit("Must specify an experiment description (--file)")
+
+	if not opts.master:
+	    sys.exit("Must specify a master testbed (--master)")
+
+	out_certfile = opts.out_certfile
+
+	msg = {
+		'description': { 'ns2description': exp_desc },
+		'master': opts.master,
+		}
+
+	if opts.debug > 1: print >>sys.stderr, msg
+
+	try:
+	    resp_dict = self.do_rpc(msg, 
+		    opts.url, opts.transport, cert, opts.trusted, 
+		    serialize_only=opts.serialize_only,
+		    tracefile=opts.tracefile)
+	except self.RPCException, e:
+	    exit_with_fault(\
+		    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
+	except RuntimeError, e:
+	    sys.exit("Error processing RPC: %s" % e)
+
+	if opts.debug > 1: print >>sys.stderr, resp_dict
+
+	out = resp_dict.get('output', None)
+
+	for line in out.splitlines():
+	    print "%s" % line
+
 class access(fedd_rpc):
     def __init__(self):
@@ -702,4 +787,5 @@
 cmds = {\
 	'create': create(),\
+	'split': split(),\
 	'access': access(),\
 	'vtopo': exp_data('Vtopo'),\
Index: fedd/fedd_deter_impl.py
===================================================================
--- fedd/fedd_deter_impl.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
+++ fedd/fedd_deter_impl.py	(revision f4f4117545ada5ee8f261126922327b95a54f83b)
@@ -1,6 +1,7 @@
 #!/usr/local/bin/python
 
-from fedd_access import *
-from fedd_experiment_control import *
+from fedd_access import fedd_access
+from fedd_experiment_control import fedd_experiment_control_local
+from fedd_split import fedd_split_local
 
 class fedd_deter_impl:
@@ -37,4 +38,9 @@
 		self.xmlrpc_services.update(self.experiment.xmlrpc_services) 
 
+	    if config.has_section("splitter"):
+		self.splitter = fedd_split_local(config)
+		self.soap_services.update(self.splitter.soap_services) 
+		self.xmlrpc_services.update(self.splitter.xmlrpc_services) 
+
 def new_feddservice(config):
     return fedd_deter_impl(config)
Index: fedd/fedd_experiment_control.py
===================================================================
--- fedd/fedd_experiment_control.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
+++ fedd/fedd_experiment_control.py	(revision f4f4117545ada5ee8f261126922327b95a54f83b)
@@ -192,8 +192,10 @@
 	    self.scripts_dir = config.get("experiment_control",
 		    "federation_script_dir")
+	    self.splitter_url = config.get("experiment_control", "splitter_url")
 	else:
 	    self.debug = False
 	    self.state_filename = None
 	    self.scripts_dir = "/users/faber/testbed/federation"
+	    self.splitter_url = None
 
 	# XXX
@@ -908,4 +910,47 @@
 		if key:
 		    tbparam[tb][key]= a['value']
+
+    def remote_splitter(self, uri, desc, master):
+
+	req = {
+		'description' : { 'ns2description': desc },
+		'master': master,
+	    }
+
+	# No retry loop here.  Proxy servers must correctly authenticate
+	# themselves without help
+	try:
+	    ctx = fedd_ssl_context(self.cert_file, 
+		    self.trusted_certs, password=self.cert_pwd)
+	except SSL.SSLError:
+	    raise service_error(service_error.server_config, 
+		    "Server certificates misconfigured")
+
+	loc = feddInternalServiceLocator();
+	port = loc.getfeddInternalPortType(uri,
+		transport=M2Crypto.httpslib.HTTPSConnection, 
+		transdict={ 'ssl_context' : ctx })
+
+	# Reconstruct the full request message
+	msg = Ns2SplitRequestMessage()
+	msg.set_element_Ns2SplitRequestBody(
+		pack_soap(msg, "Ns2SplitRequestBody", req))
+
+	try:
+	    resp = port.Ns2Split(msg)
+	except ZSI.ParseException, e:
+	    raise service_error(service_error.req,
+		    "Bad format message (XMLRPC??): %s" %
+		    str(e))
+	r = unpack_soap(resp)
+	if r.has_key('Ns2SplitResponseBody'):
+	    r = r['Ns2SplitResponseBody']
+	    if r.has_key('output'):
+		return r['output'].splitlines()
+	    else:
+		raise service_error(service_error.proxy, 
+			"Bad splitter response (no output)")
+	else:
+	    raise service_error(service_error.proxy, "Bad splitter response")
 	
     class current_testbed:
@@ -1408,8 +1453,12 @@
 	    raise service_error(service_error.req, "No master testbed label")
 	
-	
-	tclcmd = [self.tclsh, self.tcl_splitter, '-s', '-x', 
-	    str(self.muxmax), '-m', master, pid, gid, eid, tclfile]
-	tclparser = Popen(tclcmd, stdout=PIPE)
+	if self.splitter_url:
+	    split_data = self.remote_splitter(self.splitter_url, file_content,
+		    master)
+	else:
+	    tclcmd = [self.tclsh, self.tcl_splitter, '-s', '-x', 
+		str(self.muxmax), '-m', master, pid, gid, eid, tclfile]
+	    tclparser = Popen(tclcmd, stdout=PIPE)
+	    split_data = tclparser.stdout
 
 	allocated = { }	    # Testbeds we can access
@@ -1432,5 +1481,5 @@
 
 	# Worling on the split data
-	for line in tclparser.stdout:
+	for line in split_data:
 	    line = line.rstrip()
 	    if parse_current_testbed(line, master, allocated, tbparams):
Index: fedd/fedd_split.py
===================================================================
--- fedd/fedd_split.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
+++ fedd/fedd_split.py	(revision f4f4117545ada5ee8f261126922327b95a54f83b)
@@ -43,5 +43,11 @@
 	Intialize the various attributes, most from the config object
 	"""
-	self.debug = config.create_debug
+	if config.has_section("splitter"):
+	    self.debug = config.getboolean("splitter", "debug")
+	    self.muxmax = config.getint("splitter", "muxmax", 3)
+	else:
+	    self.debug = False
+	    self.muxmax = 3
+
 	self.log = logging.getLogger("fedd.splitter")
 	self.tclsh = "/usr/local/bin/otclsh"
@@ -82,4 +88,5 @@
 	pid = "dummy"
 	gid = "dummy"
+	eid = "dummy"
 
 	req = req.get('Ns2SplitRequestBody', None)
@@ -88,5 +95,5 @@
 		    "Bad request format (no Ns2SplitRequestBody)")
 	# The tcl parser needs to read a file so put the content into that file
-	descr=req.get('experimentdescription', None)
+	descr=req.get('description', None)
 	if descr:
 	    file_content=descr.get('ns2description', None)
@@ -103,5 +110,5 @@
 			"Only ns2descriptions supported")
 	else:
-	    raise service_error(service_error.req, "No experiment description")
+	    raise service_error(service_error.req, "No description")
 
 	master = req.get('master', None)
@@ -114,4 +121,5 @@
 	tclparser = Popen(tclcmd, stdout=PIPE)
 
+	out = ""
 	# Package up the split data
 	for line in tclparser.stdout:
