superguard 0.0.3__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
superguard/__init__.py ADDED
@@ -0,0 +1 @@
1
+ # superguard package
superguard/compat.py ADDED
@@ -0,0 +1,26 @@
1
+ try:
2
+ import http.client as httplib
3
+ except ImportError:
4
+ import httplib
5
+
6
+ try:
7
+ from StringIO import StringIO
8
+ except ImportError:
9
+ from io import StringIO
10
+
11
+ try:
12
+ from sys import maxsize as maxint
13
+ except ImportError:
14
+ from sys import maxint
15
+
16
+ try:
17
+ import urllib.parse as urlparse
18
+ import urllib.parse as urllib
19
+ except ImportError:
20
+ import urlparse
21
+ import urllib
22
+
23
+ try:
24
+ import xmlrpc.client as xmlrpclib
25
+ except ImportError:
26
+ import xmlrpclib
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env python -u
2
+ ##############################################################################
3
+ #
4
+ # Copyright (c) 2007 Agendaless Consulting and Contributors.
5
+ # All Rights Reserved.
6
+ #
7
+ # This software is subject to the provisions of the BSD-like license at
8
+ # http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
9
+ # this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
10
+ # EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
11
+ # THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
12
+ # FITNESS FOR A PARTICULAR PURPOSE
13
+ #
14
+ ##############################################################################
15
+
16
+ # A event listener meant to be subscribed to PROCESS_STATE_CHANGE
17
+ # events. It will send mail when processes that are children of
18
+ # supervisord transition unexpectedly to the EXITED state.
19
+
20
+ # A supervisor config snippet that tells supervisor to use this script
21
+ # as a listener is below.
22
+ #
23
+ # [eventlistener:crashmail]
24
+ # command =
25
+ # /usr/bin/crashmail
26
+ # -o hostname -a -m notify-on-crash@domain.com
27
+ # -s '/usr/sbin/sendmail -t -i -f crash-notifier@domain.com'
28
+ # events=PROCESS_STATE
29
+ #
30
+ # Sendmail is used explicitly here so that we can specify the 'from' address.
31
+
32
+ from __future__ import print_function
33
+
34
+ import os
35
+ import sys
36
+ from argparse import ArgumentParser
37
+
38
+ from supervisor import childutils
39
+
40
+
41
+ class CrashMail:
42
+
43
+ def __init__(self, programs, any, email, sendmail, optionalheader):
44
+
45
+ self.programs = programs
46
+ self.any = any
47
+ self.email = email
48
+ self.sendmail = sendmail
49
+ self.optionalheader = optionalheader
50
+ self.stdin = sys.stdin
51
+ self.stdout = sys.stdout
52
+ self.stderr = sys.stderr
53
+
54
+ def runforever(self, test=False):
55
+ while 1:
56
+ # we explicitly use self.stdin, self.stdout, and self.stderr
57
+ # instead of sys.* so we can unit test this code
58
+ headers, payload = childutils.listener.wait(self.stdin, self.stdout)
59
+
60
+ if not headers["eventname"] == "PROCESS_STATE_EXITED":
61
+ # do nothing with non-TICK events
62
+ childutils.listener.ok(self.stdout)
63
+ if test:
64
+ self.stderr.write("non-exited event\n")
65
+ self.stderr.flush()
66
+ break
67
+ continue
68
+
69
+ pheaders, pdata = childutils.eventdata(payload + "\n")
70
+
71
+ if int(pheaders["expected"]):
72
+ childutils.listener.ok(self.stdout)
73
+ if test:
74
+ self.stderr.write("expected exit\n")
75
+ self.stderr.flush()
76
+ break
77
+ continue
78
+
79
+ msg = (
80
+ "Process %(processname)s in group %(groupname)s exited "
81
+ "unexpectedly (pid %(pid)s) from state %(from_state)s" % pheaders
82
+ )
83
+
84
+ subject = " %s crashed at %s" % (
85
+ pheaders["processname"],
86
+ childutils.get_asctime(),
87
+ )
88
+ if self.optionalheader:
89
+ subject = self.optionalheader + ":" + subject
90
+
91
+ self.stderr.write("unexpected exit, mailing\n")
92
+ self.stderr.flush()
93
+
94
+ self.mail(self.email, subject, msg)
95
+
96
+ childutils.listener.ok(self.stdout)
97
+ if test:
98
+ break
99
+
100
+ def mail(self, email, subject, msg):
101
+ body = "To: %s\n" % self.email
102
+ body += "Subject: %s\n" % subject
103
+ body += "\n"
104
+ body += msg
105
+ with os.popen(self.sendmail, "w") as m:
106
+ m.write(body)
107
+ self.stderr.write("Mailed:\n\n%s" % body)
108
+ self.mailed = body
109
+
110
+
111
+ def main(argv=sys.argv):
112
+ parser = ArgumentParser(
113
+ description=(
114
+ "Send email when processes that are children of supervisord "
115
+ "transition unexpectedly to the EXITED state."
116
+ ),
117
+ epilog=(
118
+ "The -p option may be specified more than once, allowing for "
119
+ "specification of multiple processes. Specifying -a overrides "
120
+ "any selection of -p.\n\n"
121
+ "A sample invocation:\n\n"
122
+ " crashmail -p program1 -p group1:program2 -m dev@example.com"
123
+ ),
124
+ )
125
+ parser.add_argument(
126
+ "-p",
127
+ "--program",
128
+ action="append",
129
+ default=[],
130
+ dest="programs",
131
+ help=(
132
+ "specify a supervisor process_name. Send mail when this process "
133
+ "transitions to the EXITED state unexpectedly. If this process is "
134
+ "part of a group, it can be specified using the "
135
+ "'group_name:process_name' syntax."
136
+ ),
137
+ )
138
+ parser.add_argument(
139
+ "-a",
140
+ "--any",
141
+ action="store_true",
142
+ default=False,
143
+ dest="any",
144
+ help=(
145
+ "Send mail when any child of the supervisord transitions "
146
+ "unexpectedly to the EXITED state. Overrides any -p parameters "
147
+ "passed in the same crashmail process invocation."
148
+ ),
149
+ )
150
+ parser.add_argument(
151
+ "-o",
152
+ "--optionalheader",
153
+ default=None,
154
+ help="Specify a parameter used as a prefix in the mail subject header.",
155
+ )
156
+ parser.add_argument(
157
+ "-s",
158
+ "--sendmail_program",
159
+ default="/usr/sbin/sendmail -t -i",
160
+ dest="sendmail",
161
+ help=(
162
+ "the sendmail command to use to send email "
163
+ '(e.g. "/usr/sbin/sendmail -t -i"). Must be a command which '
164
+ "accepts header and message data on stdin and sends mail. "
165
+ 'Default is "/usr/sbin/sendmail -t -i".'
166
+ ),
167
+ )
168
+ parser.add_argument(
169
+ "-m",
170
+ "--email",
171
+ default=None,
172
+ help=(
173
+ "specify an email address. The script will send mail to this "
174
+ "address when crashmail detects a process crash. If no email "
175
+ "address is specified, email will not be sent."
176
+ ),
177
+ )
178
+
179
+ args = parser.parse_args(argv[1:])
180
+
181
+ if "SUPERVISOR_SERVER_URL" not in os.environ:
182
+ sys.stderr.write("crashmail must be run as a supervisor event " "listener\n")
183
+ sys.stderr.flush()
184
+ return
185
+
186
+ prog = CrashMail(
187
+ args.programs, args.any, args.email, args.sendmail, args.optionalheader
188
+ )
189
+ prog.runforever()
190
+
191
+
192
+ if __name__ == "__main__":
193
+ main()
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env python -u
2
+ ##############################################################################
3
+ #
4
+ # Copyright (c) 2007 Agendaless Consulting and Contributors.
5
+ # All Rights Reserved.
6
+ #
7
+ # This software is subject to the provisions of the BSD-like license at
8
+ # http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
9
+ # this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
10
+ # EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
11
+ # THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
12
+ # FITNESS FOR A PARTICULAR PURPOSE
13
+ #
14
+ ##############################################################################
15
+
16
+ # A event listener meant to be subscribed to PROCESS_STATE_CHANGE
17
+ # events. It will send mail when processes that are children of
18
+ # supervisord transition unexpectedly to the EXITED state.
19
+
20
+ # A supervisor config snippet that tells supervisor to use this script
21
+ # as a listener is below.
22
+ #
23
+ # [eventlistener:crashmailbatch]
24
+ # command=python crashmailbatch --toEmail=you@bar.com --fromEmail=me@bar.com
25
+ # events=PROCESS_STATE,TICK_60
26
+
27
+ from __future__ import print_function
28
+
29
+ from supervisor import childutils
30
+ from superguard.process_state_email_monitor import ProcessStateEmailMonitor
31
+
32
+
33
+ class CrashMailBatch(ProcessStateEmailMonitor):
34
+
35
+ process_state_events = ["PROCESS_STATE_EXITED"]
36
+
37
+ def __init__(self, **kwargs):
38
+ if kwargs.get("subject") is None:
39
+ kwargs["subject"] = "Crash alert from supervisord"
40
+ ProcessStateEmailMonitor.__init__(self, **kwargs)
41
+ self.now = kwargs.get("now", None)
42
+
43
+ def get_process_state_change_msg(self, headers, payload):
44
+ pheaders, pdata = childutils.eventdata(payload + "\n")
45
+
46
+ if int(pheaders["expected"]):
47
+ return None
48
+
49
+ txt = "Process %(groupname)s:%(processname)s (pid %(pid)s) died \
50
+ unexpectedly" % pheaders
51
+ return "%s -- %s" % (childutils.get_asctime(self.now), txt)
52
+
53
+
54
+ def main():
55
+ crash = CrashMailBatch.create_from_cmd_line()
56
+ crash.run()
57
+
58
+
59
+ if __name__ == "__main__":
60
+ main()
superguard/crashsms.py ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env python -u
2
+ ##############################################################################
3
+ #
4
+ # Copyright (c) 2007 Agendaless Consulting and Contributors.
5
+ # All Rights Reserved.
6
+ #
7
+ # This software is subject to the provisions of the BSD-like license at
8
+ # http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
9
+ # this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
10
+ # EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
11
+ # THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
12
+ # FITNESS FOR A PARTICULAR PURPOSE
13
+ #
14
+ ##############################################################################
15
+
16
+ ##############################################################################
17
+ # crashsms
18
+ # author: Juan Batiz-Benet (http://github.com/jbenet)
19
+ # based on crashmailbatch.py
20
+ ##############################################################################
21
+
22
+
23
+ # A event listener meant to be subscribed to PROCESS_STATE_CHANGE
24
+ # events. It will send mail when processes that are children of
25
+ # supervisord transition unexpectedly to the EXITED state.
26
+
27
+ # A supervisor config snippet that tells supervisor to use this script
28
+ # as a listener is below.
29
+ #
30
+ # [eventlistener:crashsms]
31
+ # command =
32
+ # python crashsms
33
+ # -t <mobile phone>@<mobile provider> -f me@bar.com -e TICK_5
34
+ # events=PROCESS_STATE,TICK_5
35
+
36
+ from __future__ import print_function
37
+
38
+ from supervisor import childutils
39
+ from superguard.process_state_email_monitor import ProcessStateEmailMonitor
40
+
41
+
42
+ class CrashSMS(ProcessStateEmailMonitor):
43
+ process_state_events = ["PROCESS_STATE_EXITED"]
44
+
45
+ def __init__(self, **kwargs):
46
+ ProcessStateEmailMonitor.__init__(self, **kwargs)
47
+ self.now = kwargs.get("now", None)
48
+
49
+ def get_process_state_change_msg(self, headers, payload):
50
+ pheaders, pdata = childutils.eventdata(payload + "\n")
51
+
52
+ if int(pheaders["expected"]):
53
+ return None
54
+
55
+ txt = "[%(groupname)s:%(processname)s](%(pid)s) exited unexpectedly" % pheaders
56
+ return "%s %s" % (txt, childutils.get_asctime(self.now))
57
+
58
+
59
+ def main():
60
+ crash = CrashSMS.create_from_cmd_line()
61
+ crash.run()
62
+
63
+
64
+ if __name__ == "__main__":
65
+ main()
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env python -u
2
+ ##############################################################################
3
+ #
4
+ # Copyright (c) 2007 Agendaless Consulting and Contributors.
5
+ # All Rights Reserved.
6
+ #
7
+ # This software is subject to the provisions of the BSD-like license at
8
+ # http://www.repoze.org/LICENSE.txt. A copy of the license should accompany
9
+ # this distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
10
+ # EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
11
+ # THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
12
+ # FITNESS FOR A PARTICULAR PURPOSE
13
+ #
14
+ ##############################################################################
15
+
16
+ # A event listener meant to be subscribed to PROCESS_STATE_CHANGE
17
+ # events. It will send mail when processes that are children of
18
+ # supervisord transition unexpectedly to the EXITED state.
19
+
20
+ # A supervisor config snippet that tells supervisor to use this script
21
+ # as a listener is below.
22
+ #
23
+ # [eventlistener:fatalmailbatch]
24
+ # command=python fatalmailbatch
25
+ # events=PROCESS_STATE,TICK_60
26
+
27
+ from __future__ import print_function
28
+
29
+ from supervisor import childutils
30
+ from superguard.process_state_email_monitor import ProcessStateEmailMonitor
31
+
32
+
33
+ class FatalMailBatch(ProcessStateEmailMonitor):
34
+
35
+ process_state_events = ["PROCESS_STATE_FATAL"]
36
+
37
+ def __init__(self, **kwargs):
38
+ if kwargs.get("subject") is None:
39
+ kwargs["subject"] = "Fatal start alert from supervisord"
40
+ ProcessStateEmailMonitor.__init__(self, **kwargs)
41
+ self.now = kwargs.get("now", None)
42
+
43
+ def get_process_state_change_msg(self, headers, payload):
44
+ pheaders, pdata = childutils.eventdata(payload + "\n")
45
+
46
+ txt = "Process %(groupname)s:%(processname)s failed to start too many \
47
+ times" % pheaders
48
+ return "%s -- %s" % (childutils.get_asctime(self.now), txt)
49
+
50
+
51
+ def main():
52
+ fatal = FatalMailBatch.create_from_cmd_line()
53
+ fatal.run()
54
+
55
+
56
+ if __name__ == "__main__":
57
+ main()