[CalendarServer-changes] [2142] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Feb 13 15:41:17 PST 2008


Revision: 2142
          http://trac.macosforge.org/projects/calendarserver/changeset/2142
Author:   wsanchez at apple.com
Date:     2008-02-13 15:41:16 -0800 (Wed, 13 Feb 2008)

Log Message:
-----------
Merge http://svn.macosforge.org/repository/calendarserver/CalendarServer/branches/users/wsanchez/cache-miss

Modified Paths:
--------------
    CalendarServer/trunk/test
    CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/trunk/twistedcaldav/directory/idirectory.py
    CalendarServer/trunk/twistedcaldav/directory/principal.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py
    CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py

Modified: CalendarServer/trunk/test
===================================================================
--- CalendarServer/trunk/test	2008-02-13 23:32:53 UTC (rev 2141)
+++ CalendarServer/trunk/test	2008-02-13 23:41:16 UTC (rev 2142)
@@ -18,15 +18,20 @@
 # DRI: Wilfredo Sanchez, wsanchez at apple.com
 ##
 
-random="--random=$(date "+%s")";
+set -e
+set -u
 
+    random="--random=$(date "+%s")";
+ no_colour="";
+until_fail="";
+
 usage ()
 {
   program="$(basename "$0")";
 
   if [ "${1--}" != "-" ]; then echo "$@"; echo; fi;
 
-  echo "Usage: ${program} [-hnr]";
+  echo "Usage: ${program} [options]";
   echo "Options:";
   echo "        -h  Print this help and exit";
   echo "        -n  Do not use color";
@@ -41,8 +46,8 @@
   case "${option}" in
     '?') usage; ;;
     'h') usage -; exit 0; ;;
-    'n') no_colour="--reporter=bwverbose"; ;;
-    'o') random=""; ;;
+    'o')     random=""; ;;
+    'n')  no_colour="--reporter=bwverbose"; ;;
     'u') until_fail="--until-failure"; ;;
   esac;
 done;
@@ -59,4 +64,4 @@
     test_modules="twistedcaldav twisted";
 fi;
 
-cd "${wd}" && "${twisted}/bin/trial" ${random} ${until_fail} ${no_colour} ${test_modules};
+cd "${wd}" && "${twisted}/bin/trial" ${random} ${until_fail} ${no_colour} --coverage ${test_modules};

Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2008-02-13 23:32:53 UTC (rev 2141)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2008-02-13 23:41:16 UTC (rev 2142)
@@ -43,8 +43,8 @@
 
 from plistlib import readPlistFromString, readPlist
 
-_serverPreferences = '/Library/Preferences/com.apple.servermgr_info.plist'
-_saclGroup = 'com.apple.access_calendar'
+serverPreferences = '/Library/Preferences/com.apple.servermgr_info.plist'
+saclGroup = 'com.apple.access_calendar'
 
 recordListCacheTimeout = 60 * 30 # 30 minutes
 
@@ -91,12 +91,10 @@
                     logging.err("Unable to locate virtual host record: %s" % (e,), system="OpenDirectoryService")
                     raise
 
-                if os.path.exists(_serverPreferences):
-                    serverInfo = readPlist(_serverPreferences)
+                if os.path.exists(serverPreferences):
+                    serverInfo = readPlist(serverPreferences)
 
-                    self.isWorkgroupServer = serverInfo.get(
-                        'ServiceConfig', {}).get(
-                        'IsWorkgroupServer', False)
+                    self.isWorkgroupServer = serverInfo.get('ServiceConfig', {}).get('IsWorkgroupServer', False)
 
                     if self.isWorkgroupServer:
                         logging.info("Enabling Workgroup Server compatibility mode", system="OpenDirectoryService")
@@ -131,11 +129,14 @@
                 dsattributes.eDSExact,
                 False,
                 dsattributes.kDSStdRecordTypeGroups,
-                [dsattributes.kDSNAttrGroupMembers,
-                 dsattributes.kDSNAttrNestedGroups])
+                [dsattributes.kDSNAttrGroupMembers, dsattributes.kDSNAttrNestedGroups]
+            )
 
             if not result:
-                logging.err("Couldn't find group %s when trying to expand nested groups." % (groupGUID,), system="OpenDirectoryService")
+                logging.err(
+                    "Couldn't find group %s when trying to expand nested groups."
+                    % (groupGUID,), system="OpenDirectoryService"
+                )
                 continue
 
             group = result[0][1]
@@ -204,7 +205,7 @@
         if len(records) == 0:
             raise OpenDirectoryInitError(
                 "Open Directory (node=%s) has no /Computers records with a virtual hostname: %s"
-                % (self.realmName, vhostname,)
+                % (self.realmName, vhostname)
             )
 
         # Now find all appropriate records and determine the enabled (only) service tags for each.
@@ -228,14 +229,14 @@
             raise OpenDirectoryInitError(
                 "Open Directory (node=%s) no /Computers records with an enabled and valid "
                 "calendar service were found matching virtual hostname: %s"
-                % (self.realmName, vhostname,)
+                % (self.realmName, vhostname)
             )
 
     def _parseServiceInfo(self, vhostname, recordname, record):
 
         # Extract some useful attributes
         recordguid = record[dsattributes.kDS1AttrGeneratedUID]
-        recordlocation = "%s/Computers/%s" % (record[dsattributes.kDSNAttrMetaNodeLocation], recordname,)
+        recordlocation = "%s/Computers/%s" % (record[dsattributes.kDSNAttrMetaNodeLocation], recordname)
 
         # First check for apple-serviceinfo attribute
         plist = record.get('dsAttrTypeNative:apple-serviceinfo', None)
@@ -249,7 +250,7 @@
             logging.err(
                 "Open Directory (node=%s) %s record does not have a "
                 "com.apple.macosxserver.virtualhosts in its apple-serviceinfo attribute value"
-                % (self.realmName, recordlocation,), system="OpenDirectoryService"
+                % (self.realmName, recordlocation), system="OpenDirectoryService"
             )
             return False
         
@@ -308,14 +309,14 @@
         # Create the string we will use to match users with accounts on this server
         servicetag = "%s:%s:calendar" % (recordguid, hostguid)
         
-        self.computerRecords[recordlocation] = (recordname, enabled, servicetag,)
+        self.computerRecords[recordlocation] = (recordname, enabled, servicetag)
         
         if enabled:
             self.servicetags.add(servicetag)
         
         return True
     
-    def _getCalendarUserAddresses(self, recordType, recordName, record):
+    def _calendarUserAddresses(self, recordType, recordName, record):
         """
         Extract specific attributes from the directory record for use as calendar user address.
         
@@ -323,7 +324,6 @@
         @param record: a C{dict} containing the attributes retrieved from the directory.
         @return: a C{set} of C{str} for each expanded calendar user address.
         """
-        
         # Now get the addresses
         result = set()
         
@@ -348,9 +348,9 @@
         plist = readPlistFromString(plist)
         wpframework = plist.get("com.apple.WhitePagesFramework", {})
         autoaccept = wpframework.get("AutoAcceptsInvitation", False)
-        proxy= wpframework.get("CalendaringDelegate")
+        proxy = wpframework.get("CalendaringDelegate")
         
-        return (autoaccept, proxy,)
+        return (autoaccept, proxy)
 
     def recordTypes(self):
         return (
@@ -372,8 +372,10 @@
 
                 def onError(f):
                     storage["status"] = "stale" # Keep trying
-                    logging.err("Unable to load records of type %s from OpenDirectory due to unexpected error: %s"
-                            % (recordType, f), system="OpenDirectoryService")
+                    logging.err(
+                        "Unable to load records of type %s from OpenDirectory due to unexpected error: %s"
+                        % (recordType, f), system="OpenDirectoryService"
+                    )
 
                 d = deferToThread(self.reloadCache, recordType)
                 d.addErrback(onError)
@@ -398,55 +400,87 @@
         except KeyError:
             # Cache miss; try looking the record up, in case it is new
             # FIXME: This is a blocking call (hopefully it's a fast one)
-            self.reloadCache(recordType, shortName)
+            self.reloadCache(recordType, shortName=shortName)
             return self.recordsForType(recordType).get(shortName, None)
 
     def recordWithGUID(self, guid):
-        # Override super's implementation with something faster.
-        for recordType in self.recordTypes():
-            record = self._storage(recordType)["guids"].get(guid, None)
-            if record:
-                return record
-        else:
-            return None
+        def lookup():
+            for recordType in self.recordTypes():
+                record = self._storage(recordType)["guids"].get(guid, None)
+                if record:
+                    return record
+            else:
+                return None
 
-    def reloadCache(self, recordType, shortName=None):
-        
+        record = lookup()
+
+        if record is None:
+            # Cache miss; try looking the record up, in case it is new
+            for recordType in self.recordTypes():
+                self.reloadCache(recordType, guid=guid)
+                record = lookup()
+                if record is not None:
+                    logging.info("Faulted record with GUID %s into %s record cache" % (guid, recordType), system="OpenDirectoryService")
+                    break
+            else:
+                logging.info("Unable to find any record with GUID %s" % (guid,), system="OpenDirectoryService")
+
+        return record
+
+    def reloadCache(self, recordType, shortName=None, guid=None):
         if shortName:
-            logging.info("Trying to add record %s to %s record cache" % (shortName, recordType,), system="OpenDirectoryService")
-        else:
+            logging.info("Faulting record %s into %s record cache" % (shortName, recordType), system="OpenDirectoryService")
+        elif guid is None:
             logging.info("Reloading %s record cache" % (recordType,), system="OpenDirectoryService")
 
-        results = self._queryDirectory(recordType, shortName)
+        results = self._queryDirectory(recordType, shortName=shortName, guid=guid)
         
-        records  = {}
-        guids    = {}
-        disabled_names = set()
-        disabled_guids = set()
+        if shortName is None and guid is None:
+            records = {}
+            guids   = {}
 
-        for (key, value) in results:
+            disabledNames = set()
+            disabledGUIDs = set()
+        else:
+            storage = self._records[recordType]
+
+            records = storage["records"]
+            guids   = storage["guids"]
+
+            disabledNames = storage["disabled names"]
+            disabledGUIDs = storage["disabled guids"]
+
+        for (recordShortName, value) in results:
             enabledForCalendaring = True
 
             if self.requireComputerRecord:
                 if not value.get(dsattributes.kDSNAttrServicesLocator):
                     if recordType == DirectoryService.recordType_groups:
                         enabledForCalendaring = False
-                        logging.debug("Group %s is not enabled for calendaring but may be used in ACLs" % (key,), system="OpenDirectoryService")
+                        logging.debug(
+                            "Group %s is not enabled for calendaring but may be used in ACLs"
+                            % (recordShortName,), system="OpenDirectoryService"
+                        )
                     else:
-                        logging.err("Directory (incorrectly) returned a record with no ServicesLocator attribute: %s" % (key,), system="OpenDirectoryService")
+                        logging.err(
+                            "Directory (incorrectly) returned a record with no ServicesLocator attribute: %s"
+                            % (recordShortName,), system="OpenDirectoryService"
+                        )
                         continue
 
             # Now get useful record info.
-            recordShortName = key
-            guid = value.get(dsattributes.kDS1AttrGeneratedUID)
-            if not guid:
+            recordGUID     = value.get(dsattributes.kDS1AttrGeneratedUID)
+            recordFullName = value.get(dsattributes.kDS1AttrDistinguishedName)
+            recordNodeName = value.get(dsattributes.kDSNAttrMetaNodeLocation)
+
+            if not recordGUID:
+                logging.debug("Record (%s)%s in node %s has no GUID; ignoring." % (recordType, recordShortName, recordNodeName),
+                              system="OpenDirectoryService")
                 continue
-            realName = value.get(dsattributes.kDS1AttrDistinguishedName)
-            nodename = value.get(dsattributes.kDSNAttrMetaNodeLocation)
 
             # Get calendar user addresses from directory record.
             if enabledForCalendaring:
-                calendarUserAddresses = self._getCalendarUserAddresses(recordType, key, value)
+                calendarUserAddresses = self._calendarUserAddresses(recordType, recordShortName, value)
             else:
                 calendarUserAddresses = ()
 
@@ -478,53 +512,56 @@
             record = OpenDirectoryRecord(
                 service               = self,
                 recordType            = recordType,
-                guid                  = guid,
-                nodename              = nodename,
+                guid                  = recordGUID,
+                nodeName              = recordNodeName,
                 shortName             = recordShortName,
-                fullName              = realName,
+                fullName              = recordFullName,
                 calendarUserAddresses = calendarUserAddresses,
                 autoSchedule          = autoSchedule,
                 enabledForCalendaring = enabledForCalendaring,
                 memberGUIDs           = memberGUIDs,
                 proxyGUIDs            = proxyGUIDs,
             )
-            
+
+            del recordShortName
+            del recordGUID
+
+            def disableRecord(record):
+                logging.warn("Record disabled due to conflict: %s" % (record,), system="OpenDirectoryService")
+
+                shortName = record.shortName
+                guid      = record.guid
+
+                disabledNames.add(shortName)
+                disabledGUIDs.add(guid)
+
+                if shortName in records:
+                    del records[shortName]
+                if guid in guids:
+                    del guids[guid]
+
             # Check for disabled items
-            if recordShortName in disabled_names or guid in disabled_guids:
-                disabled_names.add(recordShortName)
-                disabled_guids.add(guid)
-                logging.warn("Record disabled: %s, with GUID: %s" % (recordShortName, guid,), system="OpenDirectoryService")
+            if record.shortName in disabledNames or record.guid in disabledGUIDs:
+                disableRecord(record)
             else:
                 # Check for duplicate items and disable all names/guids for mismatched duplicates.
-                ok_to_add = True
-                if recordShortName in records:
-                    existing_record = records[recordShortName]
-                    if existing_record.guid != guid:
-                        disabled_names.add(recordShortName)
-                        disabled_guids.add(guid)
-                        disabled_guids.add(existing_record.guid)
-                        del records[existing_record.shortName]
-                        del guids[existing_record.guid]
-                        logging.warn("Record disabled: %s, with GUID: %s" % (existing_record.shortName, existing_record.guid,), system="OpenDirectoryService")
-                        logging.warn("Record disabled: %s, with GUID: %s" % (recordShortName, guid,), system="OpenDirectoryService")
-                        ok_to_add = False
-                elif guid in guids:
-                    existing_record = guids[guid]
-                    if existing_record.shortName != recordShortName:
-                        disabled_names.add(recordShortName)
-                        disabled_guids.add(guid)
-                        disabled_names.add(existing_record.shortName)
-                        del records[existing_record.shortName]
-                        del guids[existing_record.guid]
-                        logging.warn("Record disabled: %s, with GUID: %s" % (existing_record.shortName, existing_record.guid,), system="OpenDirectoryService")
-                        logging.warn("Record disabled: %s, with GUID: %s" % (recordShortName, guid,), system="OpenDirectoryService")
-                        ok_to_add = False
-                
-                if ok_to_add:
-                    records[recordShortName] = guids[guid] = record
-                    logging.debug("Populated record: %s, with GUID: %s" % (records[recordShortName], guid,), system="OpenDirectoryService")
+                if record.shortName in records:
+                    existing_record = records[record.shortName]
+                elif record.guid in guids:
+                    existing_record = guids[record.guid]
+                else:
+                    existing_record = None
 
-        if shortName is None:
+                if existing_record is not None:
+                    if record.guid != existing_record.guid or record.shortName != existing_record.shortName:
+                        disableRecord(existing_record)
+                        disableRecord(record)
+
+                if record.shortName not in disabledNames:
+                    records[record.shortName] = guids[record.guid] = record
+                    logging.debug("Added record %s to OD record cache" % (record,), system="OpenDirectoryService")
+
+        if shortName is None and guid is None:
             #
             # Replace the entire cache
             #
@@ -532,8 +569,8 @@
                 "status"        : "new",
                 "records"       : records,
                 "guids"         : guids,
-                "disabled_names": disabled_names,
-                "disabled_guids": disabled_guids,
+                "disabled names": disabledNames,
+                "disabled guids": disabledGUIDs,
             }
 
             def rot():
@@ -549,37 +586,9 @@
 
             self._records[recordType] = storage
 
-        elif records:
-            #
-            # Update one record, if found
-            #
-            assert len(records) == 1, "shortName = %r, records = %r" % (shortName, len(records))
-            
-            # Need to check that this record has not been disabled
-            storage = self._records[recordType]
-            if shortName in storage["disabled_names"] or record.guid in storage["disabled_guids"]:
-                storage["disabled_guids"].add(record.guid)
-                storage["disabled_names"].add(shortName)
-                logging.warn("Record disabled: %s, with GUID: %s" % (shortName, record.guid,), system="OpenDirectoryService")
-                records = {}
-            elif record.guid in storage["guids"]:
-                # Got a duplicate GUID - for now we disable the record  being looked up. On the next cache refresh
-                # the existing record will also get disabled.
-                storage["disabled_guids"].add(record.guid)
-                storage["disabled_names"].add(shortName)
-                logging.warn("Record disabled: %s, with GUID: %s" % (shortName, record.guid,), system="OpenDirectoryService")
-                records = {}
-            else:
-                storage["records"][shortName] = record
-                storage["guids"][record.guid] = record
+            logging.debug("Added %d records to %s OD record cache" % (len(self._records[recordType]["guids"]), recordType), system="OpenDirectoryService")
 
-        if shortName:
-            logging.info("Added %d records for %s in %s record cache" % (len(records), shortName, recordType,), system="OpenDirectoryService")
-        else:
-            logging.info("Found %d records for %s record cache" % (len(self._records[recordType]["guids"]), recordType,), system="OpenDirectoryService")
-
-    def _queryDirectory(self, recordType, shortName=None):
-
+    def _queryDirectory(self, recordType, shortName=None, guid=None):
         attrs = [
             dsattributes.kDS1AttrGeneratedUID,
             dsattributes.kDS1AttrDistinguishedName,
@@ -606,46 +615,40 @@
             attrs.append(dsattributes.kDSNAttrResourceInfo)
         
         else:
-            raise UnknownRecordTypeError("Unknown Open Directory record type: %s"
-                                         % (recordType,))
+            raise UnknownRecordTypeError("Unknown Open Directory record type: %s" % (recordType))
 
         if self.requireComputerRecord:
             if self.isWorkgroupServer and recordType == DirectoryService.recordType_users:
-                if shortName is None:
+                if shortName is None and guid is None:
                     results = opendirectory.queryRecordsWithAttribute_list(
                         self.directory,
                         dsattributes.kDSNAttrRecordName,
-                        _saclGroup,
+                        saclGroup,
                         dsattributes.eDSExact,
                         False,
                         dsattributes.kDSStdRecordTypeGroups,
-                        [dsattributes.kDSNAttrGroupMembers,
-                         dsattributes.kDSNAttrNestedGroups])
+                        [dsattributes.kDSNAttrGroupMembers, dsattributes.kDSNAttrNestedGroups]
+                    )
 
                     if len(results) == 1:
-                        members = results[0][1].get(
-                            dsattributes.kDSNAttrGroupMembers, [])
-    
-                        nestedGroups = results[0][1].get(
-                            dsattributes.kDSNAttrNestedGroups, [])
+                        members      = results[0][1].get(dsattributes.kDSNAttrGroupMembers, [])
+                        nestedGroups = results[0][1].get(dsattributes.kDSNAttrNestedGroups, [])
                     else:
                         members = []
                         nestedGroups = []
 
                     guidQueries = []
 
-                    for GUID in self._expandGroupMembership(members,
-                                                            nestedGroups):
+                    for GUID in self._expandGroupMembership(members, nestedGroups):
                         guidQueries.append(
-                            dsquery.match(dsattributes.kDS1AttrGeneratedUID,
-                                          GUID, dsattributes.eDSExact))
+                            dsquery.match(dsattributes.kDS1AttrGeneratedUID, GUID, dsattributes.eDSExact)
+                        )
 
                     if not guidQueries:
                         logging.warn("No SACL enabled users found.", system="OpenDirectoryService")
                         return ()
 
-                    query = dsquery.expression(dsquery.expression.OR,
-                                               guidQueries)
+                    query = dsquery.expression(dsquery.expression.OR, guidQueries)
 
             #
             # For groups, we'll load all entries, even if they don't
@@ -653,12 +656,15 @@
             #
             elif recordType != DirectoryService.recordType_groups:
                 tag_queries = []
+
                 for tag in self.servicetags:
                     tag_queries.append(dsquery.match(dsattributes.kDSNAttrServicesLocator, tag, dsattributes.eDSExact))
+
                 if len(tag_queries) == 1:
                     subquery = tag_queries[0]
                 else:
                     subquery = dsquery.expression(dsquery.expression.OR, tag_queries)
+
                 if query is None:
                     query = subquery
                 else:
@@ -666,12 +672,17 @@
 
         if shortName is not None:
             subquery = dsquery.match(dsattributes.kDSNAttrRecordName, shortName, dsattributes.eDSExact)
+        elif guid is not None:
+            subquery = dsquery.match(dsattributes.kDS1AttrGeneratedUID, guid, dsattributes.eDSExact)
+        else:
+            subquery = None
+
+        if subquery is not None:
             if query is None:
                 query = subquery
             else:
                 query = dsquery.expression(dsquery.expression.AND, (subquery, query))
 
-
         try:
             if query:
                 if isinstance(query, dsquery.match):
@@ -709,7 +720,7 @@
     Open Directory implementation of L{IDirectoryRecord}.
     """
     def __init__(
-        self, service, recordType, guid, nodename, shortName, fullName,
+        self, service, recordType, guid, nodeName, shortName, fullName,
         calendarUserAddresses, autoSchedule, enabledForCalendaring,
         memberGUIDs, proxyGUIDs,
     ):
@@ -723,10 +734,26 @@
             autoSchedule          = autoSchedule,
             enabledForCalendaring = enabledForCalendaring,
         )
-        self._nodename = nodename
+        self.nodeName = nodeName
         self._memberGUIDs = tuple(memberGUIDs)
         self._proxyGUIDs = tuple(proxyGUIDs)
 
+    def __repr__(self):
+        if self.service.realmName == self.nodeName:
+            location = self.nodeName
+        else:
+            location = "%s->%s" % (self.service.realmName, self.nodeName)
+
+        return "<%s[%s@%s(%s)] %s(%s) %r>" % (
+            self.__class__.__name__,
+            self.recordType,
+            self.service.guid,
+            location,
+            self.guid,
+            self.shortName,
+            self.fullName
+        )
+
     def members(self):
         if self.recordType != DirectoryService.recordType_groups:
             return
@@ -754,9 +781,9 @@
 
     def proxyFor(self):
         for proxyRecord in itertools.chain(
-                                  self.service.recordsForType(DirectoryService.recordType_resources).itervalues(),
-                                  self.service.recordsForType(DirectoryService.recordType_locations).itervalues()
-                              ):
+            self.service.recordsForType(DirectoryService.recordType_resources).itervalues(),
+            self.service.recordsForType(DirectoryService.recordType_locations).itervalues(),
+        ):
             if self.guid in proxyRecord._proxyGUIDs:
                 yield proxyRecord
 
@@ -771,7 +798,7 @@
 
             # Check with directory services
             try:
-                if opendirectory.authenticateUserBasic(self.service.directory, self._nodename, self.shortName, credentials.password):
+                if opendirectory.authenticateUserBasic(self.service.directory, self.nodeName, self.shortName, credentials.password):
                     # Cache the password to avoid future DS queries
                     self.password = credentials.password
                     return True
@@ -788,15 +815,21 @@
             #
             try:
                 challenge = 'Digest realm="%(realm)s", nonce="%(nonce)s", algorithm=%(algorithm)s' % credentials.fields
-                response = ('Digest username="%(username)s", '
-                            'realm="%(realm)s", '
-                            'nonce="%(nonce)s", '
-                            'uri="%(uri)s", '
-                            'response="%(response)s",'
-                            'algorithm=%(algorithm)s') % credentials.fields
+                response = (
+                    'Digest username="%(username)s", '
+                    'realm="%(realm)s", '
+                    'nonce="%(nonce)s", '
+                    'uri="%(uri)s", '
+                    'response="%(response)s",'
+                    'algorithm=%(algorithm)s'
+                ) % credentials.fields
             except KeyError, e:
-                logging.err("Error while performing digest authentication for record %s: missing digest response field: %s in: %s"
-                            % (self, e, credentials.fields), system="OpenDirectoryService")
+                logging.err(
+                    "Open Directory (node=%s) error while performing digest authentication for user %s: "
+                    "missing digest response field: %s in: %s"
+                    % (self.service.realmName, self.shortName, e, credentials.fields),
+                    system="OpenDirectoryService"
+                )
                 return False
 
             try:
@@ -808,7 +841,7 @@
             try:
                 if opendirectory.authenticateUserDigest(
                     self.service.directory,
-                    self._nodename,
+                    self.nodeName,
                     self.shortName,
                     challenge,
                     response,
@@ -823,8 +856,11 @@
 
                     return True
             except opendirectory.ODError, e:
-                logging.err("Open Directory error while performing digest authentication for record %s: %s"
-                            % (self, e), system="OpenDirectoryService")
+                logging.err(
+                    "Open Directory (node=%s) error while performing digest authentication for user %s: %s"
+                    % (self.service.realmName, self.shortName, e), system="OpenDirectoryService"
+                )
+                return False
 
             return False
 

Modified: CalendarServer/trunk/twistedcaldav/directory/idirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/idirectory.py	2008-02-13 23:32:53 UTC (rev 2141)
+++ CalendarServer/trunk/twistedcaldav/directory/idirectory.py	2008-02-13 23:41:16 UTC (rev 2142)
@@ -62,8 +62,14 @@
     def recordWithCalendarUserAddress(address):
         """
         @param address: the calendar user address of the record to look up.
-        @return: an L{IDirectoryRecord} provider with the given calendar user
-            address, or C{None} if no such record exists.
+        @return: an L{IDirectoryRecord} provider with the given
+            calendar user address, or C{None} if no such record is
+            found.  Note that some directory services may not be able
+            to locate records by calendar user address, or may return
+            partial results.  Note also that the calendar server may
+            add to the list of valid calendar user addresses for a
+            user, and the directory service may not be aware of these
+            addresses.
         """
 
 class IDirectoryRecord(Interface):

Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/principal.py	2008-02-13 23:32:53 UTC (rev 2141)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py	2008-02-13 23:41:16 UTC (rev 2142)
@@ -88,7 +88,7 @@
         return self.principalForShortName(DirectoryService.recordType_users, user)
 
     def principalForGUID(self, guid):
-        return self.principalForUID(guid)
+        return self.principalForRecord(self.directory.recordWithGUID(guid))
 
     def principalForUID(self, uid):
         raise NotImplementedError("Subclass must implement principalForUID()")
@@ -96,7 +96,7 @@
     def principalForRecord(self, record):
         if record is None:
             return None
-        return self.principalForGUID(record.guid)
+        return self.principalForUID(record.guid)
 
     def principalForCalendarUserAddress(self, address):
         raise NotImplementedError("Subclass must implement principalForCalendarUserAddress()")

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py	2008-02-13 23:32:53 UTC (rev 2141)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py	2008-02-13 23:41:16 UTC (rev 2142)
@@ -64,7 +64,7 @@
                 service               = self.service(),
                 recordType            = DirectoryService.recordType_users,
                 guid                  = "B1F93EB1-DA93-4772-9141-81C250DA35B3",
-                nodename              = "/LDAPv2/127.0.0.1",
+                nodeName              = "/LDAPv2/127.0.0.1",
                 shortName             = "user",
                 fullName              = "Some user",
                 calendarUserAddresses = set(("mailtoguid at example.com",)),

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py	2008-02-13 23:32:53 UTC (rev 2141)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py	2008-02-13 23:41:16 UTC (rev 2142)
@@ -17,30 +17,35 @@
 import twisted.trial.unittest
 
 try:
-    from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
+    from twistedcaldav.directory.appleopendirectory import OpenDirectoryService as RealOpenDirectoryService
     import dsattributes
 except ImportError:
     pass
 else:
     from twistedcaldav.directory.directory import DirectoryService
+    from twistedcaldav.directory.util import uuidFromName
 
-    def _queryDirectory(dir, recordType, shortName=None):
+    class OpenDirectoryService (RealOpenDirectoryService):
+        def _queryDirectory(directory, recordType, shortName=None, guid=None):
+            if shortName is None and guid is None:
+                return directory.fakerecords[recordType]
 
-        if shortName:
-            for name, record in dir.fakerecords[recordType]:
-                if name == shortName:
-                    return ((name, record),)
-            else:
-                return ()
-        else:
-            return dir.fakerecords[recordType]
+            assert shortName is None or guid is None
+            if guid is not None:
+                guid = guid.lower()
+
+            records = []
+
+            for name, record in directory.fakerecords[recordType]:
+                if name == shortName or record[dsattributes.kDS1AttrGeneratedUID] == guid:
+                    records.append((name, record))
+
+            return tuple(records)
     
     class ReloadCache(twisted.trial.unittest.TestCase):
-
         def setUp(self):
             super(ReloadCache, self).setUp()
             self._service = OpenDirectoryService(node="/Search", dosetup=False)
-            OpenDirectoryService._queryDirectory = _queryDirectory
             
         def tearDown(self):
             for call in self._service._delayedCalls:
@@ -56,82 +61,37 @@
             self.assertTrue(len(missing) == 0, msg="Directory records not found: %s" % (missing,))
             self.assertTrue(len(extras) == 0, msg="Directory records not expected: %s" % (extras,))
                 
-        def _verifyDisabledRecords(self, recordType, disabled_type, expected):
-            expected = set(expected)
-            found = self._service._records[recordType]["disabled_%s" % (disabled_type,)]
+        def _verifyDisabledRecords(self, recordType, expectedNames, expectedGUIDs):
+            def check(disabledType, expected):
+                expected = set(expected)
+                found = self._service._records[recordType][disabledType]
             
-            missing = expected.difference(found)
-            extras = found.difference(expected)
+                missing = expected.difference(found)
+                extras = found.difference(expected)
 
-            self.assertTrue(len(missing) == 0, msg="Disabled directory records not found: %s" % (missing,))
-            self.assertTrue(len(extras) == 0, msg="Disabled directory records not expected: %s" % (extras,))
+                self.assertTrue(len(missing) == 0, msg="Disabled directory records not found: %s" % (missing,))
+                self.assertTrue(len(extras) == 0, msg="Disabled directory records not expected: %s" % (extras,))
 
-        def test_Normal(self):
-            
+            check("disabled names", expectedNames)
+            check("disabled guids", (guid.lower() for guid in expectedGUIDs))
+
+        def test_normal(self):
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
-                    ["user01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user01",
-                        dsattributes.kDS1AttrDistinguishedName: "User 01",
-                        dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02"),
                 ],
                 DirectoryService.recordType_groups: [
-                    ["group01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_group01",
-                        dsattributes.kDS1AttrDistinguishedName: "Group 01",
-                        dsattributes.kDSNAttrEMailAddress: "group01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["group02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_group02",
-                        dsattributes.kDS1AttrDistinguishedName: "Group 02",
-                        dsattributes.kDSNAttrEMailAddress: "group02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("Group 01"),
+                    fakeODRecord("Group 02"),
                 ],
                 DirectoryService.recordType_resources: [
-                    ["resource01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_resource01",
-                        dsattributes.kDS1AttrDistinguishedName: "Resource 01",
-                        dsattributes.kDSNAttrEMailAddress: "resource01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["resource02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_resource02",
-                        dsattributes.kDS1AttrDistinguishedName: "Resource 02",
-                        dsattributes.kDSNAttrEMailAddress: "resource02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("Resource 01"),
+                    fakeODRecord("Resource 02"),
                 ],
                 DirectoryService.recordType_locations: [
-                    ["location01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_location01",
-                        dsattributes.kDS1AttrDistinguishedName: "Location 01",
-                        dsattributes.kDSNAttrEMailAddress: "location01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["location02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_location02",
-                        dsattributes.kDS1AttrDistinguishedName: "Location 02",
-                        dsattributes.kDSNAttrEMailAddress: "location02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("Location 01"),
+                    fakeODRecord("Location 02"),
                 ],
             }
 
@@ -140,221 +100,173 @@
             self._service.reloadCache(DirectoryService.recordType_resources)
             self._service.reloadCache(DirectoryService.recordType_locations)
 
-            self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "names", ())
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "guids", ())
+            self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02"))
+            self._verifyDisabledRecords(DirectoryService.recordType_users, (), ())
 
-            self._verifyRecords(DirectoryService.recordType_groups, ("group01", "group02",))
-            self._verifyDisabledRecords(DirectoryService.recordType_groups, "names", ())
-            self._verifyDisabledRecords(DirectoryService.recordType_groups, "guids", ())
+            self._verifyRecords(DirectoryService.recordType_groups, ("group01", "group02"))
+            self._verifyDisabledRecords(DirectoryService.recordType_groups, (), ())
 
-            self._verifyRecords(DirectoryService.recordType_resources, ("resource01", "resource02",))
-            self._verifyDisabledRecords(DirectoryService.recordType_resources, "names", ())
-            self._verifyDisabledRecords(DirectoryService.recordType_resources, "guids", ())
+            self._verifyRecords(DirectoryService.recordType_resources, ("resource01", "resource02"))
+            self._verifyDisabledRecords(DirectoryService.recordType_resources, (), ())
 
-            self._verifyRecords(DirectoryService.recordType_locations, ("location01", "location02",))
-            self._verifyDisabledRecords(DirectoryService.recordType_locations, "names", ())
-            self._verifyDisabledRecords(DirectoryService.recordType_locations, "guids", ())
+            self._verifyRecords(DirectoryService.recordType_locations, ("location01", "location02"))
+            self._verifyDisabledRecords(DirectoryService.recordType_locations, (), ())
 
-        def test_DuplicateRecords(self):
+        def test_normalCacheMiss(self):
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
-                    ["user01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user01",
-                        dsattributes.kDS1AttrDistinguishedName: "User 01",
-                        dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("User 01"),
                 ],
             }
 
             self._service.reloadCache(DirectoryService.recordType_users)
 
-            self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "names", ())
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "guids", ())
+            self._verifyRecords(DirectoryService.recordType_users, ("user01",))
+            self._verifyDisabledRecords(DirectoryService.recordType_users, (), ())
 
+            self._service.fakerecords = {
+                DirectoryService.recordType_users: [
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02"),
+                    fakeODRecord("User 03", guid="D10F3EE0-5014-41D3-8488-3819D3EF3B2A"),
+                ],
+            }
 
-        def test_DuplicateName(self):
-            
+            self._service.reloadCache(DirectoryService.recordType_users, shortName="user02")
+            self._service.reloadCache(DirectoryService.recordType_users, guid="D10F3EE0-5014-41D3-8488-3819D3EF3B2A")
+
+            self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02", "user03"))
+            self._verifyDisabledRecords(DirectoryService.recordType_users, (), ())
+
+        def test_duplicateRecords(self):
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
-                    ["user01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user01",
-                        dsattributes.kDS1AttrDistinguishedName: "User 01",
-                        dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02-1",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02-2",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02"),
+                    fakeODRecord("User 02"),
                 ],
             }
 
             self._service.reloadCache(DirectoryService.recordType_users)
 
+            self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02"))
+            self._verifyDisabledRecords(DirectoryService.recordType_users, (), ())
+            self._verifyDisabledRecords(DirectoryService.recordType_users, (), ())
+
+
+        def test_duplicateName(self):
+            self._service.fakerecords = {
+                DirectoryService.recordType_users: [
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02", guid="A25775BB-1281-4606-98C6-2893B2D5CCD7"),
+                    fakeODRecord("User 02", guid="30CA2BB9-C935-4A5D-80E2-79266BCB0255"),
+                ],
+            }
+
+            self._service.reloadCache(DirectoryService.recordType_users)
+
             self._verifyRecords(DirectoryService.recordType_users, ("user01",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "names", ("user02",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "guids", ("GUID_user02-1", "GUID_user02-2", ))
+            self._verifyDisabledRecords(
+                DirectoryService.recordType_users,
+                ("user02",),
+                ("A25775BB-1281-4606-98C6-2893B2D5CCD7", "30CA2BB9-C935-4A5D-80E2-79266BCB0255"),
+            )
 
-        def test_DuplicateGUID(self):
-            
+        def test_duplicateGUID(self):
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
-                    ["user01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user01",
-                        dsattributes.kDS1AttrDistinguishedName: "User 01",
-                        dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user03", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02", guid="113D7F74-F84A-4F17-8C96-CE8F10D68EF8"),
+                    fakeODRecord("User 03", guid="113D7F74-F84A-4F17-8C96-CE8F10D68EF8"),
                 ],
             }
 
             self._service.reloadCache(DirectoryService.recordType_users)
 
             self._verifyRecords(DirectoryService.recordType_users, ("user01",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "names", ("user02", "user03",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "guids", ("GUID_user02", ))
+            self._verifyDisabledRecords(
+                DirectoryService.recordType_users,
+                ("user02", "user03"),
+                ("113D7F74-F84A-4F17-8C96-CE8F10D68EF8",),
+            )
 
-        def test_DuplicateCombo(self):
-            
+        def test_duplicateCombo(self):
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
-                    ["user01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user01",
-                        dsattributes.kDS1AttrDistinguishedName: "User 01",
-                        dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user03", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02-2",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02", guid="113D7F74-F84A-4F17-8C96-CE8F10D68EF8"),
+                    fakeODRecord("User 02", guid="113D7F74-F84A-4F17-8C96-CE8F10D68EF8", shortName="user03"),
+                    fakeODRecord("User 02", guid="136E369F-DB40-4135-878D-B75D38242D39"),
                 ],
             }
 
             self._service.reloadCache(DirectoryService.recordType_users)
 
             self._verifyRecords(DirectoryService.recordType_users, ("user01",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "names", ("user02", "user03",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "guids", ("GUID_user02", "GUID_user02-2"))
+            self._verifyDisabledRecords(
+                DirectoryService.recordType_users,
+                ("user02", "user03"),
+                ("113D7F74-F84A-4F17-8C96-CE8F10D68EF8", "136E369F-DB40-4135-878D-B75D38242D39"),
+            )
 
-        def test_DuplicateGUIDCacheMiss(self):
-            
+        def test_duplicateGUIDCacheMiss(self):
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
-                    ["user01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user01",
-                        dsattributes.kDS1AttrDistinguishedName: "User 01",
-                        dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02", guid="EDB9EE55-31F2-4EA9-B5FB-D8AE2A8BA35E"),
+                    fakeODRecord("User 03", guid="D10F3EE0-5014-41D3-8488-3819D3EF3B2A"),
                 ],
             }
 
             self._service.reloadCache(DirectoryService.recordType_users)
 
-            self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "names", ())
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "guids", ())
+            self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02", "user03"))
+            self._verifyDisabledRecords(DirectoryService.recordType_users, (), ())
             
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
-                    ["user01", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user01",
-                        dsattributes.kDS1AttrDistinguishedName: "User 01",
-                        dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user02", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
-                    ["user03", {
-                        dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
-                        dsattributes.kDS1AttrDistinguishedName: "User 02",
-                        dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
-                        dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
-                        dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
-                    }],
+                    fakeODRecord("User 01"),
+                    fakeODRecord("User 02", guid="EDB9EE55-31F2-4EA9-B5FB-D8AE2A8BA35E"),
+                    fakeODRecord("User 02", guid="EDB9EE55-31F2-4EA9-B5FB-D8AE2A8BA35E", shortName="user04"),
+                    fakeODRecord("User 03", guid="62368DDF-0C62-4C97-9A58-DE9FD46131A0"),
+                    fakeODRecord("User 03", guid="62368DDF-0C62-4C97-9A58-DE9FD46131A0", shortName="user05"),
                 ],
             }
 
-            self._service.reloadCache(DirectoryService.recordType_users, "user03")
+            self._service.reloadCache(DirectoryService.recordType_users, shortName="user04")
+            self._service.reloadCache(DirectoryService.recordType_users, guid="62368DDF-0C62-4C97-9A58-DE9FD46131A0")
 
-            self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "names", ("user03",))
-            self._verifyDisabledRecords(DirectoryService.recordType_users, "guids", ("GUID_user02", ))
+            self._verifyRecords(DirectoryService.recordType_users, ("user01",))
+            self._verifyDisabledRecords(
+                DirectoryService.recordType_users,
+                ("user02", "user03", "user04", "user05"),
+                ("EDB9EE55-31F2-4EA9-B5FB-D8AE2A8BA35E", "62368DDF-0C62-4C97-9A58-DE9FD46131A0", "D10F3EE0-5014-41D3-8488-3819D3EF3B2A"),
+            )
 
+def fakeODRecord(fullName, shortName=None, guid=None, email=None):
+    if shortName is None:
+        shortName = shortNameForFullName(fullName)
+
+    if guid is None:
+        guid = guidForShortName(shortName)
+    else:
+        guid = guid.lower()
+
+    if email is None:
+        email = "%s at example.com" % (shortName,)
+
+    return [
+        shortName, {
+            dsattributes.kDS1AttrDistinguishedName: fullName,
+            dsattributes.kDS1AttrGeneratedUID: guid,
+            dsattributes.kDSNAttrEMailAddress: email,
+            dsattributes.kDSNAttrServicesLocator: "FE588D50-0514-4DF9-BCB5-8ECA5F3DA274:030572AE-ABEC-4E0F-83C9-FCA304769E5F:calendar",
+            dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
+        }
+    ]
+
+def shortNameForFullName(fullName):
+    return fullName.lower().replace(" ", "")
+
+def guidForShortName(shortName):
+    return uuidFromName(OpenDirectoryService.baseGUID, shortName)

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py	2008-02-13 23:32:53 UTC (rev 2141)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py	2008-02-13 23:41:16 UTC (rev 2142)
@@ -975,7 +975,7 @@
                 self.assertEqual(service.servicetags.pop(), "GUIDIFY:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar")
 
         def test_expandcuaddrs(self):
-            def _doTest(recordName, record, result, title):
+            def doTest(recordName, record, result, title):
                 service = OpenDirectoryService(node="/Search", dosetup=False)
                 if not service._parseServiceInfo("calendar.apple.com", recordName, {
                 'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_good,
@@ -983,7 +983,7 @@
                 dsattributes.kDSNAttrMetaNodeLocation:  "/LDAPv3/127.0.0.1"}):
                     self.fail(msg="Plist parse should not have failed: %s" % (recordName,))
                 else:
-                    expanded = service._getCalendarUserAddresses(DirectoryService.recordType_users, recordName, record)
+                    expanded = service._calendarUserAddresses(DirectoryService.recordType_users, recordName, record)
 
                     # Verify that we extracted the proper items
                     self.assertEqual(expanded, result, msg=title % (expanded, result,))
@@ -1023,7 +1023,7 @@
             )
 
             for recordName, record, result, title in data:
-                _doTest(recordName, record, result, title)
+                doTest(recordName, record, result, title)
 
     class ODRecordsParse (twisted.trial.unittest.TestCase):
 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080213/3d45ad7f/attachment-0001.html


More information about the calendarserver-changes mailing list