Index: fedd/fedd.py
===================================================================
--- fedd/fedd.py	(revision 4700b3b0b1232a00e97f0335d74b51400160f7db)
+++ fedd/fedd.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
@@ -23,4 +23,5 @@
 from time import sleep
 import logging
+from ConfigParser import *
 
 # The SSL server here is based on the implementation described at
@@ -29,4 +30,19 @@
 # Turn off the matching of hostname to certificate ID
 SSL.Connection.clientPostConnectionCheck = None
+
+class fedd_config_parser(SafeConfigParser):
+    """
+    A SafeConfig parser with a more forgiving get attribute
+    """
+    def get(self, sect, opt, default=None):
+	"""
+	This returns the requested option or a given default.
+
+	It's more like getattr than get.
+	"""
+	if self.has_option(sect, opt):
+	    return SafeConfigParser.get(self, sect, opt)
+	else:
+	    return default
 
 class fedd_server(ThreadingSSLServer):
@@ -302,14 +318,22 @@
 flog.addHandler(fh)
 
+
+
 # Initialize the implementation
 if opts.configfile != None: 
     try:
-	impl = new_feddservice(opts.configfile)
-    except RuntimeError, e:
-	str = getattr(e, 'desc', None) or getattr(e,'message', None) or \
-		"No message"
-	sys.exit("Error configuring fedd: %s" % str)
+	config= fedd_config_parser()
+	config.read(opts.configfile)
+    except e:
+	sys.exit("Cannot parse confgi file: %s" % e)
 else: 
     sys.exit("--configfile is required")
+
+try:
+    impl = new_feddservice(config)
+except RuntimeError, e:
+    str = getattr(e, 'desc', None) or getattr(e,'message', None) or \
+	    "No message"
+    sys.exit("Error configuring fedd: %s" % str)
 
 if impl.cert_file == None:
Index: fedd/fedd_access.py
===================================================================
--- fedd/fedd_access.py	(revision 4700b3b0b1232a00e97f0335d74b51400160f7db)
+++ fedd/fedd_access.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
@@ -15,5 +15,4 @@
 import copy
 
-from fedd_config_file import config_file
 from fedd_access_project import access_project
 from fedd_services import *
@@ -40,25 +39,192 @@
     """
 
+    bool_attrs = ("dynamic_projects", "project_priority")
+    emulab_attrs = ("boss", "ops", "domain", "fileserver", "eventserver")
+    id_attrs = ("testbed", "proxy",
+	    "proxy_cert_file", "proxy_cert_pwd", "proxy_trusted_certs",
+	    "dynamic_projects_url", "dynamic_projects_cert_file", 
+	    "dynamic_projects_cert_pwd", "dynamic_projects_trusted_certs")
+    id_list_attrs = ("restricted",)
+
+    def read_trust(self, trust):
+	"""
+	Read a trust file that splits fedids into testbeds, users or projects
+
+	Format is:
+
+	[type]
+	fedid
+	fedid
+	default: type
+	"""
+	lineno = 0;
+	cat = None
+	cat_re = re.compile("\[(user|testbed|project)\]$", re.IGNORECASE)
+	fedid_re = re.compile("[" + string.hexdigits + "]+$")
+	default_re = re.compile("default:\s*(user|testbed|project)$", 
+		re.IGNORECASE)
+
+	f = open(trust, "r")
+	for line in f:
+	    lineno += 1
+	    line = line.strip()
+	    if len(line) == 0 or line.startswith("#"):
+		continue
+	    # Category line
+	    m = cat_re.match(line)
+	    if m != None:
+		cat = m.group(1).lower()
+		continue
+	    # Fedid line
+	    m = fedid_re.match(line)
+	    if m != None:
+		if cat != None:
+		    self.fedid_category[fedid(hexstr=m.string)] = cat
+		else:
+		    raise parse_error(\
+			    "Bad fedid in trust file (%s) line: %d" % \
+			    (trust, lineno))
+		continue
+	    # default line
+	    m = default_re.match(line)
+	    if m != None:
+		self.fedid_default = m.group(1).lower()
+		continue
+	    # Nothing matched - bad line, raise exception
+	    f.close()
+	    raise parse_error(\
+		    "Unparsable line in trustfile %s line %d" % (trust, lineno))
+	f.close()
+
+    def read_access(self, config):
+	"""
+	Read a configuration file and set internal parameters.
+
+	The format is more complex than one might hope.  The basic format is
+	attribute value pairs separated by colons(:) on a signle line.  The
+	attributes in bool_attrs, emulab_attrs and id_attrs can all be set
+	directly using the name: value syntax.  E.g. 
+	boss: hostname
+	sets self.boss to hostname.  In addition, there are access lines of the
+	form (tb, proj, user) -> (aproj, auser) that map the first tuple of
+	names to the second for access purposes.  Names in the key (left side)
+	can include "<NONE> or <ANY>" to act as wildcards or to require the
+	fields to be empty.  Similarly aproj or auser can be <SAME> or
+	<DYNAMIC> indicating that either the matching key is to be used or a
+	dynamic user or project will be created.  These names can also be
+	federated IDs (fedid's) if prefixed with fedid:.  Finally, the aproj
+	can be followed with a colon-separated list of node types to which that
+	project has access (or will have access if dynamic).
+	Testbed attributes outside the forms above can be given using the
+	format attribute: name value: value.  The name is a single word and the
+	value continues to the end of the line.  Empty lines and lines startin
+	with a # are ignored.
+
+	Parsing errors result in a parse_error exception being raised.
+	"""
+	lineno=0
+	name_expr = "["+string.ascii_letters + string.digits + "\.\-_]+"
+	fedid_expr = "fedid:[" + string.hexdigits + "]+"
+	key_name = "(<ANY>|<NONE>|"+fedid_expr + "|"+ name_expr + ")"
+	access_proj = "(<DYNAMIC>(?::" + name_expr +")*|"+ \
+		"<SAME>" + "(?::" + name_expr + ")*|" + \
+		fedid_expr + "(?::" + name_expr + ")*|" + \
+		name_expr + "(?::" + name_expr + ")*)"
+	access_name = "(<DYNAMIC>|<SAME>|" + fedid_expr + "|"+ name_expr + ")"
+
+	restricted_re = re.compile("restricted:\s*(.*)", re.IGNORECASE)
+	attr_re = re.compile('attribute:\s*([\._\-a-z0-9]+)\s+value:\s*(.*)',
+		re.IGNORECASE)
+	access_re = re.compile('\('+key_name+'\s*,\s*'+key_name+'\s*,\s*'+
+		key_name+'\s*\)\s*->\s*\('+access_proj + '\s*,\s*' + 
+		access_name + '\s*\)', re.IGNORECASE)
+
+	def parse_name(n):
+	    if n.startswith('fedid:'): return fedid(n[len('fedid:'):])
+	    else: return n
+
+	f = open(config, "r");
+	for line in f:
+	    lineno += 1
+	    line = line.strip();
+	    if len(line) == 0 or line.startswith('#'):
+		continue
+
+	    # Extended (attribute: x value: y) attribute line
+	    m = attr_re.match(line)
+	    if m != None:
+		attr, val = m.group(1,2)
+		self.attrs[attr] = val
+		continue
+
+	    # Restricted entry 
+	    m = restricted_re.match(line)
+	    if m != None:
+		val = m.group(1)
+		self.restricted.append(val)
+		continue
+
+	    # Access line (t, p, u) -> (ap, au) line
+	    m = access_re.match(line)
+	    if m != None:
+		access_key = tuple([ parse_name(x) for x in m.group(1,2,3)])
+		aps = m.group(4).split(":");
+		if aps[0] == 'fedid:':
+		    del aps[0]
+		    aps[0] = fedid(hexstr=aps[0])
+
+		au = m.group(5)
+		if au.startswith("fedid:"):
+		    au = fedid(hexstr=aus[len("fedid:"):])
+
+		access_val = (access_project(aps[0], aps[1:]), au)
+
+		self.access[access_key] = access_val
+		continue
+
+	    # Nothing matched to here: unknown line - raise exception
+	    f.close()
+	    raise parse_error("Unknown statement at line %d of %s" % \
+		    (lineno, config))
+	f.close()
+
+
     def __init__(self, config=None):
 	"""
-	Initializer.  Parses a configuration if one is given.
-	"""
-
-	# Read the configuration
-	if not config: raise RunTimeError("No config to fedd_allocate")
+	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 config_file.bool_attrs:
-	    setattr(self, a, getattr(config, a, False))
-
-	for a in config_file.emulab_attrs + config_file.id_attrs:
-	    setattr(self, a, getattr(config, a, None))
-
-
-	self.attrs = copy.deepcopy(config.attrs);
-	self.access = copy.deepcopy(config.access);
-	self.fedid_category = copy.deepcopy(config.fedid_category)
-	self.fedid_default = config.fedid_default
-	self.restricted = copy.copy(config.restricted)
+	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.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.log = logging.getLogger("fedd.access")
@@ -69,27 +235,37 @@
 	# proxy certs are used, and if none of those the main certs.
 
-	if config.proxy_cert_file:
+	if config.has_option("globals", "proxy_cert_file"):
 	    if not self.dynamic_projects_cert_file:
-		self.dynamic_projects_cert_file = config.proxy_cert_file
-		self.dynamic_projects_cert_pwd = config.proxy_cert_pwd
-
-	if config.proxy_trusted_certs:
+		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.proxy_trusted_certs
-
-	if config.cert_file:
+			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.cert_file
-		self.dynamic_projects_cert_pwd = config.cert_pwd
+		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.cert_file
-		self.proxy_cert_pwd = config.cert_pwd
-
-	if config.trusted_certs:
+		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.trusted_certs
+		self.proxy_trusted_certs = \
+			config.get("globals", "trusted_certs")
 	    if not self.dynamic_projects_trusted_certs:
-		self.dynamic_projects_trusted_certs = config.trusted_certs
+		self.dynamic_projects_trusted_certs = \
+			config.get("globals", "trusted_certs")
 
 	proj_certs = (self.dynamic_projects_cert_file, 
@@ -109,12 +285,13 @@
 
 
-	if config.dynamic_projects_url == None:
+	if not config.has_option("access", "dynamic_projects_url"):
 	    self.allocate_project = \
-		fedd_allocate_project_local(config.dynamic_projects, 
-			config.dynamic_projects_url, proj_certs)
+		fedd_allocate_project_local(self.dynamic_projects, 
+			None, proj_certs)
 	else:
 	    self.allocate_project = \
-		fedd_allocate_project_remote(config.dynamic_projects, 
-			config.dynamic_projects_url, proj_certs)
+		fedd_allocate_project_remote(self.dynamic_projects, 
+			config.get("access", "dynamic_projects_url"),
+			proj_certs)
 
 	# If the project allocator exports services, put them in this object's
@@ -127,7 +304,7 @@
 	Dump the state read from a configuration file.  Mostly for debugging.
 	"""
-	for a in fedd_proj.bool_attrs:
+	for a in fedd_access.bool_attrs:
 	    print "%s: %s" % (a, getattr(self, a ))
-	for a in fedd_proj.emulab_attrs + fedd_proj.id_attrs:
+	for a in fedd_access.emulab_attrs + fedd_access.id_attrs:
 	    print "%s: %s" % (a, getattr(self, a))
 	for k, v in self.attrs.iteritems():
Index: fedd/fedd_client.py
===================================================================
--- fedd/fedd_client.py	(revision 4700b3b0b1232a00e97f0335d74b51400160f7db)
+++ fedd/fedd_client.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
@@ -656,5 +656,6 @@
 		'allocID': pack_id('test alloc'),
 		'destinationTestbed': pack_id(opts.testbed),
-		'access' : [ { a.type: a.buf } for a in access_keys ],
+		'serviceAccess' : [ { a.type: a.buf } for a in access_keys ],
+		'createAccess' : [ { a.type: a.buf } for a in access_keys ],
 		}
 
Index: fedd/fedd_config_file.py
===================================================================
--- fedd/fedd_config_file.py	(revision 4700b3b0b1232a00e97f0335d74b51400160f7db)
+++ 	(revision )
@@ -1,234 +1,0 @@
-#!/usr/local/bin/python
-
-import os,sys
-
-import re
-import string
-
-from fedd_util import *
-from fedd_access_project import access_project
-
-# Used to report errors parsing the configuration files, not in providing
-# service
-class parse_error(RuntimeError): pass
-
-class config_file:
-    """
-    The implementation of access control based on mapping users to projects.
-
-    Users can be mapped to existing projects or have projects created
-    dynamically.  This implements both direct requests and proxies.
-    """
-    # Attributes that can be parsed from the configuration file
-    bool_attrs = ("dynamic_projects", "project_priority", "create_debug")
-    emulab_attrs = ("boss", "ops", "domain", "fileserver", "eventserver")
-    id_attrs = ("testbed", "cert_file", "cert_pwd", "trusted_certs", "proxy",
-	    "proxy_cert_file", "proxy_cert_pwd", "proxy_trusted_certs",
-	    "dynamic_projects_url", "dynamic_projects_cert_file", 
-	    "dynamic_projects_cert_pwd", "dynamic_projects_trusted_certs",
-	    "create_experiment_cert_file", "create_experiment_cert_pwd",
-	    "create_experiment_trusted_certs", "federation_script_dir",
-	    "ssh_pubkey_file", "experiment_state_file", "experiment_log")
-    id_list_attrs = ("restricted",)
-
-
-    def __init__(self, config=None):
-	"""
-	Initializer.  Parses a configuration if one is given.
-	"""
-
-	# Create instance attributes from the static lists
-	for a in config_file.bool_attrs:
-	    setattr(self, a, False)
-
-	for a in config_file.emulab_attrs + config_file.id_attrs:
-	    setattr(self, a, None)
-	
-	for a in config_file.id_list_attrs:
-	    setattr(self, a, [])
-
-	self.attrs = { }
-	self.fedid_category = { }
-	self.fedid_default = "user"
-	self.access = { }
-
-	if config:
-	    self.read_config(config)
-
-    def read_trust(self, trust):
-	"""
-	Read a trust file that splits fedids into testbeds, users or projects
-
-	Format is:
-
-	[type]
-	fedid
-	fedid
-	default: type
-	"""
-	lineno = 0;
-	cat = None
-	cat_re = re.compile("\[(user|testbed|project)\]$", re.IGNORECASE)
-	fedid_re = re.compile("[" + string.hexdigits + "]+$")
-	default_re = re.compile("default:\s*(user|testbed|project)$", 
-		re.IGNORECASE)
-
-	f = open(trust, "r")
-	for line in f:
-	    lineno += 1
-	    line = line.strip()
-	    if len(line) == 0 or line.startswith("#"):
-		continue
-	    # Category line
-	    m = cat_re.match(line)
-	    if m != None:
-		cat = m.group(1).lower()
-		continue
-	    # Fedid line
-	    m = fedid_re.match(line)
-	    if m != None:
-		if cat != None:
-		    self.fedid_category[fedid(hexstr=m.string)] = cat
-		else:
-		    raise parse_error(\
-			    "Bad fedid in trust file (%s) line: %d" % \
-			    (trust, lineno))
-		continue
-	    # default line
-	    m = default_re.match(line)
-	    if m != None:
-		self.fedid_default = m.group(1).lower()
-		continue
-	    # Nothing matched - bad line, raise exception
-	    f.close()
-	    raise parse_error(\
-		    "Unparsable line in trustfile %s line %d" % (trust, lineno))
-	f.close()
-
-    def read_config(self, config):
-	"""
-	Read a configuration file and set internal parameters.
-
-	The format is more complex than one might hope.  The basic format is
-	attribute value pairs separated by colons(:) on a signle line.  The
-	attributes in bool_attrs, emulab_attrs and id_attrs can all be set
-	directly using the name: value syntax.  E.g. 
-	boss: hostname
-	sets self.boss to hostname.  In addition, there are access lines of the
-	form (tb, proj, user) -> (aproj, auser) that map the first tuple of
-	names to the second for access purposes.  Names in the key (left side)
-	can include "<NONE> or <ANY>" to act as wildcards or to require the
-	fields to be empty.  Similarly aproj or auser can be <SAME> or
-	<DYNAMIC> indicating that either the matching key is to be used or a
-	dynamic user or project will be created.  These names can also be
-	federated IDs (fedid's) if prefixed with fedid:.  Finally, the aproj
-	can be followed with a colon-separated list of node types to which that
-	project has access (or will have access if dynamic).
-	Testbed attributes outside the forms above can be given using the
-	format attribute: name value: value.  The name is a single word and the
-	value continues to the end of the line.  Empty lines and lines startin
-	with a # are ignored.
-
-	Parsing errors result in a parse_error exception being raised.
-	"""
-	lineno=0
-	name_expr = "["+string.ascii_letters + string.digits + "\.\-_]+"
-	fedid_expr = "fedid:[" + string.hexdigits + "]+"
-	key_name = "(<ANY>|<NONE>|"+fedid_expr + "|"+ name_expr + ")"
-	access_proj = "(<DYNAMIC>(?::" + name_expr +")*|"+ \
-		"<SAME>" + "(?::" + name_expr + ")*|" + \
-		fedid_expr + "(?::" + name_expr + ")*|" + \
-		name_expr + "(?::" + name_expr + ")*)"
-	access_name = "(<DYNAMIC>|<SAME>|" + fedid_expr + "|"+ name_expr + ")"
-
-	bool_re = re.compile('(' + '|'.join(config_file.bool_attrs) + 
-		'):\s+(true|false)', re.IGNORECASE)
-	string_re = re.compile( "(" + \
-		'|'.join(config_file.emulab_attrs + config_file.id_attrs) + \
-		'):\s*(.*)', re.IGNORECASE)
-	list_re = re.compile("(" + '|'.join(config_file.id_list_attrs) + \
-		"):\s*(.*)", re.IGNORECASE)
-	attr_re = re.compile('attribute:\s*([\._\-a-z0-9]+)\s+value:\s*(.*)',
-		re.IGNORECASE)
-	access_re = re.compile('\('+key_name+'\s*,\s*'+key_name+'\s*,\s*'+
-		key_name+'\s*\)\s*->\s*\('+access_proj + '\s*,\s*' + 
-		access_name + '\s*\)', re.IGNORECASE)
-	trustfile_re = re.compile("trustfile:\s*(.*)", re.IGNORECASE)
-
-	def parse_name(n):
-	    if n.startswith('fedid:'): return fedid(n[len('fedid:'):])
-	    else: return n
-
-	f = open(config, "r");
-	for line in f:
-	    lineno += 1
-	    line = line.strip();
-	    if len(line) == 0 or line.startswith('#'):
-		continue
-
-	    # Boolean attribute line
-	    m = bool_re.match(line);
-	    if m != None:
-		attr, val = m.group(1,2)
-		setattr(self, attr.lower(), bool(val.lower() == "true"))
-		continue
-
-	    # String attribute line
-	    m = string_re.match(line)
-	    if m != None:
-		attr, val = m.group(1,2)
-		setattr(self, attr.lower(), val)
-		continue
-
-	    # List attributes
-	    m = list_re.match(line)
-	    if m != None:
-		attr, val = m.group(1,2)
-		l = getattr(self, attr.lower())
-		l.append(val)
-		continue
-
-
-	    # Extended (attribute: x value: y) attribute line
-	    m = attr_re.match(line)
-	    if m != None:
-		attr, val = m.group(1,2)
-		self.attrs[attr] = val
-		continue
-
-	    # Access line (t, p, u) -> (ap, au) line
-	    m = access_re.match(line)
-	    if m != None:
-		access_key = tuple([ parse_name(x) for x in m.group(1,2,3)])
-		aps = m.group(4).split(":");
-		if aps[0] == 'fedid:':
-		    del aps[0]
-		    aps[0] = fedid(hexstr=aps[0])
-
-		au = m.group(5)
-		if au.startswith("fedid:"):
-		    au = fedid(hexstr=aus[len("fedid:"):])
-
-		access_val = (access_project(aps[0], aps[1:]), au)
-
-		self.access[access_key] = access_val
-		continue
-
-	    # Trustfile inclusion
-	    m = trustfile_re.match(line)
-	    if m != None:
-		self.read_trust(m.group(1))
-		continue
-
-	    # Nothing matched to here: unknown line - raise exception
-	    f.close()
-	    raise parse_error("Unknown statement at line %d of %s" % \
-		    (lineno, config))
-	f.close()
-
-if __name__ == '__main__':
-    if sys.argv[1]:
-	config = config_file(sys.argv[1])
-	for a in [ a for a in dir(config) if a[0] != '_'  \
-		and not callable(getattr(config,a))]:
-	    print "%s: %s" % (a, getattr(config, a))
Index: fedd/fedd_deter_impl.py
===================================================================
--- fedd/fedd_deter_impl.py	(revision 4700b3b0b1232a00e97f0335d74b51400160f7db)
+++ fedd/fedd_deter_impl.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
@@ -3,5 +3,4 @@
 from fedd_access import *
 from fedd_experiment_control import *
-from fedd_config_file import *
 
 class fedd_deter_impl:
@@ -16,26 +15,26 @@
 	    'http://www.isi.edu/faber/fedd_internal.wsdl')
 
-    def __init__(self, config_path=None):
+    def __init__(self, config=None):
 	"""
 	Initializer.  Parses a configuration if one is given.
 	"""
-	if config_path:
-	    self.soap_services = { }
-	    self.xmlrpc_services = { }
-	    config = config_file(config_path)
+	self.soap_services = { }
+	self.xmlrpc_services = { }
 
-	    self.cert_file = config.cert_file;
-	    self.cert_pwd = config.cert_pwd;
-	    self.trusted_certs = config.trusted_certs;
+	if config:
+	    self.cert_file = config.get("globals", "cert_file");
+	    self.cert_pwd = config.get("globals", "cert_pwd");
+	    self.trusted_certs = config.get("globals", "trusted_certs");
 
-	    self.access = fedd_access(config)
-	    self.experiment = fedd_experiment_control_local(config)
+	    if config.has_section("access"):
+		self.access = fedd_access(config)
+		self.soap_services.update(self.access.soap_services) 
+		self.xmlrpc_services.update(self.access.xmlrpc_services) 
 
-	    self.soap_services.update(self.access.soap_services) 
-	    self.soap_services.update(self.experiment.soap_services) 
+	    if config.has_section("experiment_control"):
+		self.experiment = fedd_experiment_control_local(config)
+		self.soap_services.update(self.experiment.soap_services) 
+		self.xmlrpc_services.update(self.experiment.xmlrpc_services) 
 
-	    self.xmlrpc_services.update(self.access.xmlrpc_services) 
-	    self.xmlrpc_services.update(self.experiment.xmlrpc_services) 
-
-def new_feddservice(configfile):
-    return fedd_deter_impl(configfile)
+def new_feddservice(config):
+    return fedd_deter_impl(config)
Index: fedd/fedd_experiment_control.py
===================================================================
--- fedd/fedd_experiment_control.py	(revision 4700b3b0b1232a00e97f0335d74b51400160f7db)
+++ fedd/fedd_experiment_control.py	(revision 72ed6e42af52f04cdebc38933c098f9cbfba144a)
@@ -163,35 +163,42 @@
 	# attributes until the local certificate attributes can be resolved.
 	# The walk is from most specific to most general specification.
-	for p in ("create_experiment_", "proxy_", ""):
-	    filen = "%scert_file" % p
-	    pwn = "%scert_pwd" % p
-	    trustn = "%strusted_certs" % p
-
-	    if getattr(config, filen, None):
-		if not self.cert_file:
-		    self.cert_file = getattr(config, filen, None)
-		    self.cert_pwd = getattr(config, pwn, None)
-
-	    if getattr(config, trustn, None):
-		if not self.trusted_certs:
-		    self.trusted_certs = getattr(config, trustn, None)
+	for s in ("experiment_control", "globals"):
+	    if config.has_section(s): 
+		if config.has_option(s, "cert_file"):
+		    if not self.cert_file:
+			self.cert_file = config.get(s, "cert_file")
+			self.cert_pwd = config.get(s, "cert_pwd")
+
+		if config.has_option(s, "trusted_certs"):
+		    if not self.trusted_certs:
+			self.trusted_certs = config.get(s, "trusted_certs")
 
 	self.exp_stem = "fed-stem"
-	self.debug = config.create_debug
 	self.log = logging.getLogger("fedd.experiment_control")
 	self.muxmax = 2
 	self.nthreads = 2
 	self.randomize_experiments = False
+
 	self.scp_exec = "/usr/bin/scp"
-	self.scripts_dir = "/users/faber/testbed/federation"
 	self.splitter = None
 	self.ssh_exec="/usr/bin/ssh"
 	self.ssh_keygen = "/usr/bin/ssh-keygen"
 	self.ssh_identity_file = None
+
+	if config.has_section("experiment_control"):
+	    self.debug = config.get("experiment_control", "create_debug")
+	    self.state_filename = config.get("experiment_control", 
+		    "experiment_state_file")
+	    self.scripts_dir = config.get("experiment_control",
+		    "federation_script_dir")
+	else:
+	    self.debug = False
+	    self.state_filename = None
+	    self.scripts_dir = "/users/faber/testbed/federation"
+
 	# XXX
 	self.ssh_pubkey_file = "/users/faber/.ssh/id_rsa.pub"
 	self.ssh_type = "rsa"
 	self.state = { }
-	self.state_filename = config.experiment_state_file
 	self.state_lock = Lock()
 	self.tclsh = "/usr/local/bin/otclsh"
@@ -227,7 +234,8 @@
 	# hand finds the logging level constant corrersponding to the string.
 	# We're a little paranoid to avoid user mayhem.
-	if config.experiment_log:
+	if config.has_option("experiment_control", "log_level"):
 	    try:
-		level = int(getattr(logging, config.experiment_log.upper(),-1))
+		level = int(getattr(logging, 
+		    config.get("experiment_control", "log_level").upper(),-1))
 
 		if  logging.DEBUG <= level <= logging.CRITICAL:
@@ -235,5 +243,5 @@
 		else:
 		    self.log.error("Bad experiment_log value: %s" % \
-			    config.experiment_log)
+			    config.get("experiment_control", "log_level"))
 
 	    except ValueError:
