[CalendarServer-changes] [2940] CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937

source_changes at macosforge.org source_changes at macosforge.org
Fri Sep 5 10:38:55 PDT 2008


Revision: 2940
          http://trac.macosforge.org/projects/calendarserver/changeset/2940
Author:   cdaboo at apple.com
Date:     2008-09-05 10:38:54 -0700 (Fri, 05 Sep 2008)
Log Message:
-----------
Removed serviceslocator/computer record stuff. Now gets enabled calendar users from a group.
SACLs now also used all the time if configured and present.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/conf/caldavd-test.plist
    CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/conf/caldavd.plist
    CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/config.py
    CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/test/test_opendirectoryrecords.py
    CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/test/test_opendirectoryschema.py
    CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/test/test_config.py
    CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/test/test_tap.py

Modified: CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/conf/caldavd-test.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/conf/caldavd-test.plist	2008-09-04 18:22:25 UTC (rev 2939)
+++ CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/conf/caldavd-test.plist	2008-09-05 17:38:54 UTC (rev 2940)
@@ -116,8 +116,12 @@
     <dict>
       <key>node</key>
       <string>/Search</string>
-      <key>requireComputerRecord</key>
-      <true/>
+      <key>restrictEnabledRecords</key>
+      <false/>
+      <key>restrictToGroupGUID</key>
+      <string></string>
+      <key>restrictToGroupName</key>
+      <string></string>
     </dict>
   </dict>
   -->

Modified: CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/conf/caldavd.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/conf/caldavd.plist	2008-09-04 18:22:25 UTC (rev 2939)
+++ CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/conf/caldavd.plist	2008-09-05 17:38:54 UTC (rev 2940)
@@ -120,8 +120,12 @@
     <dict>
       <key>node</key>
       <string>/Search</string>
-      <key>requireComputerRecord</key>
-      <true/>
+      <key>restrictEnabledRecords</key>
+      <false/>
+      <key>restrictToGroupGUID</key>
+      <string></string>
+      <key>restrictToGroupName</key>
+      <string></string>
     </dict>
   </dict>
 

Modified: CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/config.py
===================================================================
--- CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/config.py	2008-09-04 18:22:25 UTC (rev 2939)
+++ CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/config.py	2008-09-05 17:38:54 UTC (rev 2940)
@@ -35,7 +35,9 @@
     },
     "twistedcaldav.directory.appleopendirectory.OpenDirectoryService": {
         "node": "/Search",
-        "requireComputerRecord": True,
+        "restrictEnabledRecords": False,
+        "restrictToGroupGUID": "",
+        "restrictToGroupName": "",
         "cacheTimeout": 30,
     },
 }

Modified: CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/appleopendirectory.py	2008-09-04 18:22:25 UTC (rev 2939)
+++ CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/appleopendirectory.py	2008-09-05 17:38:54 UTC (rev 2940)
@@ -25,7 +25,6 @@
 
 import itertools
 import sys
-import os
 from random import random
 
 import opendirectory
@@ -41,7 +40,7 @@
 from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
 from twistedcaldav.directory.directory import DirectoryError, UnknownRecordTypeError
 
-from plistlib import readPlistFromString, readPlist
+from plistlib import readPlistFromString
 
 serverPreferences = '/Library/Preferences/com.apple.servermgr_info.plist'
 saclGroup = 'com.apple.access_calendar'
@@ -55,14 +54,26 @@
     def __repr__(self):
         return "<%s %r: %r>" % (self.__class__.__name__, self.realmName, self.node)
 
-    def __init__(self, node="/Search", requireComputerRecord=True, dosetup=True, cacheTimeout=30):
+    def __init__(
+        self,
+        node="/Search",
+        restrictEnabledRecords=False,
+        restrictToGroupGUID="",
+        restrictToGroupName="",
+        dosetup=True,
+        cacheTimeout=30
+    ):
         """
         @param node: an OpenDirectory node name to bind to.
-        @param requireComputerRecord: C{True} if the directory schema is to be used to determine
+        @param restrictEnabledRecords: C{True} if a group in the directory is to be used to determine
             which calendar users are enabled.
+        @param restrictToGroupGUID: C{str} guid of group used to restrict enabled users.
+        @param restrictToGroupName: C{str} name of group used to restrict enabled users, not
+            used if restrictToGroupGUID is set.
         @param dosetup: if C{True} then the directory records are initialized,
                         if C{False} they are not.
                         This should only be set to C{False} when doing unit tests.
+        @param cacheTimeout: C{int} number of minutes before cache is invalidated.
         """
         try:
             directory = opendirectory.odInit(node)
@@ -73,34 +84,37 @@
         self.realmName = node
         self.directory = directory
         self.node = node
-        self.requireComputerRecord = requireComputerRecord
-        self.computerRecords = {}
-        self.servicetags = set()
+        self.restrictEnabledRecords = restrictEnabledRecords
+        self.restrictToGroupGUID = restrictToGroupGUID
+        self.restrictToGroupName = restrictToGroupName
+        self.restrictedGUIDs = None
         self.cacheTimeout = cacheTimeout
         self._records = {}
         self._delayedCalls = set()
 
-        self.isWorkgroupServer = False
+        self.doSACLs = config.EnableSACLs
+        self.SACLwasEnabled = False
 
         if dosetup:
-            if self.requireComputerRecord:
-                try:
-                    self._lookupVHostRecord()
-                except Exception, e:
-                    self.log_error("Unable to locate virtual host record: %s" % (e,))
-                    raise
+            for recordType in self.recordTypes():
+                self.recordsForType(recordType)
 
-                if os.path.exists(serverPreferences):
-                    serverInfo = readPlist(serverPreferences)
+    def __cmp__(self, other):
+        if not isinstance(other, DirectoryRecord):
+            return super(DirectoryRecord, self).__eq__(other)
 
-                    self.isWorkgroupServer = serverInfo.get('ServiceConfig', {}).get('IsWorkgroupServer', False)
+        for attr in ("directory", "node"):
+            diff = cmp(getattr(self, attr), getattr(other, attr))
+            if diff != 0:
+                return diff
+        return 0
 
-                    if self.isWorkgroupServer:
-                        self.log_info("Enabling Workgroup Server compatibility mode")
+    def __hash__(self):
+        h = hash(self.__class__)
+        for attr in ("directory", "node"):
+            h = (h + hash(getattr(self, attr))) & sys.maxint
+        return h
 
-            for recordType in self.recordTypes():
-                self.recordsForType(recordType)
-
     def _expandGroupMembership(self, members, nestedGroups, processedGUIDs=None):
 
         if processedGUIDs is None:
@@ -156,184 +170,6 @@
             ):
                 yield GUID
 
-    def __cmp__(self, other):
-        if not isinstance(other, DirectoryRecord):
-            return super(DirectoryRecord, self).__eq__(other)
-
-        for attr in ("directory", "node"):
-            diff = cmp(getattr(self, attr), getattr(other, attr))
-            if diff != 0:
-                return diff
-        return 0
-
-    def __hash__(self):
-        h = hash(self.__class__)
-        for attr in ("directory", "node"):
-            h = (h + hash(getattr(self, attr))) & sys.maxint
-        return h
-
-    def _lookupVHostRecord(self):
-        """
-        Get the OD service record for this host.
-        """
-
-        # The server must have been configured with a virtual hostname.
-        vhostname = config.ServerHostName
-        if not vhostname:
-            raise OpenDirectoryInitError(
-                "There is no virtual hostname configured for the server for use with Open Directory (node=%s)"
-                % (self.realmName,)
-            )
-         
-        # Find a record in /Computers with an apple-serviceinfo attribute value equal to the virtual hostname
-        # and return some useful attributes.
-        attrs = [
-            dsattributes.kDS1AttrGeneratedUID,
-            dsattributes.kDSNAttrRecordName,
-            dsattributes.kDSNAttrMetaNodeLocation,
-            "dsAttrTypeNative:apple-serviceinfo",
-        ]
-
-        self.log_debug("opendirectory.queryRecordsWithAttribute_list(%r,%r,%r,%r,%r)" % (
-            self.directory,
-            dsquery.match(
-                "dsAttrTypeNative:apple-serviceinfo",
-                vhostname,
-                dsattributes.eDSContains,
-            ).generate(),
-            True,    # case insentive for hostnames
-            dsattributes.kDSStdRecordTypeComputers,
-            attrs
-        ))
-        records = opendirectory.queryRecordsWithAttributes_list(
-            self.directory,
-            dsquery.match(
-                "dsAttrTypeNative:apple-serviceinfo",
-                vhostname,
-                dsattributes.eDSContains,
-            ).generate(),
-            True,    # case insentive for hostnames
-            dsattributes.kDSStdRecordTypeComputers,
-            attrs
-        )
-        self._parseComputersRecords(records, vhostname)
-
-    def _parseComputersRecords(self, records, vhostname):
-        # Must have some results
-        if len(records) == 0:
-            raise OpenDirectoryInitError(
-                "Open Directory (node=%s) has no /Computers records with a virtual hostname: %s"
-                % (self.realmName, vhostname)
-            )
-
-        # Now find all appropriate records and determine the enabled (only) service tags for each.
-        for recordname, record in records:
-            self._parseServiceInfo(vhostname, recordname, record)
-
-        # Log all the matching records
-        for key, value in self.computerRecords.iteritems():
-            _ignore_recordname, enabled, servicetag = value
-            self.log_info("Matched Directory record: %s with ServicesLocator: %s, state: %s" % (
-                key,
-                servicetag,
-                {True:"enabled", False:"disabled"}[enabled]
-            ))
-
-        # Log all the enabled service tags - or generate an error if there are none
-        if self.servicetags:
-            for tag in self.servicetags:
-                self.log_info("Enabled ServicesLocator: %s" % (tag,))
-        else:
-            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)
-            )
-
-    def _parseServiceInfo(self, vhostname, recordname, record):
-
-        # Extract some useful attributes
-        recordguid = record[dsattributes.kDS1AttrGeneratedUID]
-        recordlocation = "%s/Computers/%s" % (record[dsattributes.kDSNAttrMetaNodeLocation], recordname)
-
-        # First check for apple-serviceinfo attribute
-        plist = record.get("dsAttrTypeNative:apple-serviceinfo", None)
-        if not plist:
-            return False
-
-        # Parse the plist and look for our special entry
-        plist = readPlistFromString(plist)
-        vhosts = plist.get("com.apple.macosxserver.virtualhosts", None)
-        if not vhosts:
-            self.log_error(
-                "Open Directory (node=%s) %s record does not have a "
-                "com.apple.macosxserver.virtualhosts in its apple-serviceinfo attribute value"
-                % (self.realmName, recordlocation)
-            )
-            return False
-        
-        # Iterate over each vhost and find one that is a calendar service
-        hostguid = None
-        for key, value in vhosts.iteritems():
-            serviceTypes = value.get("serviceType", None)
-            if serviceTypes:
-                for type in serviceTypes:
-                    if type == "calendar":
-                        hostguid = key
-                        break
-                    
-        if not hostguid:
-            # We can get false positives from the query - we ignore those.
-            return False
-            
-        # Get host name
-        hostname = vhosts[hostguid].get("hostname", None)
-        if not hostname:
-            self.log_error(
-                "Open Directory (node=%s) %s record does not have "
-                "any host name in its apple-serviceinfo attribute value"
-                % (self.realmName, recordlocation)
-            )
-            return False
-        if hostname != vhostname:
-            # We can get false positives from the query - we ignore those.
-            return False
-        
-        # Get host details. At this point we only check that it is present. We actually
-        # ignore the details themselves (scheme/port) as we use our own config for that.
-        hostdetails = vhosts[hostguid].get("hostDetails", None)
-        if not hostdetails:
-            self.log_error(
-                "Open Directory (node=%s) %s record does not have "
-                "any host details in its apple-serviceinfo attribute value"
-                % (self.realmName, recordlocation)
-            )
-            return False
-        
-        # Look at the service data
-        serviceInfos = vhosts[hostguid].get("serviceInfo", None)
-        if not serviceInfos or not serviceInfos.has_key("calendar"):
-            self.log_error(
-                "Open Directory (node=%s) %s record does not have a "
-                "calendar service in its apple-serviceinfo attribute value"
-                % (self.realmName, recordlocation)
-            )
-            return False
-        serviceInfo = serviceInfos["calendar"]
-        
-        # Check that this service is enabled
-        enabled = serviceInfo.get("enabled", True)
-
-        # 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)
-        
-        if enabled:
-            self.servicetags.add(servicetag)
-        
-        return True
-    
     def _calendarUserAddresses(self, recordType, recordName, record):
         """
         Extract specific attributes from the directory record for use as calendar user address.
@@ -409,6 +245,10 @@
                         % (recordType, f)
                     )
 
+                # Reload the restricted access group details if reloading user records
+                if recordType == DirectoryService.recordType_users:
+                    self.restrictedGUIDs = None
+
                 d = deferToThread(self.reloadCache, recordType)
                 d.addErrback(onError)
 
@@ -418,7 +258,7 @@
         """
         @param recordType: a record type
         @return: a dictionary containing all records for the given record
-        type.  Keys are short names and values are the cooresponding
+        type.  Keys are short names and values are the corresponding
         OpenDirectoryRecord for the given record type.
         """
         return self._storage(recordType)["records"]
@@ -483,53 +323,9 @@
             disabledNames = storage["disabled names"]
             disabledGUIDs = storage["disabled guids"]
 
+        enabled_count = 0
         for (recordShortName, value) in results:
-            enabledForCalendaring = True
 
-            if self.requireComputerRecord:
-                servicesLocators = value.get(dsattributes.kDSNAttrServicesLocator)
-
-                def allowForACLs():
-                    return recordType in (
-                        DirectoryService.recordType_users,
-                        DirectoryService.recordType_groups,
-                    )
-
-                def disableForCalendaring():
-                    self.log_debug(
-                        "Record (%s) %s is not enabled for calendaring but may be used in ACLs"
-                        % (recordType, recordShortName)
-                    )
-
-                def invalidRecord():
-                    self.log_error(
-                        "Directory (incorrectly) returned a record with no applicable "
-                        "ServicesLocator attribute: (%s) %s"
-                        % (recordType, recordShortName)
-                    )
-
-                if servicesLocators:
-                    if type(servicesLocators) is str:
-                        servicesLocators = (servicesLocators,)
-
-                    for locator in servicesLocators:
-                        if locator in self.servicetags:
-                            break
-                    else:
-                        if allowForACLs():
-                            disableForCalendaring()
-                            enabledForCalendaring = False
-                        else:
-                            invalidRecord()
-                            continue
-                else:
-                    if allowForACLs():
-                        disableForCalendaring()
-                        enabledForCalendaring = False
-                    else:
-                        invalidRecord()
-                        continue
-
             # Now get useful record info.
             recordGUID     = value.get(dsattributes.kDS1AttrGeneratedUID)
             recordFullName = value.get(dsattributes.kDS1AttrDistinguishedName)
@@ -540,6 +336,40 @@
                                % (recordType, recordShortName, recordNodeName))
                 continue
 
+            # Determine enabled state
+            enabledForCalendaring = True
+
+            if self.doSACLs and self.SACLwasEnabled and recordType == DirectoryService.recordType_users:
+                # We have already filtered based on allowed GUIDs
+                enabledForCalendaring = True
+
+            elif not self.restrictEnabledRecords:
+                # Enable everything
+                enabledForCalendaring = True
+            
+            elif self.restrictedGUIDs is not None:
+                enabledForCalendaring = recordGUID in self.restrictedGUIDs
+
+            if not enabledForCalendaring:
+                # Some records we want to keep even though they are not enabled for calendaring.
+                # Others we discard.
+                if recordType in (
+                    DirectoryService.recordType_users,
+                    DirectoryService.recordType_groups,
+                ):
+                    self.log_debug(
+                        "Record (%s) %s is not enabled for calendaring but may be used in ACLs"
+                        % (recordType, recordShortName)
+                    )
+                else:
+                    self.log_debug(
+                        "Record (%s) %s is not enabled for calendaring"
+                        % (recordType, recordShortName)
+                    )
+                    continue
+            else:
+                enabled_count += 1
+
             # Get calendar user addresses from directory record.
             if enabledForCalendaring:
                 calendarUserAddresses = self._calendarUserAddresses(recordType, recordShortName, value)
@@ -619,6 +449,9 @@
                     if record.guid != existing_record.guid or record.shortName != existing_record.shortName:
                         disableRecord(existing_record)
                         disableRecord(record)
+                        
+                        if existing_record.enabledForCalendaring:
+                            enabled_count -= 1
 
                 if record.shortName not in disabledNames:
                     records[record.shortName] = guids[record.guid] = record
@@ -657,8 +490,8 @@
             self._records[recordType] = storage
 
             self.log_info(
-                "Added %d records to %s OD record cache; expires in %d seconds"
-                % (len(self._records[recordType]["guids"]), recordType, cacheTimeout)
+                "Added %d (%d enabled) records to %s OD record cache; expires in %d seconds"
+                % (len(self._records[recordType]["guids"]), enabled_count, recordType, cacheTimeout)
             )
 
     def _queryDirectory(self, recordType, shortName=None, guid=None):
@@ -666,7 +499,6 @@
             dsattributes.kDS1AttrGeneratedUID,
             dsattributes.kDS1AttrDistinguishedName,
             dsattributes.kDSNAttrEMailAddress,
-            dsattributes.kDSNAttrServicesLocator,
             dsattributes.kDSNAttrMetaNodeLocation,
         ]
 
@@ -690,71 +522,98 @@
         else:
             raise UnknownRecordTypeError("Unknown Open Directory record type: %s" % (recordType))
 
-        if self.requireComputerRecord:
-            if self.isWorkgroupServer and recordType == DirectoryService.recordType_users:
-                if shortName is None and guid is None:
-                    self.log_debug("opendirectory.queryRecordsWithAttribute_list(%r,%r,%r,%r,%r,%r,%r)" % (
-                        self.directory,
-                        dsattributes.kDSNAttrRecordName,
-                        saclGroup,
-                        dsattributes.eDSExact,
-                        False,
-                        dsattributes.kDSStdRecordTypeGroups,
-                        [dsattributes.kDSNAttrGroupMembers, dsattributes.kDSNAttrNestedGroups],
-                    ))
-                    results = opendirectory.queryRecordsWithAttribute_list(
-                        self.directory,
-                        dsattributes.kDSNAttrRecordName,
-                        saclGroup,
-                        dsattributes.eDSExact,
-                        False,
-                        dsattributes.kDSStdRecordTypeGroups,
-                        [dsattributes.kDSNAttrGroupMembers, dsattributes.kDSNAttrNestedGroups]
-                    )
+        # Query policy:
+        #
+        # For Users - always check for SACL and use that to determine enabled users
+        #             if no SACL then do same processing as for other types
+        #
+        # Other types - load all records. If restricted access is in place, load the
+        #               group membership for the restricted group and enable those users
+        #               in the group
 
-                    if len(results) == 1:
-                        members      = results[0][1].get(dsattributes.kDSNAttrGroupMembers, [])
-                        nestedGroups = results[0][1].get(dsattributes.kDSNAttrNestedGroups, [])
-                    else:
-                        members = []
-                        nestedGroups = []
+        processed = False
+        if self.doSACLs and recordType == DirectoryService.recordType_users:
+            if shortName is None and guid is None:
+                self.log_debug("Doing SACL membership check")
+                self.log_debug("opendirectory.queryRecordsWithAttribute_list(%r,%r,%r,%r,%r,%r,%r)" % (
+                    self.directory,
+                    dsattributes.kDSNAttrRecordName,
+                    saclGroup,
+                    dsattributes.eDSExact,
+                    False,
+                    dsattributes.kDSStdRecordTypeGroups,
+                    [dsattributes.kDSNAttrGroupMembers, dsattributes.kDSNAttrNestedGroups],
+                ))
+                results = opendirectory.queryRecordsWithAttribute_list(
+                    self.directory,
+                    dsattributes.kDSNAttrRecordName,
+                    saclGroup,
+                    dsattributes.eDSExact,
+                    False,
+                    dsattributes.kDSStdRecordTypeGroups,
+                    [dsattributes.kDSNAttrGroupMembers, dsattributes.kDSNAttrNestedGroups]
+                )
 
+                if len(results) == 1:
+                    self.SACLwasEnabled = True
+                    members      = results[0][1].get(dsattributes.kDSNAttrGroupMembers, [])
+                    nestedGroups = results[0][1].get(dsattributes.kDSNAttrNestedGroups, [])
+    
                     guidQueries = []
-
+    
                     for GUID in self._expandGroupMembership(members, nestedGroups):
                         guidQueries.append(
                             dsquery.match(dsattributes.kDS1AttrGeneratedUID, GUID, dsattributes.eDSExact)
                         )
-
+    
                     if not guidQueries:
                         self.log_warn("No SACL enabled users found.")
                         return ()
-
+    
                     query = dsquery.expression(dsquery.expression.OR, guidQueries)
+                    self.log_debug("Got %d SACL members" % (len(guidQueries),))
+                    processed = True
+                else:
+                    self.SACLwasEnabled = False
+                    self.log_debug("SACL not enabled for calendar service")
+        
+        if not processed and self.restrictEnabledRecords and self.restrictedGUIDs is None:
 
-            #
-            # For users and groups, we'll load all entries, even if
-            # they don't have a services locator for this server.
-            #
-            elif (
-                recordType != DirectoryService.recordType_users and
-                recordType != DirectoryService.recordType_groups
-            ):
-                tag_queries = []
+            attributeToMatch = dsattributes.kDS1AttrGeneratedUID if self.restrictToGroupGUID else dsattributes.kDSNAttrRecordName 
+            valueToMatch = self.restrictToGroupGUID if self.restrictToGroupGUID else self.restrictToGroupName
 
-                for tag in self.servicetags:
-                    tag_queries.append(dsquery.match(dsattributes.kDSNAttrServicesLocator, tag, dsattributes.eDSExact))
+            self.log_debug("Doing restricted group membership check")
+            self.log_debug("opendirectory.queryRecordsWithAttribute_list(%r,%r,%r,%r,%r,%r,%r)" % (
+                self.directory,
+                attributeToMatch,
+                valueToMatch,
+                dsattributes.eDSExact,
+                False,
+                dsattributes.kDSStdRecordTypeGroups,
+                [dsattributes.kDSNAttrGroupMembers, dsattributes.kDSNAttrNestedGroups,],
+            ))
+            results = opendirectory.queryRecordsWithAttribute_list(
+                self.directory,
+                attributeToMatch,
+                valueToMatch,
+                dsattributes.eDSExact,
+                False,
+                dsattributes.kDSStdRecordTypeGroups,
+                [dsattributes.kDSNAttrGroupMembers, dsattributes.kDSNAttrNestedGroups,],
+            )
+    
+            if len(results) == 1:
+                members      = results[0][1].get(dsattributes.kDSNAttrGroupMembers, [])
+                nestedGroups = results[0][1].get(dsattributes.kDSNAttrNestedGroups, [])
+            else:
+                members = []
+                nestedGroups = []
 
-                if len(tag_queries) == 1:
-                    subquery = tag_queries[0]
-                else:
-                    subquery = dsquery.expression(dsquery.expression.OR, tag_queries)
+            self.restrictedGUIDs = set()
+            for expanded_guid in self._expandGroupMembership(members, nestedGroups):
+                self.restrictedGUIDs.add(expanded_guid)
+            self.log_debug("Got %d restricted group members" % (len(self.restrictedGUIDs),))
 
-                if query is None:
-                    query = subquery
-                else:
-                    query = dsquery.expression(dsquery.expression.AND, (subquery, query))
-
         if shortName is not None:
             subquery = dsquery.match(dsattributes.kDSNAttrRecordName, shortName, dsattributes.eDSExact)
         elif guid is not None:

Modified: CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/test/test_opendirectoryrecords.py
===================================================================
--- CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/test/test_opendirectoryrecords.py	2008-09-04 18:22:25 UTC (rev 2939)
+++ CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/test/test_opendirectoryrecords.py	2008-09-05 17:38:54 UTC (rev 2940)
@@ -46,7 +46,6 @@
         def setUp(self):
             super(ReloadCache, self).setUp()
             self._service = OpenDirectoryService(node="/Search", dosetup=False)
-            self._service.servicetags.add("FE588D50-0514-4DF9-BCB5-8ECA5F3DA274:030572AE-ABEC-4E0F-83C9-FCA304769E5F:calendar")
             
         def tearDown(self):
             for call in self._service._delayedCalls:
@@ -125,33 +124,49 @@
             self._verifyDisabledRecords(DirectoryService.recordType_locations, (), ())
 
         def test_normal_disabledusers(self):
+            
+            self._service.restrictEnabledRecords = True
+            self._service.restrictToGroupName = "restrictedaccess"
+
             self._service.fakerecords = {
                 DirectoryService.recordType_users: [
                     fakeODRecord("User 01"),
                     fakeODRecord("User 02"),
-                    fakeODRecord("User 03", addLocator=False),
-                    fakeODRecord("User 04", addLocator=False),
+                    fakeODRecord("User 03"),
+                    fakeODRecord("User 04"),
                 ],
                 DirectoryService.recordType_groups: [
                     fakeODRecord("Group 01"),
                     fakeODRecord("Group 02"),
-                    fakeODRecord("Group 03", addLocator=False),
-                    fakeODRecord("Group 04", addLocator=False),
+                    fakeODRecord("Group 03"),
+                    fakeODRecord("Group 04"),
                 ],
                 DirectoryService.recordType_resources: [
                     fakeODRecord("Resource 01"),
                     fakeODRecord("Resource 02"),
-                    fakeODRecord("Resource 03", addLocator=False),
-                    fakeODRecord("Resource 04", addLocator=False),
+                    fakeODRecord("Resource 03"),
+                    fakeODRecord("Resource 04"),
                 ],
                 DirectoryService.recordType_locations: [
                     fakeODRecord("Location 01"),
                     fakeODRecord("Location 02"),
-                    fakeODRecord("Location 03", addLocator=False),
-                    fakeODRecord("Location 04", addLocator=False),
+                    fakeODRecord("Location 03"),
+                    fakeODRecord("Location 04"),
                 ],
             }
 
+            # Disable certain records
+            self._service.restrictedGUIDs = set((
+                self._service.fakerecords[DirectoryService.recordType_users][0][1][dsattributes.kDS1AttrGeneratedUID],
+                self._service.fakerecords[DirectoryService.recordType_users][1][1][dsattributes.kDS1AttrGeneratedUID],
+                self._service.fakerecords[DirectoryService.recordType_resources][0][1][dsattributes.kDS1AttrGeneratedUID],
+                self._service.fakerecords[DirectoryService.recordType_resources][1][1][dsattributes.kDS1AttrGeneratedUID],
+                self._service.fakerecords[DirectoryService.recordType_locations][0][1][dsattributes.kDS1AttrGeneratedUID],
+                self._service.fakerecords[DirectoryService.recordType_locations][1][1][dsattributes.kDS1AttrGeneratedUID],
+                self._service.fakerecords[DirectoryService.recordType_groups][0][1][dsattributes.kDS1AttrGeneratedUID],
+                self._service.fakerecords[DirectoryService.recordType_groups][1][1][dsattributes.kDS1AttrGeneratedUID],
+            ))
+
             self._service.reloadCache(DirectoryService.recordType_users)
             self._service.reloadCache(DirectoryService.recordType_groups)
             self._service.reloadCache(DirectoryService.recordType_resources)
@@ -300,7 +315,7 @@
                 ("EDB9EE55-31F2-4EA9-B5FB-D8AE2A8BA35E", "62368DDF-0C62-4C97-9A58-DE9FD46131A0", "D10F3EE0-5014-41D3-8488-3819D3EF3B2A"),
             )
 
-def fakeODRecord(fullName, shortName=None, guid=None, email=None, addLocator=True):
+def fakeODRecord(fullName, shortName=None, guid=None, email=None):
     if shortName is None:
         shortName = shortNameForFullName(fullName)
 
@@ -319,9 +334,6 @@
         dsattributes.kDSNAttrMetaNodeLocation: "/LDAPv3/127.0.0.1",
     }
 
-    if addLocator:
-        attrs[dsattributes.kDSNAttrServicesLocator] = "FE588D50-0514-4DF9-BCB5-8ECA5F3DA274:030572AE-ABEC-4E0F-83C9-FCA304769E5F:calendar"
-
     return [ shortName, attrs ]
 
 def shortNameForFullName(fullName):

Modified: CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/test/test_opendirectoryschema.py
===================================================================
--- CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/test/test_opendirectoryschema.py	2008-09-04 18:22:25 UTC (rev 2939)
+++ CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/directory/test/test_opendirectoryschema.py	2008-09-05 17:38:54 UTC (rev 2940)
@@ -16,1162 +16,11 @@
 
 try:
     from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
-    from twistedcaldav.directory.appleopendirectory import OpenDirectoryInitError
-    import dsattributes
 except ImportError:
     pass
 else:
-    from twistedcaldav.directory.directory import DirectoryService
     import twisted.trial.unittest
 
-    class PlistParse (twisted.trial.unittest.TestCase):
-        """
-        Test Open Directory service schema.
-        """
-
-        plist_nomacosxserver_key = """<?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>
-    </dict>
-</plist>
-"""
-
-        plist_nocalendarservice = """<?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>4F088107-51FD-4DE5-904D-2C0AD9C6C893</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>
-                        <integer>443</integer>
-                    </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>
-
-        </dict>
-    </dict>
-</plist>
-"""
-
-        plist_noserviceinfo = """<?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>4F088107-51FD-4DE5-904D-2C0AD9C6C893</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>
-                        <integer>443</integer>
-                    </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>C18C34AC-3D9E-403C-8A33-BFC303F3840E</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>webCalendar</key>
-                    <dict>
-                        <key>enabled</key>
-                        <true/>
-                        <key>urlMask</key>
-                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(name)s/webcalendar</string>
-                    </dict>
-                </dict>
-            </dict>
-
-        </dict>
-    </dict>
-</plist>
-"""
-
-        plist_disabledservice = """<?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>4F088107-51FD-4DE5-904D-2C0AD9C6C893</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>C18C34AC-3D9E-403C-8A33-BFC303F3840E</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>enabled</key>
-                        <false/>
-                        <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>
-"""
-
-        plist_nohostname = """<?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>4F088107-51FD-4DE5-904D-2C0AD9C6C893</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>C18C34AC-3D9E-403C-8A33-BFC303F3840E</key>
-            <dict>
-                <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>
-"""
-
-        plist_nohostdetails = """<?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>4F088107-51FD-4DE5-904D-2C0AD9C6C893</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>C18C34AC-3D9E-403C-8A33-BFC303F3840E</key>
-            <dict>
-                <key>hostname</key>
-                <string>calendar.apple.com</string>
-
-                <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>
-"""
-
-        plist_good = """<?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>4F088107-51FD-4DE5-904D-2C0AD9C6C893</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>C18C34AC-3D9E-403C-8A33-BFC303F3840E</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>
-"""
-
-        plist_good_other = """<?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>4F088107-51FD-4DE5-904D-2C0AD9C6C893</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>C18C34AC-3D9E-403C-8A33-BFC303F3840E</key>
-            <dict>
-                <key>hostname</key>
-                <string>privatecalendar.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>
-"""
-
-        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._parseServiceInfo("calendar.apple.com", "recordit", {
-                'dsAttrTypeNative:apple-serviceinfo'  : plist,
-                dsattributes.kDS1AttrGeneratedUID:      "GUIDIFY",
-                dsattributes.kDSNAttrMetaNodeLocation:  "/LDAPv3/127.0.0.1"}) and service.servicetags:
-                    self.fail(msg="Plist parse should have failed: %s" % (title,))
-
-            plists = (
-                (PlistParse.plist_nomacosxserver_key, "nomacosxserver_key"),
-                (PlistParse.plist_nocalendarservice,  "nocalendarservice"),
-                (PlistParse.plist_noserviceinfo,      "noserviceinfo"),
-                (PlistParse.plist_disabledservice,    "disabledservice"),
-                (PlistParse.plist_nohostname,         "nohostname"),
-                (PlistParse.plist_nohostdetails,      "nohostdetails"),
-            )
-            for plist, title in plists:
-                _doParse(plist, title)
-
-        def test_goodplist(self):
-            service = OpenDirectoryService(node="/Search", dosetup=False)
-            if not service._parseServiceInfo("calendar.apple.com", "recordit", {
-                'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_good,
-                dsattributes.kDS1AttrGeneratedUID:      "GUIDIFY",
-                dsattributes.kDSNAttrMetaNodeLocation:  "/LDAPv3/127.0.0.1"}):
-                self.fail(msg="Plist parse should not have failed")
-            else:
-                # Verify that we extracted the proper items
-                self.assertEqual(service.servicetags.pop(), "GUIDIFY:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar")
-
-        def test_expandcuaddrs(self):
-            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,
-                dsattributes.kDS1AttrGeneratedUID:      "GUIDIFY",
-                dsattributes.kDSNAttrMetaNodeLocation:  "/LDAPv3/127.0.0.1"}):
-                    self.fail(msg="Plist parse should not have failed: %s" % (recordName,))
-                else:
-                    expanded = service._calendarUserAddresses(DirectoryService.recordType_users, recordName, record)
-
-                    # Verify that we extracted the proper items
-                    self.assertEqual(expanded, result, msg=title % (expanded, result,))
-
-            data = (
-                (
-                 "user01",
-                 {
-                    dsattributes.kDS1AttrGeneratedUID: "GUID-USER-01",
-                    dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
-                 },
-                 set((
-                    "mailto:user01 at example.com",
-                 )),
-                 "User with one email address, %s != %s",
-                ),
-                (
-                 "user02",
-                 {
-                    dsattributes.kDS1AttrGeneratedUID: "GUID-USER-02",
-                    dsattributes.kDSNAttrEMailAddress: ["user02 at example.com", "user02 at calendar.example.com"],
-                 },
-                 set((
-                    "mailto:user02 at example.com",
-                    "mailto:user02 at calendar.example.com",
-                 )),
-                 "User with multiple email addresses, %s != %s",
-                ),
-                (
-                 "user03",
-                 {
-                    dsattributes.kDS1AttrGeneratedUID: "GUID-USER-03",
-                 },
-                 set(()),
-                 "User with no email addresses, %s != %s",
-                ),
-            )
-
-            for recordName, record, result, title in data:
-                doTest(recordName, record, result, title)
-
-    class ODRecordsParse (twisted.trial.unittest.TestCase):
-
-        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_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_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       : "computer3.apple.com",
-            'dsAttrTypeNative:apple-serviceinfo'  : PlistParse.plist_good,
-            dsattributes.kDSNAttrMetaNodeLocation : "/LDAPv3/directory.apple.com",
-        })
-        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       : "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):
-                service = OpenDirectoryService(node="/Search", dosetup=False)
-                try:
-                    service._parseComputersRecords(recordlist, "calendar.apple.com")
-                    self.fail(msg="Record parse should have failed: %s" % (title,))
-                except OpenDirectoryInitError:
-                    pass
-
-            records = (
-                ((), "no records found"),
-                ((
-                      (ODRecordsParse.record_localod_good_other[0], ODRecordsParse.record_localod_good_other[1]),
-                 ), "non-matching record found"),
-            )
-
-            for recordlist, title in records:
-                _doParseRecords(recordlist, title)
-
-        def test_odrecords_good(self):
-            def _doParseRecords(recordlist, title):
-                service = OpenDirectoryService(node="/Search", dosetup=False)
-                try:
-                    service._parseComputersRecords(recordlist, "calendar.apple.com")
-                except OpenDirectoryInitError, ex:
-                    self.fail(msg="Record parse should not have failed: \"%s\" with error: %s" % (title, ex))
-
-            records = (
-                ((
-                      (ODRecordsParse.record_localod_good[0],       ODRecordsParse.record_localod_good[1]),
-                 ), "single good plist"),
-                ((
-                      (ODRecordsParse.record_localod_good[0],       ODRecordsParse.record_localod_good[1]),
-                      (ODRecordsParse.record_localod_good_other[0], ODRecordsParse.record_localod_good_other[1]),
-                 ), "multiple plists"),
-            )
-
-            for recordlist, title in records:
-                _doParseRecords(recordlist, title)
-
-        def test_odrecords_multiple(self):
-            def _doParseRecords(recordlist, title, tags):
-                service = OpenDirectoryService(node="/Search", dosetup=False)
-                service._parseComputersRecords(recordlist, "calendar.apple.com")
-
-                self.assertEquals(service.servicetags, set(tags),
-                                  "Got wrong service tags: %s and %s" % (service.servicetags, set(tags),))
-
-            records = (
-                (((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])),
-                 "Three records",
-                 ("GUID2:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar",
-                  "GUID1:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar",
-                  "GUID3:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar")),
-                (((ODRecordsParse.record_localod_good[0],   ODRecordsParse.record_localod_good[1]),
-                  (ODRecordsParse.record_default_good[0],   ODRecordsParse.record_default_good[1])),
-                 "Two records",
-                 ("GUID1:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar",
-                  "GUID3:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar")),
-                (((ODRecordsParse.record_default_good[0],   ODRecordsParse.record_default_good[1]),),
-                 "One record",
-                 ("GUID3:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar",)),
-            )
-
-            for recordlist, title, tags in records:
-                _doParseRecords(recordlist, title, tags)
-
-        def test_odrecords_duplicates(self):
-            def _doParseRecords(recordlist, title, items, tags):
-                service = OpenDirectoryService(node="/Search", dosetup=False)
-                service._parseComputersRecords(recordlist, "calendar.apple.com")
-                self.assertEquals(service.servicetags, set(tags))
-
-            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",),
-                 ("GUID2:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar",
-                  "GUID2:1C8C34AC-3D9E-403C-8A33-FBC303F3840E:calendar",
-                  "GUID1:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar",
-                  "GUID3:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar")),
-                (((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",),
-                 ("GUID1:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar",
-                  "GUID1_bad:1C8C34AC-3D9E-403C-8A33-FBC303F3840E:calendar",
-                  "GUID3:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar")),
-                (((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",),
-                 ("GUID3:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar",
-                  "GUID3:1C8C34AC-3D9E-403C-8A33-FBC303F3840E:calendar")),
-            )
-
-            for recordlist, title, items, tags in records:
-                _doParseRecords(recordlist, title, items, tags)
-
     class ODResourceInfoParse (twisted.trial.unittest.TestCase):
 
         plist_good_false = """<?xml version="1.0" encoding="UTF-8"?>

Modified: CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/test/test_config.py
===================================================================
--- CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/test/test_config.py	2008-09-04 18:22:25 UTC (rev 2939)
+++ CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/test/test_config.py	2008-09-05 17:38:54 UTC (rev 2940)
@@ -158,24 +158,30 @@
         self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.appleopendirectory.OpenDirectoryService")
         self.assertNotIn("xmlFile", config.DirectoryService["params"])
         self.assertEquals(config.DirectoryService["params"]["node"], "/Search")
-        self.assertEquals(config.DirectoryService["params"]["requireComputerRecord"], True)
+        self.assertEquals(config.DirectoryService["params"]["restrictEnabledRecords"], False)
 
     def testDirectoryService_newParam(self):
         self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService")
         self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml")
 
         config.update({"DirectoryService": {"type": "twistedcaldav.directory.appleopendirectory.OpenDirectoryService"}})
-        config.update({"DirectoryService": {"params": {"requireComputerRecord": False}}})
+        config.update({"DirectoryService": {"params": {
+            "restrictEnabledRecords": True,
+            "restrictToGroupGUID": "12345",
+            "restrictToGroupName": "Group",
+        }}})
 
         self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.appleopendirectory.OpenDirectoryService")
         self.assertEquals(config.DirectoryService["params"]["node"], "/Search")
-        self.assertEquals(config.DirectoryService["params"]["requireComputerRecord"], False)
+        self.assertEquals(config.DirectoryService["params"]["restrictEnabledRecords"], True)
+        self.assertEquals(config.DirectoryService["params"]["restrictToGroupGUID"], "12345")
+        self.assertEquals(config.DirectoryService["params"]["restrictToGroupName"], "Group")
 
     def testDirectoryService_badParam(self):
         self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService")
         self.assertEquals(config.DirectoryService["params"]["xmlFile"], "/etc/caldavd/accounts.xml")
 
-        self.assertRaises(ConfigurationError, config.update, {"DirectoryService": {"params": {"requireComputerRecord": False}}})
+        self.assertRaises(ConfigurationError, config.update, {"DirectoryService": {"params": {"restrictEnabledRecords": False}}})
 
     def testDirectoryService_unknownType(self):
         self.assertEquals(config.DirectoryService["type"], "twistedcaldav.directory.xmlfile.XMLDirectoryService")

Modified: CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/test/test_tap.py
===================================================================
--- CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/test/test_tap.py	2008-09-04 18:22:25 UTC (rev 2939)
+++ CalendarServer/branches/users/cdaboo/byebye-serviceslocator-2937/twistedcaldav/test/test_tap.py	2008-09-05 17:38:54 UTC (rev 2940)
@@ -158,7 +158,7 @@
         a '/' seperated path.  Such as '-o MultiProcess/ProcessCount=1'
         """
 
-        argv = ['-o', 'MultiProcess/ProcessCount=102']
+        argv = ['-o', 'MultiProcess/ProcessCount=102', '-f', 'conf/caldavd.plist',]
         self.config.parseOptions(argv)
 
         self.assertEquals(config.MultiProcess['ProcessCount'], 102)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080905/35224a72/attachment-0001.html 


More information about the calendarserver-changes mailing list