def create(self): """ _create_ Create the couch document for this object. """ if not self.couch.documentExists(self.document_id): couchDoc = CMSCouch.Document(self.document_id, { self.cdb_document_data : dict(self)}) self.couch.commitOne(couchDoc)
def __init__(self, couchUrl, couchDatabase): self.cdb_url = couchUrl self.cdb_database = couchDatabase try: self.cdb_server = CMSCouch.CouchServer(self.cdb_url) self.couch = self.cdb_server.connectDatabase(self.cdb_database) except Exception as ex: msg = "Exception instantiating couch services for :\n" msg += " url = %s\n database = %s\n" % (self.cdb_url, self.cdb_database) msg += " Exception: %s" % str(ex) print(msg) raise CouchConnectionError(msg)
def publicationStatus(self, workflow, asourl): publication_info = {} if not asourl: raise ExecutionError("This CRAB server is not configured to publish; no publication status is available.") server = CMSCouch.CouchServer(dburl=asourl, ckey=self.serverKey, cert=self.serverCert) try: db = server.connectDatabase('asynctransfer') except Exception, ex: msg = "Error while connecting to asynctransfer CouchDB" self.logger.exception(msg) publication_info = {'error' : msg} return publication_info
def publicationStatusCouch(self, workflow, asourl, asodb): publicationInfo = {'status': {}, 'failure_reasons': {}} if not asourl: raise ExecutionError("This CRAB server is not configured to publish; no publication status is available.") server = CMSCouch.CouchServer(dburl=asourl, ckey=self.serverKey, cert=self.serverCert) try: db = server.connectDatabase(asodb) except Exception: msg = "Error while connecting to asynctransfer CouchDB for workflow %s " % workflow msg += "\n asourl=%s asodb=%s" % (asourl, asodb) self.logger.exception(msg) publicationInfo['status'] = {'error': msg} return publicationInfo # Get the publication status for the given workflow. The next query to the # CouchDB view returns a list of 1 dictionary (row) with: # 'key' : workflow, # 'value' : a dictionary with possible publication statuses as keys and the # counts as values. query = {'reduce': True, 'key': workflow, 'stale': 'update_after'} try: publicationList = db.loadView('AsyncTransfer', 'PublicationStateByWorkflow', query)['rows'] except Exception: msg = "Error while querying CouchDB for publication status information for workflow %s " % workflow self.logger.exception(msg) publicationInfo['status'] = {'error': msg} return publicationInfo if publicationList: publicationStatusDict = publicationList[0]['value'] publicationInfo['status'] = publicationStatusDict # Get the publication failure reasons for the given workflow. The next query to # the CouchDB view returns a list of N_different_publication_failures # dictionaries (rows) with: # 'key' : [workflow, publication failure], # 'value' : count. numFailedPublications = publicationStatusDict['publication_failed'] if numFailedPublications: query = {'group': True, 'startkey': [workflow], 'endkey': [workflow, {}], 'stale': 'update_after'} try: publicationFailedList = db.loadView('DBSPublisher', 'PublicationFailedByWorkflow', query)['rows'] except Exception: msg = "Error while querying CouchDB for publication failures information for workflow %s " % workflow self.logger.exception(msg) publicationInfo['failure_reasons']['error'] = msg return publicationInfo publicationInfo['failure_reasons']['result'] = [] for publicationFailed in publicationFailedList: failureReason = publicationFailed['key'][1] numFailedFiles = publicationFailed['value'] publicationInfo['failure_reasons']['result'].append((failureReason, numFailedFiles)) return publicationInfo
def makeFilelist(self, files={}): """ _makeFilelist_ Create a new filelist document containing the id """ input = { "collection_name": self.collectionName, "collection_type": self.collectionType, "fileset_name": self["name"], "files": files } document = CMSCouch.Document(None, input) self.owner.ownThis(document) commitInfo = self.couchdb.commitOne(document) document['_id'] = commitInfo[0]['id'] document['_rev'] = commitInfo[0]['rev'] return document
def initialiseCouch(objectRef): if objectRef.couchdb != None: return if objectRef.url == None: msg = "url for couch service not provided" raise CouchConnectionError(msg) if objectRef.database == None: msg = "database name for couch service not provided" raise CouchConnectionError(msg) try: objectRef.server = CMSCouch.CouchServer(objectRef.url) objectRef.couchdb = objectRef.server.connectDatabase( objectRef.database) except Exception as e: msg = "Exception instantiating couch services for :\n" msg += " url = %s\n database = %s\n" % (objectRef.url, objectRef.database) msg += " Exception: %s" % str(e) print msg raise CouchConnectionError(msg)
def removeOwner(self, owner): """ _removeOwner_ Remove an owner and all the associated collections and filesets """ result = self.couchdb.loadView( "GroupUser", 'owner_group_user', { 'startkey': [owner.group.name, owner.name], 'endkey': [owner.group.name, owner.name] }, []) for row in result[u'rows']: deleteMe = CMSCouch.Document() deleteMe[u'_id'] = row[u'value'][u'id'] deleteMe[u'_rev'] = row[u'value'][u'rev'] deleteMe.delete() self.couchdb.queue(deleteMe) self.couchdb.commit() owner.drop() return
def killTransfers(self, apmon): self.logger.info("About to kill transfers from workflow %s." % self.workflow) ASOURL = self.task.get('tm_asourl', None) if not ASOURL: self.logger.info("ASO URL not set; will not kill transfers") return False try: hostname = socket.getfqdn() except: hostname = '' server = CMSCouch.CouchServer(dburl=ASOURL, ckey=self.proxy, cert=self.proxy) try: db = server.connectDatabase('asynctransfer') except Exception, ex: msg = "Error while connecting to asynctransfer CouchDB" self.logger.exception(msg) raise TaskWorkerException(msg)
def makeFilelist(self, files=None): """ _makeFilelist_ Create a new filelist document containing the id """ files = files or {} # add a version to each of these ACDC docs such that we can properly # parse them and avoid issues between ACDC docs and agent base code input = { "collection_name": self.collectionName, "collection_type": self.collectionType, "fileset_name": self["name"], "files": files, "acdc_version": 2, "timestamp": time.time() } document = CMSCouch.Document(None, input) commitInfo = self.couchdb.commitOne(document) document['_id'] = commitInfo[0]['id'] if 'rev' in commitInfo[0]: document['_rev'] = commitInfo[0]['rev'] else: if commitInfo[0]['reason'].find('{exit_status,0}') != -1: # TODO: in this case actually insert succeeded but return error # due to the bug # https://issues.apache.org/jira/browse/COUCHDB-893 # if rev is needed to proceed need to get by # self.couchdb.documentExist(document['_id']) # but that function need to be changed to return _rev document['_rev'] = "NeedToGet" else: msg = "Unable to insert document: check acdc server doc id: %s" % document[ '_id'] raise RuntimeError(msg) return document
def connect(self): """ _connect_ Initialise the couch database connection for this object. This gets called automagically by the requireConnected decorator """ if self.connected: return if self.cdb_url == None: msg = "url for couch service not provided" raise CouchConnectionError(msg) if self.cdb_database == None: msg = "database name for couch service not provided" raise CouchConnectionError(msg) try: self.cdb_server = CMSCouch.CouchServer(self.cdb_url) self.couch = self.cdb_server.connectDatabase(self.cdb_database) except Exception as ex: msg = "Exception instantiating couch services for :\n" msg += " url = %s\n database = %s\n" % (self.cdb_url, self.cdb_database) msg += " Exception: %s" % str(ex) print msg raise CouchConnectionError(msg)
def killTransfers(self, apmon): self.logger.info("About to kill transfers from workflow %s." % self.workflow) ASOURL = self.task.get('tm_asourl', None) if not ASOURL: self.logger.info("ASO URL not set; will not kill transfers") return False try: hostname = socket.getfqdn() except: hostname = '' server = CMSCouch.CouchServer(dburl=ASOURL, ckey=self.proxy, cert=self.proxy) try: db = server.connectDatabase('asynctransfer') except Exception as ex: msg = "Error while connecting to asynctransfer CouchDB" self.logger.exception(msg) raise TaskWorkerException(msg) self.queryKill = {'reduce':False, 'key':self.workflow, 'include_docs': True} try: filesKill = db.loadView('AsyncTransfer', 'forKill', self.queryKill)['rows'] except Exception as ex: msg = "Error while connecting to asynctransfer CouchDB" self.logger.exception(msg) raise TaskWorkerException(msg) if len(filesKill) == 0: self.logger.warning('No files to kill found') for idt in filesKill: now = str(datetime.datetime.now()) id = idt['value'] data = { 'end_time': now, 'state': 'killed', 'last_update': time.time(), 'retry': now, } updateUri = "/%s/_design/AsyncTransfer/_update/updateJobs/%s?%s" % (db.name, id, urllib.urlencode(data)) jobid = idt.get('jobid') jobretry = idt.get('job_retry_count') if not self.task['kill_all']: if idt.get("jobid") not in self.task['kill_ids']: continue self.logger.info("Killing transfer %s (job ID %s; job retry %s)." % (id, str(jobid), str(jobretry))) jobid = str(jobid) jobretry = str(jobretry) if jobid and jobretry != None: jinfo = {'broker': hostname, 'bossId': jobid, 'StatusValue': 'killed', } insertJobIdSid(jinfo, jobid, self.workflow, jobretry) self.logger.info("Sending kill info to Dashboard: %s" % str(jinfo)) apmon.sendToML(jinfo) try: db.makeRequest(uri = updateUri, type = "PUT", decode = False) except Exception as ex: msg = "Error updating document in couch" msg += str(ex) msg += str(traceback.format_exc()) raise TaskWorkerException(msg) return True