[CalendarServer-changes] [1448] CalDAVTester/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Apr 5 09:04:08 PDT 2007


Revision: 1448
          http://trac.macosforge.org/projects/calendarserver/changeset/1448
Author:   cdaboo at 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 at 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 at 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 at 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 at 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 at 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 ""

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20070405/63ca82c0/attachment.html


More information about the calendarserver-changes mailing list