All of lore.kernel.org
 help / color / mirror / Atom feed
From: rmccabe@sourceware.org <rmccabe@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] conga/luci/site/luci/Extensions cluster_adapte ...
Date: 18 Jan 2007 02:48:38 -0000	[thread overview]
Message-ID: <20070118024838.10092.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/cluster
Module name:	conga
Changes by:	rmccabe at sourceware.org	2007-01-18 02:48:37

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

Log message:
	add support for the new resource agents

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/cluster_adapters.py.diff?cvsroot=cluster&r1=1.204&r2=1.205

--- conga/luci/site/luci/Extensions/cluster_adapters.py	2007/01/17 22:14:02	1.204
+++ conga/luci/site/luci/Extensions/cluster_adapters.py	2007/01/18 02:48:37	1.205
@@ -17,6 +17,11 @@
 from NFSExport import NFSExport
 from Service import Service
 from Netfs import Netfs
+from Apache import Apache
+from MySQL import MySQL
+from Postgres8 import Postgres8
+from Tomcat5 import Tomcat5
+from OpenLDAP import OpenLDAP
 from Vm import Vm
 from Script import Script
 from Samba import Samba
@@ -119,7 +124,7 @@
 
 	system_list, incomplete, errors, messages = parseHostForm(request, check_certs)
 	add_cluster['nodes'] = system_list
-	
+
 	for i in system_list:
 		cur_system = system_list[i]
 
@@ -150,7 +155,7 @@
 			try:
 				if prev_auth:
 					messages.append('Host %s is already authenticated.' \
-						% cur_host) 
+						% cur_host)
 				else:
 					rc.auth(cur_passwd)
 
@@ -258,7 +263,7 @@
 		try:
 			rc = RicciCommunicator(i)
 			if not rc:
-				raise 'rc is None'
+				raise Exception, 'rc is None'
 		except Exception, e:
 			msg = 'Unable to connect to the ricci agent on %s: %s' % (i, str(e))
 			errors.append(msg)
@@ -327,7 +332,7 @@
 		except Exception, e:
 			luci_log.debug_verbose('VACN1: %s: %s' % (clusterName, str(e)))
 			return (False, { 'errors': [ 'The database object for %s is missing.' % clusterName ] })
-		
+
 		try:
 			cluster_os = cluster_folder.manage_getProperty('cluster_os')
 			if not cluster_os:
@@ -369,7 +374,7 @@
 
 	system_list, incomplete, errors, messages = parseHostForm(request, check_certs)
 	add_cluster['nodes'] = system_list
-	
+
 	for i in system_list:
 		cur_system = system_list[i]
 
@@ -399,7 +404,7 @@
 			try:
 				if prev_auth:
 					messages.append('Host %s is already authenticated.' \
-						% cur_host) 
+						% cur_host)
 				else:
 					rc.auth(cur_passwd)
 
@@ -855,7 +860,7 @@
 		return (False, {'errors': errors})
 
 	return (True, {'messages': ['Resource added successfully']})
-	
+
 ## Cluster properties form validation routines
 
 # rhel5 cluster version
@@ -1215,7 +1220,7 @@
       raise Exception, 'cluster name from model.getClusterName() is blank'
   except Exception, e:
     luci_log.debug_verbose('VCC5: error: getClusterName: %s' % str(e))
-    errors.append('Unable to determine cluster name from model') 
+    errors.append('Unable to determine cluster name from model')
 
   if len(errors) > 0:
     return (retcode, {'errors': errors, 'messages': messages})
@@ -1251,7 +1256,7 @@
   errors = list()
   messages = list()
   rc = None
-                                                                                
+
   try:
     model = request.SESSION.get('model')
     if not model:
@@ -1266,12 +1271,12 @@
       except:
         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:
       luci_log.debug_verbose('VFE: unable to get model from session')
       return (False, {'errors': ['No cluster model was found.']})
@@ -1312,7 +1317,7 @@
         raise Exception, 'cluster name from model.getClusterName() is blank'
     except Exception, e:
       luci_log.debug_verbose('VFA: error: getClusterName: %s' % str(e))
-      errors.append('Unable to determine cluster name from model') 
+      errors.append('Unable to determine cluster name from model')
 
     if not rc:
       rc = getRicciAgent(self, clustername)
@@ -1345,7 +1350,7 @@
   errors = list()
   messages = list()
   rc = None
-                                                                                
+
   try:
     model = request.SESSION.get('model')
     if not model:
@@ -1360,12 +1365,12 @@
       except:
         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:
       luci_log.debug_verbose('VFE: unable to get model from session')
       return (False, {'errors': ['No cluster model was found.']})
@@ -1409,7 +1414,7 @@
         raise Exception, 'cluster name from model.getClusterName() is blank'
     except Exception, e:
       luci_log.debug_verbose('VFA: error: getClusterName: %s' % str(e))
-      errors.append('Unable to determine cluster name from model') 
+      errors.append('Unable to determine cluster name from model')
 
     if not rc:
       rc = getRicciAgent(self, clustername)
@@ -1519,10 +1524,10 @@
 				break
 		if delete_target is not None:
 			try:
-				node.getChildren()[0].removeChild(l)
+				node.getChildren()[0].removeChild(delete_target)
 			except Exception, e:
 				luci_log.debug_verbose('vNFC6a: %s: %s' % (method_id, str(e)))
-				return (False, {'errors': ['An error occurred while deleting fence method %s' % method_id ]}) 
+				return (False, {'errors': ['An error occurred while deleting fence method %s' % method_id ]})
 		else:
 			return (True, {'messages': ['No changes were made.'] })
 
@@ -1563,7 +1568,7 @@
 				return (False, {'errors': [ 'Unable to determine what device the current instance uses.' ]})
 
 			try:
-				parent_form = form_hash[parent][1].append(dummy_form)
+				form_hash[parent][1].append(dummy_form)
 				del dummy_form['fence_instance']
 			except Exception, e:
 				luci_log.debug_verbose('vNFC10: no parent for instance')
@@ -1777,7 +1782,7 @@
   errors = list()
   messages = list()
   rc = None
-                                                                                
+
   try:
     model = request.SESSION.get('model')
     if not model:
@@ -1792,12 +1797,12 @@
       except:
         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:
       luci_log.debug_verbose('VFE: unable to get model from session')
       return (False, {'errors': ['No cluster model was found.']})
@@ -1844,12 +1849,12 @@
   except:
     error_code = FD_VAL_FAIL
     error_string = "Fence device %s could not be removed from configuration" % fencedev_name
- 
+
   try:
     model.removeFenceInstancesForFenceDevice(fencedev_name)
   except:
     luci_log.debug_verbose('VFD: Could not remove fence instances for')
-     
+
 
   if error_code == FD_VAL_SUCCESS:
     messages.append(error_string)
@@ -1871,7 +1876,7 @@
         raise Exception, 'cluster name from model.getClusterName() is blank'
     except Exception, e:
       luci_log.debug_verbose('VFA: error: getClusterName: %s' % str(e))
-      errors.append('Unable to determine cluster name from model') 
+      errors.append('Unable to determine cluster name from model')
 
     if not rc:
       rc = getRicciAgent(self, clustername)
@@ -1960,7 +1965,7 @@
 		luci_log.debug_verbose('VDP5: RC %s: %s' % (nodename_resolved, str(e)))
 		errors.append('Unable to connect to the ricci agent on %s to update cluster daemon properties' % nodename_resolved)
 		return (False, {'errors': errors})
-		
+
 	batch_id, result = updateServices(rc, enable_list, disable_list)
 	if batch_id is None or result is None:
 		luci_log.debug_verbose('VDP6: setCluserConf: batchid or result is None')
@@ -2716,7 +2721,7 @@
 		except Exception, e:
 			luci_log.debug_verbose('GRA4b: %s' % str(e))
 			cur_alias = None
-			
+
 		if (cur_name is not None and cluname != cur_name) and (cur_alias is not None and cluname != cur_alias):
 			try:
 				luci_log.debug('GRA5: %s reports it\'s in cluster %s:%s; we expect %s' \
@@ -3176,7 +3181,7 @@
 	if batch_number is None or result is None:
 		luci_log.debug_verbose('serviceRestart2: %s failed' % svcname)
 		return None
-				
+
 	try:
 		set_node_flag(self, cluname, rc.hostname(), str(batch_number), SERVICE_RESTART, "Restarting service \'%s\'" % svcname)
 	except Exception, e:
@@ -4174,8 +4179,7 @@
         except:
           luci_log.debug_verbose('GNI0: unable to determine cluster name')
           return {}
-      
- 
+
   for item in nodelist:
     map = {}
     name = item['name']
@@ -4285,7 +4289,7 @@
               clustername = model.getClusterName()
               node_hash = {}
               node_hash['nodename'] = node.getName().strip()
-              node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE 
+              node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE
               nodes_used.append(node_hash)
 
       map['nodesused'] = nodes_used
@@ -4299,7 +4303,7 @@
       return fd
 
   raise
-  
+
 def getFenceInfo(self, model, request):
   if not model:
     luci_log.debug_verbose('getFenceInfo00: model is None')
@@ -4342,12 +4346,12 @@
       luci_log.debug_verbose('getFenceInfo2: unable to extract nodename: %s' \
           % str(e))
       return {}
-    
+
   #Here we need to get fences for a node - just the first two levels
   #Each level has its own list of fence devs used in that level
   #For each fence dev, a list of instance structs is appended
   #In addition, for each level, a list of available but unused fence devs
-  #is returned. 
+  #is returned.
   try:
     node = model.retrieveNodeByName(nodename)
   except GeneralError, e:
@@ -4396,7 +4400,7 @@
             if kee == "name":
               continue #Don't duplicate name attr
             fencedev[kee] = kidattrs[kee]
-          #This fencedev struct is complete, and needs to be placed on the 
+          #This fencedev struct is complete, and needs to be placed on the
           #level1 Q. Because it is non-shared, we should set last_kid_fd
           #to none.
           last_kid_fd = None
@@ -4425,7 +4429,7 @@
               fencedev['unknown'] = True
               fencedev['prettyname'] = fd.getAgentType()
             fencedev['isShared'] = True
-            fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV 
+            fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV
             fencedev['id'] = str(major_num)
             major_num = major_num + 1
             inlist = list()
@@ -4441,7 +4445,7 @@
               if kee == "name":
                 continue
               instance_struct[kee] = kidattrs[kee]
-            inlist.append(instance_struct) 
+            inlist.append(instance_struct)
             level1.append(fencedev)
             last_kid_fd = fencedev
             continue
@@ -4503,7 +4507,7 @@
             if kee == "name":
               continue #Don't duplicate name attr
             fencedev[kee] = kidattrs[kee]
-          #This fencedev struct is complete, and needs to be placed on the 
+          #This fencedev struct is complete, and needs to be placed on the
           #level2 Q. Because it is non-shared, we should set last_kid_fd
           #to none.
           last_kid_fd = None
@@ -4532,7 +4536,7 @@
               fencedev['unknown'] = True
               fencedev['prettyname'] = fd.getAgentType()
             fencedev['isShared'] = True
-            fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV 
+            fencedev['cfgurl'] = baseurl + "?clustername=" + clustername + "&fencename=" + fd.getName().strip() + "&pagetype=" + FENCEDEV
             fencedev['id'] = str(major_num)
             major_num = major_num + 1
             inlist = list()
@@ -4548,7 +4552,7 @@
               if kee == "name":
                 continue
               instance_struct[kee] = kidattrs[kee]
-            inlist.append(instance_struct) 
+            inlist.append(instance_struct)
             level2.append(fencedev)
             last_kid_fd = fencedev
             continue
@@ -4576,8 +4580,8 @@
         shared2.append(shared_struct)
     map['shared2'] = shared2
 
-  return map    
-      
+  return map
+
 def getFencesInfo(self, model, request):
   map = {}
   if not model:
@@ -4625,7 +4629,7 @@
                 continue
               node_hash = {}
               node_hash['nodename'] = node.getName().strip()
-              node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE 
+              node_hash['nodeurl'] = baseurl + "?clustername=" + clustername + "&nodename=" + node.getName() + "&pagetype=" + NODE
               nodes_used.append(node_hash)
 
       fencedev['nodesused'] = nodes_used
@@ -4634,7 +4638,6 @@
   map['fencedevs'] = fencedevs
   return map
 
-    
 def getLogsForNode(self, request):
 	try:
 		nodename = request['nodename']
@@ -4700,7 +4703,7 @@
     xenvmname = req['servicename']
   except KeyError, e:
     isNew = True
-  
+
   if isNew == True:
     xvm = Vm()
     xvm.addAttribute("name", req.form['xenvmname'])
@@ -4829,7 +4832,7 @@
       node_report = {}
       node_report['isnodecreation'] = True
       node_report['iserror'] = False  #Default value
-      node_report['desc'] = item[1].getProperty(FLAG_DESC) 
+      node_report['desc'] = item[1].getProperty(FLAG_DESC)
       batch_xml = None
       ricci = item[0].split("____") #This removes the 'flag' suffix
 
@@ -4885,7 +4888,7 @@
       if batch_xml is None:  #The job is done and gone from queue
         if redirect_message == False: #We have not displayed this message yet
           node_report['desc'] = REDIRECT_MSG
-          node_report['iserror'] = True 
+          node_report['iserror'] = True
           node_report['errormessage'] = ""
           nodereports.append(node_report)
           redirect_message = True
@@ -4984,7 +4987,7 @@
             luci_log.debug_verbose('ICB16: last_status err: %s %d: %s' \
               % (item[0], creation_status, str(e)))
           continue
-          
+
     else:
       node_report = {}
       node_report['isnodecreation'] = False
@@ -5306,696 +5309,1464 @@
 	response.redirect(request['URL'] + "?pagetype=" + RESOURCES + "&clustername=" + clustername + '&busyfirst=true')
 
 def addIp(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addIp error: form is missing')
+		luci_log.debug_verbose('addIp0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addIp error: model is missing')
+		luci_log.debug_verbose('addIp1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank.'
+
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No IP resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addIp error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this IP resource.')
 	else:
 		try:
 			res = Ip()
 			if not res:
-				raise Exception, 'apply(Ip) is None'
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addIp error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating an IP resource.')
+			luci_log.debug_verbose('addIp3: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addIp error: res is none')
-		return None
+		return [None, None, errors]
 
-	errors = list()
 	try:
 		addr = form['ip_address'].strip()
 		if not addr:
 			raise KeyError, 'ip_address is blank'
 		# XXX: validate IP addr
-		res.attr_hash['address'] = addr
+		res.addAttribute('address', addr)
 	except KeyError, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addIp error: %s' % err)
+		luci_log.debug_verbose('addIp4: %s' % err)
 
 	if 'monitorLink' in form:
-		res.attr_hash['monitor_link'] = '1'
+		res.addAttribute('monitor_link', '1')
 	else:
-		res.attr_hash['monitor_link'] = '0'
+		res.addAttribute('monitor_link', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addFs(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addFs error: form is missing')
+		luci_log.debug_verbose('addFs0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addFs error: model is missing')
+		luci_log.debug_verbose('addFs1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank.'
+
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No filesystem resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addFs error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this filesystem resource.')
+			luci_log.debug_verbose('addFs3: %s' % str(e))
 	else:
 		try:
 			res = Fs()
 			if not res:
-				raise Exception, 'apply(Fs) is None'
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addFs error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating a filesystem resource.')
+			luci_log.debug_verbose('addFs4: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addFs error: fs obj was not created')
-		return None
+		return [None, None, errors]
 
 	# XXX: sanity check these fields
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
-		res.attr_hash['name'] = name
+		if not name:
+			raise Exception, 'No name was given for this filesystem resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs5: %s' % err)
 
 	try:
 		mountpoint = form['mountpoint'].strip()
-		res.attr_hash['mountpoint'] = mountpoint
+		if not mountpoint:
+			raise Exception, 'No mount point was given for this filesystem resource.'
+		res.addAttribute('mountpoint', mountpoint)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs6: %s' % err)
 
 	try:
 		device = form['device'].strip()
-		res.attr_hash['device'] = device
+		if not device:
+			raise Exception, 'No device was given for this filesystem resource.'
+		res.addAttribute('device', device)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs7: %s' % err)
 
 	try:
 		options = form['options'].strip()
-		res.attr_hash['options'] = options
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('options')
+		except:
+			pass
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs8: %s' % err)
 
 	try:
 		fstype = form['fstype'].strip()
-		res.attr_hash['fstype'] = fstype
+		if not fstype:
+			raise Exception, 'No filesystem type was given for this filesystem resource.'
+		res.addAttribute('fstype', fstype)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs9: %s' % err)
 
 	try:
 		fsid = form['fsid'].strip()
-		res.attr_hash['fsid'] = fsid
+		if not fsid:
+			raise Exception, 'No filesystem ID was given for this filesystem resource.'
+		res.addAttribute('fsid', fsid)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addFs error: %s' % err)
+		luci_log.debug_verbose('addFs10: %s' % err)
 
 	if form.has_key('forceunmount'):
-		res.attr_hash['force_unmount'] = '1'
+		res.addAttribute('force_unmount', '1')
 	else:
-		res.attr_hash['force_unmount'] = '0'
+		res.addAttribute('force_unmount', '0')
 
 	if form.has_key('selffence'):
-		res.attr_hash['self_fence'] = '1'
+		res.addAttribute('self_fence', '1')
 	else:
-		res.attr_hash['self_fence'] = '0'
+		res.addAttribute('self_fence', '0')
 
 	if form.has_key('checkfs'):
-		res.attr_hash['force_fsck'] = '1'
+		res.addAttribute('force_fsck', '1')
 	else:
-		res.attr_hash['force_fsck'] = '0'
+		res.addAttribute('force_fsck', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addGfs(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addGfs error: form is missing')
+		luci_log.debug_verbose('addGfs0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addGfs error: model is missing')
+		luci_log.debug_verbose('addGfs1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
-			if not res:
-				luci_log.debug('resource %s was not found for editing' % oldname)
-				return None
+				raise Exception, 'oldname is blank'
+
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No filesystem resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug('resource %s was not found for editing: %s' \
-				% (oldname, str(e)))
-			return None
+			errors.append('No original name was found for this cluster filesystem resource.')
+			luci_log.debug_verbose('addGfs2: %s' % str(e))
 	else:
 		try:
 			res = Clusterfs()
 			if not res:
-				raise Exception, 'apply(Clusterfs) is None'
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug('addGfs error: %s' % str(e))
-			return None
-		except:
-			luci_log.debug('addGfs error')
-			return None
+			errors.append('An error occurred while creating a cluster filesystem resource.')
+			luci_log.debug('addGfs3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
 
 	# XXX: sanity check these fields
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this cluster filesystem resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs4: %s' % err)
 
 	try:
 		mountpoint = form['mountpoint'].strip()
-		res.attr_hash['mountpoint'] = mountpoint
+		if not mountpoint:
+			raise Exception, 'No mount point was given for this cluster filesystem resource.'
+		res.addAttribute('mountpoint', mountpoint)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs5: %s' % err)
 
 	try:
 		device = form['device'].strip()
-		res.attr_hash['device'] = device
+		if not device:
+			raise Exception, 'No device was given for this cluster filesystem resource.'
+		res.addAttribute('device', device)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs6: %s' % err)
 
 	try:
 		options = form['options'].strip()
-		res.attr_hash['options'] = options
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('options')
+		except:
+			pass
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs7: %s' % err)
 
 	try:
 		fsid = form['fsid'].strip()
-		res.attr_hash['fsid'] = fsid
+		if not fsid:
+			raise Exception, 'No filesystem ID was given for this cluster filesystem resource.'
+		res.addAttribute('fsid', fsid)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addGfs error: %s' % err)
+		luci_log.debug_verbose('addGfs8: %s' % err)
 
 	if form.has_key('forceunmount'):
-		res.attr_hash['force_unmount'] = '1'
+		res.addAttribute('force_unmount', '1')
 	else:
-		res.attr_hash['force_unmount'] = '0'
+		res.addAttribute('force_unmount', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
+
 	return [res, model, None]
 
 def addNfsm(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addNfsm error: form is missing')
+		luci_log.debug_verbose('addNfsm0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addNfsm error: model is missing')
+		luci_log.debug_verbose('addNfsm1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No NFS mount resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addNfsm error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this NFS mount resource.')
+			luci_log.debug_verbose('addNfsm2: %s' % str(e))
 	else:
 		try:
 			res = Netfs()
+			if not res:
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addNfsm error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating a NFS mount resource.')
+			luci_log.debug_verbose('addNfsm3: %s' % str(e))
 
 	if not res:
-		return None
+		return [None, None, errors]
 
 	# XXX: sanity check these fields
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this NFS mount resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm4: %s' % err)
 
 	try:
 		mountpoint = form['mountpoint'].strip()
-		res.attr_hash['mountpoint'] = mountpoint
+		if not mountpoint:
+			raise Exception, 'No mount point was given for NFS mount resource.'
+		res.addAttribute('mountpoint', mountpoint)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
-		
+		luci_log.debug_verbose('addNfsm5: %s' % err)
+
 	try:
 		host = form['host'].strip()
-		res.attr_hash['host'] = host
+		if not host:
+			raise Exception, 'No host server was given for this NFS mount resource.'
+		res.addAttribute('host', host)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm6 error: %s' % err)
 
 	try:
 		options = form['options'].strip()
-		res.attr_hash['options'] = options
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('options')
+		except:
+			pass
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm7: %s' % err)
 
 	try:
 		exportpath = form['exportpath'].strip()
-		res.attr_hash['exportpath'] = exportpath 
+		if not exportpath:
+			raise Exception, 'No export path was given for this NFS mount resource.'
+		res.addAttribute('exportpath', exportpath)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm8: %s' % err)
 
 	try:
 		nfstype = form['nfstype'].strip().lower()
 		if nfstype != 'nfs' and nfstype != 'nfs4':
-			raise KeyError, 'invalid nfs type: %s' % nfstype
-		res.attr_hash['nfstype'] = nfstype
+			raise Exception, 'An invalid NFS version \"%s\" was given.' % nfstype
+		res.addAttribute('nfstype', nfstype)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsm error: %s' % err)
+		luci_log.debug_verbose('addNfsm9: %s' % err)
 
 	if form.has_key('forceunmount'):
-		res.attr_hash['force_unmount'] = '1'
+		res.addAttribute('force_unmount', '1')
 	else:
-		res.attr_hash['force_unmount'] = '0'
+		res.addAttribute('force_unmount', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addNfsc(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addNfsc error: form is missing')
+		luci_log.debug_verbose('addNfsc0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addNfsc error: model is missing')
+		luci_log.debug_verbose('addNfsc1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No NFS client resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addNfsc error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this NFS client resource.')
+			luci_log.debug_verbose('addNfsc2: %s' % str(e))
 	else:
 		try:
 			res = NFSClient()
-		except:
-			luci_log.debug_verbose('addNfsc error: %s' % str(e))
-			return None
+			if not res:
+				raise Exception, 'res is None'
+		except Exception, e:
+			errors.append('An error occurred while creating a NFS client resource.')
+			luci_log.debug_verbose('addNfsc3: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addNfsc error: res is none')
-		return None
+		return [None, None, errors]
 
-	errors = list()
+	# XXX: sanity check these fields
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this NFS client resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsc error: %s' % err)
+		luci_log.debug_verbose('addNfsc4: %s' % err)
 
 	try:
 		target = form['target'].strip()
-		res.attr_hash['target'] = target 
+		if not target:
+			raise Exception, 'No target was given for NFS client resource.'
+		res.addAttribute('target', target)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsc error: %s' % err)
+		luci_log.debug_verbose('addNfsc5: %s' % err)
 
 	try:
 		options = form['options'].strip()
-		res.attr_hash['options'] = options
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('options')
+		except:
+			pass
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsc error: %s' % err)
+		luci_log.debug_verbose('addNfsc6: %s' % err)
+
+	if form.has_key('allow_recover'):
+		res.addAttribute('allow_recover', '1')
+	else:
+		res.addAttribute('allow_recover', '0')
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addNfsx(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addNfsx error: model is missing')
+		luci_log.debug_verbose('addNfsx0: model is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addNfsx error: model is missing')
+		luci_log.debug_verbose('addNfsx0: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No NFS export resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addNfsx error: %s', str(e))
-			return None
+			errors.append('No original name was found for this NFS export resource.')
+			luci_log.debug_verbose('addNfsx2: %s', str(e))
 	else:
 		try:
 			res = NFSExport()
-		except:
-			luci_log.debug_verbose('addNfsx error: %s', str(e))
-			return None
+			if not res:
+				raise Exception, 'res is None'
+		except Exception, e:
+			errors.append('An error occurred while creating a NFS clientresource.')
+			luci_log.debug_verbose('addNfsx3: %s', str(e))
 
 	if not res:
-		luci_log.debug_verbose('addNfsx error: res is None')
-		return None
+		return [None, None, errors]
 
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this NFS export resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addNfsx error: %s', err)
+		luci_log.debug_verbose('addNfsx4: %s' % err)
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addScr(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addScr error: form is missing')
+		luci_log.debug_verbose('addScr0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addScr error: model is missing')
+		luci_log.debug_verbose('addScr1: model is missing')
 		return None
 
+	res = None
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No script resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addScr error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this script resource.')
+			luci_log.debug_verbose('addScr2: %s' % str(e))
 	else:
 		try:
 			res = Script()
+			if not res:
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addScr error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating a script resource.')
+			luci_log.debug_verbose('addScr3: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addScr error: res is None')
-		return None
+		return [None, None, errors]
 
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this script resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addScr error: %s' % err)
+		luci_log.debug_verbose('addScr4: %s' % err)
 
 	try:
 		path = form['file'].strip()
 		if not path:
-			raise KeyError, 'file path is blank'
-		res.attr_hash['file'] = path
+			raise Exception, 'No path to a script file was given for this script resource.'
+		res.addAttribute('file', path)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addScr error: %s' % err)
+		luci_log.debug_verbose('addScr5: %s' % err)
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
 def addSmb(request, form=None):
+	errors = list()
+
 	if form is None:
 		form = request.form
 
 	if not form:
-		luci_log.debug_verbose('addSmb error: form is missing')
+		luci_log.debug_verbose('addSmb0: form is missing')
 		return None
 
 	model = request.SESSION.get('model')
 	if not model:
-		luci_log.debug_verbose('addSmb error: model is missing')
+		luci_log.debug_verbose('addSmb1: model is missing')
 		return None
 
 	if form.has_key('edit'):
 		try:
 			oldname = form['oldname'].strip()
 			if not oldname:
-				raise KeyError, 'oldname is blank.'
-			res = getResourceForEdit(model, oldname)
+				raise Exception, 'oldname is blank'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e1:
+				errors.append('No Samba resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('addSmb error: %s' % str(e))
-			return None
+			errors.append('No original name was found for this Samba resource.')
+			luci_log.debug_verbose('addSmb2: %s' % str(e))
 	else:
 		try:
 			res = Samba()
+			if not res:
+				raise Exception, 'res is None'
 		except Exception, e:
-			luci_log.debug_verbose('addSmb error: %s' % str(e))
-			return None
+			errors.append('An error occurred while creating a Samba resource.')
+			luci_log.debug_verbose('addSmb3: %s' % str(e))
 
 	if not res:
-		luci_log.debug_verbose('addSmb error: res is None')
-		return None
+		return [None, None, errors]
 
-	errors = list()
 	try:
 		name = form['resourceName'].strip()
 		if not name:
-			raise KeyError, 'resourceName is blank'
-		res.attr_hash['name'] = name
+			raise Exception, 'No name was given for this Samba resource.'
+		res.addAttribute('name', name)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addSmb error: %s' % err)
+		luci_log.debug_verbose('addSmb4: %s' % err)
 
 	try:
 		workgroup = form['workgroup'].strip()
-		res.attr_hash['workgroup'] = workgroup
+		if not workgroup:
+			raise Exception, 'No workgroup was given for this Samba resource.'
+		res.addAttribute('workgroup', workgroup)
 	except Exception, e:
 		err = str(e)
 		errors.append(err)
-		luci_log.debug_verbose('addSmb error: %s' % err)
+		luci_log.debug_verbose('addSmb5: %s' % err)
 
 	if len(errors) > 1:
 		return [None, None, errors]
 	return [res, model, None]
 
-resourceAddHandler = {
-	'ip': addIp,
-	'fs': addFs,
-	'gfs': addGfs,
-	'nfsm': addNfsm,
-	'nfsx': addNfsx,
-	'nfsc': addNfsc,
-	'scr': addScr,
-	'smb': addSmb
-}
-
-def resolveClusterChanges(self, clusterName, model):
-	try:
-		mb_nodes = model.getNodes()
-		if not mb_nodes or not len(mb_nodes):
-			raise Exception, 'node list is empty'
-	except Exception, e:
-		luci_log.debug_verbose('RCC0: no model builder nodes found for %s: %s' \
-				% (str(e), clusterName))
-		return 'Unable to find cluster nodes for %s' % clusterName
-
-	try:
-		cluster_node = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName)
-		if not cluster_node:
-			raise Exception, 'cluster node is none'
-	except Exception, e:
-		luci_log.debug('RCC1: cant find cluster node for %s: %s'
-			% (clusterName, str(e)))
-		return 'Unable to find an entry for %s in the Luci database.' % clusterName
-
-	try:
-		db_nodes = map(lambda x: x[0], cluster_node.objectItems('Folder'))
-		if not db_nodes or not len(db_nodes):
-			raise Exception, 'no database nodes'
-	except Exception, e:
-		# Should we just create them all? Can this even happen?
-		luci_log.debug('RCC2: error: %s' % str(e))
-		return 'Unable to find database entries for any nodes in %s' % clusterName
+def addApache(request, form=None):
+	errors = list()
 
-	same_host = lambda x, y: x == y or x[:len(y) + 1] == y + '.' or y[:len(x) + 1] == x + '.'
+	if form is None:
+		form = request.form
 
-	# this is a really great algorithm.
-	missing_list = list()
-	new_list = list()
-	for i in mb_nodes:
-		for j in db_nodes:
-			f = 0
-			if same_host(i, j):
-				f = 1
-				break
-		if not f:
-			new_list.append(i)
+	if not form:
+		luci_log.debug_verbose('addApache0: form is missing')
+		return None
 
-	for i in db_nodes:
-		for j in mb_nodes:
-			f = 0
-			if same_host(i, j):
-				f = 1
-				break
-		if not f:
-			missing_list.append(i)
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addApache1: model is missing')
+		return None
 
-	messages = list()
-	for i in missing_list:
+	res = None
+	if form.has_key('edit'):
 		try:
-			## or alternately
-			##new_node = cluster_node.restrictedTraverse(i)
-			##setNodeFlag(self, new_node, CLUSTER_NODE_NOT_MEMBER)
-			cluster_node.delObjects([i])
-			messages.append('Node \"%s\" is no longer in a member of cluster \"%s\." It has been deleted from the management interface for this cluster.' % (i, clusterName))
-			luci_log.debug_verbose('VCC3: deleted node %s' % i)
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No Apache resource named \"%s\" exists.' % oldname)
 		except Exception, e:
-			luci_log.debug_verbose('VCC4: delObjects: %s: %s' % (i, str(e)))
-
-	new_flags = CLUSTER_NODE_NEED_AUTH | CLUSTER_NODE_ADDED
-	for i in new_list:
+			errors.append('No original name was found for this Apache resource.')
+			luci_log.debug_verbose('addApache2: %s' % str(e))
+	else:
 		try:
-			cluster_node.manage_addFolder(i, '__luci__:csystem:' + clusterName)
-			new_node = cluster_node.restrictedTraverse(i)
-			setNodeFlag(self, new_node, new_flags)
-			messages.append('A new cluster node, \"%s,\" is now a member of cluster \"%s.\" It has been added to the management interface for this cluster, but you must authenticate to it in order for it to be fully functional.' % (i, clusterName))
+			res = Apache()
+			if not res:
+				raise Exception, 'could not create Apache object'
 		except Exception, e:
-			messages.append('A new cluster node, \"%s,\" is now a member of cluster \"%s,\". but it has not been added to the management interface for this cluster as a result of an error creating a database entry for it.' % (i, clusterName))
-			luci_log.debug_verbose('VCC5: addFolder: %s/%s: %s' \
-				% (clusterName, i, str(e)))
-	
-	return messages
+			errors.append('An error occurred while creating an Apache resource.')
+			luci_log.debug_verbose('addApache3: %s' % str(e))
 
-def addResource(self, request, model, res, res_type):
-	clustername = model.getClusterName()
-	if not clustername:
-		luci_log.debug_verbose('addResource0: no cluname from mb')
-		return 'Unable to determine cluster name'
+	if not res:
+		return [None, None, errors]
 
-	rc = getRicciAgent(self, clustername)
-	if not rc:
-		luci_log.debug_verbose('addResource1: unable to find a ricci agent for cluster %s' % clustername)
-		return 'Unable to find a ricci agent for the %s cluster' % clustername
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this Apache resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache4: %s' % err)
 
 	try:
-		model.getResourcesPtr().addChild(res)
+		server_root = form['server_root'].strip()
+		if not server_root:
+			raise KeyError, 'No server root was given for this Apache resource.'
+		res.addAttribute('server_root', server_root)
 	except Exception, e:
-		luci_log.debug_verbose('addResource2: adding the new resource failed: %s' % str(e))
-		return 'Unable to add the new resource'
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache5: %s' % err)
 
 	try:
-		cp = model.getClusterPtr()
-		cp.incrementConfigVersion()
-		model.setModified(True)
-		conf = model.exportModelAsString()
-		if not conf:
-			raise Exception, 'model string for %s is blank' % clustername
+		config_file = form['config_file'].strip()
+		if not server_root:
+			raise KeyError, 'No path to the Apache configuration file was given.'
+		res.addAttribute('config_file', config_file)
 	except Exception, e:
-		luci_log.debug_verbose('addResource3: exportModelAsString : %s' \
-			% str(e))
-		return 'An error occurred while adding this resource'
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache6: %s' % err)
 
 	try:
-		ragent = rc.hostname()
+		options = form['httpd_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('httpd_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('httpd_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache7: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', shutdown_wait)
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', 0)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addApache7: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addMySQL(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addMySQL0: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addMySQL1: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No MySQL resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this MySQL resource.')
+			luci_log.debug_verbose('addMySQL2: %s' % str(e))
+	else:
+		try:
+			res = MySQL()
+			if not res:
+				raise Exception, 'could not create MySQL object'
+		except Exception, e:
+			errors.append('An error occurred while creating a MySQL resource.')
+			luci_log.debug_verbose('addMySQL3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this MySQL resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL4: %s' % err)
+
+	try:
+		config_file = form['config_file'].strip()
+		if not config_file:
+			raise KeyError, 'No path to the MySQL configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL5: %s' % err)
+
+	try:
+		listen_addr = form['listen_address'].strip()
+		if not listen_addr:
+			raise KeyError, 'No address was given for MySQL server to listen on.'
+		res.addAttribute('listen_address', listen_addr)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL6: %s' % err)
+
+	try:
+		options = form['mysql_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('mysql_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('mysql_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL7: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', shutdown_wait)
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', 0)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addMySQL7: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addOpenLDAP(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addOpenLDAP0: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addOpenLDAP1: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No OpenLDAP resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this OpenLDAP resource.')
+			luci_log.debug_verbose('addOpenLDAP2: %s' % str(e))
+	else:
+		try:
+			res = OpenLDAP()
+			if not res:
+				raise Exception, 'could not create OpenLDAP object'
+		except Exception, e:
+			errors.append('An error occurred while creating an OpenLDAP resource.')
+			luci_log.debug_verbose('addOpenLDAP3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this OpenLDAP resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP4: %s' % err)
+
+	try:
+		url_list = form['url_list'].strip()
+		if not url_list:
+			raise KeyError, 'No URL list was given for this OpenLDAP resource.'
+		res.addAttribute('url_list', url_list)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP5: %s' % err)
+
+	try:
+		config_file = form['config_file'].strip()
+		if not config_file:
+			raise KeyError, 'No path to the OpenLDAP configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP6: %s' % err)
+
+	try:
+		options = form['slapd_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('slapd_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('slapd_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP7: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', shutdown_wait)
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', 0)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addOpenLDAP7: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addPostgres8(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addPostgreSQL80: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addPostgreSQL81: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No PostgreSQL 8 resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this PostgreSQL 8 resource.')
+			luci_log.debug_verbose('addPostgreSQL82: %s' % str(e))
+	else:
+		try:
+			res = Postgres8()
+			if not res:
+				raise Exception, 'could not create PostgreSQL 8 object'
+		except Exception, e:
+			errors.append('An error occurred while creating a PostgreSQL 8 resource.')
+			luci_log.debug_verbose('addPostgreSQL83: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this PostgreSQL 8 resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL84: %s' % err)
+
+	try:
+		user = form['postmaster_user'].strip()
+		if not user:
+			raise KeyError, 'No postmaster user was given for this PostgreSQL 8 resource.'
+		res.addAttribute('postmaster_user', user)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL85: %s' % err)
+
+	try:
+		config_file = form['config_file'].strip()
+		if not config_file:
+			raise KeyError, 'No path to the PostgreSQL 8 configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL86: %s' % err)
+
+	try:
+		options = form['postmaster_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('postmaster_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('postmaster_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL87: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', shutdown_wait)
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', 0)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addPostgreSQL87: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addTomcat5(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addTomcat50: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addTomcat51: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No Tomcat 5 resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this Tomcat 5 resource.')
+			luci_log.debug_verbose('addTomcat52: %s' % str(e))
+	else:
+		try:
+			res = Tomcat5()
+			if not res:
+				raise Exception, 'could not create Tomcat5 object'
+		except Exception, e:
+			errors.append('An error occurred while creating a Tomcat 5 resource.')
+			luci_log.debug_verbose('addTomcat53: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this Tomcat 5 resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat54: %s' % err)
+
+	try:
+		user = form['tomcat_user'].strip()
+		if not user:
+			raise KeyError, 'No user was given for this Tomcat 5 resource.'
+		res.addAttribute('tomcat_user', user)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat55: %s' % err)
+
+	try:
+		config_file = form['config_file'].strip()
+		if not config_file:
+			raise KeyError, 'No path to the Tomcat 5 configuration file was given.'
+		res.addAttribute('config_file', config_file)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat56: %s' % err)
+
+	try:
+		options = form['catalina_options'].strip()
+		if not options:
+			raise KeyError, 'no options'
+		res.addAttribute('catalina_options', options)
+	except KeyError, e:
+		try:
+			res.removeAttribute('catalina_options')
+		except:
+			pass
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat57: %s' % err)
+
+	try:
+		catalina_base = form['catalina_base'].strip()
+		if not catalina_base:
+			raise KeyError, 'No cataliny base directory was given for this Tomcat 5 resource.'
+		res.addAttribute('catalina_base', catalina_base)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat58: %s' % err)
+
+	try:
+		shutdown_wait = int(form['shutdown_wait'].strip())
+		res.addAttribute('shutdown_wait', shutdown_wait)
+	except KeyError, e:
+		res.addAttribute('shutdown_wait', 0)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addTomcat59: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+def addVM(request, form=None):
+	errors = list()
+
+	if form is None:
+		form = request.form
+
+	if not form:
+		luci_log.debug_verbose('addVM0: form is missing')
+		return None
+
+	model = request.SESSION.get('model')
+	if not model:
+		luci_log.debug_verbose('addVM1: model is missing')
+		return None
+
+	res = None
+	if form.has_key('edit'):
+		try:
+			oldname = form['oldname'].strip()
+			if not oldname:
+				raise Exception, 'oldname is blank.'
+			try:
+				res = getResourceForEdit(model, oldname)
+			except KeyError, e:
+				errors.append('No VM resource named \"%s\" exists.' % oldname)
+		except Exception, e:
+			errors.append('No original name was found for this VM resource.')
+			luci_log.debug_verbose('addVM2: %s' % str(e))
+	else:
+		try:
+			res = Vm()
+			if not res:
+				raise Exception, 'could not create VM object'
+		except Exception, e:
+			errors.append('An error occurred while creating an VM resource.')
+			luci_log.debug_verbose('addVM3: %s' % str(e))
+
+	if not res:
+		return [None, None, errors]
+
+	try:
+		name = form['resourceName'].strip()
+		if not name:
+			raise Exception, 'No name was given for this VM resource.'
+		res.addAttribute('name', name)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM4: %s' % err)
+
+	try:
+		domain = form['domain'].strip()
+		if not domain:
+			raise KeyError, 'No domain was given for this VM resource.'
+		res.addAttribute('domain', domain)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM5: %s' % err)
+
+	try:
+		bootloader = form['bootloader'].strip()
+		if not bootloader:
+			raise KeyError, 'No bootloader was given for this VM resource.'
+		res.addAttribute('bootloader', bootloader)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM6: %s' % err)
+
+	try:
+		path = form['path'].strip()
+		if not path:
+			raise KeyError, 'No path specification was given for this VM resource.'
+		res.addAttribute('path', path)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM7: %s' % err)
+
+	try:
+		disk = form['rootdisk_physical'].strip()
+		if not disk:
+			raise KeyError, 'No physical root disk was given for this VM resource.'
+		res.addAttribute('rootdisk_physical', disk)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM8: %s' % err)
+
+	try:
+		disk = form['rootdisk_virtual'].strip()
+		if not disk:
+			raise KeyError, 'No virtual root disk was given for this VM resource.'
+		res.addAttribute('rootdisk_virtual', disk)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM9: %s' % err)
+
+	try:
+		disk = form['swapdisk_physical'].strip()
+		if not disk:
+			raise KeyError, 'No physical swap disk was given for this VM resource.'
+		res.addAttribute('swapdisk_physical', disk)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM10: %s' % err)
+
+	try:
+		disk = form['swapdisk_virtual'].strip()
+		if not disk:
+			raise KeyError, 'No virtual swap disk was given for this VM resource.'
+		res.addAttribute('swapdisk_virtual', disk)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM11: %s' % err)
+
+	try:
+		vif = form['vif'].strip()
+		if not vif:
+			raise KeyError, 'No virtual interface MAC address was given for this VM resource.'
+		res.addAttribute('vif', vif)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM12: %s' % err)
+
+	try:
+		memsize = int(form['memory'].strip())
+		res.addAttribute('memory', memsize)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM13: %s' % err)
+
+	try:
+		recovery = form['recovery'].lower().strip()
+		if not recovery:
+			raise Exception, 'No recovery method was given for this VM resource.'
+		if recovery != 'restart' and recovery != 'relocate' and recovery != 'disable':
+			raise Exception, 'An invalid recovery type, \"%s\", was given for this VM resource.' % recovery
+		res.addAttribute('recovery', recovery)
+	except Exception, e:
+		err = str(e)
+		errors.append(err)
+		luci_log.debug_verbose('addVM14: %s' % err)
+
+	if len(errors) > 1:
+		return [None, None, errors]
+	return [res, model, None]
+
+resourceAddHandler = {
+	'ip': addIp,
+	'fs': addFs,
+	'gfs': addGfs,
+	'nfsm': addNfsm,
+	'nfsx': addNfsx,
+	'nfsc': addNfsc,
+	'scr': addScr,
+	'smb': addSmb,
+	'vm': addVM,
+	'tomcat-5': addTomcat5,
+	'postgres-8': addPostgres8,
+	'apache': addApache,
+	'openldap': addOpenLDAP,
+	'mysql': addMySQL
+}
+
+def resolveClusterChanges(self, clusterName, model):
+	try:
+		mb_nodes = model.getNodes()
+		if not mb_nodes or not len(mb_nodes):
+			raise Exception, 'node list is empty'
+	except Exception, e:
+		luci_log.debug_verbose('RCC0: no model builder nodes found for %s: %s' \
+				% (str(e), clusterName))
+		return 'Unable to find cluster nodes for %s' % clusterName
+
+	try:
+		cluster_node = self.restrictedTraverse(PLONE_ROOT + '/systems/cluster/' + clusterName)
+		if not cluster_node:
+			raise Exception, 'cluster node is none'
+	except Exception, e:
+		luci_log.debug('RCC1: cant find cluster node for %s: %s'
+			% (clusterName, str(e)))
+		return 'Unable to find an entry for %s in the Luci database.' % clusterName
+
+	try:
+		db_nodes = map(lambda x: x[0], cluster_node.objectItems('Folder'))
+		if not db_nodes or not len(db_nodes):
+			raise Exception, 'no database nodes'
+	except Exception, e:
+		# Should we just create them all? Can this even happen?
+		luci_log.debug('RCC2: error: %s' % str(e))
+		return 'Unable to find database entries for any nodes in %s' % clusterName
+
+	same_host = lambda x, y: x == y or x[:len(y) + 1] == y + '.' or y[:len(x) + 1] == x + '.'
+
+	# this is a really great algorithm.
+	missing_list = list()
+	new_list = list()
+	for i in mb_nodes:
+		for j in db_nodes:
+			f = 0
+			if same_host(i, j):
+				f = 1
+				break
+		if not f:
+			new_list.append(i)
+
+	for i in db_nodes:
+		for j in mb_nodes:
+			f = 0
+			if same_host(i, j):
+				f = 1
+				break
+		if not f:
+			missing_list.append(i)
+
+	messages = list()
+	for i in missing_list:
+		try:
+			## or alternately
+			##new_node = cluster_node.restrictedTraverse(i)
+			##setNodeFlag(self, new_node, CLUSTER_NODE_NOT_MEMBER)
+			cluster_node.delObjects([i])
+			messages.append('Node \"%s\" is no longer in a member of cluster \"%s\." It has been deleted from the management interface for this cluster.' % (i, clusterName))
+			luci_log.debug_verbose('VCC3: deleted node %s' % i)
+		except Exception, e:
+			luci_log.debug_verbose('VCC4: delObjects: %s: %s' % (i, str(e)))
+
+	new_flags = CLUSTER_NODE_NEED_AUTH | CLUSTER_NODE_ADDED
+	for i in new_list:
+		try:
+			cluster_node.manage_addFolder(i, '__luci__:csystem:' + clusterName)
+			new_node = cluster_node.restrictedTraverse(i)
+			setNodeFlag(self, new_node, new_flags)
+			messages.append('A new cluster node, \"%s,\" is now a member of cluster \"%s.\" It has been added to the management interface for this cluster, but you must authenticate to it in order for it to be fully functional.' % (i, clusterName))
+		except Exception, e:
+			messages.append('A new cluster node, \"%s,\" is now a member of cluster \"%s,\". but it has not been added to the management interface for this cluster as a result of an error creating a database entry for it.' % (i, clusterName))
+			luci_log.debug_verbose('VCC5: addFolder: %s/%s: %s' \
+				% (clusterName, i, str(e)))
+
+	return messages
+
+def addResource(self, request, model, res, res_type):
+	clustername = model.getClusterName()
+	if not clustername:
+		luci_log.debug_verbose('addResource0: no cluname from mb')
+		return 'Unable to determine cluster name'
+
+	rc = getRicciAgent(self, clustername)
+	if not rc:
+		luci_log.debug_verbose('addResource1: unable to find a ricci agent for cluster %s' % clustername)
+		return 'Unable to find a ricci agent for the %s cluster' % clustername
+
+	try:
+		model.getResourcesPtr().addChild(res)
+	except Exception, e:
+		luci_log.debug_verbose('addResource2: adding the new resource failed: %s' % str(e))
+		return 'Unable to add the new resource'
+
+	try:
+		cp = model.getClusterPtr()
+		cp.incrementConfigVersion()
+		model.setModified(True)
+		conf = model.exportModelAsString()
+		if not conf:
+			raise Exception, 'model string for %s is blank' % clustername
+	except Exception, e:
+		luci_log.debug_verbose('addResource3: exportModelAsString : %s' \
+			% str(e))
+		return 'An error occurred while adding this resource'
+
+	try:
+		ragent = rc.hostname()
 		if not ragent:
 			luci_log.debug_verbose('addResource4: missing ricci hostname')
 			raise Exception, 'unknown ricci agent hostname'
@@ -6049,7 +6820,7 @@
 		request.SESSION.set('model', model)
 	except:
 		luci_log.debug_verbose('Appending model to request failed')
-		return 'An error occurred while storing the cluster model.' 
+		return 'An error occurred while storing the cluster model.'
 
 def resolve_nodename(self, clustername, nodename):
 	path = str(CLUSTER_FOLDER_PATH + clustername)
@@ -6206,7 +6977,7 @@
 			msg += 'Fix the error and try again:\n'
 		else:
 			msg += 'PASSED\n'
-			
+
 			msg += 'Making sure no clustername change has accured - '
 			new_name = cc_xml.firstChild.getAttribute('name')
 			if new_name != clustername:
@@ -6214,13 +6985,13 @@
 				msg += 'Fix the error and try again:\n'
 			else:
 				msg += 'PASSED\n'
-				
+
 				msg += 'Increasing cluster version number - '
 				version = cc_xml.firstChild.getAttribute('config_version')
 				version = int(version) + 1
 				cc_xml.firstChild.setAttribute('config_version', str(version))
 				msg += 'DONE\n'
-				
+
 				msg += 'Propagating new cluster.conf'
 				rc = getRicciAgent(self, clustername)
 				if not rc:
@@ -6231,7 +7002,7 @@
 					if batch_id is None or result is None:
 						luci_log.debug_verbose('VFA: setClusterConf: batchid or result is None')
 						msg += '\nUnable to propagate the new cluster configuration for ' + clustername + '\n\n'
-					else:	
+					else:
 						msg += ' - DONE\n'
 						cc = cc_xml.toxml()
 						msg += '\n\nALL DONE\n\n'



             reply	other threads:[~2007-01-18  2:48 UTC|newest]

Thread overview: 185+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-01-18  2:48 rmccabe [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-07-17 16:36 [Cluster-devel] conga/luci/site/luci/Extensions cluster_adapte rmccabe
2008-04-18 20:37 rmccabe
2007-12-12 15:45 rmccabe
2007-08-23 19:00 rmccabe
2007-08-22 20:57 rmccabe
2007-05-03 19:51 rmccabe
2007-04-02 16:35 rmccabe
2007-04-02 15:56 rmccabe
2007-03-27  2:03 rmccabe
2007-03-16  3:19 rmccabe
2007-03-16  3:19 rmccabe
2007-03-16  3:19 rmccabe
2007-03-13  3:07 rmccabe
2007-03-13  3:06 rmccabe
2007-03-12  5:47 rmccabe
2007-03-12  5:46 rmccabe
2007-03-12  5:46 rmccabe
2007-03-06 22:48 rmccabe
2007-03-01 20:22 rmccabe
2007-03-01 20:22 rmccabe
2007-03-01 20:22 rmccabe
2007-02-13 19:50 rmccabe
2007-02-13 19:50 rmccabe
2007-02-12 20:25 rmccabe
2007-02-12 20:24 rmccabe
2007-02-07 22:00 rmccabe
2007-02-07 21:30 rmccabe
2007-02-05 19:56 rmccabe
2007-01-31 23:45 rmccabe
2007-01-31 19:28 rmccabe
2007-01-31 18:50 rmccabe
2007-01-30 21:41 jparsons
2007-01-30 21:21 jparsons
2007-01-30 21:05 jparsons
2007-01-29 23:30 rmccabe
2007-01-26 19:35 rmccabe
2007-01-17 22:26 rmccabe
2007-01-17 22:14 rmccabe
2007-01-10 23:33 jparsons
2007-01-10 22:45 rmccabe
2007-01-10 20:06 rmccabe
2006-12-20 20:40 jparsons
2006-12-14 21:37 rmccabe
2006-12-14 17:03 rmccabe
2006-12-08 23:02 rmccabe
2006-11-30 20:12 jparsons
2006-11-27 21:06 rmccabe
2006-11-27 21:05 rmccabe
2006-11-27 18:15 rmccabe
2006-11-20 23:32 rmccabe
2006-11-20 15:05 jparsons
2006-11-17  5:50 rmccabe
2006-11-17  5:48 rmccabe
2006-11-10 18:18 rmccabe
2006-11-10 17:59 rmccabe
2006-11-09 22:30 rmccabe
2006-11-09 14:17 rmccabe
2006-11-08 21:42 rmccabe
2006-11-08 15:52 jparsons
2006-11-07 20:14 jparsons
2006-11-07 20:13 jparsons
2006-11-07  2:36 jparsons
2006-11-07  1:32 jparsons
2006-11-06 23:55 rmccabe
2006-11-05  0:59 rmccabe
2006-11-03 21:13 jparsons
2006-11-03  1:24 rmccabe
2006-11-03  1:08 rmccabe
2006-11-02 20:58 rmccabe
2006-11-02 20:45 rmccabe
2006-11-02 20:41 rmccabe
2006-11-02  3:17 rmccabe
2006-10-31 17:18 rmccabe
2006-10-31  0:16 rmccabe
2006-10-30 22:52 rmccabe
2006-10-30 20:43 jparsons
2006-10-27  1:11 rmccabe
2006-10-25  0:43 rmccabe
2006-10-24 14:08 rmccabe
2006-10-23 20:47 jparsons
2006-10-20 22:09 rmccabe
2006-10-20 21:59 rmccabe
2006-10-19 14:57 rmccabe
2006-10-18 23:12 rmccabe
2006-10-18 19:16 rmccabe
2006-10-16 21:01 rmccabe
2006-10-16 20:51 jparsons
2006-10-16 19:17 jparsons
2006-10-16  5:28 rmccabe
2006-10-16  4:54 rmccabe
2006-10-16  4:51 rmccabe
2006-10-13 22:56 rmccabe
2006-10-12 22:11 jparsons
2006-10-12 21:00 kupcevic
2006-10-12 20:54 jparsons
2006-10-12 20:48 jparsons
2006-10-12 19:40 rmccabe
2006-10-12 17:27 jparsons
2006-10-12 17:08 jparsons
2006-10-12 15:50 jparsons
2006-10-12 15:45 jparsons
2006-10-12  0:04 jparsons
2006-10-11 23:56 jparsons
2006-10-11 23:11 jparsons
2006-10-11 23:08 rmccabe
2006-10-11 22:37 jparsons
2006-10-11 20:58 jparsons
2006-10-11 17:43 jparsons
2006-10-11 17:29 rmccabe
2006-10-11 16:35 jparsons
2006-10-11 16:25 jparsons
2006-10-11 16:18 rmccabe
2006-10-10 21:33 kupcevic
2006-10-09 20:21 rmccabe
2006-10-04 16:20 rmccabe
2006-10-04 16:05 jparsons
2006-10-04 15:11 jparsons
2006-10-02 22:30 rmccabe
2006-10-02 21:42 rmccabe
2006-10-02 21:09 rmccabe
2006-10-02 20:53 rmccabe
2006-09-28 22:04 rmccabe
2006-09-28 20:10 rmccabe
2006-09-27 18:46 rmccabe
2006-09-27 16:18 jparsons
2006-09-27 15:51 jparsons
2006-09-27 15:35 jparsons
2006-09-25 22:59 rmccabe
2006-09-22 18:24 rmccabe
2006-08-30 22:59 rmccabe
2006-08-22 17:46 jparsons
2006-08-22 17:41 jparsons
2006-08-16 23:40 jparsons
2006-08-16 21:56 jparsons
2006-08-16 21:54 jparsons
2006-08-16 21:51 jparsons
2006-08-16 19:14 rmccabe
2006-08-16 16:10 jparsons
2006-08-14 15:12 jparsons
2006-08-13 19:38 jparsons
2006-08-13 19:37 jparsons
2006-08-13 18:36 jparsons
2006-08-13 16:32 jparsons
2006-08-13 16:15 jparsons
2006-08-13 15:02 jparsons
2006-08-13 14:57 jparsons
2006-08-13 13:48 jparsons
2006-08-12 21:13 jparsons
2006-08-12 20:31 jparsons
2006-08-12 18:22 jparsons
2006-08-12 17:53 jparsons
2006-08-11  0:29 jparsons
2006-08-10 23:06 shuennek
2006-08-10 16:50 jparsons
2006-08-10 14:16 jparsons
2006-08-09 22:05 jparsons
2006-08-09 21:48 jparsons
2006-08-03 13:37 jparsons
2006-08-02 18:59 rmccabe
2006-08-02 17:25 rmccabe
2006-08-01 15:29 jparsons
2006-08-01 15:25 jparsons
2006-08-01 15:20 jparsons
2006-08-01 15:13 jparsons
2006-08-01 15:04 jparsons
2006-07-31 18:21 rmccabe
2006-07-28 19:03 jparsons
2006-07-28 18:57 jparsons
2006-07-28 18:40 jparsons
2006-07-28 14:16 jparsons
2006-07-28 14:02 jparsons
2006-07-28 11:46 jparsons
2006-07-27 16:34 jparsons
2006-07-27 15:53 rmccabe
2006-07-25 20:16 jparsons
2006-07-25 20:01 jparsons
2006-07-25  0:56 jparsons
2006-07-24 21:51 jparsons
2006-07-24 21:13 jparsons
2006-07-24 19:50 jparsons
2006-07-19 22:28 rmccabe
2006-07-19 21:38 rmccabe
2006-07-19 20:57 rmccabe
2006-07-19 20:19 rmccabe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070118024838.10092.qmail@sourceware.org \
    --to=rmccabe@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.