[CalendarServer-changes] [1908] CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav /directory

source_changes at macosforge.org source_changes at macosforge.org
Tue Sep 25 16:03:25 PDT 2007


Revision: 1908
          http://trac.macosforge.org/projects/calendarserver/changeset/1908
Author:   wsanchez at apple.com
Date:     2007-09-25 16:03:25 -0700 (Tue, 25 Sep 2007)

Log Message:
-----------
Pulled up r1896 from trunk.

Modified Paths:
--------------
    CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav/directory/test/test_opendirectoryschema.py

Modified: CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav/directory/appleopendirectory.py	2007-09-25 23:02:56 UTC (rev 1907)
+++ CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav/directory/appleopendirectory.py	2007-09-25 23:03:25 UTC (rev 1908)
@@ -183,24 +183,17 @@
         attrs = [
             dsattributes.kDS1AttrGeneratedUID,
             dsattributes.kDSNAttrRecordName,
-            dsattributes.kDS1AttrXMLPlist,
             dsattributes.kDSNAttrMetaNodeLocation,
             'dsAttrTypeNative:apple-serviceinfo',
         ]
 
-        from dsquery import expression, match
-
         records = opendirectory.queryRecordsWithAttributes(
             self.directory,
-            expression(
-                expression.OR,
-                (
-                    match(dsattributes.kDS1AttrXMLPlist,
-                          vhostname,
-                          dsattributes.eDSContains),
-                    match('dsAttrTypeNative:apple-serviceinfo',
-                          vhostname,
-                          dsattributes.eDSContains))).generate(),
+            dsquery.match(
+                'dsAttrTypeNative:apple-serviceinfo',
+                vhostname,
+                dsattributes.eDSContains,
+            ).generate(),
             True,    # case insentive for hostnames
             dsattributes.kDSStdRecordTypeComputers,
             attrs
@@ -222,9 +215,9 @@
         # Prefering the remote OD node to the local OD Node and
         # the local OD Node to the local node.
 
-        _localNode = None
-        _localODNode = None
-        _remoteNode = None
+        _localNodes = []
+        _localODNodes = []
+        _remoteNodes = []
 
         for recordname, record in records.iteritems():
             # May have an apple-serviceinfo
@@ -251,19 +244,38 @@
                 continue
 
             if record[dsattributes.kDSNAttrMetaNodeLocation] == localNodePath:
-                _localNode = (recordname, plist, record[dsattributes.kDS1AttrGeneratedUID])
+                _localNodes.append((recordname, plist, record[dsattributes.kDS1AttrGeneratedUID]))
 
             elif record[dsattributes.kDSNAttrMetaNodeLocation] == localODNodePath:
-                _localODNode = (recordname, plist, record[dsattributes.kDS1AttrGeneratedUID])
+                _localODNodes.append((recordname, plist, record[dsattributes.kDS1AttrGeneratedUID]))
 
             else:
-                _remoteNode = (recordname, plist, record[dsattributes.kDS1AttrGeneratedUID])
+                _remoteNodes.append((recordname, plist, record[dsattributes.kDS1AttrGeneratedUID]))
 
-        # XXX: These calls to self._parseXMLPlist will cause the plsit to be parsed _again_
+        # Verify that we only have a single record type to match
+        if len(_remoteNodes) > 1:
+            raise OpenDirectoryInitError(
+                "Open Directory (node=%s) too many remote /Computers records (%s) were found matching virtual hostname: %s"
+                % (self.realmName, ", ".join([r[0] for r in _remoteNodes]), vhostname,)
+            )
+
+        if len(_remoteNodes) == 0 and len(_localODNodes) > 1:
+            raise OpenDirectoryInitError(
+                "Open Directory (node=%s) too many local OD /Computers records (%s) were found matching virtual hostname: %s"
+                % (self.realmName, ", ".join([r[0] for r in _localODNodes]), vhostname,)
+            )
+
+        if len(_remoteNodes) == 0 and len(_localODNodes) == 0 and len(_localNodes) > 1:
+            raise OpenDirectoryInitError(
+                "Open Directory (node=%s) too many local /Computers records (%s) were found matching virtual hostname: %s"
+                % (self.realmName, ", ".join([r[0] for r in _localNodes]), vhostname,)
+            )
+
+        # XXX: These calls to self._parseServiceInfo will cause the plist to be parsed _again_
         #      refactor later so we only ever parse it once.
 
-        for node in (_remoteNode, _localODNode, _localNode):
-            if node and self._parseXMLPlist(vhostname, *node):
+        for node in itertools.chain(_remoteNodes, _localODNodes, _localNodes):
+            if node and self._parseServiceInfo(vhostname, *node):
                 break
 
         else:
@@ -273,14 +285,14 @@
                 % (self.realmName, vhostname,)
             )
 
-    def _parseXMLPlist(self, vhostname, recordname, plist, recordguid):
+    def _parseServiceInfo(self, vhostname, recordname, plist, recordguid):
         # Parse the plist and look for our special entry
         plist = readPlistFromString(plist)
         vhosts = plist.get("com.apple.macosxserver.virtualhosts", None)
         if not vhosts:
             log.msg(
                 "Open Directory (node=%s) /Computers/%s record does not have a "
-                "com.apple.macosxserver.virtualhosts in its XMLPlist attribute value"
+                "com.apple.macosxserver.virtualhosts in its ServiceInfo attribute value"
                 % (self.realmName, recordname)
             )
             return False
@@ -298,7 +310,7 @@
         if not hostguid:
             log.msg(
                 "Open Directory (node=%s) /Computers/%s record does not have a "
-                "calendar service in its XMLPlist attribute value"
+                "calendar service in its ServiceInfo attribute value"
                 % (self.realmName, recordname)
             )
             return False
@@ -308,7 +320,7 @@
         if not hostname:
             log.msg(
                 "Open Directory (node=%s) /Computers/%s record does not have "
-                "any host name in its XMLPlist attribute value"
+                "any host name in its ServiceInfo attribute value"
                 % (self.realmName, recordname)
             )
             return False
@@ -325,7 +337,7 @@
         if not hostdetails:
             log.msg(
                 "Open Directory (node=%s) /Computers/%s record does not have "
-                "any host details in its XMLPlist attribute value"
+                "any host details in its ServiceInfo attribute value"
                 % (self.realmName, recordname)
             )
             return False
@@ -339,7 +351,7 @@
         if not serviceInfos or not serviceInfos.has_key("calendar"):
             log.msg(
                 "Open Directory (node=%s) /Computers/%s record does not have a "
-                "calendar service in its XMLPlist attribute value"
+                "calendar service in its ServiceInfo attribute value"
                 % (self.realmName, recordname)
             )
             return False
@@ -350,7 +362,7 @@
         if not enabled:
             log.msg(
                 "Open Directory (node=%s) /Computers/%s record does not have an "
-                "enabled calendar service in its XMLPlist attribute value"
+                "enabled calendar service in its ServiceInfo attribute value"
                 % (self.realmName, recordname)
             )
             return False

Modified: CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav/directory/test/test_opendirectoryschema.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav/directory/test/test_opendirectoryschema.py	2007-09-25 23:02:56 UTC (rev 1907)
+++ CalendarServer/branches/release/CalendarServer-1.0-dev/twistedcaldav/directory/test/test_opendirectoryschema.py	2007-09-25 23:03:25 UTC (rev 1908)
@@ -823,10 +823,132 @@
 </plist>
 """
 
+        plist_duplicate = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+    <dict>
+        <key>ReplicaName</key>
+        <string>Master</string>
+
+        <key>com.apple.od.role</key>
+        <string>master</string>
+
+        <key>com.apple.macosxserver.virtualhosts</key>
+        <dict>
+            <key>F4088107-51FD-4DE5-904D-C20AD9C6C893</key>
+            <dict>
+                <key>hostname</key>
+                <string>foo.apple.com</string>
+
+                <key>hostDetails</key>
+                <dict>
+                    <key>access</key>
+                    <dict>
+                        <key>somethingorother</key>
+                        <string>somethingelse</string>
+                    </dict>
+                    <key>http</key>
+                    <dict>
+                        <key>port</key>
+                        <integer>80</integer>
+                    </dict>
+                    <key>https</key>
+                    <dict>
+                        <key>port</key>
+                        <string>443</string>
+                    </dict>
+                </dict>
+
+                <key>serviceType</key>
+                <array>
+                    <string>wiki</string>
+                    <string>webCalendar</string>
+                    <string>webMailingList</string>
+                </array>
+
+                <key>serviceInfo</key>
+                <dict>
+                    <key>webCalendar</key>
+                    <dict>
+                        <key>enabled</key>
+                        <true/>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(name)s/webcalendar</string>
+                    </dict>
+                    <key>wiki</key>
+                    <dict>
+                        <key>enabled</key>
+                        <true/>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(name)s/wiki</string>
+                    </dict>
+                    <key>webMailingList</key>
+                    <dict>
+                        <key>enabled</key>
+                        <true/>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(name)s/mailinglist</string>
+                    </dict>
+                </dict>
+            </dict>
+
+            <key>1C8C34AC-3D9E-403C-8A33-FBC303F3840E</key>
+            <dict>
+                <key>hostname</key>
+                <string>calendar.apple.com</string>
+
+                <key>hostDetails</key>
+                <dict>
+                    <key>access</key>
+                    <dict>
+                        <key>somethingorother</key>
+                        <string>somethingelse</string>
+                    </dict>
+                    <key>http</key>
+                    <dict>
+                        <key>port</key>
+                        <integer>8008</integer>
+                    </dict>
+                    <key>https</key>
+                    <dict>
+                        <key>port</key>
+                        <integer>8443</integer>
+                    </dict>
+                </dict>
+
+                <key>serviceType</key>
+                <array>
+                    <string>calendar</string>
+                </array>
+
+                <key>serviceInfo</key>
+                <dict>
+                    <key>calendar</key>
+                    <dict>
+                        <key>templates</key>
+                        <dict>
+                            <key>principalPath</key>
+                            <string>/principals/%(type)s/%(name)s</string>
+                            <key>calendarUserAddresses</key>
+                            <array>
+                                <string>%(scheme)s://%(hostname)s:%(port)s/principals/%(type)s/%(name)s</string>
+                                <string>mailto:%(email)s</string>
+                                <string>urn:uuid:%(guid)s</string>
+                            </array>
+                        </dict>
+                    </dict>
+                </dict>
+            </dict>
+
+        </dict>
+    </dict>
+</plist>
+"""
+
         def test_plist_errors(self):
             def _doParse(plist, title):
                 service = OpenDirectoryService(node="/Search", dosetup=False)
-                if service._parseXMLPlist("calendar.apple.com", "recordit", plist, "GUIDIFY"):
+                if service._parseServiceInfo("calendar.apple.com", "recordit", plist, "GUIDIFY"):
                     self.fail(msg="Plist parse should have failed: %s" % (title,))
 
             plists = (
@@ -842,7 +964,7 @@
 
         def test_goodplist(self):
             service = OpenDirectoryService(node="/Search", dosetup=False)
-            if not service._parseXMLPlist("calendar.apple.com", "recordit", PlistParse.plist_good, "GUIDIFY"):
+            if not service._parseServiceInfo("calendar.apple.com", "recordit", PlistParse.plist_good, "GUIDIFY"):
                 self.fail(msg="Plist parse should not have failed")
             else:
                 # Verify that we extracted the proper items
@@ -851,7 +973,7 @@
         def test_expandcuaddrs(self):
             def _doTest(recordName, record, result, title):
                 service = OpenDirectoryService(node="/Search", dosetup=False)
-                if not service._parseXMLPlist("calendar.apple.com", recordName, PlistParse.plist_good, "GUIDIFY"):
+                if not service._parseServiceInfo("calendar.apple.com", recordName, PlistParse.plist_good, "GUIDIFY"):
                     self.fail(msg="Plist parse should not have failed: %s" % (recordName,))
                 else:
                     expanded = service._getCalendarUserAddresses(DirectoryService.recordType_users, recordName, record)
@@ -898,30 +1020,48 @@
 
     class ODRecordsParse (twisted.trial.unittest.TestCase):
 
-        record_good = ("computer1.apple.com", {
+        record_localod_good = ("computer1.apple.com", {
             dsattributes.kDS1AttrGeneratedUID     : "GUID1",
             dsattributes.kDSNAttrRecordName       : "computer1.apple.com",
             'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_good,
             dsattributes.kDSNAttrMetaNodeLocation : "/LDAPv3/127.0.0.1",
         })
-        record_good_other = ("computer2.apple.com", {
+        record_localod_good_other = ("computer2.apple.com", {
             dsattributes.kDS1AttrGeneratedUID     : "GUID1",
             dsattributes.kDSNAttrRecordName       : "computer2.apple.com",
             'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_good_other,
             dsattributes.kDSNAttrMetaNodeLocation : "/LDAPv3/127.0.0.1",
         })
-        record_good_duplicate = ("computer3.apple.com", {
+        record_localod_duplicate = ("computer1", {
+            dsattributes.kDS1AttrGeneratedUID     : "GUID1_bad",
+            dsattributes.kDSNAttrRecordName       : "computer1",
+            'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_duplicate,
+            dsattributes.kDSNAttrMetaNodeLocation : "/LDAPv3/127.0.0.1",
+        })
+        record_remoteod_good = ("computer3.apple.com", {
             dsattributes.kDS1AttrGeneratedUID     : "GUID2",
-            dsattributes.kDSNAttrRecordName       : "computer2.apple.com",
+            dsattributes.kDSNAttrRecordName       : "computer3.apple.com",
             'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_good,
             dsattributes.kDSNAttrMetaNodeLocation : "/LDAPv3/directory.apple.com",
         })
-        record_good_local_duplicate = ("ServiceInformation", {
+        record_remoteod_duplicate = ("computer3", {
+            dsattributes.kDS1AttrGeneratedUID     : "GUID2",
+            dsattributes.kDSNAttrRecordName       : "computer3",
+            'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_duplicate,
+            dsattributes.kDSNAttrMetaNodeLocation : "/LDAPv3/directory.apple.com",
+        })
+        record_default_good = ("computer4.apple.com", {
             dsattributes.kDS1AttrGeneratedUID     : "GUID3",
-            dsattributes.kDSNAttrRecordName       : "computer2.apple.com",
+            dsattributes.kDSNAttrRecordName       : "computer4.apple.com",
             'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_good,
             dsattributes.kDSNAttrMetaNodeLocation : "/Local/Default",
         })
+        record_default_duplicate = ("computer4", {
+            dsattributes.kDS1AttrGeneratedUID     : "GUID3",
+            dsattributes.kDSNAttrRecordName       : "computer4",
+            'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_duplicate,
+            dsattributes.kDSNAttrMetaNodeLocation : "/Local/Default",
+        })
 
         def test_odrecords_error(self):
             def _doParseRecords(recordlist, title):
@@ -935,7 +1075,7 @@
             records = (
                 ({}, "no records found"),
                 ({
-                      ODRecordsParse.record_good_other[0]  : ODRecordsParse.record_good_other[1],
+                      ODRecordsParse.record_localod_good_other[0]  : ODRecordsParse.record_localod_good_other[1],
                  }, "non-matching record found"),
             )
 
@@ -952,11 +1092,11 @@
 
             records = (
                 ({
-                      ODRecordsParse.record_good[0]        : ODRecordsParse.record_good[1],
+                      ODRecordsParse.record_localod_good[0]        : ODRecordsParse.record_localod_good[1],
                  }, "single good plist"),
                 ({
-                      ODRecordsParse.record_good[0]        : ODRecordsParse.record_good[1],
-                      ODRecordsParse.record_good_other[0]  : ODRecordsParse.record_good_other[1],
+                      ODRecordsParse.record_localod_good[0]        : ODRecordsParse.record_localod_good[1],
+                      ODRecordsParse.record_localod_good_other[0]  : ODRecordsParse.record_localod_good_other[1],
                  }, "multiple plists"),
             )
 
@@ -973,23 +1113,50 @@
                                   "Got wrong guid, %s: Expected %s not %s" % (title, guid, gotGuid))
 
             records = (
-                ({ODRecordsParse.record_good_other[0]           : ODRecordsParse.record_good_other[1],
-                  ODRecordsParse.record_good_duplicate[0]       : ODRecordsParse.record_good_duplicate[1],
-                  ODRecordsParse.record_good_local_duplicate[0] :
-                      ODRecordsParse.record_good_local_duplicate[1]},
+                ({ODRecordsParse.record_remoteod_good[0] : ODRecordsParse.record_remoteod_good[1],
+                  ODRecordsParse.record_localod_good[0]  : ODRecordsParse.record_localod_good[1],
+                  ODRecordsParse.record_default_good[0]  : ODRecordsParse.record_default_good[1]},
                  "Remote Record Preferred", "GUID2"),
-                ({ODRecordsParse.record_good[0]                 : ODRecordsParse.record_good[1],
-                  ODRecordsParse.record_good_local_duplicate[0] :
-                      ODRecordsParse.record_good_local_duplicate[1]},
+                ({ODRecordsParse.record_localod_good[0]  : ODRecordsParse.record_localod_good[1],
+                  ODRecordsParse.record_default_good[0]  : ODRecordsParse.record_default_good[1]},
                  "Local OD Preferred", "GUID1"),
-                ({ODRecordsParse.record_good_local_duplicate[0] :
-                      ODRecordsParse.record_good_local_duplicate[1]},
+                ({ODRecordsParse.record_default_good[0]  : ODRecordsParse.record_default_good[1]},
                  "Local Node Preferred", "GUID3"),
             )
 
             for recordlist, title, guid in records:
                 _doParseRecords(recordlist, title, guid)
 
+        def test_odrecords_duplicates(self):
+            def _doParseRecords(recordlist, title, items):
+                service = OpenDirectoryService(node="/Search", dosetup=False)
+                try:
+                    service._parseComputersRecords(recordlist, "calendar.apple.com")
+                except OpenDirectoryInitError, ex:
+                    for item in items:
+                        if item not in str(ex):
+                            self.fail(msg="Record parse should have failed: \"%s\" with error: %s containing %s" % (title, ex, item))
+                else:
+                    self.fail(msg="Record parse should have failed: \"%s\"" % (title, ))
+
+            records = (
+                ({ODRecordsParse.record_remoteod_good[0]      : ODRecordsParse.record_remoteod_good[1],
+                  ODRecordsParse.record_remoteod_duplicate[0] : ODRecordsParse.record_remoteod_duplicate[1],
+                  ODRecordsParse.record_localod_good[0]       : ODRecordsParse.record_localod_good[1],
+                  ODRecordsParse.record_default_good[0]       : ODRecordsParse.record_default_good[1]},
+                 "Remote Record Duplicated", ("computer3.apple.com", "computer3",)),
+                ({ODRecordsParse.record_localod_good[0]       : ODRecordsParse.record_localod_good[1],
+                  ODRecordsParse.record_localod_duplicate[0]  : ODRecordsParse.record_localod_duplicate[1],
+                  ODRecordsParse.record_default_good[0]       : ODRecordsParse.record_default_good[1]},
+                 "Local OD Duplicated", ("computer1.apple.com", "computer1",)),
+                ({ODRecordsParse.record_default_good[0]       : ODRecordsParse.record_default_good[1],
+                  ODRecordsParse.record_default_duplicate[0]  : ODRecordsParse.record_default_duplicate[1]},
+                 "Local Node Duplicated", ("computer4.apple.com", "computer4",)),
+            )
+
+            for recordlist, title, items in records:
+                _doParseRecords(recordlist, title, items)
+
     class ODResourceInfoParse (twisted.trial.unittest.TestCase):
 
         plist_good_false = """<?xml version="1.0" encoding="UTF-8"?>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20070925/2561b36f/attachment.html


More information about the calendarserver-changes mailing list