Index: fedd/federation/emulab_access.py
===================================================================
--- fedd/federation/emulab_access.py	(revision 22a1a77015d7254a2c8a9f81b420a91df69516f5)
+++ fedd/federation/emulab_access.py	(revision b709861c37a497e1ae0e4e757f53e205aa0440ec)
@@ -102,12 +102,15 @@
 	    self.stop_segment = proxy_emulab_segment.stop_segment
 	    self.info_segment = proxy_emulab_segment.info_segment
+	    self.operation_segment = proxy_emulab_segment.operation_segment
 	elif self.access_type == 'local_emulab':
 	    self.start_segment = local_emulab_segment.start_segment
 	    self.stop_segment = local_emulab_segment.stop_segment
 	    self.info_segment = local_emulab_segment.info_segment
+	    self.operation_segment = local_emulab_segment.operation_segment
 	else:
 	    self.start_segment = None
 	    self.stop_segment = None
 	    self.info_segment = None
+	    self.operation_segment = None
 
         self.restricted = [ ]
@@ -185,4 +188,6 @@
 		self.TerminateSegment),
             'InfoSegment': soap_handler("InfoSegment", self.InfoSegment),
+            'OperationSegment': soap_handler("OperationSegment",
+		self.OperationSegment),
             }
         self.xmlrpc_services =  {\
@@ -195,4 +200,6 @@
                 self.TerminateSegment),
             'InfoSegment': xmlrpc_handler("InfoSegment", self.InfoSegment),
+            'OperationSegment': xmlrpc_handler("OperationSegment",
+		self.OperationSegment),
             }
 
@@ -1060,9 +1067,9 @@
 		'allocationLog': logv,
 		'segmentdescription': { 
-		    'topdldescription': t.clone().to_dict()
+		    'topdldescription': t.to_dict()
 		    },
 		'proof': proof.to_dict(),
 		}
-	self.allocation[aid]['topo'] = topo.clone()
+	self.allocation[aid]['topo'] = t
 	retval = copy.copy(self.allocation[aid]['started'])
 	self.write_state()
@@ -1239,10 +1246,9 @@
 	    user = self.allocation[aid].get('user', None)
 	    ename = self.allocation[aid].get('experiment', None)
-	    nonce = self.allocation[aid].get('nonce', False)
 	else:
 	    proj = None
 	    user = None
 	    ename = None
-	    nonce = False
+	    topo = None
 	self.state_lock.release()
 
@@ -1270,2 +1276,65 @@
 		'proof': proof.to_dict(),
 		}
+
+    def OperationSegment(self, req, fid):
+	def get_pname(e):
+	    """
+	    Get the physical name of a node
+	    """
+	    if e.localname:
+		return re.sub('\..*','', e.localname[0])
+	    else:
+		return None
+
+	try:
+	    req = req['OperationSegmentRequestBody']
+	except KeyError:
+	    raise service_error(server_error.req, "Badly formed request")
+
+	auth_attr = req['allocID']['fedid']
+	aid = "%s" % auth_attr
+
+	access_ok, proof = self.auth.check_attribute(fid, auth_attr, 
+		with_proof=True)
+	if not access_ok:
+	    raise service_error(service_error.access, "Access denied")
+
+	op = req.get('operation', None)
+	targets = req.get('target', None)
+	params = req.get('parameter', None)
+
+	if op is None :
+	    raise service_error(service_error.req, "missing operation")
+	elif targets is None:
+	    raise service_error(service_error.req, "no targets")
+
+	if aid in self.allocation:
+	    topo = self.allocation[aid].get('topo', None)
+	    if topo: topo = topo.clone()
+	else:
+	    topo = None
+
+	targets = copy.copy(targets)
+	ptargets = { }
+	for e in topo.elements:
+	    if isinstance(e, topdl.Computer):
+		if e.name in targets:
+		    targets.remove(e.name)
+		    pn = get_pname(e)
+		    if pn: ptargets[e.name] = pn
+
+	status = [ operation_status(t, operation_status.no_target) \
+		for t in targets]
+
+	ops = self.operation_segment(keyfile=self.ssh_privkey_file,
+		debug=self.create_debug, boss=self.boss, 
+		cert=self.xmlrpc_cert)
+	ops(self, op, ptargets, params)
+	
+	status.extend(ops.status)
+
+	return { 
+		'allocID': req['allocID'], 
+		'status': [s.to_dict() for s in status],
+		'proof': proof.to_dict(),
+		}
Index: fedd/federation/emulab_segment.py
===================================================================
--- fedd/federation/emulab_segment.py	(revision 22a1a77015d7254a2c8a9f81b420a91df69516f5)
+++ fedd/federation/emulab_segment.py	(revision b709861c37a497e1ae0e4e757f53e205aa0440ec)
@@ -14,4 +14,5 @@
 from federation.util import fedd_ssl_context
 from federation import service_error
+from federation.operation_status import operation_status
 
 class emulab_segment:
@@ -32,4 +33,5 @@
 	self.debug = getattr(self, 'debug', False)
 	self.node = { }
+	self.status = [ ]
 
     def emulab_call(self, method, params):
@@ -103,5 +105,6 @@
 	if self.debug:
 	    if self.log:
-		self.log.debug("[make_null_experiment]: (debug) Creating experiment")
+		self.log.debug("[make_null_experiment]: " + \
+			"(debug) Creating experiment")
 	    return True
 	else:
@@ -243,2 +246,47 @@
 			"Cannot get node mapping of segment:%s/%s" % (pid, eid))
 
+    def do_operation(self, op, lnode, pnode, params):
+	"""
+	Carry out operation on node in the given experiment.
+	"""
+	def get_param(params, name):
+	    if params is None:
+		return None
+	    for d in params:
+		if 'attribute' in d and d['attribute'] == name:
+		    return d.get('value', None)
+	    else:
+		return None
+
+	op = op.lower()
+
+	if op == 'restore':
+	    state = get_param(params, 'state')
+	    if state is None:
+		self.status.append(operation_status(lnode, 
+			operation_status.bad_param, 'No state to restore'))
+		return False
+	    elif state == 'initial': 
+		self.status.append(operation_status(lnode,
+			operation_status.unsupp, 'Image load unsupported'))
+		return False
+	    elif state == 'boot': 
+		p = {'nodes': pnode, 'wait': False}
+		code, result = self.emulab_call('node.reboot', p)
+		if code == 0: 
+		    self.status.append(operation_status(lnode,
+			operation_status.success, 'rebooting'))
+		    return True
+		else:
+		    self.status.append(operation_status(lnode,
+			    operation_status.federant, 'Error code: %d' % code))
+		    return False
+	    else: 
+		self.status.append(operation_status(lnode, 
+			operation_status.bad_param, 
+			"Unsupported state %s" % state))
+		return False
+	else: 
+	    self.status.append(operation_status(lnode, operation_status.unsupp))
+	    return False
+
Index: fedd/federation/experiment_control.py
===================================================================
--- fedd/federation/experiment_control.py	(revision 22a1a77015d7254a2c8a9f81b420a91df69516f5)
+++ fedd/federation/experiment_control.py	(revision b709861c37a497e1ae0e4e757f53e205aa0440ec)
@@ -2391,5 +2391,5 @@
 		    results.append(operation_status(t, 
 			operation_status.federant,
-			'Unexpected error ion %s' % tb))
+			'Unexpected error on %s' % tb))
 	# Clean up the tmpdir no matter what
 	finally:
@@ -2412,4 +2412,11 @@
 	    else: return { }
 
+	def element_name(e):
+	    if isinstance(e, topdl.Computer): return e.name
+	    elif isinstance(e, topdl.Testbed): 
+		if e.localname: return e.localname[0]
+		else: return None
+	    else: return None
+
         req = req.get('OperationRequestBody', None)
         if not req:
@@ -2418,5 +2425,5 @@
         exp = req.get('experiment', None)
 	op = req.get('operation', None)
-	target = set(req.get('target', []))
+	targets = set(req.get('target', []))
 	params = req.get('parameter', None)
 
@@ -2433,5 +2440,5 @@
             raise service_error(service_error.req, "No request?")
 
-	if op is None or not target
+	if op is None or not targets:
             raise service_error(service_error.req, "No request?")
 
@@ -2440,5 +2447,6 @@
 	if key in self.state:
 	    d1, op_params, cert, d2 = \
-		    self.get_segment_info(self.state[key], need_lock=False)
+		    self.get_segment_info(self.state[key], need_lock=False,
+			    key='tb')
 	    top = self.state[key].top
 	    if top is not None:
@@ -2453,9 +2461,11 @@
 	results = []
 	for e in top.elements:
-	    if e.name in targets:
+	    ename = element_name(e)
+	    if ename in targets:
 		tb = element_to_tb(e)
+		targets.remove(ename)
 		if tb is not None:
-		    if tb in testbeds: testbeds[tb].append(e.name)
-		    else: testbeds[tb] = [ e.name ]
+		    if tb in testbeds: testbeds[tb].append(ename)
+		    else: testbeds[tb] = [ ename ]
 		else:
 		    results.append(operation_status(e.name, 
@@ -2463,4 +2473,7 @@
 			description='Cannot map target to testbed'))
 
+	for t in targets:
+	    results.append(operation_status(t, operation_status.no_target))
+
 	self.operate_on_segments(op_params, cert, op, testbeds, params,
 		results)
@@ -2468,5 +2481,5 @@
 	return { 
 		'experiment': exp, 
-		'status': [make_dict(r) for r in results]
+		'status': [make_dict(r) for r in results],
 		'proof': proof.to_dict()
 		}
@@ -2524,5 +2537,5 @@
 		    "Experiment has no status!?")
 
-    def get_segment_info(self, fed_exp, need_lock=True):
+    def get_segment_info(self, fed_exp, need_lock=True, key='aid'):
 	ids = []
 	term_params = { }
@@ -2537,5 +2550,7 @@
 	    uri = fed.uri
 	    aid = fed.allocID
-	    term_params[aid] = (uri, aid)
+	    if key == 'aid': term_params[aid] = (uri, aid)
+	    elif key == 'tb': term_params[fed.tb] = (uri, aid)
+
 	if need_lock: self.state_lock.release()
 	return ids, term_params, expcert, repo
Index: fedd/federation/local_emulab_segment.py
===================================================================
--- fedd/federation/local_emulab_segment.py	(revision 22a1a77015d7254a2c8a9f81b420a91df69516f5)
+++ fedd/federation/local_emulab_segment.py	(revision b709861c37a497e1ae0e4e757f53e205aa0440ec)
@@ -132,2 +132,14 @@
 	self.get_mapping(pid,eid)
 	return True
+
+class operation_segment(local_segment, emulab_segment):
+    def __init__(self, log=None, keyfile=None, debug=False, boss=None, 
+	    cert=None):
+	local_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
+	emulab_segment.__init__(self, boss=boss, cert=cert)
+
+    def __call__(self, parent, op, targets, param):
+	for l, p in targets.items():
+	    self.log.info("[operation_segment]: Calling op on %s(%s)" % (l,p))
+	    self.do_operation(op, l, p, param)
+	return True
