def update(self, body): data = threaded_loads(body) if '_rev' not in data: self.logger.error('Could not locate the CouchDB revision number in object: %s' % data) return {"results": False, 'message': 'could not locate revision number in the object'} db = database('mccms') if not db.document_exists(data['_id']): return {"results": False, 'message': 'mccm %s does not exist' % ( data['_id'])} else: if db.get(data['_id'])['_rev'] != data['_rev']: return {"results": False, 'message': 'revision clash'} new_version = mccm(json_input=data) if not new_version.get_attribute('prepid') and not new_version.get_attribute('_id'): self.logger.error('Prepid returned was None') raise ValueError('Prepid returned was None') ## operate a check on whether it can be changed previous_version = mccm(db.get(new_version.get_attribute('prepid'))) editable = previous_version.get_editable() for (key, right) in editable.items(): # does not need to inspect the ones that can be edited if right: continue if previous_version.get_attribute(key) != new_version.get_attribute(key): self.logger.error('Illegal change of parameter, %s: %s vs %s : %s' % ( key, previous_version.get_attribute(key), new_version.get_attribute(key), right)) return {"results": False, 'message': 'Illegal change of parameter %s' % key} self.logger.log('Updating mccm %s...' % (new_version.get_attribute('prepid'))) # update history new_version.update_history({'action': 'update'}) return {"results": db.update(new_version.json())}
def update(self, body): data = threaded_loads(body) if '_rev' not in data: self.logger.error( 'Could not locate the CouchDB revision number in object: %s' % data) return { "results": False, 'message': 'could not locate revision number in the object' } db = database('mccms') if not db.document_exists(data['_id']): return { "results": False, 'message': 'mccm %s does not exist' % (data['_id']) } else: if db.get(data['_id'])['_rev'] != data['_rev']: return {"results": False, 'message': 'revision clash'} new_version = mccm(json_input=data) if not new_version.get_attribute( 'prepid') and not new_version.get_attribute('_id'): self.logger.error('Prepid returned was None') raise ValueError('Prepid returned was None') ## operate a check on whether it can be changed previous_version = mccm(db.get(new_version.get_attribute('prepid'))) editable = previous_version.get_editable() for (key, right) in editable.items(): # does not need to inspect the ones that can be edited if right: continue if previous_version.get_attribute( key) != new_version.get_attribute(key): self.logger.error( 'Illegal change of parameter, %s: %s vs %s : %s' % (key, previous_version.get_attribute(key), new_version.get_attribute(key), right)) return { "results": False, 'message': 'Illegal change of parameter %s' % key } self.logger.log('Updating mccm %s...' % (new_version.get_attribute('prepid'))) # update history new_version.update_history({'action': 'update'}) return {"results": db.update(new_version.json())}
def PUT(self): """ Create the mccm with the provided json content """ try: mccm_d = mccm(threaded_loads(cherrypy.request.body.read().strip())) except Exception as e: self.logger.error(mccm_d.json()) self.logger.error("Something went wrong with loading the mccm data:\n {0}".format(e)) return dumps({"results": False, "message": "Something went wrong with loading the mccm data:\n {0}".format(e)}) if not mccm_d.get_attribute('prepid'): self.logger.error('Non-existent prepid') return dumps({"results": False, "message": "The mccm ticket has no id!"}) db = database('mccms') if mccm_d.get_attribute('prepid') == mccm_d.get_attribute('pwg'): # need to complete the pwg mccm_d.set_attribute('prepid', self.fill_id(mccm_d.get_attribute('pwg'), db)) elif db.document_exists(mccm_d.get_attribute('prepid')): return dumps({"results": False, "message": "Mccm document {0} already exists".format(mccm_d.get_attribute('prepid'))}) mccm_d.set_attribute('_id', mccm_d.get_attribute('prepid')) mccm_d.set_attribute('meeting', mccm.get_meeting_date().strftime("%Y-%m-%d")) mccm_d.update_history({'action': 'created'}) self.logger.log('Saving mccm {0}'.format(mccm_d.get_attribute('prepid'))) return dumps({"results": db.save(mccm_d.json()), "prepid": mccm_d.get_attribute('prepid')})
def get(self, mccm_id): """ Cancel the MccM ticket provided in argument. Does not delete it but put the status as cancelled. """ db = database('mccms') udb = database('users') mcm_mccm = mccm(db.get(mccm_id)) curr_user = user(udb.get(mcm_mccm.current_user)) self.logger.info("Canceling an mccm: %s" % (mccm_id)) if mcm_mccm.get_attribute('status') == 'done': self.logger.info("You cannot cancel 'done' mccm ticket") return {"results": False, "message": "Cannot cancel done tickets"} if not mcm_mccm.get_attribute("pwg") in curr_user.get_pwgs(): self.logger.info("User's PWGs: %s doesnt include ticket's PWG: %s" % ( curr_user.get_pwgs(), mcm_mccm.get_attribute("pwg"))) return {"results": False, "message": "You cannot cancel ticket with different PWG than yours"} mcm_mccm.set_attribute('status', 'cancelled') mcm_mccm.update_history({'action': 'cancelled'}) saved = db.update(mcm_mccm.json()) if saved: return {"results": True} else: return {"results": False, "message": "Could not save the ticket to be cancelled."}
def GET(self, *args): """ Cancel the MccM ticket provided in argument. Does not delete it but put the status as cancelled. """ if not args: return dumps({ "results": False, "message": "No id given to cancel." }) db = database('mccms') mcm_mccm = mccm(db.get(args[0])) if mcm_mccm.get_attribute('status') == 'done': return dumps({ "results": False, "message": "Cannot cancel done tickets" }) mcm_mccm.set_attribute('status', 'cancelled') mcm_mccm.update_history({'action': 'cancelled'}) saved = db.update(mcm_mccm.json()) if saved: return dumps({"results": True}) else: return dumps({ "results": False, "message": "Could not save the ticket to be cancelled." })
def streaming_function(): mccms_db = database('mccms') users_db = database('users') generator_contacts_query = users_db.construct_lucene_query({'role': 'generator_contact'}) generator_contacts = users_db.full_text_search("search", generator_contacts_query, page=-1) generator_contacts_by_pwg = {} generator_contacts_emails = set() for contact in generator_contacts: for pwg in contact.get('pwg', []): if pwg not in generator_contacts_by_pwg: generator_contacts_by_pwg[pwg] = [] generator_contacts_by_pwg[pwg].append(contact.get('email')) generator_contacts_emails.add(contact.get('email')) __query = mccms_db.construct_lucene_query({'status': 'new'}) mccms_tickets = mccms_db.full_text_search('search', __query, page=-1) authors_tickets_dict = dict() yield '<pre>' for ticket in mccms_tickets: yield 'Processing ticket %s\n' % (ticket['prepid']) mccm_ticket = mccm(json_input=ticket) pwg = mccm_ticket.get_attribute('pwg') authors = mccm_ticket.get_actors(what='author_email') yield '%s worked on %s\n' % (authors, ticket['prepid']) authors = filter(lambda e: e in generator_contacts_emails, list(set(authors + generator_contacts_by_pwg.get(pwg, [])))) yield '%s will be notified about %s\n' % (authors, ticket['prepid']) for author_email in authors: if author_email in generator_contacts_emails: if author_email not in authors_tickets_dict: authors_tickets_dict[author_email] = set() authors_tickets_dict[author_email].add(ticket['prepid']) subject_template = 'Gentle reminder on %s ticket%s to be operated by you' message_template = ('Dear GEN Contact,\nPlease find below the details of %s MccM ticket%s in status "new". ' + 'Please present them in next MccM googledoc or cancel tickets if these are not needed anymore.\n\n') base_url = locator().baseurl() mail_communicator = communicator() service_account = settings.get_value('service_account') for author_email, ticket_prepids in authors_tickets_dict.iteritems(): num_tickets = len(ticket_prepids) subject = subject_template % (num_tickets, '' if num_tickets == 1 else 's') message = message_template % (num_tickets, '' if num_tickets == 1 else 's') for ticket_prepid in ticket_prepids: message += 'Ticket: %s\n%smccms?prepid=%s\n\n' % (ticket_prepid, base_url, ticket_prepid) yield '.' yield '\n' message += 'You received this email because you are listed as generator contact of physics group(s) of these tickets.\n' self.logger.info('Email:%s\nSubject: %s\nMessage:%s' % (author_email, subject, message)) mail_communicator.sendMail([author_email, service_account], subject, message) yield 'Email sent to %s\n' % (author_email)
def streaming_function(): mccms_db = database('mccms') users_db = database('users') __query = mccms_db.construct_lucene_query({'status': 'new'}) mccms_tickets = mccms_db.full_text_search('search', __query, page=-1) non_gen_contact_authors = set() authors_tickets_dict = dict() emails_prepids = dict() for ticket in mccms_tickets: yield '\nProcessing ticket %s' % (ticket['prepid']) mccm_ticket = mccm(json_input=ticket) authors = mccm_ticket.get_actors(what='author_email') for author_email in authors: if author_email in authors_tickets_dict: authors_tickets_dict[author_email].append(ticket['prepid']) elif author_email not in non_gen_contact_authors: __role_query = users_db.construct_lucene_query({'email': author_email}) result = users_db.full_text_search('search', __role_query, page=-1, include_fields='role,prepid') time.sleep(0.5) # we don't want to crash DB with a lot of single queries if result and result[0]['role'] == 'generator_contact': authors_tickets_dict[author_email] = [ticket['prepid']] emails_prepids[author_email] = result[0]['prepid'] else: non_gen_contact_authors.add(author_email) yield '.' subject_part1 = 'Gentle reminder on %s ' subject_part2 = ' to be operated by you' message_part1 = 'Dear GEN Contact, \nPlease find below the details of %s MccM ' message_part2 = ' in status "new". Please present them in next MccM googledoc or cancel tickets if these are not needed anymore.\n\n' base_url = locator().baseurl() mail_communicator = communicator() for author_email, ticket_prepids in authors_tickets_dict.iteritems(): num_tickets = len(ticket_prepids) full_message = (message_part1 % (num_tickets)) + ('ticket' if num_tickets == 1 else 'tickets') + message_part2 for ticket_prepid in ticket_prepids: full_message += 'Ticket: %s \n' % (ticket_prepid) full_message += '%smccms?prepid=%s \n\n' % (base_url, ticket_prepid) yield '.' full_message += '\n' subject = (subject_part1 % (num_tickets)) + ('ticket' if num_tickets == 1 else 'tickets') + subject_part2 notification( subject, full_message, [emails_prepids[author_email]], group=notification.REMINDERS, action_objects=ticket_prepids, object_type='mccms') mail_communicator.sendMail([author_email], subject, full_message) yield '\nEmail sent to %s\n' % (author_email)
def PUT(self): """ Create the mccm with the provided json content """ try: mccm_d = mccm(threaded_loads(cherrypy.request.body.read().strip())) except Exception as e: self.logger.error(mccm_d.json()) self.logger.error( "Something went wrong with loading the mccm data:\n {0}". format(e)) return dumps({ "results": False, "message": "Something went wrong with loading the mccm data:\n {0}". format(e) }) if not mccm_d.get_attribute('prepid'): self.logger.error('Non-existent prepid') return dumps({ "results": False, "message": "The mccm ticket has no id!" }) db = database('mccms') if mccm_d.get_attribute('prepid') == mccm_d.get_attribute( 'pwg'): # need to complete the pwg mccm_d.set_attribute('prepid', self.fill_id(mccm_d.get_attribute('pwg'), db)) elif db.document_exists(mccm_d.get_attribute('prepid')): return dumps({ "results": False, "message": "Mccm document {0} already exists".format( mccm_d.get_attribute('prepid')) }) mccm_d.set_attribute('_id', mccm_d.get_attribute('prepid')) mccm_d.set_attribute('meeting', mccm.get_meeting_date().strftime("%Y-%m-%d")) mccm_d.update_history({'action': 'created'}) self.logger.log('Saving mccm {0}'.format( mccm_d.get_attribute('prepid'))) return dumps({ "results": db.save(mccm_d.json()), "prepid": mccm_d.get_attribute('prepid') })
def get(self, mccm_id): """ Force to recalculate total_events for ticket """ db = database('mccms') if not db.document_exists(mccm_id): return {"results": {}} mccm_doc = mccm(db.get(prepid=mccm_id)) mccm_doc.update_total_events() saved = db.update(mccm_doc.json()) if saved: return {"results": True} else: return {"results": False, "message": "Could not save the ticket to be cancelled."}
def GET(self, *args): """ Cancel the MccM ticket provided in argument. Does not delete it but put the status as cancelled. """ if not args: return dumps({"results": False, "message": "No id given to cancel."}) db = database('mccms') mcm_mccm = mccm(db.get( args[0] )) if mcm_mccm.get_attribute('status') == 'done': return dumps({"results": False, "message": "Cannot cancel done tickets"}) mcm_mccm.set_attribute('status','cancelled') mcm_mccm.update_history({'action': 'cancelled'}) saved = db.update(mcm_mccm.json()) if saved: return dumps({"results": True}) else: return dumps({"results": False, "message": "Could not save the ticket to be cancelled."})
def put(self): """ Create the mccm with the provided json content """ try: mccm_d = mccm(loads(flask.request.data.strip())) except Exception as e: self.logger.error(mccm_d.json()) self.logger.error("Something went wrong with loading the mccm data:\n {0}".format(e)) return { "results": False, "message": "Something went wrong with loading the mccm data:\n {0}".format(e)} if not mccm_d.get_attribute('prepid'): self.logger.error('Non-existent prepid') return {"results": False, "message": "The mccm ticket has no id!"} if mccm_d.get_attribute("pwg") not in self.possible_pwgs: self.logger.error('Trying to create Mccm with non-existant PWG: %s' % (mccm_d.get_attribute("pwg"))) return { "results": False, "message": "The mccm ticket has non-existant PWG!"} db = database('mccms') # need to complete the prepid if mccm_d.get_attribute('prepid') == mccm_d.get_attribute('pwg'): mccm_d.set_attribute('prepid', self.fill_id(mccm_d.get_attribute('pwg'), db)) elif db.document_exists(mccm_d.get_attribute('prepid')): return {"results": False, "message": "Mccm document {0} already exists".format( mccm_d.get_attribute('prepid'))} mccm_d.set_attribute('_id', mccm_d.get_attribute('prepid')) mccm_d.set_attribute('meeting', mccm.get_meeting_date().strftime("%Y-%m-%d")) mccm_d.update_history({'action': 'created'}) self.logger.info('Saving mccm {0}'.format(mccm_d.get_attribute('prepid'))) return { "results": db.save(mccm_d.json()), "prepid": mccm_d.get_attribute('prepid')}
def generate(self, mid, reserve=False): mdb = database('mccms') mcm_m = mccm(mdb.get( mid )) if mcm_m.get_attribute('status')!='new': return {"prepid":mid, "results" : False, "message" : "status is %s, expecting new"%( mcm_m.get_attribute('status'))} if mcm_m.get_attribute('block')==0: return {"prepid":mid, "results" : False, "message" : "No block selected"} if len(mcm_m.get_attribute('chains'))==0: return {"prepid":mid, "results" : False, "message" : "No chains selected"} if len(mcm_m.get_attribute('requests'))==0: return {"prepid":mid, "results" : False, "message" : "No requests selected"} aids = [] for r in mcm_m.get_attribute('requests'): if type(r)==list: if len(r) >2: return {"prepid":mid, "results" : False, "message" : "range of id too large"} (pwg1, campaign1, serial1) = r[0].split('-') (pwg2, campaign2, serial2) = r[1].split('-') serial1=int(serial1) serial2=int(serial2) if pwg1!=pwg2 or campaign1!=campaign2: return {"prepid":mid, "results" : False, "message" : "inconsistent range of ids %s -> %s" %(r[0],r[1])} aids.extend( map( lambda s : "%s-%s-%05d"%( pwg1, campaign1, s), range( serial1, serial2+1))) else: aids.append( r ) res=[] for aid in aids: for times in range(mcm_m.get_attribute('repetitions')): for cc in mcm_m.get_attribute('chains'): b=mcm_m.get_attribute('block') s=None t=None if mcm_m.get_attribute('staged')!=0: s= mcm_m.get_attribute('staged') if mcm_m.get_attribute('threshold')!=0: t=mcm_m.get_attribute('threshold') res.append( {"prepid":mid,"results" : True,"message": "%s x %s in %s block %s s %s t %s"%( times, aid, cc, b, s ,t )}) res.append(self.setter.set_action(aid, cc, b, staged=s, threshold=t, reserve=reserve)) mcm_m.set_status() mdb.update( mcm_m.json()) return {"prepid":mid, "results" : True, "message" : res}
def generate(self, mid, reserve=False): mdb = database('mccms') rdb = database('requests') mcm_m = mccm(mdb.get(mid)) if mcm_m.get_attribute('status') != 'new': return { "prepid": mid, "results": False, "message": "status is %s, expecting new" % (mcm_m.get_attribute('status')) } if mcm_m.get_attribute('block') == 0: return { "prepid": mid, "results": False, "message": "No block selected" } if len(mcm_m.get_attribute('chains')) == 0: return { "prepid": mid, "results": False, "message": "No chains selected" } if len(mcm_m.get_attribute('requests')) == 0: return { "prepid": mid, "results": False, "message": "No requests selected" } aids = [] for r in mcm_m.get_attribute('requests'): if type(r) == list: if len(r) > 2: return { "prepid": mid, "results": False, "message": "range of id too large" } (pwg1, campaign1, serial1) = r[0].split('-') (pwg2, campaign2, serial2) = r[1].split('-') serial1 = int(serial1) serial2 = int(serial2) if pwg1 != pwg2 or campaign1 != campaign2: return { "prepid": mid, "results": False, "message": "inconsistent range of ids %s -> %s" % (r[0], r[1]) } aids.extend( map(lambda s: "%s-%s-%05d" % (pwg1, campaign1, s), range(serial1, serial2 + 1))) else: aids.append(r) if len(aids) != len(list(set(aids))): return { "prepid": mid, "results": False, "message": "There are duplicate actions in the ticket" } ccdb = database('chained_campaigns') ccs = [] for cc in mcm_m.get_attribute('chains'): if cc.startswith('chain'): ccs.extend(ccdb.queries(['prepid==%s' % cc])) else: ccs.extend(ccdb.queries(['alias==%s' % cc])) ## collect the name of the campaigns it can belong to ccs = list(set(map(lambda cc: cc['campaigns'][0][0], ccs))) if len(ccs) != 1: return { "prepid": mid, "results": False, "message": "inconsistent list of chains %s, leading to different root campaigns %s" % (mcm_m.get_attribute('chains'), ccs) } allowed_campaign = ccs[0] for aid in aids: mcm_r = rdb.get(aid) if mcm_r['member_of_campaign'] != allowed_campaign: return { "prepid": mid, "results": False, "message": "A request (%s) is not from the allowed root campaign %s" % (aid, allowed_campaign) } if mcm_r['status'] == 'new' and mcm_r['approval'] == 'validation': return { "prepid": mid, "results": False, "message": "A request (%s) is being validated." % (aid) } if mcm_r['flown_with']: return { "prepid": mid, "results": False, "message": "A request (%s) is in the middle of a chain already." % (aid) } if not mcm_m.get_attribute('repetitions'): return { "prepid": mid, "results": False, "message": "The number of repetitions (%s) is invalid" % (mcm_m.get_attribute('repetitions')) } res = [] for aid in aids: for times in range(mcm_m.get_attribute('repetitions')): for cc in mcm_m.get_attribute('chains'): b = mcm_m.get_attribute('block') s = None t = None special = mcm_m.get_attribute('special') if mcm_m.get_attribute('staged') != 0: s = mcm_m.get_attribute('staged') if mcm_m.get_attribute('threshold') != 0: t = mcm_m.get_attribute('threshold') res.append({ "prepid": mid, "results": True, "message": "%s x %s in %s block %s s %s t %s" % (times, aid, cc, b, s, t) }) res.append( self.setter.set_action(aid, cc, b, staged=s, threshold=t, reserve=reserve, special=special)) mcm_m.set_status() mdb.update(mcm_m.json()) return {"prepid": mid, "results": True, "message": res}
def generate(self, mid, reserve=False): mdb = database('mccms') rdb = database('requests') mcm_m = mccm(mdb.get(mid)) if mcm_m.get_attribute('status') != 'new': return { "prepid": mid, "results": False, "message": "status is %s, expecting new" % ( mcm_m.get_attribute('status'))} if mcm_m.get_attribute('block') == 0: return { "prepid": mid, "results": False, "message": "No block selected"} if len(mcm_m.get_attribute('chains')) == 0: return { "prepid": mid, "results": False, "message": "No chains selected"} if len(mcm_m.get_attribute('requests')) == 0: return { "prepid": mid, "results": False, "message": "No requests selected"} request_prepids = [] for r in mcm_m.get_attribute('requests'): if type(r) == list: if len(r) > 2: return { "prepid": mid, "results": False, "message": "range of id too large"} (pwg1, campaign1, serial1) = r[0].split('-') (pwg2, campaign2, serial2) = r[1].split('-') serial1 = int(serial1) serial2 = int(serial2) if pwg1 != pwg2 or campaign1 != campaign2: return { "prepid": mid, "results": False, "message": "inconsistent range of ids %s -> %s" % (r[0], r[1])} request_prepids.extend(map(lambda s: "%s-%s-%05d" % (pwg1, campaign1, s), range(serial1, serial2 + 1))) else: request_prepids.append(r) if len(request_prepids) != len(set(request_prepids)): return { "prepid": mid, "results": False, "message": "There are duplicate actions in the ticket"} ccdb = database('chained_campaigns') chained_campaigns = [] for cc in mcm_m.get_attribute('chains'): __query = ccdb.construct_lucene_query({ 'prepid': cc, 'alias': cc }, boolean_operator="OR" ) query_result = ccdb.full_text_search('search', __query, page=-1) chained_campaigns.extend(map(lambda cc: chained_campaign(cc), query_result)) # collect the name of the campaigns it can belong to ccs = list(set(map(lambda cc: cc.get_attribute('campaigns')[0][0], chained_campaigns))) if len(ccs) != 1: return { "prepid": mid, "results": False, "message": "inconsistent list of chains %s, leading to different root campaigns %s" % (mcm_m.get_attribute('chains'), ccs)} allowed_campaign = ccs[0] for request_prepid in request_prepids: mcm_r = rdb.get(request_prepid) if mcm_r['member_of_campaign'] != allowed_campaign: return { "prepid" : mid, "results" : False, "message" : "A request (%s) is not from the allowed root campaign %s" % (request_prepid, allowed_campaign)} if mcm_r['status'] == 'new' and mcm_r['approval'] == 'validation': return { "prepid": mid, "results": False, "message": "A request (%s) is being validated." % (request_prepid)} if mcm_r['flown_with']: return { "prepid": mid, "results": False, "message": "A request (%s) is in the middle of a chain already." % (request_prepid)} if not mcm_m.get_attribute('repetitions'): return { "prepid": mid, "results": False, "message": "The number of repetitions (%s) is invalid" % (mcm_m.get_attribute('repetitions'))} res = [] special = mcm_m.get_attribute('special') if isinstance(reserve, bool): reserve_campaigns = [reserve] * len(request_prepids) else: reserve_campaigns = reserve.split(',') for request_prepid in request_prepids: self.logger.info("Generating all chained request for request %s" % request_prepid) for times in range(mcm_m.get_attribute('repetitions')): for index, mcm_chained_campaign in enumerate(chained_campaigns): res.append(self.generate_chained_requests(mcm_m, request_prepid, mcm_chained_campaign, reserve=reserve_campaigns[index], special=special)) # for now we put a small delay to not crash index with a lot of action time.sleep(1) generated_chains = {} for el in res: if not el['results']: return { "prepid": mid, "results": False, "message": el['message'], 'chained_request_prepid': el['prepid'] if 'prepid' in el else ''} generated_chains[el['prepid']] = el['generated_requests'] self.logger.debug("just generated chains: %s" % (generated_chains)) mcm_m.set_attribute("generated_chains", generated_chains) mcm_m.set_status() mdb.update(mcm_m.json()) return { "prepid": mid, "results": True, "message": res}
def get_editable(self, prepid): db = database(self.db_name) mccm_d = mccm(db.get(prepid)) editable = mccm_d.get_editable() return {"results": editable}
def generate(self, mid, reserve=False): mdb = database('mccms') rdb = database('requests') mcm_m = mccm(mdb.get( mid )) if mcm_m.get_attribute('status')!='new': return {"prepid":mid, "results" : False, "message" : "status is %s, expecting new"%( mcm_m.get_attribute('status'))} if mcm_m.get_attribute('block')==0: return {"prepid":mid, "results" : False, "message" : "No block selected"} if len(mcm_m.get_attribute('chains'))==0: return {"prepid":mid, "results" : False, "message" : "No chains selected"} if len(mcm_m.get_attribute('requests'))==0: return {"prepid":mid, "results" : False, "message" : "No requests selected"} aids = [] for r in mcm_m.get_attribute('requests'): if type(r)==list: if len(r) >2: return {"prepid":mid, "results" : False, "message" : "range of id too large"} (pwg1, campaign1, serial1) = r[0].split('-') (pwg2, campaign2, serial2) = r[1].split('-') serial1=int(serial1) serial2=int(serial2) if pwg1!=pwg2 or campaign1!=campaign2: return {"prepid":mid, "results" : False, "message" : "inconsistent range of ids %s -> %s" %(r[0],r[1])} aids.extend( map( lambda s : "%s-%s-%05d"%( pwg1, campaign1, s), range( serial1, serial2+1))) else: aids.append( r ) if len(aids) != len(list(set( aids ))): return {"prepid":mid, "results" : False, "message" : "There are duplicate actions in the ticket"} ccdb = database('chained_campaigns') ccs=[] for cc in mcm_m.get_attribute('chains'): if cc.startswith('chain'): ccs.extend( ccdb.queries(['prepid==%s'% cc]) ) else: ccs.extend( ccdb.queries(['alias==%s'% cc]) ) ## collect the name of the campaigns it can belong to ccs = list(set(map(lambda cc : cc['campaigns'][0][0], ccs))) if len(ccs)!=1: return {"prepid":mid, "results" : False, "message" : "inconsistent list of chains %s, leading to different root campaigns %s"%(mcm_m.get_attribute('chains'),ccs)} allowed_campaign=ccs[0] for aid in aids: mcm_r = rdb.get(aid) if mcm_r['member_of_campaign'] != allowed_campaign: return {"prepid":mid, "results" : False, "message" : "A request (%s) is not from the allowed root campaign %s" %( aid, allowed_campaign) } if mcm_r['status']=='new' and mcm_r['approval']=='validation': return {"prepid":mid, "results" : False, "message" : "A request (%s) is being validated." %( aid) } if mcm_r['flown_with']: return {"prepid":mid, "results" : False, "message" : "A request (%s) is in the middle of a chain already."%(aid)} if not mcm_m.get_attribute('repetitions'): return {"prepid":mid, "results" : False, "message" : "The number of repetitions (%s) is invalid"%( mcm_m.get_attribute('repetitions') )} res=[] for aid in aids: for times in range(mcm_m.get_attribute('repetitions')): for cc in mcm_m.get_attribute('chains'): b=mcm_m.get_attribute('block') s=None t=None special=mcm_m.get_attribute('special') if mcm_m.get_attribute('staged')!=0: s= mcm_m.get_attribute('staged') if mcm_m.get_attribute('threshold')!=0: t=mcm_m.get_attribute('threshold') res.append( {"prepid":mid,"results" : True,"message": "%s x %s in %s block %s s %s t %s"%( times, aid, cc, b, s ,t )}) res.append(self.setter.set_action(aid, cc, b, staged=s, threshold=t, reserve=reserve, special=special)) mcm_m.set_status() mdb.update( mcm_m.json()) return {"prepid":mid, "results" : True, "message" : res}
def generate(self, mid, reserve=False): mdb = database('mccms') rdb = database('requests') mcm_m = mccm(mdb.get(mid)) if mcm_m.get_attribute('status') != 'new': return { "prepid": mid, "results": False, "message": "status is %s, expecting new" % ( mcm_m.get_attribute('status'))} if mcm_m.get_attribute('block') == 0: return { "prepid": mid, "results": False, "message": "No block selected"} if len(mcm_m.get_attribute('chains')) == 0: return { "prepid": mid, "results": False, "message": "No chains selected"} if len(mcm_m.get_attribute('requests')) == 0: return { "prepid": mid, "results": False, "message": "No requests selected"} request_prepids = [] for r in mcm_m.get_attribute('requests'): if type(r) == list: if len(r) > 2: return { "prepid": mid, "results": False, "message": "range of id too large"} (pwg1, campaign1, serial1) = r[0].split('-') (pwg2, campaign2, serial2) = r[1].split('-') serial1 = int(serial1) serial2 = int(serial2) if pwg1 != pwg2 or campaign1 != campaign2: return { "prepid": mid, "results": False, "message": "inconsistent range of ids %s -> %s" % (r[0], r[1])} request_prepids.extend(map(lambda s: "%s-%s-%05d" % (pwg1, campaign1, s), range(serial1, serial2 + 1))) else: request_prepids.append(r) if len(request_prepids) != len(set(request_prepids)): return { "prepid": mid, "results": False, "message": "There are duplicate actions in the ticket"} ccdb = database('chained_campaigns') chained_campaigns = [] for cc in mcm_m.get_attribute('chains'): __query = ccdb.construct_lucene_query({ 'prepid': cc, 'alias': cc }, boolean_operator="OR" ) query_result = ccdb.full_text_search('search', __query, page=-1) chained_campaigns.extend(map(lambda cc: chained_campaign(cc), query_result)) # collect the name of the campaigns it can belong to ccs = list(set(map(lambda cc: cc.get_attribute('campaigns')[0][0], chained_campaigns))) if len(ccs) != 1: return { "prepid": mid, "results": False, "message": "inconsistent list of chains %s, leading to different root campaigns %s" % (mcm_m.get_attribute('chains'), ccs)} allowed_campaign = ccs[0] for request_prepid in request_prepids: mcm_r = rdb.get(request_prepid) if mcm_r['member_of_campaign'] != allowed_campaign: return { "prepid" : mid, "results" : False, "message" : "A request (%s) is not from the allowed root campaign %s" % (request_prepid, allowed_campaign)} if mcm_r['status'] == 'new' and mcm_r['approval'] == 'validation': return { "prepid": mid, "results": False, "message": "A request (%s) is being validated." % (request_prepid)} if mcm_r['flown_with']: return { "prepid": mid, "results": False, "message": "A request (%s) is in the middle of a chain already." % (request_prepid)} if not mcm_m.get_attribute('repetitions'): return { "prepid": mid, "results": False, "message": "The number of repetitions (%s) is invalid" % (mcm_m.get_attribute('repetitions'))} res = [] special = mcm_m.get_attribute('special') for request_prepid in request_prepids: self.logger.info("Generating all chained request for request %s" % request_prepid) for times in range(mcm_m.get_attribute('repetitions')): for mcm_chained_campaign in chained_campaigns: res.append(self.generate_chained_requests(mcm_m, request_prepid, mcm_chained_campaign, reserve=reserve, special=special)) # for now we put a small delay to not crash index with a lot of action time.sleep(1) generated_chains = {} for el in res: if not el['results']: return { "prepid": mid, "results": False, "message": el['message'], 'chained_request_prepid': el['prepid'] if 'prepid' in el else ''} generated_chains[el['prepid']] = el['generated_requests'] self.logger.debug("just generated chains: %s" % (generated_chains)) mcm_m.set_attribute("generated_chains", generated_chains) mcm_m.set_status() mdb.update(mcm_m.json()) return { "prepid": mid, "results": True, "message": res}