Index: fedd/fedd_util.py
===================================================================
--- fedd/fedd_util.py	(revision f8582c9a024862e2f99c61a303029f0c7929d8b3)
+++ fedd/fedd_util.py	(revision c922f23933185172b4e16710ef2d4751c92e6353)
@@ -5,9 +5,15 @@
 import tempfile
 import logging
+import copy
 
 from M2Crypto import SSL, X509, EVP
+from M2Crypto.m2xmlrpclib import SSL_Transport
+import M2Crypto.httpslib
 from pyasn1.codec.der import decoder
 
-from xmlrpclib import Binary
+from fedd_services import *
+from fedd_internal_services import *
+from service_error import *
+from xmlrpclib import ServerProxy, dumps, loads, Fault, Error, Binary
 
 
@@ -413,10 +419,9 @@
 	decap_fedids = (('fedid', lambda x: fedid(bits=x.data)),)
 
-	#p = decapsulate_binaries(params[0], input_binaries)
 	p = apply_to_tags(params[0], decap_fedids)
 	msg = method(p, fid)
 
 	if msg != None:
-	    return encapsulate_binaries({ body_name: msg }, ('fedid',))
+	    return make_unicode(encapsulate_binaries({ body_name: msg }, ('fedid',)))
 	else:
 	    return None
@@ -424,4 +429,88 @@
     return handler
 
+def make_service_callers(service_name, port_name, request_message, 
+	request_body_name):
+
+    def call_xmlrpc_service(self, url, req, cert_file=None, cert_pwd=None, 
+	    trusted_certs=None):
+	"""Send an XMLRPC request.  """
+	decap_fedids = (('fedid', lambda x: fedid(bits=x.data)),)
+
+	# No retry loop here.  Proxy servers must correctly authenticate
+	# themselves without help
+	try:
+	    ctx = fedd_ssl_context(cert_file, trusted_certs, password=cert_pwd)
+	except SSL.SSLError:
+	    raise service_error(service_error.server_config,
+		    "Server certificates misconfigured")
+
+	# Of all the dumbass things.  The XMLRPC library in use here won't
+	# properly encode unicode strings, so we make a copy of req with the
+	# unicode objects converted.  We also convert the url to a basic string
+	# if it isn't one already.
+	r = strip_unicode(copy.deepcopy(req))
+	url = str(url)
+	
+	transport = SSL_Transport(ctx)
+	port = ServerProxy(url, transport=transport)
+	try:
+	    remote_method = getattr(port, service_name, None)
+	    resp = remote_method(encapsulate_binaries({ request_body_name: r},
+		('fedid',)))
+	except Fault, f:
+	    raise service_error(None, f.faultString, f.faultCode)
+	except Error, e:
+	    raise service_error(service_error.proxy, 
+		    "Remote XMLRPC Fault: %s" % e)
+
+	return apply_to_tags(resp, decap_fedids) 
+
+    def call_soap_service(self, url, req, loc_const, cert_file=None, cert_pwd=None, 
+	    trusted_certs=None):
+	"""
+	Send req on to the real destination in dt and return the response
+
+	Req is just the requestType object.  This function re-wraps it.  It
+	also rethrows any faults.
+	"""
+	# No retry loop here.  Proxy servers must correctly authenticate
+	# themselves without help
+	try:
+	    ctx = fedd_ssl_context(cert_file, trusted_certs, password=cert_pwd)
+	except SSL.SSLError:
+	    raise service_error(service_error.server_config, 
+		    "Server certificates misconfigured")
+
+	loc = loc_const()
+	get_port = getattr(loc, port_name, None)
+	if not get_port:
+	    raise service_error(service_error.internal, 
+		    "Cannot get port %s from locator" % port_name)
+	port = get_port(url,
+		transport=M2Crypto.httpslib.HTTPSConnection, 
+		transdict={ 'ssl_context' : ctx })
+	remote_method = getattr(port, service_name, None)
+	if not remote_method:
+	    raise service_error(service_error.internal,
+		    "Cannot get service from SOAP port")
+
+	# Reconstruct the full request message
+	msg = request_message()
+	set_element = getattr(msg, "set_element_%s" % request_body_name, None)
+	if not set_element:
+	    raise service_error(service_error.internal,
+		    "Cannot get element setting method for %s" % \
+			    request_body_name)
+	set_element(pack_soap(msg, request_body_name, req))
+	try:
+	    resp = remote_method(msg)
+	except ZSI.ParseException, e:
+	    raise service_error(service_error.proxy,
+		    "Bad format message (XMLRPC??): %s" %
+		    str(e))
+	r = unpack_soap(resp)
+	return r
+
+    return (call_soap_service, call_xmlrpc_service)
 
 def set_log_level(config, sect, log):
