Index: fedd/federation/dragon_access.py
===================================================================
--- fedd/federation/dragon_access.py	(revision 05fceefd2236460835d61858f2f132f99d6936e5)
+++ fedd/federation/dragon_access.py	(revision ab847bc9dbf2f2164d533821757acdf8dcaa7b04)
@@ -9,5 +9,5 @@
 import time
 
-from threading import *
+from threading import Thread, Lock
 from subprocess import Popen, call, PIPE, STDOUT
 
@@ -804,5 +804,5 @@
 	    # redoing the allocation.
 	    self.state_lock.acquire()
-	    retval = self.allocation[aid].get('started', None)
+	    retval = self.state[aid].get('started', None)
 	    self.state_lock.release()
 	    if retval:
@@ -858,5 +858,11 @@
 	self.export_store_info(certfile, vlan_no, connInfo)
 
+
 	if gri:
+	    rtopo = topo.clone()
+	    for s in rtopo.substrates:
+		s.set_attribute('vlan', vlan_no)
+		s.set_attribute('gri', gri)
+
 	    # Grab the log (this is some anal locking, but better safe than
 	    # sorry)
@@ -867,9 +873,12 @@
 	    # if the 'started' key is in the allocation, we'll return it rather
 	    # than redo the setup.
-	    self.allocation[aid]['started'] = { 
+	    self.state[aid]['started'] = { 
 		    'allocID': req['allocID'],
 		    'allocationLog': logv,
+		    'segmentdescription': {
+			'topdldescription': rtopo.to_dict()
+			},
 		    }
-	    retval = self.allocation[aid]['started']
+	    retval = self.state[aid]['started']
 	    self.write_state()
 	    self.state_lock.release()
Index: fedd/federation/emulab_access.py
===================================================================
--- fedd/federation/emulab_access.py	(revision 05fceefd2236460835d61858f2f132f99d6936e5)
+++ fedd/federation/emulab_access.py	(revision ab847bc9dbf2f2164d533821757acdf8dcaa7b04)
@@ -4,4 +4,5 @@
 import stat # for chmod constants
 import re
+import random
 import string
 import copy
@@ -1458,4 +1459,7 @@
 		    copy_file(f, "%s/%s" % (softdir, base))
 
+	    ename = None
+	    pubkey_base = None
+	    secretkey_base = None
 	    for a in attrs:
 		if a['attribute'] in configs:
@@ -1474,4 +1478,19 @@
 		if a['attribute'] == 'experiment_name':
 		    ename = a['value']
+
+	    if not ename:
+		ename = ""
+		for i in range(0,5):
+		    ename += random.choice(string.ascii_letters)
+		self.log.warn("No experiment name: picked one randomly: %s" \
+			% ename)
+
+	    if not pubkey_base:
+		raise service_error(service_error.req, 
+			"No public key attribute")
+
+	    if not secretkey_base:
+		raise service_error(service_error.req, 
+			"No secret key attribute")
 
 	    # If the userconf service was imported, collect the configuration
Index: fedd/federation/experiment_control.py
===================================================================
--- fedd/federation/experiment_control.py	(revision 05fceefd2236460835d61858f2f132f99d6936e5)
+++ fedd/federation/experiment_control.py	(revision ab847bc9dbf2f2164d533821757acdf8dcaa7b04)
@@ -816,5 +816,5 @@
 			"More than one project export is not supported")
 
-        uri = self.tbmap.get(tb, None)
+        uri = self.tbmap.get(testbed_base(tb), None)
         if not uri:
             raise service_error(service_error.server_config, 
@@ -1120,6 +1120,14 @@
 	    # Create and start a thread to start the segment, and save it
 	    # to get the return value later
+	    tb_attrs = copy.copy(attrs)
 	    thread_pool.wait_for_slot()
-	    uri = tbparams[tb].get('uri', self.tbmap.get(tb, None))
+	    uri = tbparams[tb].get('uri', \
+		    self.tbmap.get(testbed_base(tb), None))
+	    base, suffix = split_testbed(tb)
+	    if suffix:
+		tb_attrs.append({'attribute': 'experiment_name', 
+		    'value': "%s_%s" % (eid, suffix)})
+	    else:
+		tb_attrs.append({'attribute': 'experiment_name', 'value': eid})
 	    if not uri:
 		raise service_error(service_error.internal, 
@@ -1141,5 +1149,5 @@
 	    t  = self.pooled_thread(\
 		    target=s, name=tb,
-		    args=(uri, aid, topo[tb], masters, attrs, connInfo[tb]),
+		    args=(uri, aid, topo[tb], masters, tb_attrs, connInfo[tb]),
 		    pdata=thread_pool, trace_file=self.trace_file)
 	    threads.append(t)
@@ -1723,6 +1731,6 @@
 	    try:
 		os.makedirs(configdir)
-	    except IOError, e:
-		raise service_error(
+	    except EnvironmentError, e:
+		raise service_error(service_error.internal,
 			"Cannot create config directory: %s" % e)
 	    try:
@@ -1752,24 +1760,14 @@
 	    part.add_portals(top, topo, eid, masters, tbparams, ip_allocator,
 		    connInfo, expid)
-	    # Now get access to the dynamic testbeds
-	    for k, t in topo.items():
-		if not t.get_attribute('dynamic'):
-		    continue
-		tb = t.get_attribute('testbed')
-		if tb: 
-		    self.get_access(tb, None, tbparams, export_project, 
-			    access_user, masters)
-		    tbparams[k] = tbparams[tb]
-		    del tbparams[tb]
-		    allocated[k] = 1
-		    store_keys = t.get_attribute('store_keys')
-		    # Give the testbed access to keys it exports or imports
-		    if store_keys:
-			for sk in store_keys.split(" "):
-			    self.auth.set_attribute(\
-				    tbparams[k]['allocID']['fedid'], sk)
-		else:
-		    raise service_error(service_error.internal, 
-			    "Dynamic allocation from no testbed!?")
+	    # Now get access to the dynamic testbeds (those added above)
+	    for tb in [ t for t in topo if t not in allocated]:
+		self.get_access(tb, None, tbparams, access_user, masters)
+		allocated[tb] = 1
+		store_keys = topo[tb].get_attribute('store_keys')
+		# Give the testbed access to keys it exports or imports
+		if store_keys:
+		    for sk in store_keys.split(" "):
+			self.auth.set_attribute(\
+				tbparams[tb]['allocID']['fedid'], sk)
 
 	    self.wrangle_software(expid, top, topo, tbparams)
@@ -1848,8 +1846,4 @@
 			    (self.repo_url, expid)
 		},
-		{
-		    'attribute': 'experiment_name',
-		    'value': eid,
-		},
 	    ]
 
Index: fedd/federation/experiment_partition.py
===================================================================
--- fedd/federation/experiment_partition.py	(revision 05fceefd2236460835d61858f2f132f99d6936e5)
+++ fedd/federation/experiment_partition.py	(revision ab847bc9dbf2f2164d533821757acdf8dcaa7b04)
@@ -212,10 +212,10 @@
 		    "Cannot DRAGON split substrate w/o capacity")
 	segs = [ ]
-	substr = topdl.Substrate(name="dragon%d" % idx, 
+	name = join_testbed("dragon", "%d" % idx)
+	substr = topdl.Substrate(name=name, 
 		capacity=sub.capacity.clone(),
 		attribute=[ topdl.Attribute(attribute=n, value=v)
 		    for n, v, in (\
 			    ('vlan', 'unassigned%d' % idx),)])
-	name = "dragon%d" % idx
 	store_key = 'fedid:%s/vlan%d' % (expid, idx)
 	for tb in tbs.keys():
@@ -574,5 +574,5 @@
 				id= tbparams[mtb]['allocID'],
 				type='emulab',
-				uri = self.tbmap.get(master, None),
+				uri = self.tbmap.get(testbed_base(mtb), None),
 				interface=[ 
 				    topdl.Interface(
@@ -603,5 +603,5 @@
 				id= tbparams[tb]['allocID'],
 				type='emulab',
-				uri = self.tbmap.get(tb, None),
+				uri = self.tbmap.get(testbed_base(tb), None),
 				interface=[ 
 				    topdl.Interface(
@@ -625,5 +625,5 @@
 			topo[mtb].elements.append(portal)
 			topo[mtb].elements.append(seg)
-			for t in (master, tb):
+			for t in (mtb, tb):
 			    topo[t].incorporate_elements()
 
Index: fedd/federation/util.py
===================================================================
--- fedd/federation/util.py	(revision 05fceefd2236460835d61858f2f132f99d6936e5)
+++ fedd/federation/util.py	(revision ab847bc9dbf2f2164d533821757acdf8dcaa7b04)
@@ -213,2 +213,44 @@
 	raise failed_excpetion
 
+# Functions to manipulate composite testbed names
+def testbed_base(tb):
+    """
+    Simple code to get the base testebd name.
+    """
+    i = tb.find('/')
+    if i == -1: return tb
+    else: return tb[0:i]
+
+def testbed_suffix(tb):
+    """
+    Simple code to get a testbed suffix, if nay.  No suffix returns None.
+    """
+    i = tb.find('/')
+    if i != -1: return tb[i+1:]
+    else: return None
+
+def split_testbed(tb):
+    """
+    Return a testbed and a suffix as a tuple.  No suffix returns None for that
+    field
+    """
+
+    i = tb.find('/')
+    if i != -1: return (tb[0:i], tb[i+1:])
+    else: return (tb, None)
+
+def join_testbed(base, suffix=None):
+    """
+    Build a testbed with suffix.  If base is itself a tuple, combine them,
+    otherwise combine the two.
+    """
+    if isinstance(base, tuple):
+	if len(base) == 2:
+	    return '/'.join(base)
+	else:
+	    raise RuntimeError("Too many tuple elements for join_testbed")
+    else:
+	if suffix:
+	    return '/'.join((base, suffix))
+	else:
+	    return base
