Index: fedd/federation/geniapi_proxy.py
===================================================================
--- fedd/federation/geniapi_proxy.py	(revision 208797c18a36ab60d41373d4305eb6da39360f64)
+++ fedd/federation/geniapi_proxy.py	(revision 208797c18a36ab60d41373d4305eb6da39360f64)
@@ -0,0 +1,117 @@
+#!/usr/local/bin/python
+
+import os,sys
+
+from M2Crypto.SSL import SSLError
+from M2Crypto.m2xmlrpclib import SSL_Transport
+from service_error import service_error
+from xmlrpclib import ServerProxy, Fault, Error
+
+
+from protogeni_proxy import protogeni_proxy
+
+import topdl
+import list_log
+
+class geniapi_proxy(protogeni_proxy):
+    '''
+    This exports the same interface as the protogeni_proxy, but uses GENIAPI
+    calls when avaliable.  These calls are currently only available only for
+    the component manager/aggregate manager.  The keyword arguments of the
+    ProtoGENI interface are converted into XMLRPC positional parameters on
+    GENIAPI calls.  Tables to do that are established in the constructior.
+    '''
+    def __init__(self, log=None, keyfile=None, debug=False, 
+	    ch_url=None, sa_url=None, cm_url=None):
+	protogeni_proxy.__init__(self, log, keyfile, debug, ch_url, sa_url,
+		cm_url)
+
+	def get_key(k, d):
+	    '''
+	    Return a function that takes a dict and returns the value bound to
+	    key k or the default d
+	    '''
+	    return lambda x : x.get(k, d)
+
+	def user_filter(params):
+	    '''
+	    Take a dict assumed to hold a key 'users' that is a dict of a urn
+	    (keyed by 'urn' and a list of dicts describing ssh keys (keyed by
+	    'key'.  Construct a list of dicts with the same 'urn' and a 'keys'
+	    value holding only the 'key' value of the subdict.  This converts
+	    ProtoGENI users to GENIAPI users.
+	    '''
+
+	    # That conversion is a nested list comprehension.
+	    return [ { 
+		'urn': u.get('urn', ''), 
+		'keys': [ k.get('key', '') for k in u.get('keys', []) ] 
+		} for u in params.get('users', [])]
+
+	self.ProtoGENIError = protogeni_proxy.ProtoGENIError
+	# These ProtoGENI requests are mapped to the given GENIAPI request.
+	self.method_map = { 
+		'DeleteSlice': 'DeleteSliver',
+		'RenewSlice': 'RenewSliver',
+		}
+	# Conversion tables for changing the dict of keyword arguments into a
+	# list of arguments for GENIAPI.  The list of positional params is
+	# created by calling the functions in the dict below (keyed by the
+	# requested function) in order on the params dict, placing the results
+	# into the arguments list.  The list so constructed is the positional
+	# parameters in order.  Mostly this is just putting the right key in
+	# the right place, but the users choice is actually reformatted some.
+	# This dict is indexed by ProtoGENI method.
+	self.arg_map = {
+		'CreateSliver': [
+		    get_key('slice_urn', ''), 
+		    get_key('credentials', []), 
+		    get_key('rspec', ''), 
+		    user_filter ],
+		'SliverStatus': [
+		    get_key('slice_urn', ''),
+		    get_key('credentials','') ],
+		'DeleteSlice': [
+		    get_key('slice_urn', ''),
+		    get_key('credentials','') ],
+		'RenewSlice': [
+		    get_key('slice_urn', ''),
+		    get_key('credentials','') ],
+		}
+
+    def geniapi_call(self, url, method, params, context):
+	'''
+	Make an SSL authenticated (and encrypted) GENIAPI call on the given url.
+	'''
+	try:
+	    if self.log:
+		self.log.debug("Calling %s %s" % (url, method))
+	    transport = SSL_Transport(context)
+	    port = ServerProxy(url, transport=transport)
+	    remote_method = getattr(port, method, None)
+	    if remote_method is not None:
+		return remote_method(*params)
+	    else:
+		raise service_error(service_error.internal, 
+			"Bad method: %s" % method)
+	except Fault, f:
+	    raise service_error(f.faultCode, f.faultString)
+	except Error, e:
+	    raise service_error(service_error.protocol, 
+		    "Remote XMLRPC Fault: %s" % e)
+	except:
+	    raise self.ProtoGENIError(op=method, code=-1, 
+		    output="%s" % sys.exc_info()[1])
+
+
+    def component_manager_call(self, method, params, context):
+	'''
+	Convert the ProtoGENI call into a GENIAPI call using the translation
+	tables above.
+	'''
+	gmethod = self.method_map.get(method, method)
+	gparams = [f(params) for f in self.arg_map.get(method, [])]
+
+	return self.geniapi_call(self.cm_url, gmethod, gparams, context)
+
+
Index: fedd/federation/protogeni_access.py
===================================================================
--- fedd/federation/protogeni_access.py	(revision 88dbe6330de24f2673a50c961f1651c0f63d0338)
+++ fedd/federation/protogeni_access.py	(revision 208797c18a36ab60d41373d4305eb6da39360f64)
@@ -15,5 +15,4 @@
 
 from threading import Thread, Timer, Lock
-from M2Crypto.SSL import SSLError
 
 from util import *
@@ -29,5 +28,6 @@
 
 from access import access_base
-from proxy_segment import proxy_segment
+from protogeni_proxy import protogeni_proxy
+from geniapi_proxy import geniapi_proxy
 
 import topdl
@@ -41,75 +41,4 @@
 fl = logging.getLogger("fedd.access")
 fl.addHandler(nullHandler())
-
-class protogeni_proxy(proxy_segment):
-    class ProtoGENIError(Exception): 
-	def __init__(self, op, code, output):
-	    Exception.__init__(self, output)
-	    self.op = op
-	    self.code = code
-	    self.output = output
-
-    def __init__(self, log=None, keyfile=None, debug=False, 
-	    ch_url=None, sa_url=None, cm_url=None):
-	proxy_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
-
-	self.ProtoGENIError = protogeni_proxy.ProtoGENIError
-	self.ch_url = ch_url
-	self.sa_url = sa_url
-	self.cm_url = cm_url
-
-	self.call_SetValue = service_caller('SetValue')
-
-	self.debug_fail = ['Resolve']
-	self.debug_response = {
-		'RedeemTicket': ("XML blob1", "XML blob2"),
-		'SliceStatus': { 'status': 'ready' },
-	    }
-
-
-    def pg_call(self, url, method, params, context):
-	max_retries = 5
-	retries = 0
-
-	s = service_caller(method, request_body_name="", strict=False)
-	self.log.debug("Calling %s %s" % (url, method))
-	if not self.debug:
-	    while retries < max_retries:
-		r = s.call_xmlrpc_service(url, params, context=context)
-		code = r.get('code', -1)
-		if code == 0:
-		    # Success leaves the loop here
-		    return r.get('value', None)
-		elif code == 14 and retries +1 < max_retries:
-		    # Busy resource
-		    retries+= 1
-		    self.log.info("Resource busy, retrying in 30 secs")
-		    time.sleep(30)
-		else:
-		    # NB: out of retries falls through to here
-		    raise self.ProtoGENIError(op=method, 
-			    code=r.get('code', 'unknown'), 
-			    output=r.get('output', 'No output'))
-	else:
-	    if method in self.debug_fail:
-		raise self.ProtoGENIError(op=method, code='unknown',
-			output='No output')
-	    elif self.debug_response.has_key(method):
-		return self.debug_response[method]
-	    else:
-		return "%s XML blob" % method
-
-    def clearinghouse_call(self, method, params, context):
-	return self.pg_call(self.ch_url, method, params, context)
-
-    def slice_authority_call(self, method, params, context):
-	return self.pg_call(self.sa_url, method, params, context)
-
-    def component_manager_call(self, method, params, context):
-	return self.pg_call(self.cm_url, method, params, context)
-
-
-
-
 
 class access(access_base):
@@ -198,4 +127,13 @@
 
 	self.lookup_access = self.lookup_access_base
+
+	api = config.get("access", "api") or "protogeni"
+	if api == "protogeni":
+	    self.api_proxy = protogeni_proxy
+	elif api == "geniapi":
+	    self.api_proxy = geniapi_proxy
+	else:
+	    self.log.debug("Unknown interface, using protogeni")
+	    self.api_proxy = protogeni_proxy
 
 	self.call_SetValue = service_caller('SetValue')
@@ -978,6 +916,14 @@
 		    'slice_urn': slice_urn,
 		    }
-	    sliver_cred, manifest = segment_commands.component_manager_call(
+	    rv = segment_commands.component_manager_call(
 		    'CreateSliver', param, ctxt)
+
+	    # the GENIAPI AM just hands back the manifest, bit the ProtoGENI
+	    # API hands back a sliver credential.  This just finds the format
+	    # of choice.
+	    if isinstance(rv, tuple):
+		manifest = rv[1]
+	    else:
+		manifest = rv
 	except segment_commands.ProtoGENIError, e:
 	    raise service_error(service_error.federant,
@@ -1004,5 +950,6 @@
 		r = segment_commands.component_manager_call(
 			'SliverStatus', param, ctxt)
-		status = r.get('status', 'changing')
+		# GENIAPI uses geni_status as the key, so check for both
+		status = r.get('status', r.get('geni_status','changing'))
 		if status not in completed_states:
 		    if timeout is not None and time.time() > end:
@@ -1342,5 +1289,5 @@
 		    % (self.staging_dir, ename), connInfo)
 
-	    segment_commands = protogeni_proxy(keyfile=ssh_key,
+	    segment_commands = self.api_proxy(keyfile=ssh_key,
 		    debug=self.create_debug, log=alloc_log,
 		    ch_url = self.ch_url, sa_url=self.sa_url,
@@ -1423,5 +1370,5 @@
 	    staging = None
 
-	segment_commands = protogeni_proxy(keyfile=ssh_key,
+	segment_commands = self.api_proxy(keyfile=ssh_key,
 		debug=self.create_debug, ch_url = self.ch_url,
 		sa_url=self.sa_url, cm_url=self.cm_url)
@@ -1509,5 +1456,5 @@
 	    # There's a ProtoGENI slice associated with the segment; renew it.
 	    if name and scred and slice_urn:
-		segment_commands = protogeni_proxy(log=self.log, 
+		segment_commands = self.api_proxy(log=self.log, 
 			debug=self.create_debug, keyfile=ssh_key,
 			cm_url = self.cm_url, sa_url = self.sa_url,
Index: fedd/federation/protogeni_proxy.py
===================================================================
--- fedd/federation/protogeni_proxy.py	(revision 208797c18a36ab60d41373d4305eb6da39360f64)
+++ fedd/federation/protogeni_proxy.py	(revision 208797c18a36ab60d41373d4305eb6da39360f64)
@@ -0,0 +1,79 @@
+#!/usr/local/bin/python
+
+import os,sys
+import logging
+
+from service_error import service_error
+from remote_service import xmlrpc_handler, soap_handler, service_caller
+
+from proxy_segment import proxy_segment
+
+
+class protogeni_proxy(proxy_segment):
+    class ProtoGENIError(Exception): 
+	def __init__(self, op, code, output):
+	    Exception.__init__(self, output)
+	    self.op = op
+	    self.code = code
+	    self.output = output
+
+    def __init__(self, log=None, keyfile=None, debug=False, 
+	    ch_url=None, sa_url=None, cm_url=None):
+	proxy_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
+
+	self.ProtoGENIError = protogeni_proxy.ProtoGENIError
+	self.ch_url = ch_url
+	self.sa_url = sa_url
+	self.cm_url = cm_url
+
+	self.call_SetValue = service_caller('SetValue')
+
+	self.debug_fail = ['Resolve']
+	self.debug_response = {
+		'RedeemTicket': ("XML blob1", "XML blob2"),
+		'SliceStatus': { 'status': 'ready' },
+	    }
+
+
+    def pg_call(self, url, method, params, context):
+	max_retries = 5
+	retries = 0
+
+	s = service_caller(method, request_body_name="", strict=False)
+	if self.log:
+	    self.log.debug("Calling %s %s" % (url, method))
+	if not self.debug:
+	    while retries < max_retries:
+		r = s.call_xmlrpc_service(url, params, context=context)
+		code = r.get('code', -1)
+		if code == 0:
+		    # Success leaves the loop here
+		    return r.get('value', None)
+		elif code == 14 and retries +1 < max_retries:
+		    # Busy resource
+		    retries+= 1
+		    self.log.info("Resource busy, retrying in 30 secs")
+		    time.sleep(30)
+		else:
+		    # NB: out of retries falls through to here
+		    raise self.ProtoGENIError(op=method, 
+			    code=r.get('code', 'unknown'), 
+			    output=r.get('output', 'No output'))
+	else:
+	    if method in self.debug_fail:
+		raise self.ProtoGENIError(op=method, code='unknown',
+			output='No output')
+	    elif self.debug_response.has_key(method):
+		return self.debug_response[method]
+	    else:
+		return "%s XML blob" % method
+
+    def clearinghouse_call(self, method, params, context):
+	return self.pg_call(self.ch_url, method, params, context)
+
+    def slice_authority_call(self, method, params, context):
+	return self.pg_call(self.sa_url, method, params, context)
+
+    def component_manager_call(self, method, params, context):
+	return self.pg_call(self.cm_url, method, params, context)
+
