Revision: 1448 http://trac.macosforge.org/projects/calendarserver/changeset/1448 Author: cdaboo@apple.com Date: 2007-04-05 09:04:08 -0700 (Thu, 05 Apr 2007) Log Message: ----------- Add the ability for the monitor tool to send email notices in the event of a failure. Modified Paths: -------------- CalDAVTester/trunk/monitor.py CalDAVTester/trunk/scripts/monitoring/monitorinfo.dtd CalDAVTester/trunk/scripts/monitoring/monitorinfo.xml CalDAVTester/trunk/src/monitorinfo.py CalDAVTester/trunk/src/xmlDefs.py Added Paths: ----------- CalDAVTester/trunk/src/sendemail.py CalDAVTester/trunk/src/xmlUtils.py Modified: CalDAVTester/trunk/monitor.py =================================================================== --- CalDAVTester/trunk/monitor.py 2007-04-04 17:55:18 UTC (rev 1447) +++ CalDAVTester/trunk/monitor.py 2007-04-05 16:04:08 UTC (rev 1448) @@ -27,10 +27,10 @@ import time import xml.dom.minidom -import src.xmlDefs - +from src.sendemail import sendemail from src.manager import manager from src.monitorinfo import monitorinfo +import src.xmlDefs EX_INVALID_CONFIG_FILE = "Invalid Config File" @@ -74,6 +74,14 @@ doScript(minfo.endscript) sys.exit() + def doNotification(msg): + sendemail( + fromaddr = ("Do Not Reply", "icalbridge-alert@apple.com"), + toaddrs = [("", a) for a in minfo.notify], + subject = minfo.notify_subject, + body = minfo.notify_body % (msg,), + ) + signal.signal(signal.SIGINT, doEnd) doStart() @@ -81,6 +89,7 @@ if minfo.logging: print "Start:" try: + last_notify = 0 while(True): time.sleep(minfo.period) result, timing = doScript(minfo.testinfo) @@ -89,11 +98,22 @@ if timing >= minfo.warningtime: dt = str(datetime.datetime.now()) dt = dt[0:dt.rfind(".")] - print "[%s] WARNING: request time (%.3f) exceeds limit (%.3f)" % (dt, timing, minfo.warningtime,) + msg = "[%s] WARNING: request time (%.3f) exceeds limit (%.3f)" % (dt, timing, minfo.warningtime,) + print msg + if minfo.notify_time_exceeded and (time.time() - last_notify > minfo.notify_interval * 60): + print "Sending notification to %s" % (minfo.notify,) + doNotification(msg) + last_notify = time.time() if result != 0: dt = str(datetime.datetime.now()) dt = dt[0:dt.rfind(".")] - print "[%s] WARNING: request failed" % (dt,) + msg = "[%s] WARNING: request failed" % (dt,) + print msg + if minfo.notify_request_failed and (time.time() - last_notify > minfo.notify_interval * 60): + print "Sending notification to %s" % (minfo.notify,) + doNotification(msg) + last_notify = time.time() + if minfo.logging: print "Done" except SystemExit: Modified: CalDAVTester/trunk/scripts/monitoring/monitorinfo.dtd =================================================================== --- CalDAVTester/trunk/scripts/monitoring/monitorinfo.dtd 2007-04-04 17:55:18 UTC (rev 1447) +++ CalDAVTester/trunk/scripts/monitoring/monitorinfo.dtd 2007-04-05 16:04:08 UTC (rev 1448) @@ -16,7 +16,7 @@ DRI: Cyrus Daboo, cdaboo@apple.com --> -<!ELEMENT monitorinfo (logging, period, serverinfo, start, testinfo, end, warningtime)? > +<!ELEMENT monitorinfo (logging, period, serverinfo, start, testinfo, end, warningtime, notify?) > <!ELEMENT logging EMPTY> <!ATTLIST logging enable (yes|no) "no"> @@ -32,3 +32,12 @@ <!ELEMENT end (#PCDATA)> <!ELEMENT warningtime (#PCDATA)> + + <!ELEMENT notify (mailto+, subject, body)> + <!ATTLIST notify time-exceeded (yes|no) "no" + request-failed (yes|no) "yes" + interval CDATA "15"> + + <!ELEMENT mailto (#PCDATA)> + <!ELEMENT subject (#PCDATA)> + <!ELEMENT body (#PCDATA)> Modified: CalDAVTester/trunk/scripts/monitoring/monitorinfo.xml =================================================================== --- CalDAVTester/trunk/scripts/monitoring/monitorinfo.xml 2007-04-04 17:55:18 UTC (rev 1447) +++ CalDAVTester/trunk/scripts/monitoring/monitorinfo.xml 2007-04-05 16:04:08 UTC (rev 1448) @@ -24,8 +24,21 @@ <logging enable="no"/> <period>1</period> <serverinfo>scripts/server/serverinfo-monitor.xml</serverinfo> - <start/> - <testinfo>monitor/get/get.xml</testinfo> - <end/> + <start>monitor/get/get-start.xml</start> + <testinfo>monitor/get/get-small.xml</testinfo> + <end>monitor/get/get-end.xml</end> <warningtime>1.0</warningtime> + <notify time-exceeded="no" request-failed="yes"> + <mailto>test@example.com</mailto> + <subject>Calendar Server error</subject> + <body><![CDATA[Hi, +The caldav.example.com Calendar Server generated the following error: + +%s + +Please take the appropriate action. + +Thank you. +]]></body> + </notify> </monitorinfo> Modified: CalDAVTester/trunk/src/monitorinfo.py =================================================================== --- CalDAVTester/trunk/src/monitorinfo.py 2007-04-04 17:55:18 UTC (rev 1447) +++ CalDAVTester/trunk/src/monitorinfo.py 2007-04-05 16:04:08 UTC (rev 1448) @@ -20,13 +20,31 @@ Class that encapsulates the server information for CalDAV monitoring. """ +from src.xmlUtils import getDefaultAttributeValue +from src.xmlUtils import getYesNoAttributeValue +from src.xmlUtils import readOneStringElement +from src.xmlUtils import readStringElementList import src.xmlDefs class monitorinfo( object ): """ Maintains information about the monitoring test scenario. """ - __slots__ = ['logging', 'period', 'serverinfo', 'startscript', 'testinfo', 'endscript', 'warningtime'] + __slots__ = [ + 'logging', + 'period', + 'serverinfo', + 'startscript', + 'testinfo', + 'endscript', + 'warningtime', + 'notify', + 'notify_time_exceeded', + 'notify_request_failed', + 'notify_interval', + 'notify_subject', + 'notify_body', + ] def __init__( self ): self.logging = False @@ -36,11 +54,17 @@ self.testinfo = "" self.endscript = "" self.warningtime = 1.0 + self.notify = None + self.notify_time_exceeded = False + self.notify_request_failed = False + self.notify_interval = 15 + self.notify_subject = None + self.notify_body = None def parseXML( self, node ): for child in node._get_childNodes(): if child._get_localName() == src.xmlDefs.ELEMENT_LOGGING: - self.logging = child.getAttribute( src.xmlDefs.ATTR_ENABLE ) != src.xmlDefs.ATTR_VALUE_NO + self.logging = getYesNoAttributeValue(child, src.xmlDefs.ATTR_ENABLE) elif child._get_localName() == src.xmlDefs.ELEMENT_PERIOD: self.period = float(child.firstChild.data) elif child._get_localName() == src.xmlDefs.ELEMENT_SERVERINFO: @@ -55,3 +79,10 @@ self.endscript = child.firstChild.data elif child._get_localName() == src.xmlDefs.ELEMENT_WARNINGTIME: self.warningtime = float(child.firstChild.data) + elif child._get_localName() == src.xmlDefs.ELEMENT_NOTIFY: + self.notify_time_exceeded = getYesNoAttributeValue(child, src.xmlDefs.ATTR_TIME_EXCEEDED) + self.notify_request_failed = getYesNoAttributeValue(child, src.xmlDefs.ATTR_REQUEST_FAILED) + self.notify_interval = int(getDefaultAttributeValue(child, src.xmlDefs.ATTR_INTERVAL, "15")) + self.notify = readStringElementList(child, src.xmlDefs.ELEMENT_MAILTO) + self.notify_subject = readOneStringElement(child, src.xmlDefs.ELEMENT_SUBJECT) + self.notify_body = readOneStringElement(child, src.xmlDefs.ELEMENT_BODY) Added: CalDAVTester/trunk/src/sendemail.py =================================================================== --- CalDAVTester/trunk/src/sendemail.py (rev 0) +++ CalDAVTester/trunk/src/sendemail.py 2007-04-05 16:04:08 UTC (rev 1448) @@ -0,0 +1,55 @@ +# +# Copyright (c) 2007 Apple Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# DRI: Cyrus Daboo, cdaboo@apple.com +## + +""" +Send an email message. +""" + +import email.mime.text +import smtplib + +def sendemail(fromaddr=("", ""), toaddrs=[], subject="", body=""): + """ + + @param fromaddr: tuple of From address (<full name>, <email>) + @param toaddrs: list of tuples of (<full name>, <email>) for each recipient + @param subject: a C{str} containing the subject + @param body: a C{str} containing the body + """ + + def fulladdr(addr): + if addr[0]: + return "%s <%s>" % (addr[0], addr[1],) + else: + return addr[1] + + if isinstance(body, unicode): + body = body.decode("utf-8") + charset = "us-ascii" + for c in body: + if ord(c) > 0x7F: + charset = "utf-8" + break + msg = email.mime.text.MIMEText(body, "plain", charset) + msg.add_header("From", fulladdr(fromaddr)) + msg.add_header("To", ", ".join([fulladdr(a) for a in toaddrs])) + msg.add_header("Subject", subject) + msgtxt = msg.as_string(False) + server = smtplib.SMTP("relay.apple.com") + server.sendmail(fromaddr[1], [a[1] for a in toaddrs], msgtxt) + server.quit() Modified: CalDAVTester/trunk/src/xmlDefs.py =================================================================== --- CalDAVTester/trunk/src/xmlDefs.py 2007-04-04 17:55:18 UTC (rev 1447) +++ CalDAVTester/trunk/src/xmlDefs.py 2007-04-05 16:04:08 UTC (rev 1448) @@ -20,6 +20,7 @@ ELEMENT_ACCOUNT = "account" ELEMENT_ARG = "arg" +ELEMENT_BODY = "body" ELEMENT_CALDAVTEST = "caldavtest" ELEMENT_CALENDARS = "calendars" ELEMENT_CALLBACK = "callback" @@ -36,9 +37,11 @@ ELEMENT_HOST = "host" ELEMENT_KEY = "key" ELEMENT_LOGGING = "logging" +ELEMENT_MAILTO = "mailto" ELEMENT_METHOD = "method" ELEMENT_MONITORINFO = "monitorinfo" ELEMENT_NAME = "name" +ELEMENT_NOTIFY = "notify" ELEMENT_PATH = "path" ELEMENT_PERFINFO = "perfinfo" ELEMENT_PERIOD = "period" @@ -53,6 +56,7 @@ ELEMENT_SPREAD = "spread" ELEMENT_SSL = "ssl" ELEMENT_START = "start" +ELEMENT_SUBJECT = "subject" ELEMENT_SUBSTITUTIONS = "substitutions" ELEMENT_SUBSTITUTION = "substitution" ELEMENT_TEST = "test" @@ -73,12 +77,15 @@ ATTR_END_DELETE = "end-delete" ATTR_IGNORE = "ignore" ATTR_IGNORE_ALL = "ignore-all" +ATTR_INTERVAL = "interval" ATTR_MODE = "mode" ATTR_NAME = "name" ATTR_PRINT_RESPONSE = "print-response" ATTR_PSWD = "pswd" +ATTR_REQUEST_FAILED = "request-failed" ATTR_STATS = "stats" ATTR_SUBSTITUTIONS = "substitutions" +ATTR_TIME_EXCEEDED = "time-exceeded" ATTR_USER = "user" ATTR_DEFAULT_COUNT = 1 Added: CalDAVTester/trunk/src/xmlUtils.py =================================================================== --- CalDAVTester/trunk/src/xmlUtils.py (rev 0) +++ CalDAVTester/trunk/src/xmlUtils.py 2007-04-05 16:04:08 UTC (rev 1448) @@ -0,0 +1,48 @@ +## +# Copyright (c) 2007 Apple Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# DRI: Cyrus Daboo, cdaboo@apple.com +## + +""" +XML processing utilities. +""" + +import src.xmlDefs + +def readStringElementList(node, ename): + + results = [] + for child in node._get_childNodes(): + if child._get_localName() == ename: + results.append(child.firstChild.data.decode("utf-8")) + return results + +def getYesNoAttributeValue(node, attr): + return node.getAttribute(attr) != src.xmlDefs.ATTR_VALUE_NO + +def getDefaultAttributeValue(node, attr, default): + result = node.getAttribute(attr) + if result: + return result + else: + return default + +def readOneStringElement(node, ename): + + for child in node._get_childNodes(): + if child._get_localName() == ename: + return child.firstChild.data.decode("utf-8") + return ""
participants (1)
-
source_changes@macosforge.org