Index: fedd/fedd_access.py
===================================================================
--- fedd/fedd_access.py	(revision 7583a620ab90c35fbf4e32a4d8aaf69ca7ad2658)
+++ fedd/fedd_access.py	(revision f8582c9a024862e2f99c61a303029f0c7929d8b3)
@@ -16,4 +16,6 @@
 import pickle
 
+from threading import *
+
 from fedd_access_project import access_project
 from fedd_services import *
@@ -49,4 +51,130 @@
 	    "dynamic_projects_cert_pwd", "dynamic_projects_trusted_certs")
     id_list_attrs = ("restricted",)
+
+    def __init__(self, config=None):
+	"""
+	Initializer.  Pulls parameters out of the ConfigParser's access section.
+	"""
+
+	# Make sure that the configuration is in place
+	if config: 
+	    if not config.has_section("access"):
+		config.add_section("access")
+	    if not config.has_section("globals"):
+		config.add_section("globals")
+	else:
+	    raise RunTimeError("No config to fedd_access")
+
+
+	# Create instance attributes from the static lists
+	for a in fedd_access.bool_attrs:
+	    if config.has_option("access", a):
+		setattr(self, a, config.get("access", a))
+	    else:
+		setattr(self, a, False)
+
+	for a in fedd_access.emulab_attrs + fedd_access.id_attrs:
+	    if config.has_option("access", a):
+		setattr(self, a, config.get("access",a))
+	    else:
+		setattr(self, a, None)
+
+	self.attrs = { }
+	self.access = { }
+	self.restricted = [ ]
+	self.fedid_category = { }
+	self.projects = { }
+	self.keys = { }
+	self.allocation = { }
+	self.state = { 
+	    'projects': self.projects,
+	    'allocation' : self.allocation,
+	    'keys' : self.keys
+	}
+	self.state_lock = Lock()
+	self.fedid_default = "testbed"
+	if config.has_option("access", "accessdb"):
+	    self.read_access(config.get("access", "accessdb"))
+	if config.has_option("access", "trustdb"):
+	    self.read_trust(config.get("access", "trustdb"))
+
+	self.state_filename = config.get("access", "access_state", "")
+	self.log = logging.getLogger("fedd.access")
+	set_log_level(config, "access", self.log)
+	self.read_state()
+
+
+	# Certs are promoted from the generic to the specific, so without a
+	# specific proxy certificate, the main certificates are used for
+	# proxy interactions. If no dynamic project certificates, then
+	# proxy certs are used, and if none of those the main certs.
+
+	if config.has_option("globals", "proxy_cert_file"):
+	    if not self.dynamic_projects_cert_file:
+		self.dynamic_projects_cert_file = \
+			config.get("globals", "proxy_cert_file")
+		if config.has_option("globals", "porxy_cert_pwd"):
+		    self.dynamic_projects_cert_pwd = \
+			    config.get("globals", "proxy_cert_pwd")
+
+	if config.has_option("globals", "proxy_trusted_certs"):
+	    if not self.dynamic_projects_trusted_certs:
+		self.dynamic_projects_trusted_certs =\
+			config.get("globals", proxy_trusted_certs)
+
+	if config.has_option("globals", "cert_file"):
+	    has_pwd = config.has_option("globals", "cert_pwd")
+	    if not self.dynamic_projects_cert_file:
+		self.dynamic_projects_cert_file = \
+			config.get("globals", "cert_file")
+		if has_pwd: 
+		    self.dynamic_projects_cert_pwd = \
+			    config.get("globals", "cert_pwd")
+	    if not self.proxy_cert_file:
+		self.proxy_cert_file = config.get("globals", "cert_file")
+		if has_pwd:
+		    self.proxy_cert_pwd = config.get("globals", "cert_pwd")
+
+	if config.get("globals", "trusted_certs"):
+	    if not self.proxy_trusted_certs:
+		self.proxy_trusted_certs = \
+			config.get("globals", "trusted_certs")
+	    if not self.dynamic_projects_trusted_certs:
+		self.dynamic_projects_trusted_certs = \
+			config.get("globals", "trusted_certs")
+
+	proj_certs = (self.dynamic_projects_cert_file, 
+		self.dynamic_projects_trusted_certs,
+		self.dynamic_projects_cert_pwd)
+
+	self.soap_services = {\
+	    'RequestAccess': make_soap_handler(\
+		RequestAccessRequestMessage.typecode,\
+		self.RequestAccess, RequestAccessResponseMessage,\
+		"RequestAccessResponseBody"), \
+	    'ReleaseAccess': make_soap_handler(\
+		ReleaseAccessRequestMessage.typecode,\
+		self.ReleaseAccess, ReleaseAccessResponseMessage,\
+		"ReleaseAccessResponseBody")\
+	    }
+	self.xmlrpc_services =  {\
+	    'RequestAccess': make_xmlrpc_handler(\
+		self.RequestAccess, "RequestAccessResponseBody"),\
+	    'ReleaseAccess': make_xmlrpc_handler(\
+		self.ReleaseAccess, "ReleaseAccessResponseBody")\
+	    }
+
+
+	if not config.has_option("access", "dynamic_projects_url"):
+	    self.allocate_project = \
+		fedd_allocate_project_local(config)
+	else:
+	    self.allocate_project = \
+		fedd_allocate_project_remote(config)
+
+	# 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)
 
     def read_trust(self, trust):
@@ -192,128 +320,4 @@
 	f.close()
 
-
-    def __init__(self, config=None):
-	"""
-	Initializer.  Pulls parameters out of the ConfigParser's access section.
-	"""
-
-	# Make sure that the configuration is in place
-	if config: 
-	    if not config.has_section("access"):
-		config.add_section("access")
-	    if not config.has_section("globals"):
-		config.add_section("globals")
-	else:
-	    raise RunTimeError("No config to fedd_access")
-
-
-	# Create instance attributes from the static lists
-	for a in fedd_access.bool_attrs:
-	    if config.has_option("access", a):
-		setattr(self, a, config.get("access", a))
-	    else:
-		setattr(self, a, False)
-
-	for a in fedd_access.emulab_attrs + fedd_access.id_attrs:
-	    if config.has_option("access", a):
-		setattr(self, a, config.get("access",a))
-	    else:
-		setattr(self, a, None)
-
-	self.attrs = { }
-	self.access = { }
-	self.restricted = [ ]
-	self.fedid_category = { }
-	self.projects = { }
-	self.keys = { }
-	self.allocation = { }
-	self.state = { 
-	    'projects': self.projects,
-	    'allocation' : self.allocation,
-	    'keys' : self.keys
-	}
-	self.fedid_default = "testbed"
-	if config.has_option("access", "accessdb"):
-	    self.read_access(config.get("access", "accessdb"))
-	if config.has_option("access", "trustdb"):
-	    self.read_trust(config.get("access", "trustdb"))
-
-	self.state_filename = config.get("access", "access_state", "")
-	self.log = logging.getLogger("fedd.access")
-	self.read_state()
-
-
-	# Certs are promoted from the generic to the specific, so without a
-	# specific proxy certificate, the main certificates are used for
-	# proxy interactions. If no dynamic project certificates, then
-	# proxy certs are used, and if none of those the main certs.
-
-	if config.has_option("globals", "proxy_cert_file"):
-	    if not self.dynamic_projects_cert_file:
-		self.dynamic_projects_cert_file = \
-			config.get("globals", "proxy_cert_file")
-		if config.has_option("globals", "porxy_cert_pwd"):
-		    self.dynamic_projects_cert_pwd = \
-			    config.get("globals", "proxy_cert_pwd")
-
-	if config.has_option("globals", "proxy_trusted_certs"):
-	    if not self.dynamic_projects_trusted_certs:
-		self.dynamic_projects_trusted_certs =\
-			config.get("globals", proxy_trusted_certs)
-
-	if config.has_option("globals", "cert_file"):
-	    has_pwd = config.has_option("globals", "cert_pwd")
-	    if not self.dynamic_projects_cert_file:
-		self.dynamic_projects_cert_file = \
-			config.get("globals", "cert_file")
-		if has_pwd: 
-		    self.dynamic_projects_cert_pwd = \
-			    config.get("globals", "cert_pwd")
-	    if not self.proxy_cert_file:
-		self.proxy_cert_file = config.get("globals", "cert_file")
-		if has_pwd:
-		    self.proxy_cert_pwd = config.get("globals", "cert_pwd")
-
-	if config.get("globals", "trusted_certs"):
-	    if not self.proxy_trusted_certs:
-		self.proxy_trusted_certs = \
-			config.get("globals", "trusted_certs")
-	    if not self.dynamic_projects_trusted_certs:
-		self.dynamic_projects_trusted_certs = \
-			config.get("globals", "trusted_certs")
-
-	proj_certs = (self.dynamic_projects_cert_file, 
-		self.dynamic_projects_trusted_certs,
-		self.dynamic_projects_cert_pwd)
-
-	self.soap_services = {\
-	    'RequestAccess': make_soap_handler(\
-		RequestAccessRequestMessage.typecode,\
-		self.RequestAccess, RequestAccessResponseMessage,\
-		"RequestAccessResponseBody"), \
-	    'ReleaseAccess': make_soap_handler(\
-		ReleaseAccessRequestMessage.typecode,\
-		self.ReleaseAccess, ReleaseAccessResponseMessage,\
-		"ReleaseAccessResponseBody")\
-	    }
-	self.xmlrpc_services =  {\
-	    'RequestAccess': make_xmlrpc_handler(\
-		self.RequestAccess, "RequestAccessResponseBody"),\
-	    'ReleaseAccess': make_xmlrpc_handler(\
-		self.ReleaseAccess, "ReleaseAccessResponseBody")\
-	    }
-
-
-	if not config.has_option("access", "dynamic_projects_url"):
-	    self.allocate_project = \
-		fedd_allocate_project_local(config)
-	else:
-	    self.allocate_project = \
-		fedd_allocate_project_remote(config)
-
-	# 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)
 
     def dump_state(self):
@@ -735,11 +739,8 @@
 			"SSH access parameters required")
 	    # keep track of what's been added
-	    if req['allocID'].has_key('fedid'):
-		aid = unicode(req['allocId']['fedid'])
-	    elif req['allocID'].has_key('localname'):
-		aid = req['allocID']['localname']
-	    else:
-		raise service_error(service_error.req, "Bad allocation ID")
-
+	    allocID, alloc_cert = generate_fedid(subj="alloc", log=self.log)
+	    aid = unicode(allocID)
+
+	    self.state_lock.acquire()
 	    self.allocation[aid] = { }
 	    if dyn[1]:
@@ -747,4 +748,5 @@
 		    pname = ap['project']['name']['localname']
 		except KeyError:
+		    self.state_lock.release()
 		    raise service_error(service_error.internal,
 			    "Misformed allocation response?")
@@ -765,9 +767,11 @@
 			self.allocation[aid]['keys'].append((uname, k))
 	    except KeyError:
+		self.state_lock.release()
 		raise service_error(service_error.internal,
 			"Misformed allocation response?")
 
 	    self.write_state()
-	    resp = self.build_response(req['allocID'], ap)
+	    self.state_lock.release()
+	    resp = self.build_response({ 'fedid': allocID } , ap)
 	    return resp
 	else:
@@ -806,5 +810,4 @@
 	    raise service_error(service_error.req, "No request!?")
 
-	print req
 	try:
 	    if req['allocID'].has_key('localname'):
@@ -827,4 +830,5 @@
 	del_project = None
 	if self.allocation.has_key(aid):
+	    self.state_lock.acquire()
 	    for k in self.allocation[aid]['keys']:
 		kk = "%s:%s" % k
@@ -844,9 +848,11 @@
 
 	    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:
 		msg = { 'project': { }}
 		if del_project:
-		    msg['project']['name']['localname'] =  del_project
+		    msg['project']['name']= {'localname': del_project}
 		users = [ ]
 		for u in del_users.keys():
@@ -860,5 +866,4 @@
 		    msg = { 'ReleaseProjectRequestBody' : msg}
 		    self.allocate_project.release_project(msg)
-	    self.write_state()
 	    return { 'allocID': req['allocID'] } 
 	else:
