[Cluster-devel] conga/luci/site/luci/Extensions LuciClusterInf ...

rmccabe at sourceware.org rmccabe at sourceware.org
Thu Jul 26 05:52:54 UTC 2007


CVSROOT:	/cvs/cluster
Module name:	conga
Branch: 	RHEL5
Changes by:	rmccabe at sourceware.org	2007-07-26 05:52:54

Modified files:
	luci/site/luci/Extensions: LuciClusterInfo.py 
	                           cluster_adapters.py 

Log message:
	Fixes for 249086

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LuciClusterInfo.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1.4.3&r2=1.1.4.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/cluster_adapters.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.120.2.33&r2=1.120.2.34

--- conga/luci/site/luci/Extensions/LuciClusterInfo.py	2007/07/16 21:35:17	1.1.4.3
+++ conga/luci/site/luci/Extensions/LuciClusterInfo.py	2007/07/26 05:52:54	1.1.4.4
@@ -6,7 +6,6 @@
 # Free Software Foundation.
 
 from Products.Archetypes.utils import make_uuid
-from ClusterModel.GeneralError import GeneralError
 from ClusterModel.ModelBuilder import ModelBuilder
 import RicciQueries as rq
 from ricci_communicator import RicciCommunicator
@@ -124,29 +123,28 @@
 	return results
 
 def getClusterStatus(self, request, rc, cluname=None):
-
 	try:
-		doc = rq.getClusterStatusBatch(rc)
-		if not doc:
-			raise Exception, 'doc is None'
+		doc = rq.getClusterStatusBatch(rc) or None
 	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('GCS0: error: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('GCS0: error: %r: %r %s' \
+				% (cluname, e, str(e)))
 		doc = None
 
-	if doc is None and not cluname:
-		try:
-			model = request.SESSION.get('model')
-			cinfo = getClusterStatusModel(model)
-			if not cinfo or len(cinfo) < 1:
-				raise Exception, 'cinfo is None'
-			return cinfo
-		except Exception, e:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('GCS1: %r %s' % (e, str(e)))
-			doc = None
+	if doc is None:
+		model = LuciExtractCluModel(self, request, cluname)
+		if model is not None:
+			try:
+				cinfo = getClusterStatusModel(model)
+				if not cinfo or len(cinfo) < 1:
+					raise Exception, 'cinfo is None'
+				return cinfo
+			except Exception, e:
+				if LUCI_DEBUG_MODE is True:
+					luci_log.debug_verbose('GCS1: %r: %r %s' \
+						% (cluname, e, str(e)))
 
-	if not doc:
+	if doc is None:
 		try:
 			from LuciDB import getClusterStatusDB
 			if cluname:
@@ -157,13 +155,15 @@
 				clustername = fvars['clustername']
 				if clustername is None:
 					raise Exception, 'unable to determine cluster name'
+
 			cinfo = getClusterStatusDB(self, clustername)
 			if not cinfo or len(cinfo) < 1:
 				raise Exception, 'cinfo is None'
 			return cinfo
 		except Exception, e:
 			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('GCS1a: unable to get cluster info from DB: %r %s' % (e, str(e)))
+				luci_log.debug_verbose('GCS2: cluster %r info from DB: %r %s' \
+					% (cluname, e, str(e)))
 		return []
 
 	results = list()
@@ -702,11 +702,13 @@
 
 def getClustersInfo(self, status, req):
 	clu_map = {}
+
+	fvars = GetReqVars(req, [ 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+
 	nodelist = list()
 	svclist = list()
 	clulist = list()
-	baseurl = req['URL']
-
 	for item in status:
 		if item['type'] == 'node':
 			nodelist.append(item)
@@ -716,11 +718,14 @@
 			clulist.append(item)
 		else:
 			continue
+
 	if len(clulist) < 1:
 		return {}
 	clu = clulist[0]
-	if 'error' in clu:
-		clu_map['error'] = True
+	if clu.has_key('error'):
+		clu_map['error'] = clu['error']
+	if clu.has_key('errmsg'):
+		clu_map['errmsg'] = clu['errmsg']
 	clustername = clu['name']
 	if not clu['alias']:
 		clu_map['clusteralias'] = clu['alias']
@@ -791,7 +796,8 @@
 def getNodeInfo(self, model, status, request):
 	infohash = {}
 	item = None
-	baseurl = request['URL']
+	fvars = GetReqVars(request, [ 'URL', 'clustername', 'nodename' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
 
 	nodestate = NODE_ACTIVE
 	svclist = list()
@@ -799,13 +805,12 @@
 		if thing['type'] == 'service':
 			svclist.append(thing)
 
-	# Get cluster name and node name from request
-	try:
-		clustername = request['clustername']
-		nodename = request['nodename']
-	except Exception, e:
+	clustername = fvars['clustername']
+	nodename = fvars['nodename']
+	if clustername is None or nodename is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('getNodeInfo0: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('getNodeInfo0: %r %r' \
+				% (clustername, nodename))
 		return {}
 
 	# extract correct node line from cluster status
@@ -903,7 +908,7 @@
 		try:
 			rc = RicciCommunicator(nodename_resolved)
 			if not rc:
-				raise Exception, 'rc is none'
+				raise Exception, 'connection failed'
 		except Exception, e:
 			rc = None
 			infohash['ricci_error'] = True
@@ -933,6 +938,10 @@
 	nodelist = list()
 	svclist = list()
 
+	fvars = GetReqVars(req, [ 'URL', 'clustername' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+	clustername = fvars['clustername']
+
 	#Sort into lists...
 	for item in status:
 		if item['type'] == 'node':
@@ -942,24 +951,14 @@
 		else:
 			continue
 
-	try:
-		clustername = req['clustername']
-		if not clustername:
-			raise KeyError, 'clustername is blank'
-	except:
+	if clustername is None:
 		try:
-			clustername = req.form['clustername']
-			raise KeyError, 'clustername is blank'
-		except:
-			try:
-				clustername = req.form['clustername']
-			except:
-				try:
-					clustername = model.getClusterName()
-				except:
-					if LUCI_DEBUG_MODE is True:
-						luci_log.debug_verbose('GNI0: unable to determine cluster name')
-					return {}
+			clustername = model.getClusterName().strip()
+		except Exception, e:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('GNI0: no cluster name: %r %s' \
+					% (e, str(e)))
+			return {}
 
 	for item in nodelist:
 		nl_map = {}
@@ -971,11 +970,6 @@
 		except:
 			nl_map['gulm_lockserver'] = False
 
-		try:
-			baseurl = req['URL']
-		except:
-			baseurl = '/luci/cluster/index_html'
-
 		cfgurl = '%s?pagetype=%s&clustername=%s&nodename=%s' \
 			% (baseurl, NODE, clustername, name)
 		nl_map['configurl'] = cfgurl
@@ -1061,9 +1055,11 @@
 			luci_log.debug_verbose('getFence0: model is None')
 		return {}
 
-	fence_map = {}
-	fencename = request['fencename']
+	fvars = GetReqVars(request, [ 'URL', 'fencename' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+	fencename = fvars['fencename']
 
+	fence_map = {}
 	nodes = model.getNodes()
 	fencedevs = model.getFenceDevices()
 	clustername = model.getClusterName()
@@ -1093,7 +1089,6 @@
 									found_duplicate = True
 							if found_duplicate is True:
 								continue
-							baseurl = request['URL']
 							node_hash = {}
 							cur_nodename = node.getName().strip()
 							node_hash['nodename'] = cur_nodename
@@ -1148,7 +1143,7 @@
 	# is returned.
 	try:
 		node = model.retrieveNodeByName(nodename)
-	except GeneralError, e:
+	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('getFenceInfo3: unable to find node name "%s" in current node list: %r %s' % (str(nodename), e, str(e)))
 		return {}
@@ -1401,8 +1396,10 @@
 		fences_map['fencedevs'] = list()
 		return fences_map
 
-	clustername = request['clustername']
-	baseurl = request['URL']
+	fvars = GetReqVars(request, [ 'clustername', 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+	clustername = fvars['clustername'] or model.getClusterName()
+
 	fencedevs = list() #This is for the fencedev list page
 
 	#Get list of fence devices
@@ -1559,6 +1556,37 @@
 			luci_log.debug_verbose('GMFC1: unable to get model builder for %s: %r %s' % (clustername, e, str(e)))
 	return None
 
+def LuciExtractCluModel(self, request, cluster_name=None):
+	model = None
+	try:
+		model = request.SESSION.get('model')
+		model.getClusterName()
+		return model
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('LECM0: %r: %r %s' \
+				% (cluster_name, e, str(e)))
+		model = None
+
+	if not cluster_name:
+		fvar = GetReqVars(request, [ 'clustername' ])
+		cluster_name = fvar['clustername']
+
+	if cluster_name is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('LECM1: no cluster name')
+		return None
+
+	try:
+		model = getModelForCluster(self, cluster_name)
+		model.getClusterName()
+		return model
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('LECM2: no model for %s: %r %s' \
+				% (cluster_name, e, str(e)))
+	return None
+
 def getClusterOS(self, rc):
 	from HelperFunctions import resolveOSType
 
--- conga/luci/site/luci/Extensions/cluster_adapters.py	2007/07/26 04:36:34	1.120.2.33
+++ conga/luci/site/luci/Extensions/cluster_adapters.py	2007/07/26 05:52:54	1.120.2.34
@@ -19,16 +19,17 @@
 from ClusterModel.Heuristic import Heuristic
 from ClusterModel.Fence import Fence
 from ClusterModel.Method import Method
-from ClusterModel.GeneralError import GeneralError
 
 import RicciQueries as rq
 from HelperFunctions import resolveOSType
 from LuciSyslog import get_logger
 from ResourceHandler import create_resource
 from homebase_adapters import parseHostForm
-from LuciClusterInfo import getClusterInfo, getModelBuilder, getModelForCluster
 from LuciClusterActions import propagateClusterConfAsync
 
+from LuciClusterInfo import getClusterInfo, \
+	getModelBuilder, LuciExtractCluModel
+
 from conga_constants import BATCH_ID, CLUNODE_CREATE_ERRORS, \
 	CLUSTER_ADD, CLUSTER_CONFIG, CLUSTER_DAEMON, CLUSTER_DELETE, \
 	CLUSTER_FOLDER_PATH, CLUSTER_RESTART, CLUSTER_START, CLUSTER_STOP, \
@@ -43,8 +44,7 @@
 	REDIRECT_SEC, LUCI_CLUSTER_BASE_URL
 
 from FenceHandler import validateNewFenceDevice, \
-	validateFenceDevice, validate_fenceinstance, \
-	FD_VAL_FAIL, FD_VAL_SUCCESS
+	validateFenceDevice, validate_fenceinstance, FD_VAL_SUCCESS
 
 from ricci_communicator import RicciCommunicator, RicciError, \
 	batch_status, extract_module_status
@@ -547,8 +547,7 @@
 	try:
 		model = getModelBuilder(None, cluster_ricci, cluster_ricci.dom0())
 		if not model:
-			errors.append('Unable to build the cluster model for %s' \
-				% clustername)
+			errors.append('Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername)
 			raise Exception, 'unable to get model for %s' % clustername
 
 		nodesptr = model.getClusterNodesPtr()
@@ -562,8 +561,7 @@
 					% (node_name, clustername))
 	except Exception, e:
 		incomplete = True
-		errors.append('Unable to build the cluster model for %s' \
-			% clustername)
+		errors.append('Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername)
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('VACN11: %r %s' % (e, str(e)))
 
@@ -631,7 +629,7 @@
 			raise Exception, 'batch or result is None'
 	except Exception, e:
 		incomplete = True
-		errors.append('Unable to save the new cluster model')
+		errors.append('Unable to generate the new cluster configuration')
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('VACN14: %s' % e)
 
@@ -709,32 +707,28 @@
 		return (False, { 'errors': errors, 'messages': messages })
 
 	buildClusterCreateFlags(self, batch_id_map, clustername)
-
 	response = request.RESPONSE
 	response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
 		% (request['URL'], CLUSTER_CONFIG, clustername))
 
 def validateServiceAdd(self, request):
 	errors = list()
+	fvar = GetReqVars(request, [ 'form_xml', 'clustername', 'domain', 'recovery', 'svc_name', 'action', 'URL' ])
 
-	try:
-		form_xml = request['form_xml'].strip()
-		if not form_xml:
-			raise KeyError, 'form_xml must not be blank'
-	except Exception, e:
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
+	clustername = fvar['clustername']
+
+	form_xml = fvar['form_xml']
+	if form_xml is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vSA0: no form_xml: %r %s' \
-				% (e, str(e)))
+			luci_log.debug_verbose('vSA0: no form_xml')
 		return (False, { 'errors': [ 'No resource data was supplied for this service' ]})
 
-	try:
-		model = request.SESSION.get('model')
-		if not model:
-			raise Exception, 'model is None'
-	except Exception, e:
+	model = LuciExtractCluModel(self, request, clustername)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vSA0a: %r %s' % (e, str(e)))
-		return (False, { 'errors': [ 'The cluster model is missing from the session object' ]})
+			luci_log.debug_verbose('vSA1: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ]})
 
 	try:
 		doc = minidom.parseString(form_xml)
@@ -817,32 +811,17 @@
 	if len(errors) > 0:
 		return (False, {'errors': errors})
 
-	fdom = None
-	try:
-		fdom = request.form['domain'].strip()
-		if not fdom:
-			raise Exception, 'blank'
-	except:
-		fdom = None
+	fdom = fvar['domain']
 
-	recovery = None
-	try:
-		recovery = request.form['recovery'].strip()
-		if not recovery:
-			recovery = None
-		else:
-			if recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
-				errors.append('You entered an invalid recovery option: "%s" Valid options are "restart" "relocate" and "disable"')
-	except:
-		recovery = None
+	recovery = fvar['recovery']
+	if recovery is not None and recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
+		errors.append('You entered an invalid recovery option: "%s" Valid options are "restart" "relocate" and "disable."')
 
-	try:
-		service_name = request.form['svc_name'].strip()
-	except Exception, e:
+	service_name = fvar['svc_name']
+	if service_name is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vSA5: no service name: %r %s' \
-				% (e, str(e)))
-		return (False, { 'errors': [ 'No service name was given' ]})
+			luci_log.debug_verbose('vSA5: no service name')
+		errors.append('No service name was given')
 
 	autostart = '1'
 	try:
@@ -865,34 +844,28 @@
 
 	try:
 		cur_service = model.retrieveServiceByName(service_name)
-	except GeneralError, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vSA5b: no service named %s found: %r %s' \
-				% (service_name, e, str(e)))
-		cur_service = None
 	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('vSA5c: no service named %s found: %r %s' \
 				% (service_name, e, str(e)))
 		cur_service = None
 
-	try:
-		if request.form['action'] == 'edit':
-			if cur_service is None:
-				return (False, {'errors': [ 'The service %s could not be found for editing' % service_name ]})
-			model.deleteService(service_name)
-		elif request.form['action'] == 'add':
-			if cur_service is not None:
-				return (False, {'errors': [ 'A service with the name %s already exists' % service_name ]})
-		else:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('vSA4a: unknown action %s' \
-					% request.form['action'])
-			return (False, {'errors': [ 'An unknown action was specified' ]})
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vSA5: no action type: %r %s' \
-				% (e, str(e)))
+	action = fvar['action']
+	if action is None:
+		return (False, {'errors': [ 'No action was given for service %s' % service_name ] })
+
+	if action == 'edit':
+		if cur_service is None:
+			return (False, {'errors': [ 'The service %s could not be found for editing' % service_name ]})
+		model.deleteService(service_name)
+	elif action == 'add':
+		if cur_service is not None:
+			return (False, {'errors': [ 'A service with the name %s already exists' % service_name ]})
+	else:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vSA4a: unknown action %s' \
+				% request.form['action'])
+		return (False, {'errors': [ 'An unknown action was specified' ]})
 
 	def buildSvcTree(parent, child_id_list):
 		for i in child_id_list:
@@ -922,7 +895,7 @@
 	model.resourcemanager_ptr.addChild(new_service)
 	model.setModified(True)
 
-	if request.form['action'].strip().lower() == 'edit':
+	if action == 'edit':
 		action_type = SERVICE_CONFIG
 		action_msg = 'Configuring service "%s"'
 	else:
@@ -931,12 +904,12 @@
 
 	ret = propagateClusterConfAsync(self, model, rc=None,
 			action=action_type, pmsg=action_msg % service_name)
-	if ret[0] is False:
+	if ret[0] is not True:
 		return ret
 
 	response = request.RESPONSE
 	response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-		% (request['URL'], SERVICES, model.getClusterName()))
+		% (baseurl, SERVICES, model.getClusterName()))
 
 def validateResourceAdd(self, request):
 	try:
@@ -948,12 +921,11 @@
 			luci_log.debug_verbose('VRA0: type is blank')
 		return (False, {'errors': ['No resource type was given']})
 
-	try:
-		model = request.SESSION.get('model')
-	except Exception, e:
+	model = LuciExtractCluModel(self, request)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VRA1: no model: %r %s' % (e, str(e)))
-		return None
+			luci_log.debug_verbose('VRA1: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration. The configuration XML may contain errors' ]})
 
 	errors = list()
 	try:
@@ -973,15 +945,12 @@
 			luci_log.debug_verbose('resource error: %r %s' % (e, str(e)))
 		return (False, { 'errors': errors})
 
-
 	return (True, { 'messages': [ 'Resource added successfully' ]})
 
-
 ## Cluster properties form validation routines
 
 # rhel5 cluster version
 def validateMCastConfig(model, form):
-	import socket
 	try:
 		gulm_ptr = model.getGULMPtr()
 		if gulm_ptr:
@@ -1003,6 +972,7 @@
 		return (False, {'errors': errors})
 
 	if mcast_manual is True:
+		import socket
 		try:
 			addr_str = form['mcast_address'].strip()
 			socket.inet_pton(socket.AF_INET, addr_str)
@@ -1220,9 +1190,6 @@
 		version_num = int(form['cfgver'])
 		if version_num < old_ver:
 			raise ValueError, 'configuration version number must be %d or greater' % old_ver
-		if version_num != old_ver:
-			# we'll increment the cluster version before propagating it.
-			version_num -= 1
 	except KeyError, e:
 		errors.append('No cluster configuration version was given')
 	except ValueError, e:
@@ -1268,13 +1235,13 @@
 		errors.append(str(e))
 
 	try:
-		token_retransmits_before_loss_const = form['token_retransmits_before_loss_const'].strip()
-		if not token_retransmits_before_loss_const:
+		trblc = form['token_retransmits_before_loss_const'].strip()
+		if not trblc:
 			raise KeyError, 'token_retransmits_before_loss_const'
-		token_retransmits_before_loss_const = int(token_retransmits_before_loss_const)
-		if token_retransmits_before_loss_const < 1:
-			raise ValueError, '%d is an invalid value for number of token retransmits before loss' % token_retransmits_before_loss_const
-		totem.addAttribute('token_retransmits_before_loss_const', str(token_retransmits_before_loss_const))
+		trblc = int(trblc)
+		if trblc < 1:
+			raise ValueError, '%d is an invalid value for number of token retransmits before loss' % trblc
+		totem.addAttribute('token_retransmits_before_loss_const', str(trblc))
 	except KeyError, e:
 		try:
 			totem.removeAttribute('token_retransmits_before_loss_const')
@@ -1381,7 +1348,7 @@
 		return (False, {'errors': [ 'This cluster appears not to be using GULM locking' ]})
 
 	node_list = map(lambda x: x.getName(), gulm_ptr.getChildren())
-	for i in map(lambda x: x.getName(), model.getNodes()):
+	for i in model.getNodeNames():
 		if not i in node_list:
 			node_list.append(i)
 
@@ -1421,338 +1388,180 @@
 def validateConfigCluster(self, request):
 	errors = list()
 	messages = list()
-	rc = None
+	fvar = GetReqVars(request, [ 'configtype', 'clustername', 'URL' ])
 
-	try:
-		model = LuciExtractCluModel(self, request)
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VCC0a: no model, no cluster name')
-		return (False, {'errors': ['No cluster model was found']})
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
+	clustername = fvar['clustername']
 
-	try:
-		if not request.form.has_key('configtype'):
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VCC2: no configtype')
-			raise Exception, 'no config type'
-	except Exception, e:
+	model = LuciExtractCluModel(self, request, clustername)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VCC2a: %r %s' % (e, str(e)))
-		return (False, {'errors': [ 'No configuration type was submitted' ]})
+			luci_log.debug_verbose('VCC0: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ]})
+
+	if clustername is None:
+		clustername = model.getClusterName()
 
-	if not configFormValidators.has_key(request.form['configtype']):
+	config_type = fvar['configtype']
+	if config_type is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VCC3: invalid config type: %s' \
-				% request.form['configtype'])
-		return (False, { 'errors': [ 'An invalid configuration type was submitted' ]})
+			luci_log.debug_verbose('VCC1: no config type')
+		return (False, {'errors': [ 'No configuration type was given' ]})
 
-	try:
-		cp = model.getClusterPtr()
-	except:
+	if not configFormValidators.has_key(config_type):
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VCC3a: getClusterPtr failed')
-		return (False, {'errors': ['No cluster model was found']})
+			luci_log.debug_verbose('VCC2: invalid config type: %s' \
+				% config_type)
+		return (False, { 'errors': [ 'An invalid configuration type "%s" was submitted' % config_type ]})
 
-	config_validator = configFormValidators[request.form['configtype']]
+	config_validator = configFormValidators[config_type]
 	ret = config_validator(model, request.form)
 
 	retcode = ret[0]
-	if 'errors' in ret[1]:
+	if ret[1].has_key('errors'):
 		errors.extend(ret[1]['errors'])
-
-	if 'messages' in ret[1]:
+	if ret[1].has_key('messages'):
 		messages.extend(ret[1]['messages'])
 
-	if retcode is True:
-		try:
-			config_ver = int(cp.getConfigVersion()) + 1
-			# always increment the configuration version
-			cp.setConfigVersion(str(config_ver))
-			model.setModified(True)
-			conf_str = model.exportModelAsString()
-			if not conf_str:
-				raise Exception, 'conf_str is none'
-		except Exception, e:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VCC4: export model as string failed: %r %s' % (e, str(e)))
-			errors.append('Unable to store the new cluster configuration')
-
-	try:
-		clustername = model.getClusterName()
-		if not clustername:
-			raise Exception, 'cluster name from model.getClusterName() is blank'
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VCC5: error: getClusterName: %r %s' \
-				% (e, str(e)))
-		errors.append('Unable to determine cluster name from model')
-
-	if len(errors) > 0:
-		return (retcode, {'errors': errors, 'messages': messages})
-
-	if not rc:
-		rc = getRicciAgent(self, clustername)
-	if not rc:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VCC6: unable to find a ricci agent for the %s cluster' % clustername)
-		errors.append('Unable to contact a ricci agent for cluster %s' \
-			% clustername)
-
-	if rc:
-		batch_id, result = rq.setClusterConf(rc, str(conf_str))
-		if batch_id is None or result is None:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VCC7: setCluserConf: batchid or result is None')
-			errors.append('Unable to propagate the new cluster configuration for %s' % clustername)
-		else:
-			try:
-				set_node_flag(self, clustername, rc.hostname(), batch_id, CLUSTER_CONFIG, 'Updating cluster configuration')
-			except:
-				pass
+	if retcode is not True or len(errors) > 0:
+		return (False, {'errors': errors, 'messages': messages})
 
-	if len(errors) < 1:
-		messages.append('The cluster properties have been updated')
-	else:
+	ret = propagateClusterConfAsync(self, model, None,
+			CLUSTER_CONFIG, 'Updating cluster configuration')
+	if ret[0] is not True:
+		if ret[1].has_key('errors'):
+			errors.extend(ret[1]['errors'])
 		return (retcode, {'errors': errors, 'messages': messages})
 
-	response = request.RESPONSE
-	response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-		% (request['URL'], CLUSTER_CONFIG, clustername))
-
-def LuciExtractCluModel(self, request, cluster_name=None):
-	if not cluster_name:
-		fvar = GetReqVars(request, [ 'clustername' ])
-		cluster_name = fvar['clustername']
-		if cluster_name is None:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('LECM0: no cluster name')
-
-	model = None
-	try:
-		model = request.SESSION.get('model')
-		if not model:
-			model = None
-	except Exception, e:
-		model = None
-
-	try:
-		model = getModelForCluster(self, cluster_name)
-		if not model:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('LECM1: empty model')
-			model = None
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('LECM2: no model: %r %s' % (e, str(e)))
-		model = None
-	return model
+	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
+		% (baseurl, CLUSTER_CONFIG, clustername))
 
 def validateFenceAdd(self, request):
 	errors = list()
+	fvar = GetReqVars(request, [ 'clustername', 'URL' ])
 
-	model = LuciExtractCluModel(self, request)
-
-	if not model:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VFE0: no model')
-		return (False, [ 'No cluster model was found' ])
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
+	clustername = fvar['clustername']
 
-	if not request.form:
+	model = LuciExtractCluModel(self, request, clustername)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VFE: no form was submitted')
-		return (False, [ 'No form was submitted' ])
+			luci_log.debug_verbose('VFA0: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ] })
 
 	ret_code, ret_obj = validateNewFenceDevice(request.form, model)
 	if ret_code != FD_VAL_SUCCESS:
 		errors.extend(ret_obj)
-		return (False, errors)
+		return (False, { 'errors': errors })
 
-	try:
-		conf_str = str(model.exportModelAsString())
-		if not conf_str:
-			raise Exception, 'conf_str is none'
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VFE: export model as string failed: %r %s' \
-				% (e, str(e)))
-		errors.append('Unable to store the new cluster configuration')
+	ret = propagateClusterConfAsync(self, model, None,
+			CLUSTER_CONFIG, 'Creating fence device "%s"' % ret_obj)
+	if ret[0] is not True:
+		return ret
 
-	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&fencename=%s&busyfirst=true' % (request['URL'], FENCEDEV, model.getClusterName(), ret_obj))
+	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&fencename=%s&busyfirst=true' % (baseurl, FENCEDEV, clustername, ret_obj))
 
 def validateFenceEdit(self, request):
 	errors = list()
-	messages = list()
-	rc = None
 
-	try:
-		model = request.SESSION.get('model')
-		if not model:
-			raise Exception, 'model is none'
-	except Exception, e:
-		model = None
-		try:
-			cluname = request.form['clustername']
-		except:
-			try:
-				cluname = request['clustername']
-			except:
-				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('VFE: no model, no cluster name')
-				return (False, {'errors': ['No cluster model was found']})
-
-		try:
-			model = getModelForCluster(self, cluname)
-		except:
-			model = None
-
-		if model is None:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VFE: unable to get model from session')
-			return (False, {'errors': ['No cluster model was found']})
+	fvar = GetReqVars(request, [ 'clustername', 'URL' ])
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
 
-	form = None
-	try:
-		response = request.response
-		form = request.form
-		if not form:
-			form = None
-			raise Exception, 'no form was submitted'
-	except:
-		pass
+	clustername = fvar['clustername']
+	if clustername is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('VFE0: No cluster name')
+		return (False, {'errors': ['No cluster name was given']})
 
-	if form is None:
+	model = LuciExtractCluModel(self, request, clustername)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VFE: no form was submitted')
-		return (False, {'errors': ['No form was submitted']})
+			luci_log.debug_verbose('VFE1: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ] })
 
 	# This is a fence edit situation, so the model should already have an
 	# entry for this fence device.
 	#
 	# pass form and model to validation method, then save changes if it passes.
-	error_code, retobj = validateFenceDevice(form, model)
-	if error_code == FD_VAL_SUCCESS:
-		try:
-			conf_str = model.exportModelAsString()
-			if not conf_str:
-				raise Exception, 'conf_str is none'
-		except Exception, e:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VFE: export model as string failed: %r %s' % (e, str(e)))
-			errors.append('Unable to store the new cluster configuration')
-
-		try:
-			clustername = model.getClusterName()
-			if not clustername:
-				raise Exception, 'cluster name from model.getClusterName() is blank'
-		except Exception, e:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VFA: error: getClusterName: %r %s' \
-					% (e, str(e)))
-			errors.append('Unable to determine cluster name from model')
+	error_code, retobj = validateFenceDevice(request.form, model)
+	if error_code != FD_VAL_SUCCESS:
+		errors.extend(retobj)
+		return (False, { 'errors': errors })
 
-		if not rc:
-			rc = getRicciAgent(self, clustername)
-			if not rc:
-				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('VFA: unable to find a ricci agent for the %s cluster' % clustername)
-				errors.append('Unable to contact a ricci agent for cluster %s' \
-					% clustername)
-
-		if rc:
-			batch_id, result = rq.setClusterConf(rc, str(conf_str))
-			if batch_id is None or result is None:
-				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('VFA: setClusterConf: batchid or result is None')
-				errors.append('Unable to propagate the new cluster configuration for %s' \
-					% clustername)
-			else:
-				try:
-					set_node_flag(self, clustername, rc.hostname(), batch_id,
-						CLUSTER_CONFIG, 'Updating fence device "%s"' % retobj)
-				except:
-					pass
+	ret = propagateClusterConfAsync(self, model, None,
+			CLUSTER_CONFIG, 'Updating fence device "%s"' % retobj)
+	if ret[0] is not True:
+		return ret
 
-		response.redirect('%s?pagetype=%s&clustername=%s&fencename=%s&busyfirst=true' % (request['URL'], FENCEDEV, clustername, retobj))
-	else:
-		errors.extend(retobj)
-		return (False, {'errors': errors, 'messages': messages})
+	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&fencename=%s&busyfirst=true' % (baseurl, FENCEDEV, clustername, retobj))
 
 def validateNodeFenceConfig(self, request):
 	errors = list()
+	fvar = GetReqVars(request,
+			[ 'fence_xml', 'fence_level', 'nodename', 'clustername', 'URL' ])
 
-	try:
-		form_xml = request['fence_xml'].strip()
-		if not form_xml:
-			raise KeyError, 'form_xml must not be blank'
-	except Exception, e:
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
+
+	if fvar['fence_xml'] is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC0: no form_xml: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('vNFC0: no fence_xml for node %s' \
+				% fvar['nodename'])
 		return (False, {'errors': ['No fence data was supplied']})
 
-	try:
-		fence_level = int(request.form['fence_level'].strip())
-	except Exception, e:
+	if fvar['fence_level'] is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC1: no fence level: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('vNFC1: no fence level for %s' \
+				% fvar['nodename'])
 		return (False, {'errors': ['No fence level was supplied']})
 
 	try:
-		nodename = request['nodename']
-		if not nodename:
-			raise Exception, 'nodename is blank'
+		fence_level = int(fvar['fence_level'])
 	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC2: no nodename: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('vNFC2: invalid fence level: %s: %r %s' \
+				% (fvar['fence_level'], e, str(e)))
+		return (False, {'errors': ['"%s" is an invalid fence level' % fvar['fence_level'] ]})
+
+	nodename = fvar['nodename']
+	if nodename is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('vNFC3: no nodename: %r %s' % (e, str(e)))
 		return (False, {'errors': ['No node name was given']})
 
-	try:
-		clustername = request['clustername']
-		if not clustername:
-			raise Exception, 'clustername is blank'
-	except Exception, e:
+	clustername = fvar['clustername']
+	if clustername is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC3: no clustername: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('vNFC4: no clustername: %r %s' % (e, str(e)))
 		return (False, {'errors': ['No cluster name was given']})
 
-	try:
-		model = request.SESSION.get('model')
-		if not model:
-			raise Exception, 'model is none'
-	except Exception, e:
-		model = None
-		try:
-			model = getModelForCluster(self, clustername)
-		except:
-			model = None
-
+	model = LuciExtractCluModel(self, request, clustername)
 	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC4: unable to get model for cluster %s' % clustername)
-		return (False, {'errors': ['No cluster model was found']})
+			luci_log.debug_verbose('vNFC6: no model for %s' % clustername)
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ] })
 
 	try:
-		doc = minidom.parseString(form_xml)
+		doc = minidom.parseString(fvar['fence_xml'])
 	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC5: error: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('vNFC7: error: %r %s' % (e, str(e)))
 		return (False, {'errors': ['The fence data submitted is not properly formed']})
 
 	try:
 		node = model.retrieveNodeByName(nodename)
-	except GeneralError, e:
+	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC6: unable to find node name %s in current node list: %r %s' % (str(nodename), e, str(e)))
-		return (False, {'errors': ['Unable to find the cluster node %s in the node list' % str(nodename) ]})
+			luci_log.debug_verbose('vNFC8: unable to find node name %s in current node list: %r %s' % (nodename, e, str(e)))
+		return (False, {'errors': ['Unable to find the cluster node %s in the node list' % nodename ]})
 
-	fence_level_num = int(fence_level)
 	levels = node.getFenceLevels()
 	try:
-		method_id = levels[fence_level_num - 1].getAttribute('name')
+		method_id = levels[fence_level - 1].getAttribute('name')
 		if not method_id:
 			raise Exception, 'No method ID'
 		fence_method = Method()
 		fence_method.addAttribute('name', str(method_id))
-		levels[fence_level_num - 1] = fence_method
+		levels[fence_level - 1] = fence_method
 	except Exception, e:
 		method_id = fence_level
 		fence_method = Method()
@@ -1771,7 +1580,7 @@
 				node.getChildren()[0].removeChild(delete_target)
 			except Exception, e:
 				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('vNFC6a: %s: %r %s' \
+					luci_log.debug_verbose('vNFC9: %s: %r %s' \
 						% (method_id, e, str(e)))
 				return (False, {'errors': ['An error occurred while deleting fence method %s' % method_id ]})
 		else:
@@ -1793,7 +1602,7 @@
 				input_type = str(i.getAttribute('type'))
 			except Exception, e:
 				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('vNFC7: input type: %r %s' \
+					luci_log.debug_verbose('vNFC10: input type: %r %s' \
 						% (e, str(e)))
 				continue
 
@@ -1804,7 +1613,7 @@
 				dummy_form[str(i.getAttribute('name'))] = str(i.getAttribute('value'))
 			except Exception, e:
 				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('vNFC8: parsing XML: %r %s' \
+					luci_log.debug_verbose('vNFC11: parsing XML: %r %s' \
 						% (e, str(e)))
 
 		if len(dummy_form) < 1:
@@ -1815,7 +1624,7 @@
 				parent = dummy_form['parent_fencedev']
 			except:
 				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('vNFC9: no parent for instance')
+					luci_log.debug_verbose('vNFC12: no parent for instance')
 				return (False, {'errors': [ 'Unable to determine what device the current instance uses' ]})
 
 			try:
@@ -1823,7 +1632,7 @@
 				del dummy_form['fence_instance']
 			except Exception, e:
 				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('vNFC10: no parent for instance')
+					luci_log.debug_verbose('vNFC13: no parent for instance')
 				return (False, {'errors': [ 'Unable to determine what device the current instance uses' ]})
 		else:
 			form_hash[form_id] = (dummy_form, list())
@@ -1838,7 +1647,7 @@
 			fence_form, instance_list = form_hash[i]
 		except Exception, e:
 			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('vNFC11: %r %s' % (e, str(e)))
+				luci_log.debug_verbose('vNFC14: %r %s' % (e, str(e)))
 			continue
 
 		try:
@@ -1847,10 +1656,10 @@
 				raise Exception, 'fence type is blank'
 		except Exception, e:
 			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('vNFC12: %s: %r %s' % (i, e, str(e)))
+				luci_log.debug_verbose('vNFC15: %s: %r %s' % (i, e, str(e)))
 			fence_type = None
 
-		if 'existing_device' in fence_form:
+		if fence_form.has_key('existing_device'):
 			try:
 				fencedev_name = fence_form['name']
 				if not fencedev_name.strip():
@@ -1865,7 +1674,7 @@
 				# All we care about is its name.
 				fencedev_unknown = True
 			else:
-				if not 'sharable' in fence_form:
+				if not fence_form.has_key('sharable'):
 					# If it's a shared fence device that already exists, the
 					# user could not have edited it (without playing dirty
 					# games), so it's safe to pull the existing entry from
@@ -1899,7 +1708,7 @@
 			# If it's not shared, we need to create an instance form
 			# so the appropriate XML goes into the <method> block inside
 			# <node><fence>. All we need for that is the device name.
-			if not 'sharable' in fence_form:
+			if not fence_form.has_key('sharable'):
 				if type == 'fence_manual':
 					instance_list.append({'name': fencedev_name, 'nodename': nodename })
 				else:
@@ -1938,215 +1747,100 @@
 	if len(errors) > 0:
 		return (False, {'errors': errors })
 
-	try:
-		model.setModified(True)
-		conf = str(model.exportModelAsString())
-		if not conf:
-			raise Exception, 'model string is blank'
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC16: exported "%s"' % conf)
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC17: exportModelAsString failed: %r %s' \
-				% (e, str(e)))
-		return (False, {'errors': [ 'An error occurred while constructing the new cluster configuration' ]})
-
-	rc = getRicciAgent(self, clustername)
-	if not rc:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC18: unable to find a ricci agent for cluster %s' % clustername)
-		return (False, {'errors': ['Unable to find a ricci agent for the %s cluster' % clustername ]})
-	ragent = rc.hostname()
-
-	batch_number, result = rq.setClusterConf(rc, conf)
-	if batch_number is None or result is None:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC19: missing batch and/or result')
-		return (False, {'errors': [ 'An error occurred while constructing the new cluster configuration' ]})
-
-	try:
-		set_node_flag(self, clustername, ragent, str(batch_number), FENCEDEV_NODE_CONFIG, "Updating fence configuration for node \'%s\'" % nodename)
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('vNFC20: failed to set flags: %r %s' \
-				% (e, str(e)))
+	ret = propagateClusterConfAsync(self, model, None, FENCEDEV_NODE_CONFIG,
+			'Updating fence configuration for node "%s"' % fvar['nodename'])
+	if ret[0] is not True:
+		return ret
 
-	response = request.RESPONSE
-	response.redirect('%s?pagetype=%s&clustername=%s&nodename=%s&busyfirst=true' % (request['URL'], NODE, clustername, nodename))
+	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&nodename=%s&busyfirst=true' % (baseurl, NODE, clustername, nodename))
 
 def deleteFenceDevice(self, request):
 	errors = list()
-	messages = list()
-	rc = None
 
-	try:
-		model = request.SESSION.get('model')
-		if not model:
-			raise Exception, 'model is none'
-	except Exception, e:
-		model = None
-		try:
-			cluname = request.form['clustername']
-		except:
-			try:
-				cluname = request['clustername']
-			except:
-				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('VFE: no model, no cluster name')
-				return (False, {'errors': ['No cluster model was found']})
+	fvar = GetReqVars(request,
+			[ 'orig_name', 'nodename', 'clustername', 'URL' ])
 
-		try:
-			model = getModelForCluster(self, cluname)
-		except:
-			model = None
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
 
-		if model is None:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VFE: unable to get model from session')
-			return (False, {'errors': ['No cluster model was found']})
+	nodename = fvar['nodename']
+	if nodename is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('DFD0: no node name')
+		return (False, {'errors': ['No node name was given']})
 
-	form = None
-	try:
-		response = request.RESPONSE
-		form = request.form
-		if not form:
-			form = None
-			raise Exception, 'no form was submitted'
-	except:
-		pass
+	clustername = fvar['clustername']
+	if clustername is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('DFD1: no cluster name')
+		return (False, {'errors': ['No cluster name was given']})
 
-	if form is None:
+	model = LuciExtractCluModel(self, request, clustername)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VFE: no form was submitted')
-		return (False, {'errors': ['No form was submitted']})
+			luci_log.debug_verbose('DFD2: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ] })
 
-	#get name of fencedev
-	try:
-		fencedev_name = form['orig_name']
-		fencedev_name = fencedev_name.strip()
-	except KeyError, e:
-		return (False, {'errors':['No device name in form submission']})
+	fencedev_name = fvar['orig_name']
+	if fencedev_name is None:
+		return (False, {'errors': ['No device name in form submission']})
 
 	fdev_to_delete = None
-	#iterate thru list of current fencedevs and find one to be deleted
 	fdevs = model.getFenceDevices()
 	for fdev in fdevs:
 		if fdev.getName().strip() == fencedev_name:
 			fdev_to_delete = fdev
 			break
+
 	if fdev_to_delete is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VFD: Could not find fence device name in model')
-		return (False, {'errors':['Could not find fence device name in model']})
+			luci_log.debug_verbose('DFD3: Could not find fence device "%s" in model' % fencedev_name)
+		return (False, {'errors': ['Could not find fence device "%s" in model' % fencedev_name ]})
 
-	#get fencedev ptr
 	fdev_ptr = model.getFenceDevicePtr()
-	#remove child
 	try:
 		fdev_ptr.removeChild(fdev_to_delete)
-		error_code = FD_VAL_SUCCESS
-		error_string = "Fence device %s successfully removed from configuration" % fencedev_name
 	except:
-		error_code = FD_VAL_FAIL
-		error_string = "Fence device %s could not be removed from configuration" % fencedev_name
+		errors.append('Fence device "%s" could not be removed from configuration' % fencedev_name)
+		return (False, { 'errors': errors })
 
 	try:
 		model.removeFenceInstancesForFenceDevice(fencedev_name)
-	except:
+	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VFD: Could not remove fence instances for')
-
-
-	if error_code == FD_VAL_SUCCESS:
-		messages.append(error_string)
-		try:
-			model.setModified(True)
-			conf_str = model.exportModelAsString()
-			if not conf_str:
-				raise Exception, 'conf_str is none'
-		except Exception, e:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VFE: export model as string failed: %r %s' % (e, str(e)))
-			errors.append('Unable to store the new cluster configuration')
-
-		try:
-			clustername = model.getClusterName()
-			if not clustername:
-				raise Exception, 'cluster name from model.getClusterName() is blank'
-		except Exception, e:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VFA: error: getClusterName: %r %s' \
-					% (e, str(e)))
-			errors.append('Unable to determine cluster name from model')
+			luci_log.debug_verbose('DFD4: error removing %s: %r %s' \
+				% (fencedev_name, e, str(e)))
 
-		if not rc:
-			rc = getRicciAgent(self, clustername)
-			if not rc:
-				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('VFA: unable to find a ricci agent for the %s cluster' % clustername)
-				errors.append('Unable to contact a ricci agent for cluster %s' \
-				% clustername)
-
-		if rc:
-			batch_id, result = rq.setClusterConf(rc, str(conf_str))
-			if batch_id is None or result is None:
-				if LUCI_DEBUG_MODE is True:
-					luci_log.debug_verbose('VFA: setCluserConf: batchid or result is None')
-				errors.append('Unable to propagate the new cluster configuration for %s' \
-				% clustername)
-			else:
-				try:
-					set_node_flag(self, clustername, rc.hostname(), batch_id,
-						CLUSTER_CONFIG, 'Removing fence device "%s"' % fencedev_name)
-				except:
-					pass
+	ret = propagateClusterConfAsync(self, model, None, CLUSTER_CONFIG,
+			'Removing fence device "%s"' % fencedev_name)
+	if ret[0] is not True:
+		return ret
 
-		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-		% (request['URL'], FENCEDEVS, clustername))
-		return (True, {'errors': errors, 'messages': messages})
-	else:
-		errors.append(error_string)
-		return (False, {'errors': errors, 'messages': messages})
+	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
+		% (baseurl, FENCEDEVS, clustername))
 
 def validateDaemonProperties(self, request):
 	errors = list()
 
-	form = None
-	try:
-		response = request.response
-		form = request.form
-		if not form:
-			form = None
-			raise Exception, 'no form was submitted'
-	except:
-		pass
+	fvar = GetReqVars(request,
+			[ 'orig_name', 'nodename', 'clustername', 'URL' ])
 
-	if form is None:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VDP0: no form was submitted')
-		return (False, {'errors': ['No form was submitted']})
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
 
-	try:
-		nodename = form['nodename'].strip()
-		if not nodename:
-			raise Exception, 'nodename is blank'
-	except Exception, e:
-		errors.append('Unable to determine the current node name')
+	clustername = fvar['clustername']
+	if clustername is None:
+		errors.append('Unable to determine the current cluster name')
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VDP1: no nodename: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('VDP2: no clustername')
 
-	try:
-		clustername = form['clustername'].strip()
-		if not clustername:
-			raise Exception, 'clustername is blank'
-	except Exception, e:
-		errors.append('Unable to determine the current cluster name')
+	nodename = fvar['nodename']
+	if nodename is None:
+		errors.append('Unable to determine the current node name')
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('VDP2: no clustername: %r %s' % (e, str(e)))
+			luci_log.debug_verbose('VDP1: no nodename for %s' % clustername)
 
 	disable_list = list()
 	enable_list = list()
-	for i in form.items():
+	for i in request.form.items():
 		try:
 			if i[0][:11] == '__daemon__:':
 				daemon_prop = i[1]
@@ -2158,13 +1852,14 @@
 						enable_list.append(daemon_prop[0])
 		except Exception, e:
 			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('VDP3: error: %s' % str(i))
+				luci_log.debug_verbose('VDP3: error: %s: %r %s' \
+					% (str(i), e, str(e)))
 
 	if len(enable_list) < 1 and len(disable_list) < 1:
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('VDP4: no changes made')
-		response.redirect('%s?pagetype=%s&clustername=%s&nodename=%s' \
-			% (request['URL'], NODE, clustername, nodename))
+		request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&nodename=%s' \
+			% (baseurl, NODE, clustername, nodename))
 
 	nodename_resolved = resolve_nodename(self, clustername, nodename)
 	try:
@@ -2192,27 +1887,35 @@
 		if len(disable_list) > 0:
 			status_msg = 'Updating node "%s" daemon properties: disabling "%s"' \
 				% (nodename_resolved, str(disable_list)[1:-1])
-		set_node_flag(self, clustername, rc.hostname(), batch_id, CLUSTER_DAEMON, status_msg)
-	except:
-		pass
+		set_node_flag(self, clustername, rc.hostname(), batch_id,
+			CLUSTER_DAEMON, status_msg)
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('VDP: %r %s' % (e, str(e)))
 
 	if len(errors) > 0:
 		return (False, {'errors': errors})
 
-	response.redirect('%s?pagetype=%s&clustername=%s&nodename=%s&busyfirst=true' % (request['URL'], NODE, clustername, nodename))
+	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&nodename=%s&busyfirst=true' % (baseurl, NODE, clustername, nodename))
 
 def validateFdom(self, request):
 	errors = list()
+	fvar = GetReqVars(request, [ 'clustername', 'name', 'oldname', 'URL' ])
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
 
-	try:
-		model = request.SESSION.get('model')
-		if not model:
-			raise Exception, 'no model'
-	except Exception, e:
+	clustername = fvar['clustername']
+	if clustername is None:
+		errors.append('Unable to determine this cluster\'s name')
+
+	model = LuciExtractCluModel(self, request, clustername)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateFdom0: no model: %r %s' \
-				% (e, str(e)))
-		return (False, {'errors': [ 'Unable to retrieve cluster information' ]})
+			luci_log.debug_verbose('validateFdom0: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ]})
+
+	name = fvar['name']
+	if name is None:
+		errors.append('No name was given for this failover domain')
 
 	prioritized = False
 	try:
@@ -2226,39 +1929,7 @@
 	except:
 		restricted = False
 
-	clustername = None
-	try:
-		clustername = request.form['clustername'].strip()
-		if not clustername:
-			raise Exception, 'blank'
-	except:
-		try:
-			clustername = model.getClusterName()
-			if not clustername:
-				raise Exception, 'blank'
-		except:
-			clustername = None
-
-	if not clustername:
-		errors.append('Unable to determine this cluster\'s name')
-
-	try:
-		name = request.form['name'].strip()
-		if not name:
-			raise Exception, 'blank'
-	except Exception, e:
-		errors.append('No name was given for this failover domain')
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateFdom0: %r %s' \
-				% (e, str(e)))
-
-	oldname = None
-	try:
-		oldname = request.form['oldname'].strip()
-		if not oldname:
-			raise Exception, 'blank'
-	except:
-		pass
+	oldname = fvar['oldname']
 
 	if oldname is None or oldname != name:
 		if model.getFailoverDomainByName(name) is not None:
@@ -2291,9 +1962,7 @@
 	else:
 		fdom.addAttribute('restricted', '0')
 
-	cluster_nodes = map(lambda x: str(x.getName()), model.getNodes())
-
-	for i in cluster_nodes:
+	for i in model.getNodeNames():
 		if request.form.has_key(i):
 			fdn = FailoverDomainNode()
 			fdn.addAttribute('name', i)
@@ -2312,8 +1981,6 @@
 		fdom_ptr = model.getFailoverDomainPtr()
 		if not oldname:
 			fdom_ptr.addChild(fdom)
-		model.setModified(True)
-		conf = str(model.exportModelAsString())
 	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('validateFdom2: %r %s' % (e, str(e)))
@@ -2322,104 +1989,74 @@
 	if len(errors) > 0:
 		return (False, {'errors': errors })
 
-	rc = getRicciAgent(self, clustername)
-	if not rc:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateFdom3: unable to find a ricci agent for cluster %s' % clustername)
-		return (False, {'errors': ['Unable to find a ricci agent for the %s cluster' % clustername ]})
-	ragent = rc.hostname()
-
-	batch_number, result = rq.setClusterConf(rc, conf)
-	if batch_number is None or result is None:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateFdom4: missing batch and/or result')
-		return (False, {'errors': [ 'An error occurred while constructing the new cluster configuration' ]})
+	if oldname:
+		action = FDOM
+		status_msg = 'Updating failover domain "%s"' % oldname
+	else:
+		action = FDOM_ADD
+		status_msg = 'Creating failover domain "%s"' % name
 
-	try:
-		if oldname:
-			set_node_flag(self, clustername, ragent, str(batch_number), FDOM, 'Updating failover domain "%s"' % oldname)
-		else:
-			set_node_flag(self, clustername, ragent, str(batch_number), FDOM_ADD, 'Creating failover domain "%s"' % name)
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateFdom5: failed to set flags: %r %s' \
-				% (e, str(e)))
+	ret = propagateClusterConfAsync(self, model, None, action, status_msg)
+	if ret[0] is not True:
+		return ret
 
-	response = request.RESPONSE
-	response.redirect('%s?pagetype=%s&clustername=%s&fdomname=%s&busyfirst=true' \
-		% (request['URL'], FDOM, clustername, name))
+	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&fdomname=%s&busyfirst=true' % (baseurl, FDOM, clustername, name))
 
 def validateVM(self, request):
 	errors = list()
 
-	model = request.SESSION.get('model')
+	fvar = GetReqVars(request, [ 'clustername', 'vmname', 'oldname', 'vmpath', 'recovery', 'domain', 'URL' ])
 
-	try:
-		vm_name = request.form['vmname'].strip()
-		if not vm_name:
-			raise Exception, 'blank'
-	except Exception, e:
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
+
+	clustername = fvar['clustername']
+	if clustername is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateVM0: no vm name: %r %s' \
-				% (e, str(e)))
+			luci_log.debug_verbose('validateVM0: no cluster name was given')
+		return (False, {'errors': [ 'No cluster name was given' ]})
+
+	model = LuciExtractCluModel(self, request, clustername)
+	if model is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('validateVM1: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ]})
+
+	vm_name = fvar['vmname']
+	if vm_name is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('validateVM2: no vm name')
 		errors.append('No virtual machine name was given')
 
-	try:
-		vm_path = request.form['vmpath'].strip()
-		if not vm_path:
-			raise Exception, 'blank'
-	except Exception, e:
+	vm_path = fvar['vmpath']
+	if vm_path is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateVM1: no vm path: %r %s' \
-				% (e, str(e)))
-		errors.append('No path to the virtual machine configuration file was given')
+			luci_log.debug_verbose('validateVM3: no vm path')
+		errors.append('No path to the virtual machine configuration directory was given')
 
 	autostart = 1
-	try:
-		if request.form.has_key('autostart'):
-			autostart = 1
-		else:
-			autostart = 0
-	except:
+	if request.form.has_key('autostart'):
 		autostart = 1
+	else:
+		autostart = 0
 
 	exclusive = 0
-	try:
-		if request.form.has_key('exclusive'):
-			exclusive = 1
-		else:
-			exclusive = 0
-	except:
+	if request.form.has_key('exclusive'):
+		exclusive = 1
+	else:
 		exclusive = 0
 
-	recovery = None
-	try:
-		recovery = request.form['recovery'].strip()
-		if not recovery:
-			recovery = None
-		else:
-			if recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
-				errors.append('You entered an invalid recovery option: "%s" Valid options are "restart" "relocate" and "disable"')
-	except:
-		recovery = None
+	recovery = fvar['recovery']
+	if recovery is not None and recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
+		errors.append('You entered an invalid recovery option: "%s" Valid options are "restart" "relocate" and "disable"')
 
-	fdom = None
-	try:
-		fdom = request.form['domain'].strip()
-		if not fdom:
-			raise Exception, 'blank'
-	except:
-		fdom = None
+	fdom = fvar['domain']
 
 	if len(errors) > 0:
 		return (False, {'errors': errors })
 
 	isNew = False
-	try:
-		old_name = request.form['oldname'].strip()
-		if not old_name:
-			raise KeyError, 'oldname'
-	except KeyError, e:
+	old_name = fvar['oldname']
+	if old_name is None:
 		isNew = True
 
 	delete_vm = False
@@ -2468,61 +2105,36 @@
 		except:
 			pass
 
-	try:
-		model.setModified(True)
-		stringbuf = str(model.exportModelAsString())
-		if not stringbuf:
-			raise Exception, 'model is blank'
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateVM2: %r %s' % (e, str(e)))
-		errors.append('Unable to update the cluster model')
-
-	try:
-		clustername = model.getClusterName()
-		if not clustername:
-			raise Exception, 'cluster name from model.getClusterName() is blank'
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateVM3: %r %s' % (e, str(e)))
-		errors.append('Unable to determine the cluster name')
-
-	if len(errors) > 0:
-		return (False, {'errors': errors })
+	if delete_vm is True:
+		action = VM_CONFIG
+		status_msg = 'Deleting virtual machine service "%s"' % vm_name
+	elif isNew is True:
+		action = VM_ADD
+		status_msg = 'Creating virtual machine service "%s"' % vm_name
+	else:
+		action = VM_CONFIG
+		status_msg = 'Configuring virtual machine service "%s"' % vm_name
 
-	rc = getRicciAgent(self, clustername)
-	if not rc:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateVM4: no ricci for %s' % clustername)
-		return (False, {'errors': ['Unable to contact a ricci agent for this cluster']})
+	ret = propagateClusterConfAsync(self, model, None, action, status_msg)
+	if ret[0] is not True:
+		return ret
 
-	batch_number, result = rq.setClusterConf(rc, stringbuf)
-	if batch_number is None or result is None:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateVM5: missing batch and/or result')
-		return (False, {'errors': [ 'Error creating virtual machine %s' % vm_name ]})
+	request.RESPONSE.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
+		% (baseurl, SERVICES, clustername))
 
-	try:
-		if delete_vm is True:
-			set_node_flag(self, clustername, rc.hostname(), str(batch_number), VM_CONFIG, "Deleting virtual machine service \'%s\'" % vm_name)
-		elif isNew is True:
-			set_node_flag(self, clustername, rc.hostname(), str(batch_number), VM_ADD, "Creating virtual machine service \'%s\'" % vm_name)
-		else:
-			set_node_flag(self, clustername, rc.hostname(), str(batch_number), VM_CONFIG, "Configuring virtual machine service \'%s\'" % vm_name)
-	except Exception, e:
-		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('validateVM6: failed to set flags: %r %s' \
-				% (e, str(e)))
+def process_cluster_conf_editor(self, req):
+	if req.has_key('clustername'):
+		clustername = req['clustername'].strip() or None
+	else:
+		clustername = None
 
-	response = request.RESPONSE
-	response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-		% (request['URL'], SERVICES, clustername))
+	if clustername is None:
+		return { 'msg': 'No cluster name was given', 'cluster_conf': '' }
 
-def process_cluster_conf_editor(self, req):
-	clustername = req['clustername']
 	msg_list = list(('\n'))
-	cc = ''
-	if 'new_cluster_conf' in req:
+
+	cc = None
+	if req.has_key('new_cluster_conf'):
 		cc = req['new_cluster_conf']
 		msg_list.append('Checking if valid XML - ')
 		cc_xml = None
@@ -2543,14 +2155,10 @@
 				msg_list.append('Fix the error and try again:\n')
 			else:
 				msg_list.append('PASSED\n')
-
-				msg_list.append('Incrementing the cluster version number - ')
-				version = cc_xml.firstChild.getAttribute('config_version')
-				version = int(version) + 1
-				cc_xml.firstChild.setAttribute('config_version', str(version))
+				model.setModified(True)
 				msg_list.append('DONE\n')
-
 				msg_list.append('Propagating the new cluster.conf')
+
 				rc = getRicciAgent(self, clustername)
 				if not rc:
 					if LUCI_DEBUG_MODE is True:
@@ -2570,7 +2178,7 @@
 		if getClusterInfo(self, None, req) == {}:
 			msg_list.append('invalid cluster')
 		else:
-			model = req.SESSION.get('model')
+			model = LuciExtractCluModel(self, req, clustername)
 			cc = model.exportModelAsString()
 
 	return { 'msg': ''.join(msg_list), 'cluster_conf': cc }
@@ -2611,9 +2219,8 @@
 		return formValidators[pagetype](self, request)
 
 def getClusterURL(self, request, model):
-	
 	try:
-		clustername = request.clustername
+		clustername = request['clustername'].strip()
 		if not clustername:
 			raise Exception, 'cluster name from request is blank'
 	except:
@@ -2650,20 +2257,12 @@
 
 	if not model:
 		cluname = fvar['clustername']
-		if cluname is None:
-			if LUCI_DEBUG_MODE is True:
-				luci_log.debug('CTP1: no cluster name')
-			return 'No cluster name was given'
-
-		try:
-			model = getModelForCluster(self, cluname)
-			if not model:
-				raise Exception, 'No cluster model'
-		except Exception, e:
+		model = LuciExtractCluModel(self, request, cluname)
+		if model is None:
 			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('CTP2: GMFC failed for %s: %r %s' \
-					% (e, str(e), cluname))
-			return 'Unable to get the model object for %s' % cluname
+				luci_log.debug_verbose('CTP2: No cluster model for %s' \
+					% cluname)
+			return 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors.' % cluname
 
 	redirect_page = NODES
 	if task == CLUSTER_STOP:
@@ -2679,7 +2278,7 @@
 		from LuciClusterActions import ClusterDelete
 		ret = ClusterDelete(self, model)
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('CTP3: ret is %s' % str(e))
+			luci_log.debug_verbose('CTP3: ret is %r' % ret)
 		if ret is not None:
 			redirect_page = ret
 	else:
@@ -3236,20 +2835,19 @@
 	fvars = GetReqVars(req,
 				[ 'clustername', 'servicename', 'nodename', 'URL' ])
 	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+	clustername = fvars['clustername']
 
-	try:
-		model = LuciExtractCluModel(self, req,
-					cluster_name=fvars['clustername'])
-	except Exception, e:
+	model = LuciExtractCluModel(self, req, clustername)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('serviceDelete0: %r %s' % (e, str(e)))
-		return (False, { 'errors': [ 'No resource name was given' ]})
+			luci_log.debug_verbose('serviceDelete0: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ]})
 
 	ret = DeleteCluSvc(self, rc, fvars, model)
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (baseurl, SERVICES, fvars['clustername']))
+			% (baseurl, SERVICES, clustername))
 	else:
 		return ret
 
@@ -3274,22 +2872,19 @@
 	fvars = GetReqVars(req,
 		[ 'clustername', 'resourcename', 'nodename', 'URL' ])
 	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+	clustername = fvars['clustername']
 
-	try:
-		model = LuciExtractCluModel(self, req,
-					cluster_name=fvars['clustername'])
-		if not model:
-			raise Exception, 'no model'
-	except Exception, e:
+	model = LuciExtractCluModel(self, req, clustername)
+	if model is None:
 		if LUCI_DEBUG_MODE is True:
-			luci_log.debug_verbose('resourceDelete0: %r %s' % (e, str(e)))
-		return (False, { 'errors': [ 'No resource name was given' ] })
+			luci_log.debug_verbose('resourceDelete0: no model')
+		return (False, { 'errors': [ 'Unable to retrieve the cluster configuration for %s. The configuration XML may contain errors' % clustername ]})
 
 	ret = DeleteResource(self, rc, model, fvars['resourcename'])
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (baseurl, RESOURCES, fvars['clustername']))
+			% (baseurl, RESOURCES, clustername))
 	else:
 		return ret
 




More information about the Cluster-devel mailing list