def execute(self): if not os.path.isfile(self.cacheFile): self.log.error(self.cacheFile + " does not exist.") return S_OK() with sqlite3.connect(self.cacheFile) as conn: # ******************************************************* # This is for the ProductionManagementSystem's Utilities # ******************************************************* if not self.csS: self.log.error('No ProductionRequest section in configuration') return S_OK() result = conn.execute( "SELECT DISTINCT thegroup, reqName, reqWG, reqInform from ProductionManagementCache;" ) html_header = """\ <!DOCTYPE html> <html> <head> <meta charset='UTF-8'> <style> table{color:#333;font-family:Helvetica,Arial,sans-serif;min-width:850px;border-collapse:collapse;border-spacing:0} td,th{border:1px solid transparent;height:30px;transition:all .3s}th{background:#DFDFDF;font-weight:700} td{background:#FAFAFA;text-align:center}tr:nth-child(even) td{background:#F1F1F1}tr:nth-child(odd) td{background:#FEFEFE}tr td:hover{background:#666;color:#FFF}tr td.link:hover{background:inherit;} p{width: 850px;} </style> </head> <body> """ for group in result: link = "https://lhcb-portal-dirac.cern.ch/DIRAC/s:" + PathFinder.getDIRACSetup() + "/g:" + group[0] + \ "/?view=tabs&theme=Grey&url_state=1|*LHCbDIRAC.ProductionRequestManager.classes.ProductionRequestManager:" aggregated_body = "" html_elements = "" # Check if group is not empty if group[0]: if group[0] == 'lhcb_bk': header = "New Productions are requested and they have customized Simulation Conditions. " \ "As member of <span style='color:green'>" + group[0] + "</span> group, your are asked either to register new Simulation conditions " \ "or to reject the requests. In case some other member of the group has already done that, " \ "please ignore this mail.\n" elif group[0] in ['lhcb_ppg', 'lhcb_tech']: header = "New Productions are requested. As member of <span style='color:green'>" + group[0] + "</span> group, your are asked either to sign or " \ "to reject it. In case some other member of the group has already done that, please ignore this mail.\n" else: header = "As member of <span style='color:green'>" + \ group[0] + "</span> group, your are asked to review the below requests.\n" cursor = conn.execute( "SELECT reqId, reqType, reqWG, reqName, SimCondition, ProPath from ProductionManagementCache " "WHERE thegroup = ? and reqName=? and reqWG=? ", (group[0], group[1], group[2])) for reqId, reqType, reqWG, reqName, SimCondition, ProPath in cursor: html_elements += "<tr>" + \ "<td>" + reqId + "</td>" + \ "<td>" + reqName + "</td>" + \ "<td>" + reqType + "</td>" + \ "<td>" + reqWG + "</td>" + \ "<td>" + SimCondition if SimCondition else '' + "</td>" + \ "<td>" + ProPath if ProPath else '' + "</td>" + \ "<td class='link'><a href='" + link + "' target='_blank'> Link </a></td>" + \ "</tr>" html_body = """\ <p>{header}</p> <table> <tr> <th>ID</th> <th>Name</th> <th>Type</th> <th>Working Group</th> <th>Conditions</th> <th>Processing pass</th> <th>Link</th> </tr> {html_elements} </table> </body> </html> """.format(header=header, html_elements=html_elements) aggregated_body = html_header + html_body informPeople = None if group[3]: informPeople = group[3].split(',') if informPeople: for emailaddress in informPeople: res = self.diracAdmin.sendMail( emailaddress, "Notifications for production requests - Group %s; %s; %s" % (group[0], group[2], group[1]), aggregated_body, self.fromAddress, html=True) for people in _getMemberMails(group[0]): res = self.diracAdmin.sendMail( people, "Notifications for production requests - Group %s; %s; %s" % (group[0], group[2], group[1]), aggregated_body, self.fromAddress, html=True) if res['OK']: conn.execute( "DELETE FROM ProductionManagementCache;") else: self.log.error( "_inform_people: can't send email: %s" % res['Message']) return S_OK() # ************************************** # This is for the ProductionStatusAgent # ************************************** html_header2 = """\ <!DOCTYPE html> <html> <head> <meta charset='UTF-8'> <style> table{color:#333;font-family:Helvetica,Arial,sans-serif;min-width:700px;border-collapse:collapse;border-spacing:0} td,th{border:1px solid transparent;height:30px;transition:all .3s}th{background:#DFDFDF;font-weight:700} td{background:#FAFAFA;text-align:center}.setup{font-size:150%;color:grey}.Active{color:green} .Archived,.Cleaned,.Cleaning{color:gray}.Completed{color:purple}.Idle{color:#90ee90}.Stopped{color:orange} .Testing,.TransformationCleaned{color:gray}tr:nth-child(even) td{background:#F1F1F1} tr:nth-child(odd) td{background:#FEFEFE}tr td:hover{background:#666;color:#FFF} </style> </head> <body> """ aggregated_body = "" html_elements = "" html_elements2 = "" cursor = conn.execute( "SELECT production, from_status, to_status, time from ProductionStatusAgentCache;" ) # Check if the results are non-empty if cursor.rowcount > 0: for production, from_status, to_status, time in cursor: html_elements += "<tr>" + \ "<td>" + production + "</td>" + \ "<td class='" + from_status + "'>" + from_status + "</td>" + \ "<td class='" + to_status + "'>" + to_status + "</td>" + \ "<td>" + time + "</td>" + \ "</tr>" html_body1 = """\ <p class="setup">Transformations updated</p> <table> <tr> <th>Production</th> <th>From</th> <th>To</th> <th>Time</th> </tr> {html_elements} </table> """.format(html_elements=html_elements) cursor = conn.execute( "SELECT prod_requests, time from ProductionStatusAgentReqCache;" ) # Check if the results are non-empty if cursor.rowcount > 0: for prod_requests, time in cursor: html_elements2 += "<tr>" + \ "<td>" + prod_requests + "</td>" + \ "<td>" + time + "</td>" + \ "</tr>" html_body2 = """\ <br /> <p class="setup">Production Requests updated to Done status</p> <table> <tr> <th>Production Requests</th> <th>Time</th> </tr> {html_elements2} </table> </body> </html> """.format(html_elements2=html_elements2) else: html_body2 = """\ </body> </html> """ aggregated_body = html_header2 + html_body1 + html_body2 res = self.diracAdmin.sendMail('*****@*****.**', "Transformation Status Updates", aggregated_body, '*****@*****.**', html=True) if res['OK']: conn.execute("DELETE FROM ProductionStatusAgentCache;") conn.execute("VACUUM;") conn.execute("DELETE FROM ProductionStatusAgentReqCache;") conn.execute("VACUUM;") else: self.log.error("Can't send email: %s" % res['Message']) return S_OK() return S_OK()
def informPeople(rec, oldstate, state, author, inform): """ inform utility """ if not state or state == 'New': return # was no state change or resurrect reqId = rec['RequestID'] csS = PathFinder.getServiceSection( 'ProductionManagement/ProductionRequest') if not csS: gLogger.error('No ProductionRequest section in configuration') return fromAddress = gConfig.getValue('%s/fromAddress' % csS, '') if not fromAddress: gLogger.error('No fromAddress is defined in CS path %s/fromAddress' % csS) return sendNotifications = gConfig.getValue('%s/sendNotifications' % csS, 'Yes') if sendNotifications != 'Yes': gLogger.info('No notifications will be send') return footer = "\n\nNOTE: it is an automated notification." footer += " Don't reply please.\n" footer += "DIRAC Web portal: https://lhcb-portal-dirac.cern.ch/DIRAC/s:%s/g:" % \ PathFinder.getDIRACSetup() ppath = "/?view=tabs&theme=Grey&url_state=1|*LHCbDIRAC.ProductionRequestManager.classes.ProductionRequestManager:,\n\n" ppath += 'The request details:\n' ppath += ' Type: %s' % str(rec['RequestType']) ppath += ' Name: %s\n' % str(rec['RequestName']) ppath += ' Conditions: %s\n' % str(rec['SimCondition']) ppath += ' Processing pass: %s\n' % str(rec['ProPath']) gLogger.info(".... %s ...." % ppath) authorMail = getUserOption(author, 'Email') if authorMail: if not state in ['BK Check', 'Submitted']: if state == 'BK OK': subj = 'DIRAC: please resign your Production Request %s' % reqId body = '\n'.join([ 'Customized Simulation Conditions in your request was registered.', 'Since Bookkeeping expert could make changes in your request,', 'you are asked to confirm it.' ]) else: subj = "DIRAC: the state of Production Request %s is changed to '%s'; %s;%s" % ( reqId, state, rec.get('RequestWG', ''), rec.get('RequestName', '')) body = '\n'.join([ 'The state of your request is changed.', 'This mail is for information only.' ]) notification = NotificationClient() res = notification.sendMail(authorMail, subj, body + footer + 'lhcb_user' + ppath, fromAddress, True) if not res['OK']: gLogger.error("_inform_people: can't send email: %s" % res['Message']) if inform: subj = "DIRAC: the state of %s Production Request %s is changed to '%s'; %s;%s" % ( rec['RequestType'], reqId, state, rec.get( 'RequestWG', ''), rec.get('RequestName', '')) body = '\n'.join([ 'You have received this mail because you are' 'in the subscription list for this request' ]) for x in inform.replace(" ", ",").split(","): if x: if x.find("@") > 0: eMail = x else: eMail = getUserOption(x, 'Email') if eMail: notification = NotificationClient() res = notification.sendMail( eMail, subj, body + footer + 'lhcb_user' + ppath, fromAddress, True) if not res['OK']: gLogger.error("_inform_people: can't send email: %s" % res['Message']) if state == 'Accepted': subj = "DIRAC: the Production Request %s is accepted; %s;%s" % ( reqId, rec.get('RequestWG', ''), rec.get('RequestName', '')) body = '\n'.join([ "The Production Request is signed and ready to process", "You are informed as member of %s group" ]) groups = ['lhcb_prmgr'] for group in groups: for man in _getMemberMails(group): notification = NotificationClient() res = notification.sendMail( man, subj, body % group + footer + group + ppath, fromAddress, True) if not res['OK']: gLogger.error("_inform_people: can't send email: %s" % res['Message']) elif state == 'PPG OK' and oldstate == 'Accepted': subj = "DIRAC: returned Production Request %s; %s;%s" % ( reqId, rec.get('RequestWG', ''), rec.get('RequestName', '')) body = '\n'.join([ "Production Request is returned by Production Manager.", "As member of %s group, your are asked to correct and sign", "or to reject it.", "", "In case some other member of the group has already", "done that, please ignore this mail." ]) groups = ['lhcb_tech'] for group in groups: for man in _getMemberMails(group): notification = NotificationClient() res = notification.sendMail( man, subj, body % group + footer + group + ppath, fromAddress, True) if not res['OK']: gLogger.error("_inform_people: can't send email: %s" % res['Message']) elif state == 'BK Check': groups = ['lhcb_bk'] _aggregate(reqId, rec.get('RequestType', ''), rec.get('RequestWG', ''), rec.get('RequestName', ''), rec['SimCondition'], rec['ProPath'], groups, rec.get('reqInform', inform)) elif state == 'Submitted': groups = ['lhcb_ppg', 'lhcb_tech'] _aggregate(reqId, rec.get('RequestType', ''), rec.get('RequestWG', ''), rec.get('RequestName', ''), rec['SimCondition'], rec['ProPath'], groups, rec.get('reqInform', inform)) else: return