Index: fedd/access_to_abac.py
===================================================================
--- fedd/access_to_abac.py	(revision 53b5c18fd287c3c2328d13668edf13931095765b)
+++ fedd/access_to_abac.py	(revision f3898f74717e5b8ce414358fc21dbc5f88d3e788)
@@ -82,5 +82,5 @@
     '''
     right_side_str = '\s*,\s*\(\s*%s\s*,\s*%s\s*,\s*%s\s*\)' % \
-	    (id_same_str, id_same_str,id_same_str)
+	    (proj_same_str, id_same_str,id_same_str)
 
     m = re.match(right_side_str, l)
@@ -319,9 +319,12 @@
 fedid_str = 'fedid:([0-9a-fA-F]{40})'
 id_str = '[a-zA-Z][\w_-]*'
+proj_str = '[a-zA-Z][\w_/-]*'
 path_str = '[a-zA-Z_/\.-]+'
 id_any_str = '(%s|<any>)' % id_str
+proj_any_str = '(%s|<any>)' % proj_str
 id_same_str = '(%s|<same>)' % id_str
+proj_same_str = '(%s|<same>)' % proj_str
 left_side_str = '\(\s*%s\s*,\s*%s\s*,\s*%s\s*\)' % \
-	(fedid_str, id_any_str, id_any_str)
+	(fedid_str, proj_any_str, id_any_str)
 right_side_str = '(%s)(\s*,\s*\(.*\))?' % (id_str)
 line_re = re.compile('%s\s*->\s*%s' % (left_side_str, right_side_str))
Index: fedd/exp_access_db.py
===================================================================
--- fedd/exp_access_db.py	(revision 53b5c18fd287c3c2328d13668edf13931095765b)
+++ fedd/exp_access_db.py	(revision f3898f74717e5b8ce414358fc21dbc5f88d3e788)
@@ -52,5 +52,9 @@
 q_start = """
 SELECT
-    g.uid, g.pid,
+    g.uid, 
+    CASE g.gid
+	WHEN g.pid THEN g.pid
+	ELSE CONCAT(g.pid, '/', g.gid)
+    END,
     CONCAT('-----BEGIN CERTIFICATE-----\\n',
 	s.cert,
@@ -59,5 +63,5 @@
 FROM group_membership g INNER JOIN user_sslcerts s
     ON g.uid = s.uid
-WHERE revoked is NULL AND g.pid = g.gid
+WHERE revoked is NULL
 """
 q_end ="""
Index: fedd/fedd_to_abac.py
===================================================================
--- fedd/fedd_to_abac.py	(revision 53b5c18fd287c3c2328d13668edf13931095765b)
+++ fedd/fedd_to_abac.py	(revision f3898f74717e5b8ce414358fc21dbc5f88d3e788)
@@ -65,5 +65,5 @@
     comment_re = re.compile('^\s*#|^$')
     fedid_str = 'fedid:([0-9a-fA-F]{40})'
-    id_str = '[a-zA-Z][\w_-]*'
+    id_str = '[a-zA-Z][\w/_-]*'
     single_re = re.compile('\s*%s\s*->\s*(%s)' % (fedid_str, id_str))
     double_re = re.compile('\s*%s\s*->\s*\((%s)\s*,\s*(%s)\)' % \
@@ -109,8 +109,4 @@
 		    (creds_dir or 'new_cert_dir', id.name, i)
 
-	    cid = Creddy.ID(cert)
-	    cid.load_privkey(key)
-	    cattr = Creddy.Attribute(cid, r, 3600 * 24 * 365 * 10)
-	    cattr.principal(k)
 
 	    if debug:
@@ -118,4 +114,8 @@
 			(cert, key, r, k, cf)
 	    else:
+		cid = Creddy.ID(cert)
+		cid.load_privkey(key)
+		cattr = Creddy.Attribute(cid, r, 3600 * 24 * 365 * 10)
+		cattr.principal(k)
 		cattr.bake()
 		cattr.write_name(cf)
Index: fedd/federation/emulab_access.py
===================================================================
--- fedd/federation/emulab_access.py	(revision 53b5c18fd287c3c2328d13668edf13931095765b)
+++ fedd/federation/emulab_access.py	(revision f3898f74717e5b8ce414358fc21dbc5f88d3e788)
@@ -937,4 +937,15 @@
 	vchars_re = '[^' + string.ascii_letters + string.digits  + '-]'
 
+	self.state_lock.acquire()
+	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()
+
+	if not proj:
+	    raise service_error(service_error.internal, 
+		    "Can't find project for %s" %aid)
+
 	for a in attrs:
 	    if a['attribute'] in configs:
@@ -954,6 +965,7 @@
 		ename = a['value']
 
-	# Names longer than the emulab max are discarder
-	if ename and len(ename) <= self.max_name_len:
+	# Names longer than the emulab max are discarded
+	# Projects with a group require nonce experiment names as well
+	if ename and len(ename) <= self.max_name_len and '/' not in proj:
 	    # Clean up the experiment name so that emulab will accept it.
 	    ename = re.sub(vchars_re, '-', ename)
@@ -976,7 +988,4 @@
 	self.state_lock.acquire()
 	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)
 	    self.allocation[aid]['experiment'] = ename
@@ -995,8 +1004,4 @@
 	    self.write_state()
 	self.state_lock.release()
-
-	if not proj:
-	    raise service_error(service_error.internal, 
-		    "Can't find project for %s" %aid)
 
 	if not user:
@@ -1095,4 +1100,8 @@
 			    certfile, tmpdir)
 
+	    if '/' in proj: proj, gid = proj.split('/')
+	    else: gid = None
+
+
 	    # Set up userconf and seer if needed
 	    self.configure_userconf(services, tmpdir)
@@ -1112,5 +1121,5 @@
 		    debug=self.create_debug, log=alloc_log, boss=self.boss,
 		    cert=self.xmlrpc_cert)
-	    rv = starter(self, ename, proj, user, expfile, tmpdir)
+	    rv = starter(self, ename, proj, user, expfile, tmpdir, gid=gid)
 	except service_error, e:
 	    err = e
@@ -1164,4 +1173,7 @@
 	    raise service_error(service_error.internal, 
 		    "Can't find project for %s" % aid)
+	else:
+	    if '/' in proj: proj, gid = proj.split('/')
+	    else: gid = None
 
 	if not user:
@@ -1173,4 +1185,4 @@
 	stopper = self.stop_segment(keyfile=self.ssh_privkey_file,
 		debug=self.create_debug, boss=self.boss, cert=self.xmlrpc_cert)
-	stopper(self, user, proj, ename)
+	stopper(self, user, proj, ename, gid)
 	return { 'allocID': req['allocID'], 'proof': proof.to_dict() }
Index: fedd/federation/emulab_segment.py
===================================================================
--- fedd/federation/emulab_segment.py	(revision 53b5c18fd287c3c2328d13668edf13931095765b)
+++ fedd/federation/emulab_segment.py	(revision f3898f74717e5b8ce414358fc21dbc5f88d3e788)
@@ -93,5 +93,5 @@
 	return state
 
-    def make_null_experiment(self, pid, eid, tmpdir):
+    def make_null_experiment(self, pid, eid, tmpdir, gid=None):
 	"""
 	Create a null copy of the experiment so that we capture any logs there
@@ -115,4 +115,6 @@
 		    'wait': True
 		    }
+	    if gid is not None:
+		params['group'] = gid
 	    if self.log:
 		self.log.info("[make_null_experiment]: Creating experiment")
Index: fedd/federation/local_emulab_segment.py
===================================================================
--- fedd/federation/local_emulab_segment.py	(revision 53b5c18fd287c3c2328d13668edf13931095765b)
+++ fedd/federation/local_emulab_segment.py	(revision f3898f74717e5b8ce414358fc21dbc5f88d3e788)
@@ -58,5 +58,6 @@
 	return True
 
-    def __call__(self, parent, eid, pid, user, tclfile, tmpdir, timeout=0):
+    def __call__(self, parent, eid, pid, user, tclfile, tmpdir, timeout=0, 
+	    gid=None):
 	"""
 	Start a sub-experiment on a federant.
@@ -70,5 +71,5 @@
 
 	if state == 'none':
-	    if not self.make_null_experiment(pid, eid, tmpdir):
+	    if not self.make_null_experiment(pid, eid, tmpdir, gid):
 		return False
 
@@ -102,8 +103,9 @@
 	emulab_segment.__init__(self, boss=boss, cert=cert)
 
-    def __call__(self, parent, user, pid, eid):
+    def __call__(self, parent, user, pid, eid, gid=None):
 	"""
 	Stop a sub experiment by calling swapexp on the federant
 	"""
+
 	self.log.info("[stop_segment]: Stopping %s" % eid)
 	rv = False
Index: fedd/federation/proxy_emulab_segment.py
===================================================================
--- fedd/federation/proxy_emulab_segment.py	(revision 53b5c18fd287c3c2328d13668edf13931095765b)
+++ fedd/federation/proxy_emulab_segment.py	(revision f3898f74717e5b8ce414358fc21dbc5f88d3e788)
@@ -158,5 +158,5 @@
 
 
-    def make_null_experiment(self, user, host, pid, eid, tmpdir):
+    def make_null_experiment(self, user, host, pid, eid, tmpdir, gid=None):
 	"""
 	Create a null copy of the experiment so that we capture any logs there
@@ -164,4 +164,8 @@
 	startexp
 	"""
+
+	if gid is not None: gparam = '-g %s' % gid
+	else: gparam = ''
+
 	try:
 	    f = open("%s/null.tcl" % tmpdir, "w")
@@ -179,5 +183,5 @@
 	    if not self.ssh_cmd(user, host,
 		    ("/usr/testbed/bin/startexp -i -f -w -p %s " + 
-		    "-e %s null.tcl") % (pid, eid), "startexp",
+		    "-e %s %s null.tcl") % (pid, eid, gparam), "startexp",
 		    timeout=60 * 10):
 		return False
@@ -276,5 +280,6 @@
 
 
-    def __call__(self, parent, eid, pid, user, tclfile, tmpdir, timeout=0):
+    def __call__(self, parent, eid, pid, user, tclfile, tmpdir, timeout=0,
+	    gid=None):
 	"""
 	Start a sub-experiment on a federant.
@@ -294,5 +299,5 @@
 	    # Put a dummy in place to capture logs, and establish an experiment
 	    # directory.
-	    if not self.make_null_experiment(user, host, pid, eid, tmpdir):
+	    if not self.make_null_experiment(user, host, pid, eid, tmpdir, gid):
 		return False
 
@@ -325,5 +330,5 @@
 	proxy_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
 
-    def __call__(self, parent, user, pid, eid):
+    def __call__(self, parent, user, pid, eid, gid=None):
 	"""
 	Stop a sub experiment by calling swapexp on the federant
