-
Notifications
You must be signed in to change notification settings - Fork 3
/
issuesentinel.py
142 lines (118 loc) · 5.51 KB
/
issuesentinel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env python
"""check workflow issue and site issue detections,
then send notifications if any.
"""
import json
import smtplib
import socket
import urllib.request
from datetime import datetime
from email.mime.text import MIMEText
from os.path import abspath, dirname, isfile, join
import jira
from monitutils import get_yamlconfig
CRED_FILE_PATH = join(dirname(abspath(__file__)), 'config/credential.yml')
class JiraClient:
def __init__(self):
self._server = 'https://its.cern.ch/jira'
cookiefile = get_yamlconfig(CRED_FILE_PATH).get('jiracookie', None)
if not cookiefile or not isfile(cookiefile):
raise ValueError("`jiracookie` not existed in credential.yml or file not exist!\nJiraClient cannot be constructed.")
cookies = {}
for l in open(cookiefile).readlines():
_l = l.split()
if len(_l) < 7:
continue
if _l[5] in ['JSESSIONID', 'atlassian.xsrf.token']:
cookies[_l[5]] = _l[6]
if not cookies:
raise ValueError("`jiracookie` file corrupted!")
self.client = jira.JIRA(self._server, options=dict(cookies=cookies))
def create_issue(self, **kwargs):
fields = {
'project': 'CMSCOMPTNITEST',
'issuetype': {'name': 'Task'},
}
if kwargs.get('label', None):
fields['labels'] = [kwargs['label']]
if kwargs.get('assignee', None):
fields['assignee'] = dict(name=kwargs['assignee'], key=kwargs['assignee'])
if kwargs.get('summary', None):
fields['summary'] = kwargs['summary']
if kwargs.get('description', None):
fields['description'] = kwargs['description']
return self.client.create_issue(fields)
def search_issue(self, label, identifier):
assert(label in ['WorkflowIssue', 'SiteIssue'])
jql = 'project=%s AND labels=%s AND summary~%s'
return self.client.search_issues(jql % ('CMSCOMPTNITEST', label, identifier))
def add_comment(self, issuekey, comment):
return self.client.add_comment(issuekey, comment)
def get_comments(self, issuekey):
return self.client.issue(issuekey).fields.comment.comments
def jira_comments_to_json(comment):
raw = ''.join(comment.body.split('\n')[2:])
return json.loads(raw)
def json_partial_equal(j0, j1, keys):
return all([j0.get(k, None)==j1.get(k, None) for k in keys])
def send_email(subject, msg, recipients):
sender = '[email protected]'
contentMsg = MIMEText(msg)
contentMsg['Subject'] = subject
contentMsg['From'] = sender
contentMsg['To'] = ', '.join(recipients)
s = smtplib.SMTP('localhost')
s.sendmail(sender, recipients, contentMsg.as_string())
s.quit()
def main():
osdroid_addr = 'http://localhost:8020'
host_addr = f'http://{socket.gethostname()}:8020'
time_str = '{} {}'.format(datetime.now().isoformat(sep=' ', timespec='seconds'),
datetime.now().astimezone().tzname())
jc = JiraClient()
with urllib.request.urlopen(url=f'{osdroid_addr}/issues/workflow', timeout=60*8) as url:
flagged_workflows = json.loads(url.read().decode())
for workflowinfo in flagged_workflows:
workflow = workflowinfo.pop('name')
details = json.dumps(workflowinfo, indent=4)
issues = jc.search_issue(label='WorkflowIssue', identifier=workflow)
if issues:
if json_partial_equal(jira_comments_to_json(jc.get_comments(issues[0].key)[-1]),
workflowinfo, ['errorcnt_percode', 'total_error']): continue
comment = f'<sentinel> detected on {time_str}\n'
comment += '---------------------------------\n'
comment += details
jc.add_comment(issues[0].key, comment)
else:
desc = '\n'.join([
f'* [unified|https://cms-unified.web.cern.ch/cms-unified//report/{workflow}]',
f'* [OSDroid|{host_addr}/errorreport?name={workflow}]',
])
desc += '\n\n\n'
desc += details
jc.create_issue(label='WorkflowIssue',
summary=f'<Workflow> - {workflow} needs attention',
description=desc)
with urllib.request.urlopen(url=f'{osdroid_addr}/issues/site', timeout=60*8) as url:
flagged_sites = json.loads(url.read().decode())
for siteinfo in flagged_sites:
site = siteinfo.pop('site')
details = json.dumps(siteinfo, indent=4)
desc = 'site: {}, error increased: {}, detected on {}'.format(site,
siteinfo['errorinc'],
time_str)
issues = jc.search_issue(label='SiteIssue', identifier=site)
if issues:
comment = f'<sentinel> {desc}\n'
comment += '--------------------------------\n'
comment += details
jc.add_comment(issues[0].key, comment)
else:
desc_ = desc + '\n'
desc_ += '--------------------------------\n'
desc_ += details
jc.create_issue(label='SiteIssue',
summary='<Site> - {} needs attention'.format(site),
description=desc_)
if __name__ == "__main__":
main()