From mboxrd@z Thu Jan 1 00:00:00 1970 From: rmccabe@sourceware.org Date: 19 Jun 2007 15:54:11 -0000 Subject: [Cluster-devel] conga/luci cluster/form-macros site/luci/Exten ... Message-ID: <20070619155411.25337.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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 @@ + + @@ -3129,6 +3133,7 @@ @@ -3537,6 +3542,7 @@ --- 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'