def changeStatus(requestName, status, wmstatUrl, acdcUrl): """ Changes the status for this request """ request = GetRequest.getRequestByName(requestName) if not status in RequestStatus.StatusList: raise RuntimeError, "Bad status code " + status if not request.has_key('RequestStatus'): raise RuntimeError, "Cannot find status for request " + requestName oldStatus = request['RequestStatus'] if not status in RequestStatus.NextStatus[oldStatus]: raise RuntimeError, "Cannot change status from %s to %s. Allowed values are %s" % ( oldStatus, status, RequestStatus.NextStatus[oldStatus]) if status == 'aborted': # delete from the workqueue if not privileged() and not ownsRequest(request): raise cherrypy.HTTPError(403, "You are not allowed to abort this request") elif not privileged(): raise cherrypy.HTTPError(403, "You are not allowed to change the state for this request") # delete from the workqueue if it's been assigned to one if status in RequestStatus.NextStatus[oldStatus]: abortRequest(requestName) else: raise cherrypy.HTTPError(400, "You cannot abort a request in state %s" % oldStatus) if status == 'announced': # cleanup acdc database, if possible if acdcUrl: url, database = WMCore.Lexicon.splitCouchServiceURL(acdcUrl) acdcService = CouchService(url = url, database = database) acdcService.removeFilesetsByCollectionName(requestName) # finally, perform the transition, have to do it in both Oracle and CouchDB # and in WMStats ChangeState.changeRequestStatus(requestName, status, wmstatUrl=wmstatUrl)
def testRemoveByCollectionName(self): """ _testRemoveByCollectionName_ Check the function to obliterate all the filesets of a collection """ self.populateCouchDB() svc = CouchService(url=self.testInit.couchUrl, database=self.testInit.couchDbName) database = CouchServer(self.testInit.couchUrl).connectDatabase( self.testInit.couchDbName) results = database.loadView("ACDC", "byCollectionName", keys=["Thunderstruck"]) self.assertTrue(len(results["rows"]) > 0) svc.removeFilesetsByCollectionName("Thunderstruck") results = database.loadView("ACDC", "byCollectionName", keys=["Thunderstruck"]) self.assertEqual(len(results["rows"]), 0) results = database.loadView("ACDC", "byCollectionName", keys=["Struckthunder"]) self.assertTrue(len(results["rows"]) > 0) svc.removeFilesetsByCollectionName("Struckthunder") results = database.loadView("ACDC", "byCollectionName", keys=["Struckthunder"]) self.assertEqual(len(results["rows"]), 0) return
def changeStatus(requestName, status, wmstatUrl, acdcUrl): """ Changes the status for this request """ request = GetRequest.getRequestByName(requestName) if not status in RequestStatus.StatusList: raise RuntimeError, "Bad status code " + status if not request.has_key('RequestStatus'): raise RuntimeError, "Cannot find status for request " + requestName oldStatus = request['RequestStatus'] if not status in RequestStatus.NextStatus[oldStatus]: raise RuntimeError, "Cannot change status from %s to %s. Allowed values are %s" % ( oldStatus, status, RequestStatus.NextStatus[oldStatus]) if status == 'aborted' or status == 'force-complete': # delete from the workqueue if not privileged() and not ownsRequest(request): raise cherrypy.HTTPError(403, "You are not allowed to %s this request" % status) elif not privileged(): raise cherrypy.HTTPError(403, "You are not allowed to change the state for this request") # delete from the workqueue if it's been assigned to one if status in RequestStatus.NextStatus[oldStatus]: abortRequest(requestName) else: raise cherrypy.HTTPError(400, "You cannot abort a request in state %s" % oldStatus) if status == 'announced': # cleanup acdc database, if possible if acdcUrl: url, database = WMCore.Lexicon.splitCouchServiceURL(acdcUrl) acdcService = CouchService(url = url, database = database) acdcService.removeFilesetsByCollectionName(requestName) # finally, perform the transition, have to do it in both Oracle and CouchDB # and in WMStats ChangeState.changeRequestStatus(requestName, status, wmstatUrl=wmstatUrl)
def testRemoveByCollectionName(self): """ _testRemoveByCollectionName_ Check the function to obliterate all the filesets of a collection """ self.populateCouchDB() svc = CouchService(url=self.testInit.couchUrl, database=self.testInit.couchDbName) database = CouchServer(self.testInit.couchUrl).connectDatabase(self.testInit.couchDbName) results = database.loadView("ACDC", "byCollectionName", keys=["Thunderstruck"]) self.assertTrue(len(results["rows"]) > 0) svc.removeFilesetsByCollectionName("Thunderstruck") results = database.loadView("ACDC", "byCollectionName", keys=["Thunderstruck"]) self.assertEqual(len(results["rows"]), 0) results = database.loadView("ACDC", "byCollectionName", keys=["Struckthunder"]) self.assertTrue(len(results["rows"]) > 0) svc.removeFilesetsByCollectionName("Struckthunder") results = database.loadView("ACDC", "byCollectionName", keys=["Struckthunder"]) self.assertEqual(len(results["rows"]), 0) return
def acdcCleanup(self, config): """ gather active data statistics """ reqDB = RequestDBReader(config.reqmgrdb_url) from WMCore.ACDC.CouchService import CouchService baseURL, acdcDB = splitCouchServiceURL(config.acdc_url) acdcService = CouchService(url=baseURL, database=acdcDB) originalRequests = acdcService.listCollectionNames() if len(originalRequests) == 0: return # filter requests results = reqDB._getCouchView("byrequest", {}, originalRequests) # checkt he status of the requests [announced, rejected-archived, aborted-archived, normal-archived] deleteStates = [ "announced", "rejected-archived", "aborted-archived", "normal-archived" ] filteredRequests = [] for row in results["rows"]: if row["value"][0] in deleteStates: filteredRequests.append(row["key"]) total = 0 for req in filteredRequests: try: deleted = acdcService.removeFilesetsByCollectionName(req) if deleted == None: self.logger.warning("request alread deleted %s", req) else: total += len(deleted) self.logger.info("request %s deleted", req) except Exception as ex: self.logger.error( "request deleted failed: will try again %s: %s", req, str(ex)) self.logger.info("total %s requests deleted", total) return
def acdcCleanup(self, config): """ gather active data statistics """ reqDB = RequestDBReader(config.reqmgrdb_url) from WMCore.ACDC.CouchService import CouchService baseURL, acdcDB = splitCouchServiceURL(config.acdc_url) acdcService = CouchService(url = baseURL, database = acdcDB) originalRequests = acdcService.listCollectionNames() if len(originalRequests) == 0: return # filter requests results = reqDB._getCouchView("byrequest", {}, originalRequests) # checkt he status of the requests [announced, rejected-archived, aborted-archived, normal-archived] deleteStates = ["announced", "rejected-archived", "aborted-archived", "normal-archived"] filteredRequests = [] for row in results["rows"]: if row["value"][0] in deleteStates: filteredRequests.append(row["key"]) total = 0 for req in filteredRequests: try: deleted = acdcService.removeFilesetsByCollectionName(req) if deleted == None: self.logger.warning("request alread deleted %s" % req) else: total += len(deleted) self.logger.info("request %s deleted" % req) except: self.logger.error("request deleted failed: will try again %s" % req) self.logger.info("total %s requests deleted" % total) return
class CouchDBCleanup(CherryPyPeriodicTask): def __init__(self, rest, config): super(CouchDBCleanup, self).__init__(config) self.reqDB = RequestDBReader(config.reqmgrdb_url) self.reqmgrAux = ReqMgrAux(config.reqmgr2_url, logger=self.logger) # statuses that we want to keep the transfer documents self.transferStatuses = [ "assigned", "staging", "staged", "acquired", "failed", "running-open", "running-closed" ] baseURL, acdcDB = splitCouchServiceURL(config.acdc_url) self.acdcService = CouchService(url=baseURL, database=acdcDB) def setConcurrentTasks(self, config): """ sets the list of functions which """ self.concurrentTasks = [{ 'func': self.acdcCleanup, 'duration': config.acdcCleanDuration }, { 'func': self.auxCouchCleanup, 'duration': config.auxCleanDuration }] def auxCouchCleanup(self, config): """ Cleanup TRANSFER documents from the reqmgr_auxiliary CouchDB. The list of status can be expanded in the future """ self.logger.info("Fetching TRANSFER documents from CouchDB...") transferDocs = self.reqmgrAux.getTransferInfo("ALL_DOCS") if not transferDocs: self.logger.info( " there are no transfer documents in the database.") return auxDocs = [] for row in transferDocs: auxDocs.append(row['workflowName']) results = self.reqDB._getCouchView("bystatus", {}, self.transferStatuses) activeRequests = [] for row in results["rows"]: activeRequests.append(row["id"]) # now find transfer docs that are not active in the system transferDocs = [] for transferDoc in auxDocs: if transferDoc not in activeRequests: transferDocs.append(transferDoc) self.logger.info("Found %d transfer documents to delete", len(transferDocs)) for wflowName in transferDocs: self.logger.info("Deleting transfer document: %s", wflowName) try: self.reqmgrAux.deleteConfigDoc("transferinfo", wflowName) except Exception as exc: self.logger.warning( "Failed to delete transfer doc: %s. Error: %s", wflowName, str(exc)) self.logger.info("Transfer documents cleanup completed.") def acdcCleanup(self, config): """ gather active data statistics """ self.logger.info("Fetching ACDC collection names...") originalRequests = self.acdcService.listCollectionNames() if not originalRequests: self.logger.info(" there are no collection documents to delete.") return # filter requests results = self.reqDB._getCouchView("byrequest", {}, originalRequests) # filter requests only in the following status deleteStates = [ "announced", "rejected-archived", "aborted-archived", "normal-archived" ] filteredRequests = [] for row in results["rows"]: if row["value"][0] in deleteStates: filteredRequests.append(row["key"]) total = 0 for req in filteredRequests: try: self.logger.info("Removing ACDC collection for: %s", req) deleted = self.acdcService.removeFilesetsByCollectionName(req) if deleted is None: self.logger.warning(" request '%s' already deleted", req) else: total += len(deleted) self.logger.info("request %s deleted", req) except Exception as ex: self.logger.error( "Failed to delete request: %s, will try again later. Error: %s", req, str(ex)) self.logger.info("total %s requests deleted", total) return