[Cluster-devel] conga/luci cluster/form-macros site/luci/Exten ...

rmccabe at sourceware.org rmccabe at sourceware.org
Tue Jun 19 15:54:11 UTC 2007


CVSROOT:	/cvs/cluster
Module name:	conga
Branch: 	RHEL5
Changes by:	rmccabe at sourceware.org	2007-06-19 15:54:10

Modified files:
	luci/cluster   : form-macros 
	luci/site/luci/Extensions: LuciClusterActions.py 
	                           LuciClusterInfo.py 
	                           cluster_adapters.py 
	                           conga_constants.py 
Removed files:
	luci/python/Extensions: .cvsignore 

Log message:
	Fix bz238726: Conga provides no way to remove a dead node from a cluster (depends on 244867)

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/cluster/form-macros.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.90.2.23&r2=1.90.2.24
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/python/Extensions/.cvsignore.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1&r2=NONE
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LuciClusterActions.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1.4.1&r2=1.1.4.2
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.1&r2=1.1.4.2
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.30&r2=1.120.2.31
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/conga_constants.py.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.19.2.10&r2=1.19.2.11

--- conga/luci/cluster/form-macros	2007/06/18 18:39:31	1.90.2.23
+++ conga/luci/cluster/form-macros	2007/06/19 15:54:09	1.90.2.24
@@ -3117,7 +3117,11 @@
 					<option tal:attributes="value nodeinfo/delete_url"
 						tal:condition="python: not 'ricci_error' in nodeinfo">
 						Delete this node</option>
+					<option tal:attributes="value nodeinfo/force_delete_url"
+						tal:condition="python: 'ricci_error' in nodeinfo">
+						Force the deletion of this node</option>
 				</select>
+
 				<input type="button" value="Go"
 					onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
 				</form>
@@ -3129,6 +3133,7 @@
 				<select name="gourl">
 					<option value="">Choose a Task...</option>
 					<option tal:attributes="value nodeinfo/fence_url | nothing">Fence this node</option>
+					<option tal:attributes="value nodeinfo/force_delete_url | nothing">Force the deletion of this node</option>
 				</select>
 				<input type="button" value="Go"
 					onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
@@ -3537,6 +3542,7 @@
 						<select class="node" name="gourl">
 							<option value="">Choose a Task...</option>
 							<option tal:attributes="value nd/fence_it_url | nothing">Fence this node</option>
+							<option tal:attributes="value nd/force_delete_url| nothing">Force the deletion of this node</option>
 						</select>
 						<input type="button" value="Go"
 							onclick="if (this.form.gourl[this.form.gourl.selectedIndex].value && confirm(this.form.gourl[this.form.gourl.selectedIndex].text + '?')) return dropdown(this.form.gourl)" />
--- conga/luci/site/luci/Extensions/Attic/LuciClusterActions.py	2007/06/18 18:39:32	1.1.4.1
+++ conga/luci/site/luci/Extensions/Attic/LuciClusterActions.py	2007/06/19 15:54:10	1.1.4.2
@@ -17,7 +17,7 @@
 	CLUSTER_NODE_NEED_AUTH
 
 from conga_constants import CLUSTER_CONFIG, LUCI_DEBUG_MODE, \
-	NODE_DELETE, CLUSTER_DELETE, CLUSTERLIST, \
+	NODE_DELETE, NODE_FORCE_DELETE, CLUSTER_DELETE, CLUSTERLIST, \
 	NODE_FENCE, NODE_JOIN_CLUSTER, NODE_LEAVE_CLUSTER, NODE_REBOOT, \
 	RESOURCE_ADD, RESOURCE_CONFIG, RESOURCE_REMOVE, \
 	SERVICE_DELETE, SERVICE_RESTART, SERVICE_START, SERVICE_STOP
@@ -283,6 +283,64 @@
 				% (nodename_resolved, e, str(e)))
 	return True
 
+def NodeForceDeleteFromCluster(self, model, clustername, nodename, nodename_resolved):
+	rc = getRicciAgent(self, clustername,
+			exclude_names=[ nodename_resolved, nodename ], exclude_busy=True)
+
+	if rc is None:
+		rc = getRicciAgent(self, clustername,
+			exclude_names=[ nodename_resolved, nodename ])
+
+	if rc is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('NFDFC0: no agent to delete node %s "%s"' \
+				% (nodename_resolved, clustername))
+		return None
+
+	try:
+		model.deleteNodeByName(nodename.lower())
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('NFDFC1: deleteNode %s: %r %s' \
+				% (nodename, e, str(e)))
+		return None
+
+	try:
+		model.setModified(True)
+		str_buf = str(model.exportModelAsString())
+		if not str_buf:
+			raise Exception, 'model string is blank'
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('NFDFC2: exportModelAsString: %r %s' \
+				% (e, str(e)))
+		return None
+
+	batch_number, result = rq.setClusterConf(rc, str_buf)
+	if batch_number is None or result is None:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('NFDFC3: batch number is None')
+		return None
+
+	try:
+		ret = delClusterSystem(self, clustername, nodename_resolved)
+		if ret is not None:
+			raise Exception, ret
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('NFDFC4: error deleting %s: %r %s' \
+				% (nodename_resolved, e, str(e)))
+
+	try:
+		set_node_flag(self, clustername, rc.hostname(),
+			str(batch_number), NODE_FORCE_DELETE,
+			'Forcing the deletion of node "%s"' % nodename)
+	except Exception, e:
+		if LUCI_DEBUG_MODE is True:
+			luci_log.debug_verbose('NFDFC5: failed to set flags: %r %s' \
+				% (e, str(e)))
+	return True
+
 def NodeDeleteFromCluster(	self,
 							rc,
 							model,
@@ -354,7 +412,7 @@
 		batch_number, result = rq.setClusterConf(rc2, str_buf)
 		if batch_number is None:
 			if LUCI_DEBUG_MODE is True:
-				luci_log.debug_verbose('ND8: batch number is None after del node in NTP')
+				luci_log.debug_verbose('ND8: batch number is None')
 			return None
 
 	try:
--- conga/luci/site/luci/Extensions/Attic/LuciClusterInfo.py	2007/06/18 18:39:32	1.1.4.1
+++ conga/luci/site/luci/Extensions/Attic/LuciClusterInfo.py	2007/06/19 15:54:10	1.1.4.2
@@ -17,7 +17,7 @@
 
 from conga_constants import CLUSTER_CONFIG, CLUSTER_DELETE, \
 	CLUSTER_PROCESS, CLUSTER_RESTART, CLUSTER_START, CLUSTER_STOP, \
-	FDOM, FENCEDEV, NODE, NODE_ACTIVE, \
+	NODE_FORCE_DELETE, FDOM, FENCEDEV, NODE, NODE_ACTIVE, \
 	NODE_ACTIVE_STR, NODE_DELETE, NODE_FENCE, NODE_INACTIVE, \
 	NODE_INACTIVE_STR, NODE_JOIN_CLUSTER, NODE_LEAVE_CLUSTER, \
 	NODE_PROCESS, NODE_REBOOT, NODE_UNKNOWN, NODE_UNKNOWN_STR, \
@@ -149,18 +149,10 @@
 	if not doc:
 		try:
 			from LuciDB import getClusterStatusDB
+			fvars = GetReqVars(request, [ 'clustername' ])
 
-			clustername = cluname
+			clustername = fvars['clustername']
 			if clustername is None:
-				try:
-					clustername = request['clustername']
-				except:
-					try:
-						clustername = request.form['clustername']
-					except:
-						pass
-
-			if not clustername:
 				raise Exception, 'unable to determine cluster name'
 
 			cinfo = getClusterStatusDB(self, clustername)
@@ -860,6 +852,8 @@
 	else:
 		infohash['fence_url'] = '%s?pagetype=%s&task=%s&nodename=%s&clustername=%s' \
 			% (baseurl, NODE_PROCESS, NODE_FENCE, nodename, clustername)
+		infohash['force_delete_url'] = '%s?pagetype=%s&task=%s&nodename=%s&clustername=%s' \
+			% (baseurl, NODE_PROCESS, NODE_FORCE_DELETE, nodename, clustername)
 
 	# figure out current services running on this node
 	svc_dict_list = list()
@@ -1021,6 +1015,8 @@
 		else:
 			nl_map['fence_it_url'] = '%s?pagetype=%s&task=%s&nodename=%s&clustername=%s' \
 				% (baseurl, NODE_PROCESS, NODE_FENCE, name, clustername)
+			nl_map['force_delete_url'] = '%s?pagetype=%s&task=%s&nodename=%s&clustername=%s' \
+				% (baseurl, NODE_PROCESS, NODE_FORCE_DELETE, name, clustername)
 
 		# figure out current services running on this node
 		svc_dict_list = list()
--- conga/luci/site/luci/Extensions/cluster_adapters.py	2007/06/18 18:39:32	1.120.2.30
+++ conga/luci/site/luci/Extensions/cluster_adapters.py	2007/06/19 15:54:10	1.120.2.31
@@ -35,12 +35,12 @@
 	DISABLE_SVC_TASK, ENABLE_SVC_TASK, FDOM, FDOM_ADD, FENCEDEV, \
 	FENCEDEV_NODE_CONFIG, FENCEDEVS, FLAG_DESC, INSTALL_TASK, \
 	LAST_STATUS, LUCI_DEBUG_MODE, NODE, NODE_ADD, NODE_DELETE, \
-	NODE_FENCE, NODE_JOIN_CLUSTER, NODE_LEAVE_CLUSTER, NODE_REBOOT, \
-	NODES, POSSIBLE_REBOOT_MESSAGE, PRE_CFG, PRE_INSTALL, PRE_JOIN, \
-	REBOOT_TASK, REDIRECT_MSG, RESOURCES, RICCI_CONNECT_FAILURE, \
+	NODE_FENCE, NODE_FORCE_DELETE, NODE_JOIN_CLUSTER, NODE_LEAVE_CLUSTER, \
+	NODE_REBOOT, NODES, POSSIBLE_REBOOT_MESSAGE, PRE_CFG, PRE_INSTALL, \
+	PRE_JOIN, REBOOT_TASK, REDIRECT_MSG, RESOURCES, RICCI_CONNECT_FAILURE, \
 	RICCI_CONNECT_FAILURE_MSG, SEND_CONF, SERVICE_ADD, SERVICE_CONFIG, \
 	SERVICE_LIST, SERVICES, START_NODE, TASKTYPE, VM_ADD, VM_CONFIG, \
-	REDIRECT_SEC
+	REDIRECT_SEC, LUCI_CLUSTER_BASE_URL
 
 from FenceHandler import validateNewFenceDevice, \
 	validateFenceDevice, validate_fenceinstance, \
@@ -718,7 +718,7 @@
 	errors = list()
 
 	try:
-		form_xml = request['form_xml']
+		form_xml = request['form_xml'].strip()
 		if not form_xml:
 			raise KeyError, 'form_xml must not be blank'
 	except Exception, e:
@@ -740,7 +740,7 @@
 		doc = minidom.parseString(form_xml)
 		forms = doc.getElementsByTagName('form')
 		if len(forms) < 1:
-			raise
+			raise Exception, 'invalid XML'
 	except Exception, e:
 		if LUCI_DEBUG_MODE is True:
 			luci_log.debug_verbose('vSA1: error: %r %s' % (e, str(e)))
@@ -1681,7 +1681,7 @@
 	errors = list()
 
 	try:
-		form_xml = request['fence_xml']
+		form_xml = request['fence_xml'].strip()
 		if not form_xml:
 			raise KeyError, 'form_xml must not be blank'
 	except Exception, e:
@@ -2637,7 +2637,9 @@
 	return getRicciAgent(self, clustername)
 
 def clusterTaskProcess(self, model, request):
-	fvar = GetReqVars(request, [ 'task', 'clustername' ])
+	fvar = GetReqVars(request, [ 'task', 'clustername', 'URL' ])
+
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
 
 	task = fvar['task']
 	if task is None:
@@ -2646,7 +2648,7 @@
 		return 'No cluster task was given'
 
 	if not model:
-		cluname = fvar['cluname']
+		cluname = fvar['clustername']
 		if cluname is None:
 			if LUCI_DEBUG_MODE is True:
 				luci_log.debug('CTP1: no cluster name')
@@ -2684,7 +2686,7 @@
 
 	response = request.RESPONSE
 	response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-		% (request['URL'], redirect_page, model.getClusterName()))
+		% (baseurl, redirect_page, model.getClusterName()))
 
 def nodeTaskProcess(self, model, request):
 	fvar = GetReqVars(request, [ 'task', 'clustername', 'nodename', 'URL' ])
@@ -2692,6 +2694,7 @@
 	task = fvar['task']
 	clustername = fvar['clustername']
 	nodename = fvar['nodename']
+	baseurl = fvar['URL'] or LUCI_CLUSTER_BASE_URL
 
 	if clustername is None:
 		if LUCI_DEBUG_MODE is True:
@@ -2711,10 +2714,9 @@
 	nodename_resolved = resolve_nodename(self, clustername, nodename)
 	response = request.RESPONSE
 
-	if task != NODE_FENCE:
-		# Fencing is the only task for which we don't
-		# want to talk to the node on which the action is
-		# to be performed.
+	if task != NODE_FENCE and task != NODE_FORCE_DELETE:
+		# Fencing and forced deletion are the only tasks
+		# for which we don't want to talk to the target node.
 		try:
 			rc = RicciCommunicator(nodename_resolved)
 			if not rc:
@@ -2773,7 +2775,7 @@
 			return (False, {'errors': [ 'Node "%s" failed to leave cluster "%s"' % (nodename_resolved, clustername) ]})
 
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (request['URL'], NODES, clustername))
+			% (baseurl, NODES, clustername))
 	elif task == NODE_JOIN_CLUSTER:
 		from LuciClusterActions import NodeJoinCluster
 		if NodeJoinCluster(self, rc, clustername, nodename_resolved) is None:
@@ -2782,7 +2784,7 @@
 			return (False, {'errors': [ 'Node "%s" failed to join cluster "%s"' % (nodename_resolved, clustername) ]})
 
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (request['URL'], NODES, clustername))
+			% (baseurl, NODES, clustername))
 	elif task == NODE_REBOOT:
 		from LuciClusterActions import NodeReboot
 		if NodeReboot(self, rc, clustername, nodename_resolved) is None:
@@ -2792,7 +2794,7 @@
 				% nodename_resolved ]})
 
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (request['URL'], NODES, clustername))
+			% (baseurl, NODES, clustername))
 	elif task == NODE_FENCE:
 		from LuciClusterActions import NodeFence
 		if NodeFence(self, clustername, nodename, nodename_resolved) is None:
@@ -2801,7 +2803,7 @@
 			return (False, {'errors': [ 'Fencing of node "%s" failed' \
 				% nodename_resolved]})
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (request['URL'], NODES, clustername))
+			% (baseurl, NODES, clustername))
 	elif task == NODE_DELETE:
 		from LuciClusterActions import NodeDeleteFromCluster
 		if NodeDeleteFromCluster(self, rc, model, clustername, nodename, nodename_resolved) is None:
@@ -2810,7 +2812,16 @@
 			return (False, {'errors': [ 'Deletion of node "%s" from cluster "%s" failed' % (nodename_resolved, clustername) ]})
 
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (request['URL'], NODES, clustername))
+			% (baseurl, NODES, clustername))
+	elif task == NODE_FORCE_DELETE:
+		from LuciClusterActions import NodeForceDeleteFromCluster
+		if NodeForceDeleteFromCluster(self, model, clustername, nodename, nodename_resolved) is None:
+			if LUCI_DEBUG_MODE is True:
+				luci_log.debug_verbose('NTP13: nodeForceDelete failed')
+			return (False, {'errors': [ 'Deletion of node "%s" from cluster "%s" failed' % (nodename_resolved, clustername) ]})
+
+		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
+			% (baseurl, NODES, clustername))
 
 def isClusterBusy(self, req):
 	items = None
@@ -3178,11 +3189,13 @@
 
 	fvars = GetReqVars(req,
 				[ 'clustername', 'servicename', 'nodename', 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+
 	ret = RestartCluSvc(self, rc, fvars)
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (fvars['URL'], SERVICE_LIST, fvars['clustername']))
+			% (baseurl, SERVICE_LIST, fvars['clustername']))
 	else:
 		return ret
 
@@ -3191,11 +3204,13 @@
 
 	fvars = GetReqVars(req,
 				[ 'clustername', 'servicename', 'nodename', 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+
 	ret = StopCluSvc(self, rc, fvars)
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (fvars['URL'], SERVICE_LIST, fvars['clustername']))
+			% (baseurl, SERVICE_LIST, fvars['clustername']))
 	else:
 		return ret
 
@@ -3204,11 +3219,13 @@
 
 	fvars = GetReqVars(req,
 				[ 'clustername', 'servicename', 'nodename', 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+
 	ret = StartCluSvc(self, rc, fvars)
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (fvars['URL'], SERVICE_LIST, fvars['clustername']))
+			% (baseurl, SERVICE_LIST, fvars['clustername']))
 	else:
 		return ret
 
@@ -3217,6 +3234,8 @@
 
 	fvars = GetReqVars(req,
 				[ 'clustername', 'servicename', 'nodename', 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+
 	try:
 		model = LuciExtractCluModel(self, req,
 					cluster_name=fvars['clustername'])
@@ -3229,7 +3248,7 @@
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (fvars['URL'], SERVICES, fvars['clustername']))
+			% (baseurl, SERVICES, fvars['clustername']))
 	else:
 		return ret
 
@@ -3238,11 +3257,13 @@
 
 	fvars = GetReqVars(req,
 				[ 'clustername', 'servicename', 'nodename', 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+
 	ret = MigrateCluSvc(self, rc, fvars)
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (fvars['URL'], SERVICE_LIST, fvars['clustername']))
+			% (baseurl, SERVICE_LIST, fvars['clustername']))
 	else:
 		return ret
 
@@ -3251,6 +3272,8 @@
 
 	fvars = GetReqVars(req,
 		[ 'clustername', 'resourcename', 'nodename', 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
+
 	try:
 		model = LuciExtractCluModel(self, req,
 					cluster_name=fvars['clustername'])
@@ -3265,12 +3288,14 @@
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (fvars['URL'], RESOURCES, fvars['clustername']))
+			% (baseurl, RESOURCES, fvars['clustername']))
 	else:
 		return ret
 
 def resourceAdd(self, req, model, res):
 	from LuciClusterActions import AddResource, EditResource
+	fvars = GetReqVars(req, [ 'URL' ])
+	baseurl = fvars['URL'] or LUCI_CLUSTER_BASE_URL
 
 	try:
 		cluname = model.getClusterName()
@@ -3291,7 +3316,7 @@
 	if ret is None:
 		response = req.RESPONSE
 		response.redirect('%s?pagetype=%s&clustername=%s&busyfirst=true' \
-			% (req['URL'], RESOURCES, cluname))
+			% (baseurl, RESOURCES, cluname))
 	else:
 		return ret
 
--- conga/luci/site/luci/Extensions/conga_constants.py	2007/06/18 18:39:33	1.19.2.10
+++ conga/luci/site/luci/Extensions/conga_constants.py	2007/06/19 15:54:10	1.19.2.11
@@ -59,17 +59,18 @@
 SYS_SERVICE_UPDATE		= '91'
 
 # Cluster tasks
-CLUSTER_STOP	= '1000'
-CLUSTER_START	= '1001'
-CLUSTER_RESTART	= '1002'
-CLUSTER_DELETE	= '1003'
+CLUSTER_STOP			= '1000'
+CLUSTER_START			= '1001'
+CLUSTER_RESTART			= '1002'
+CLUSTER_DELETE			= '1003'
 
 # Node tasks
-NODE_LEAVE_CLUSTER	= '100'
-NODE_JOIN_CLUSTER	= '101'
-NODE_REBOOT			= '102'
-NODE_FENCE			= '103'
-NODE_DELETE			= '104'
+NODE_LEAVE_CLUSTER		= '100'
+NODE_JOIN_CLUSTER		= '101'
+NODE_REBOOT				= '102'
+NODE_FENCE				= '103'
+NODE_DELETE				= '104'
+NODE_FORCE_DELETE		= '105'
 
 # General tasks
 BASECLUSTER	= '201'




More information about the Cluster-devel mailing list