Index: fedd/fedd_access.py
===================================================================
--- fedd/fedd_access.py	(revision d81971a06d08832a3270b8db95e6dd8091450596)
+++ fedd/fedd_access.py	(revision 7583a620ab90c35fbf4e32a4d8aaf69ca7ad2658)
@@ -857,5 +857,7 @@
 		if users: 
 		    msg['project']['user'] = users
-		print msg
+		if self.allocate_project.release_project:
+		    msg = { 'ReleaseProjectRequestBody' : msg}
+		    self.allocate_project.release_project(msg)
 	    self.write_state()
 	    return { 'allocID': req['allocID'] } 
Index: fedd/fedd_allocate_project.py
===================================================================
--- fedd/fedd_allocate_project.py	(revision d81971a06d08832a3270b8db95e6dd8091450596)
+++ fedd/fedd_allocate_project.py	(revision 7583a620ab90c35fbf4e32a4d8aaf69ca7ad2658)
@@ -20,4 +20,5 @@
 from fedd_internal_services import *
 from fedd_util import *
+import fixed_key
 import parse_detail
 from service_error import *
@@ -50,4 +51,5 @@
 		'/usr/testbed/sbin/newproj')
 	self.mkproj = config.get('access', 'mkproj', '/usr/testbed/sbin/mkproj')
+	self.rmproj = config.get('access', 'rmproj', '/usr/testbed/sbin/rmproj')
 	self.addpubkey = config.get('access', 'addpubkey', 
 		'/usr/testbed/sbin/taddpubkey')
@@ -56,4 +58,26 @@
 	self.log = logging.getLogger("fedd.allocate.local")
 	set_log_level(config, "access", self.log)
+	fixed_key_db = config.get("access", "fixed_keys", None)
+	fixed_project_db = config.get("access", "fixed_projects", None)
+	if fixed_key_db:
+	    try:
+		self.fixed_keys = fixed_key.read_db(fixed_key_db)
+	    except:
+		log.debug("Can't read fixed_key_db from %s" % fixed_key_db)
+	else:
+	    self.fixed_keys = set()
+
+	if fixed_project_db:
+	    try:
+		f = open(fixed_project_db, "r")
+		for line in f:
+		    self.fixed_projects.add(line.rstrip())
+		f.close()
+	    except:
+		log.debug("Can't read fixed_project_db from %s" % \
+			fixed_project_db)
+	else:
+	    self.fixed_projects = set()
+
 
 	# Internal services are SOAP only
@@ -66,5 +90,9 @@
 		StaticProjectRequestMessage.typecode,\
 		self.static_project, StaticProjectResponseMessage,\
-		"StaticProjectResponseBody")\
+		"StaticProjectResponseBody"),\
+		#"ReleaseProject": make_soap_handler(\
+		#ReleaseProjectRequestMessage.typecode,\
+		#self.release_project, ReleaseProjectResponseMessage,\
+		#"ReleaseProjectResponseBody")\
 		}
 	self.xmlrpc_services = { }
@@ -242,5 +270,6 @@
 	    for sk in [ k['sshPubkey'] for k in u.get('access', []) \
 		    if k.has_key('sshPubkey')]:
-		cmds.append((self.addpubkey, '-w', '-u', name, '-k', sk))
+		cmds.append((self.wap, self.addpubkey, '-w', \
+			'-u', name, '-k', sk))
 	
 
@@ -274,4 +303,60 @@
 	return { 'project': req['StaticProjectRequestBody']['project']}
 
+    def release_project(self, req, fedid=None):
+	"""
+	Remove user keys from users and delete dynamic projects.
+
+	Only keys not in the set of fixed keys are deleted. and there are
+	similar protections for projects.
+	"""
+
+	cmds = []
+	pname = None
+	users = []
+
+	print "release %s" % req
+	try:
+	    if req['ReleaseProjectRequestBody']['project'].has_key('name'):
+		pname = req['ReleaseProjectRequestBody']['project']\
+			['name']['localname']
+	    if req['ReleaseProjectRequestBody']['project'].has_key('user'):
+		users = req['ReleaseProjectRequestBody']['project']['user']
+	except KeyError:
+	    raise service_error(service_error.req, "Badly formed request")
+
+	for u in users:
+	    try:
+		name = u['userID']['localname']
+	    except KeyError:
+		raise service_error(service_error.req, "Badly formed user")
+	    for sk in [ k['sshPubkey'] for k in u.get('access', []) \
+		    if k.has_key('sshPubkey')]:
+		if (name, sk) not in self.fixed_keys:
+		    cmds.append((self.wap, self.addpubkey, '-R', '-w', \
+			    '-u', name, '-k', sk))
+	if pname and pname not in fixed_projects:
+	    cmds.append((self.wap, self.rmproj, pname))
+
+	# Run the commands 
+	rc = 0
+	for cmd in cmds:
+	    self.log.debug("[release_project]: %s" % ' '.join(cmd))
+	    if not self.debug:
+		try:
+		    rc = subprocess.call(cmd)
+		except OSError, e:
+		    print "Release project subprocess creation error "+ \
+				    "[%s] (%s)" %  (cmd[0], e.strerror)
+		    raise service_error(service_error.internal,
+			    "Release project subprocess creation error "+ \
+				    "[%s] (%s)" %  (cmd[0], e.strerror))
+
+	    if rc != 0: 
+		raise service_error(service_error.internal,
+			"Release project subprocess error " +\
+				"[%s] (%d)" % (cmd[0], rc))
+
+	return { 'project': req['ReleaseProjectRequestBody']['project']}
+
 def make_proxy(method, req_name, req_alloc, resp_name):
     """
@@ -383,4 +468,3 @@
 	self.log = logging.getLogger("fedd.allocate.remote")
 	set_log_level(config, "access", self.log)
-	#self.dynamic_project = fedd_allocate_project_remote.dynamic_project
-	#self.static_project = fedd_allocate_project_remote.static_project
+	self.release_project = None
