Index: fedd/federation/emulab_access.py
===================================================================
--- fedd/federation/emulab_access.py	(revision c7141dc6739a15071ba1ae8386e6457078c1cc41)
+++ fedd/federation/emulab_access.py	(revision ee950c2260d0e0d90dc0a6a4d78740b92459415b)
@@ -16,8 +16,6 @@
 
 from access import access_base
-from legacy_access import legacy_access
 
 from util import *
-from allocate_project import allocate_project_local, allocate_project_remote
 from fedid import fedid, generate_fedid
 from authorizer import authorizer, abac_authorizer
@@ -42,5 +40,5 @@
 fl.addHandler(nullHandler())
 
-class access(access_base, legacy_access):
+class access(access_base):
     """
     The implementation of access control based on mapping users to projects.
@@ -109,13 +107,9 @@
 	# authorization information
 	self.auth_type = config.get('access', 'auth_type') \
-		or 'legacy'
+		or 'abac'
 	self.auth_dir = config.get('access', 'auth_dir')
 	accessdb = config.get("access", "accessdb")
 	# initialize the authorization system
-	if self.auth_type == 'legacy':
-	    self.access = { }
-	    if accessdb:
-		self.legacy_read_access(accessdb, self.legacy_access_tuple)
-	elif self.auth_type == 'abac':
+	if self.auth_type == 'abac':
 	    self.auth = abac_authorizer(load=self.auth_dir)
 	    self.access = [ ]
@@ -128,22 +122,6 @@
 	# read_state in the base_class
 	self.state_lock.acquire()
-	for a  in ('allocation', 'projects', 'keys', 'types'):
-	    if a not in self.state:
-		self.state[a] = { }
+	if 'allocation' not in self.state: self.state['allocation']= { }
 	self.allocation = self.state['allocation']
-	self.projects = self.state['projects']
-	self.keys = self.state['keys']
-	self.types = self.state['types']
-	if self.auth_type == "legacy": 
-	    # Add the ownership attributes to the authorizer.  Note that the
-	    # indices of the allocation dict are strings, but the attributes are
-	    # fedids, so there is a conversion.
-	    for k in self.allocation.keys():
-		for o in self.allocation[k].get('owners', []):
-		    self.auth.set_attribute(o, fedid(hexstr=k))
-		if self.allocation[k].has_key('userconfig'):
-		    sfid = self.allocation[k]['userconfig']
-		    fid = fedid(hexstr=sfid)
-		    self.auth.set_attribute(fid, "/%s" % sfid)
 	self.state_lock.release()
 	self.exports = {
@@ -195,47 +173,4 @@
 	self.call_GetValue = service_caller('GetValue', log=self.log)
 
-        if not config.has_option("allocate", "uri"):
-            self.allocate_project = \
-                allocate_project_local(config, auth)
-        else:
-            self.allocate_project = \
-                allocate_project_remote(config, auth)
-
-
-        # If the project allocator exports services, put them in this object's
-        # maps so that classes that instantiate this can call the services.
-        self.soap_services.update(self.allocate_project.soap_services)
-        self.xmlrpc_services.update(self.allocate_project.xmlrpc_services)
-
-    @staticmethod
-    def legacy_access_tuple(str):
-	"""
-	Convert a string of the form (id[:resources:resouces], id, id) into a
-	tuple of the form (project, user, user) where users may be names or
-	fedids.  The resources strings are obsolete and ignored.
-	"""
-        def parse_name(n):
-            if n.startswith('fedid:'): return fedid(hexstr=n[len('fedid:'):])
-            else: return n
-
-	str = str.strip()
-	if str.startswith('(') and str.endswith(')'):
-	    str = str[1:-1]
-	    names = [ s.strip() for s in str.split(",")]
-	    if len(names) > 3:
-		raise self.parse_error("More than three fields in name")
-	    first = names[0].split(":")
-	    if first == 'fedid:':
-		del first[0]
-		first[0] = fedid(hexstr=first[0])
-	    names[0] = first[0]
-
-	    for i in range(1,2):
-		names[i] = parse_name(names[i])
-
-	    return tuple(names)
-	else:
-	    raise self.parse_error('Bad mapping (unbalanced parens)')
-
     @staticmethod
     def access_tuple(str):
@@ -243,6 +178,5 @@
 	Convert a string of the form (id, id) into an access_project.  This is
 	called by read_access to convert to local attributes.  It returns
-	a tuple of the form (project, user, user) where the two users are
-	always the same.
+	a tuple of the form (project, user).
 	"""
 
@@ -251,5 +185,5 @@
 	    # The slice takes the parens off the string.
 	    proj, user = str[1:-1].split(',')
-	    return (proj.strip(), user.strip(), user.strip())
+	    return (proj.strip(), user.strip())
 	else:
 	    raise self.parse_error(
@@ -258,167 +192,13 @@
     # RequestAccess support routines
 
-    def legacy_lookup_access(self, req, fid):
-        """
-	Look up the local access control information mapped to this fedid and
-	credentials.  In this case it is a (project, create_user, access_user)
-	triple, and a triple of three booleans indicating which, if any will
-	need to be dynamically created.  Finally a list of owners for that
-	allocation is returned.
-
-	lookup_access_base pulls the first triple out, and it is parsed by this
-	routine into the boolean map.  Owners is always the controlling fedid.
-        """
-        # Return values
-        rp = None
-        ru = None
-        # This maps a valid user to the Emulab projects and users to use
-        found, match = self.legacy_lookup_access_base(req, fid)
-	tb, project, user = match
-        
-        if found == None:
-            raise service_error(service_error.access,
-                    "Access denied - cannot map access")
-
-        # resolve <dynamic> and <same> in found
-        dyn_proj = False
-        dyn_create_user = False
-        dyn_service_user = False
-
-        if found[0] == "<same>":
-            if project != None:
-                rp = project
-            else : 
-                raise service_error(\
-                        service_error.server_config,
-                        "Project matched <same> when no project given")
-        elif found[0] == "<dynamic>":
-            rp = None
-            dyn_proj = True
-        else:
-            rp = found[0]
-
-        if found[1] == "<same>":
-            if user_match == "<any>":
-                if user != None: rcu = user[0]
-                else: raise service_error(\
-                        service_error.server_config,
-                        "Matched <same> on anonymous request")
-            else:
-                rcu = user_match
-        elif found[1] == "<dynamic>":
-            rcu = None
-            dyn_create_user = True
-        else:
-            rcu = found[1]
-        
-        if found[2] == "<same>":
-            if user_match == "<any>":
-                if user != None: rsu = user[0]
-                else: raise service_error(\
-                        service_error.server_config,
-                        "Matched <same> on anonymous request")
-            else:
-                rsu = user_match
-        elif found[2] == "<dynamic>":
-            rsu = None
-            dyn_service_user = True
-        else:
-            rsu = found[2]
-
-        return (rp, rcu, rsu), (dyn_create_user, dyn_service_user, dyn_proj),\
-                [ fid ]
-
-    def do_project_allocation(self, dyn, project, user):
-	"""
-	Call the project allocation routines and return the info.
-	"""
-	if dyn: 
-	    # Compose the dynamic project request 
-	    # (only dynamic, dynamic currently allowed)
-	    preq = { 'AllocateProjectRequestBody': \
-			{ 'project' : {\
-			    'user': [ \
-			    { \
-				'access': [ { 
-				    'sshPubkey': self.ssh_pubkey_file } ],
-				 'role': "serviceAccess",\
-			    }, \
-			    { \
-				'access': [ { 
-				    'sshPubkey': self.ssh_pubkey_file } ],
-				 'role': "experimentCreation",\
-			    }, \
-			    ], \
-			    }\
-			}\
-		    }
-	    return self.allocate_project.dynamic_project(preq)
-	else:
-	    preq = {'StaticProjectRequestBody' : \
-		    { 'project': \
-			{ 'name' : { 'localname' : project },\
-			  'user' : [ \
-			    {\
-				'userID': { 'localname' : user }, \
-				'access': [ { 
-				    'sshPubkey': self.ssh_pubkey_file } ],
-				'role': 'experimentCreation'\
-			    },\
-			    {\
-				'userID': { 'localname' : user}, \
-				'access': [ { 
-				    'sshPubkey': self.ssh_pubkey_file } ],
-				'role': 'serviceAccess'\
-			    },\
-			]}\
-		    }\
-	    }
-	    return self.allocate_project.static_project(preq)
-
-    def save_project_state(self, aid, ap, dyn, owners):
-	"""
-	Parse out and save the information relevant to the project created for
-	this experiment.  That info is largely in ap and owners.  dyn indicates
-	that the project was created dynamically.  Return the user and project
-	names.
+    def save_project_state(self, aid, pname, uname, owners):
+	"""
+	Save the project, user, and owners associated with this allocation.
+	This creates the allocation entry.
 	"""
 	self.state_lock.acquire()
 	self.allocation[aid] = { }
-	self.allocation[aid]['auth'] = set()
-	try:
-	    pname = ap['project']['name']['localname']
-	except KeyError:
-	    pname = None
-
-	if dyn:
-	    if not pname:
-		self.state_lock.release()
-		raise service_error(service_error.internal,
-			"Misformed allocation response?")
-	    if pname in self.projects: self.projects[pname] += 1
-	    else: self.projects[pname] = 1
-	    self.allocation[aid]['project'] = pname
-	else:
-	    # sproject is a static project associated with this allocation.
-	    self.allocation[aid]['sproject'] = pname
-
-	self.allocation[aid]['keys'] = [ ]
-
-	try:
-	    for u in ap['project']['user']:
-		uname = u['userID']['localname']
-		if u['role'] == 'experimentCreation':
-		    self.allocation[aid]['user'] = uname
-		for k in [ k['sshPubkey'] for k in u['access'] \
-			if k.has_key('sshPubkey') ]:
-		    kv = "%s:%s" % (uname, k)
-		    if self.keys.has_key(kv): self.keys[kv] += 1
-		    else: self.keys[kv] = 1
-		    self.allocation[aid]['keys'].append((uname, k))
-	except KeyError:
-	    self.state_lock.release()
-	    raise service_error(service_error.internal,
-		    "Misformed allocation response?")
-
+	self.allocation[aid]['project'] = pname
+	self.allocation[aid]['user'] = uname
 	self.allocation[aid]['owners'] = owners
 	self.write_state()
@@ -481,9 +261,6 @@
 	    self.auth.save()
 
-	if self.auth_type == "legacy":
-	    found, dyn, owners= self.legacy_lookup_access(req, fid)
-	    proof = access_proof("me", fid, "create")
-	elif self.auth_type == 'abac':
-	    found, dyn, owners, proof = self.lookup_access(req, fid, filter=pf)
+	if self.auth_type == 'abac':
+	    found, owners, proof = self.lookup_access(req, fid, filter=pf)
 	else:
 	    raise service_error(service_error.internal, 
@@ -491,20 +268,9 @@
 	ap = None
 
-	# This only happens in legacy lookups, but if this user has access to
-	# the testbed but not the project to be exported, raise the error.
-	if ep and ep != found[0]:
-	    raise service_error(service_error.access,
-		    "Cannot export %s" % ep)
-
-	if self.ssh_pubkey_file:
-	    ap = self.do_project_allocation(dyn[1], found[0], found[1])
-	else:
-	    raise service_error(service_error.internal, 
-		    "SSH access parameters required")
 	# keep track of what's been added
 	allocID, alloc_cert = generate_fedid(subj="alloc", log=self.log)
 	aid = unicode(allocID)
 
-	pname, uname = self.save_project_state(aid, ap, dyn[1], owners)
+	pname, uname = self.save_project_state(aid, found[0], found[1], owners)
 
 	services, svc_state = self.export_services(req.get('service',[]),
@@ -526,29 +292,6 @@
 		    "Can't open %s/%s : %s" % (self.certdir, aid, e))
 	resp = self.build_access_response({ 'fedid': allocID } ,
-		ap, services, proof)
+		pname, services, proof)
 	return resp
-
-    def do_release_project(self, del_project, del_users, del_types):
-	"""
-	If a project and users has to be deleted, make the call.
-	"""
-	msg = { 'project': { }}
-	if del_project:
-	    msg['project']['name']= {'localname': del_project}
-	users = [ ]
-	for u in del_users.keys():
-	    users.append({ 'userID': { 'localname': u },\
-		'access' :  \
-			[ {'sshPubkey' : s } for s in del_users[u]]\
-	    })
-	if users: 
-	    msg['project']['user'] = users
-	if len(del_types) > 0:
-	    msg['resources'] = { 'node': \
-		    [ {'hardware': [ h ] } for h in del_types ]\
-		}
-	if self.allocate_project.release_project:
-	    msg = { 'ReleaseProjectRequestBody' : msg}
-	    self.allocate_project.release_project(msg)
 
     def ReleaseAccess(self, req, fid):
@@ -579,51 +322,12 @@
 	    raise service_error(service_error.access, "Access Denied")
 
-	# If we know this allocation, reduce the reference counts and
-	# remove the local allocations.  Otherwise report an error.  If
-	# there is an allocation to delete, del_users will be a dictonary
-	# of sets where the key is the user that owns the keys in the set.
-	# We use a set to avoid duplicates.  del_project is just the name
-	# of any dynamic project to delete.  We're somewhat lazy about
-	# deleting authorization attributes.  Having access to something
-	# that doesn't exist isn't harmful.
-	del_users = { }
-	del_project = None
-	del_types = set()
-
 	self.state_lock.acquire()
 	if aid in self.allocation:
 	    self.log.debug("Found allocation for %s" %aid)
 	    self.clear_allocation_authorization(aid, state_attr='allocation')
-	    for k in self.allocation[aid]['keys']:
-		kk = "%s:%s" % k
-		self.keys[kk] -= 1
-		if self.keys[kk] == 0:
-		    if not del_users.has_key(k[0]):
-			del_users[k[0]] = set()
-		    del_users[k[0]].add(k[1])
-		    del self.keys[kk]
-
-	    if 'project' in self.allocation[aid]:
-		pname = self.allocation[aid]['project']
-		self.projects[pname] -= 1
-		if self.projects[pname] == 0:
-		    del_project = pname
-		    del self.projects[pname]
-
-	    if 'types' in self.allocation[aid]:
-		for t in self.allocation[aid]['types']:
-		    self.types[t] -= 1
-		    if self.types[t] == 0:
-			if not del_project: del_project = t[0]
-			del_types.add(t[1])
-			del self.types[t]
-
 	    del self.allocation[aid]
 	    self.write_state()
 	    self.state_lock.release()
-	    # If we actually have resources to deallocate, prepare the call.
-	    if del_project or del_users:
-		self.do_release_project(del_project, del_users, del_types)
-	    # And remove the access cert
+	    # Remove the access cert
 	    cf = "%s/%s.pem" % (self.certdir, aid)
 	    self.log.debug("Removing %s" % cf)
@@ -939,6 +643,4 @@
 	if aid in self.allocation:
 	    proj = self.allocation[aid].get('project', None)
-	    if not proj: 
-		proj = self.allocation[aid].get('sproject', None)
 	self.state_lock.release()
 
@@ -1215,6 +917,4 @@
 	if aid in self.allocation:
 	    proj = self.allocation[aid].get('project', None)
-	    if not proj: 
-		proj = self.allocation[aid].get('sproject', None)
 	    user = self.allocation[aid].get('user', None)
 	    ename = self.allocation[aid].get('experiment', None)
@@ -1265,6 +965,4 @@
 	    if topo: topo = topo.clone()
 	    proj = self.allocation[aid].get('project', None)
-	    if not proj: 
-		proj = self.allocation[aid].get('sproject', None)
 	    user = self.allocation[aid].get('user', None)
 	    ename = self.allocation[aid].get('experiment', None)
