[CalendarServer-changes] [1926] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri Sep 28 13:03:41 PDT 2007
Revision: 1926
http://trac.macosforge.org/projects/calendarserver/changeset/1926
Author: cdaboo at apple.com
Date: 2007-09-28 13:03:41 -0700 (Fri, 28 Sep 2007)
Log Message:
-----------
Merged branches/users/cdaboo/multiple-computer-records-1911 to trunk. Plus updated run for new PyOpenDirectory revision.
Modified Paths:
--------------
CalendarServer/trunk/run
CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py
Added Paths:
-----------
CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py
Modified: CalendarServer/trunk/run
===================================================================
--- CalendarServer/trunk/run 2007-09-28 20:01:21 UTC (rev 1925)
+++ CalendarServer/trunk/run 2007-09-28 20:03:41 UTC (rev 1926)
@@ -480,7 +480,7 @@
if ! py_have_module opendirectory; then
opendirectory="${top}/PyOpenDirectory";
- svn_get "PyOpenDirectory" "${opendirectory}" "${svn_uri_base}/PyOpenDirectory/trunk" 1631;
+ svn_get "PyOpenDirectory" "${opendirectory}" "${svn_uri_base}/PyOpenDirectory/trunk" 1925;
py_build "PyOpenDirectory" "${opendirectory}" false;
py_install "PyOpenDirectory" "${opendirectory}";
Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py 2007-09-28 20:01:21 UTC (rev 1925)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py 2007-09-28 20:03:41 UTC (rev 1926)
@@ -33,12 +33,12 @@
import dsattributes
import dsquery
-from twisted.python import log
from twisted.internet.reactor import callLater
from twisted.internet.threads import deferToThread
from twisted.cred.credentials import UsernamePassword
from twisted.web2.auth.digest import DigestedCredentials
+from twistedcaldav import logging
from twistedcaldav.config import config
from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
from twistedcaldav.directory.directory import DirectoryError, UnknownRecordTypeError
@@ -71,14 +71,15 @@
try:
directory = opendirectory.odInit(node)
except opendirectory.ODError, e:
- log.msg("Open Directory (node=%s) Initialization error: %s" % (node, e))
+ logging.err("Open Directory (node=%s) Initialization error: %s" % (node, e), system="OpenDirectoryService")
raise
self.realmName = node
self.directory = directory
self.node = node
self.requireComputerRecord = requireComputerRecord
- self.computerRecordName = ""
+ self.computerRecords = {}
+ self.servicetags = set()
self._records = {}
self._delayedCalls = set()
@@ -89,7 +90,7 @@
try:
self._lookupVHostRecord()
except Exception, e:
- log.err("Unable to locate virtual host record: %s" % (e,))
+ logging.err("Unable to locate virtual host record: %s" % (e,), system="OpenDirectoryService")
raise
if os.path.exists(_serverPreferences):
@@ -100,7 +101,7 @@
'IsWorkgroupServer', False)
if self.isWorkgroupServer:
- log.msg("Enabling Workgroup Server compatibility mode")
+ logging.info("Enabling Workgroup Server compatibility mode", system="OpenDirectoryService")
for recordType in self.recordTypes():
self.recordsForType(recordType)
@@ -125,7 +126,7 @@
if groupGUID in processedGUIDs:
continue
- result = opendirectory.queryRecordsWithAttribute(
+ result = opendirectory.queryRecordsWithAttribute_list(
self.directory,
dsattributes.kDS1AttrGeneratedUID,
groupGUID,
@@ -136,10 +137,10 @@
dsattributes.kDSNAttrNestedGroups])
if not result:
- log.err("Couldn't find group %s when trying to expand nested groups." % (groupGUID,))
+ logging.err("Couldn't find group %s when trying to expand nested groups." % (groupGUID,), system="OpenDirectoryService")
continue
- group = result.values()[0]
+ group = result[0][1]
processedGUIDs.add(groupGUID)
@@ -178,7 +179,7 @@
% (self.realmName,)
)
- # Find a record in /Computers with an ENetAddress attribute value equal to the MAC address
+ # Find a record in /Computers with an apple-serviceinfo attribute value equal to the virtual hostname
# and return some useful attributes.
attrs = [
dsattributes.kDS1AttrGeneratedUID,
@@ -187,7 +188,7 @@
'dsAttrTypeNative:apple-serviceinfo',
]
- records = opendirectory.queryRecordsWithAttributes(
+ records = opendirectory.queryRecordsWithAttributes_list(
self.directory,
dsquery.match(
'dsAttrTypeNative:apple-serviceinfo',
@@ -201,9 +202,6 @@
self._parseComputersRecords(records, vhostname)
def _parseComputersRecords(self, records, vhostname):
- localNodePath = '/Local/Default'
- localODNodePath = '/LDAPv3/127.0.0.1'
-
# Must have some results
if len(records) == 0:
raise OpenDirectoryInitError(
@@ -211,73 +209,23 @@
% (self.realmName, vhostname,)
)
- # Now find a single record that actually matches the hostname
- # Prefering the remote OD node to the local OD Node and
- # the local OD Node to the local node.
+ # Now find all appropriate records and determine the enabled (only) service tags for each.
+ for recordname, record in records:
+ self._parseServiceInfo(vhostname, recordname, record)
- _localNodes = []
- _localODNodes = []
- _remoteNodes = []
+ # Log all the matching records
+ for key, value in self.computerRecords.iteritems():
+ _ignore_recordname, enabled, servicetag = value
+ logging.info("Matched Directory record: %s with ServicesLocator: %s, state: %s" % (
+ key,
+ servicetag,
+ {True:"enabled", False:"disabled"}[enabled]
+ ), system="OpenDirectoryService")
- for recordname, record in records.iteritems():
- # May have an apple-serviceinfo
- plist = record.get('dsAttrTypeNative:apple-serviceinfo', None)
- if not plist:
- continue
-
- # XXX: Parse the plist so we can find only calendar vhosts with our hostname.
- plistDict = readPlistFromString(plist)
- vhosts = plistDict.get("com.apple.macosxserver.virtualhosts", None)
- if not vhosts:
- continue
-
- 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 vhosts[hostguid].get("hostname", None) != vhostname:
- continue
-
- if record[dsattributes.kDSNAttrMetaNodeLocation] == localNodePath:
- _localNodes.append((recordname, plist, record[dsattributes.kDS1AttrGeneratedUID]))
-
- elif record[dsattributes.kDSNAttrMetaNodeLocation] == localODNodePath:
- _localODNodes.append((recordname, plist, record[dsattributes.kDS1AttrGeneratedUID]))
-
- else:
- _remoteNodes.append((recordname, plist, record[dsattributes.kDS1AttrGeneratedUID]))
-
- # Verify that we only have a single record type to match
- if len(_remoteNodes) > 1:
- raise OpenDirectoryInitError(
- "Open Directory (node=%s) too many remote /Computers records (%s) were found matching virtual hostname: %s"
- % (self.realmName, ", ".join([r[0] for r in _remoteNodes]), vhostname,)
- )
-
- if len(_remoteNodes) == 0 and len(_localODNodes) > 1:
- raise OpenDirectoryInitError(
- "Open Directory (node=%s) too many local OD /Computers records (%s) were found matching virtual hostname: %s"
- % (self.realmName, ", ".join([r[0] for r in _localODNodes]), vhostname,)
- )
-
- if len(_remoteNodes) == 0 and len(_localODNodes) == 0 and len(_localNodes) > 1:
- raise OpenDirectoryInitError(
- "Open Directory (node=%s) too many local /Computers records (%s) were found matching virtual hostname: %s"
- % (self.realmName, ", ".join([r[0] for r in _localNodes]), vhostname,)
- )
-
- # XXX: These calls to self._parseServiceInfo will cause the plist to be parsed _again_
- # refactor later so we only ever parse it once.
-
- for node in itertools.chain(_remoteNodes, _localODNodes, _localNodes):
- if node and self._parseServiceInfo(vhostname, *node):
- break
-
+ # Log all the enabled service tags - or generate an error if there are none
+ if self.servicetags:
+ for tag in self.servicetags:
+ logging.info("Enabled ServicesLocator: %s" % (tag,), system="OpenDirectoryService")
else:
raise OpenDirectoryInitError(
"Open Directory (node=%s) no /Computers records with an enabled and valid "
@@ -285,15 +233,25 @@
% (self.realmName, vhostname,)
)
- def _parseServiceInfo(self, vhostname, recordname, plist, recordguid):
+ 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:
- log.msg(
- "Open Directory (node=%s) /Computers/%s record does not have a "
- "com.apple.macosxserver.virtualhosts in its ServiceInfo attribute value"
- % (self.realmName, recordname)
+ 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"
)
return False
@@ -308,70 +266,55 @@
break
if not hostguid:
- log.msg(
- "Open Directory (node=%s) /Computers/%s record does not have a "
- "calendar service in its ServiceInfo attribute value"
- % (self.realmName, recordname)
- )
+ # 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:
- log.msg(
- "Open Directory (node=%s) /Computers/%s record does not have "
- "any host name in its ServiceInfo attribute value"
- % (self.realmName, recordname)
+ logging.err(
+ "Open Directory (node=%s) %s record does not have "
+ "any host name in its apple-serviceinfo attribute value"
+ % (self.realmName, recordlocation, ), system="OpenDirectoryService"
)
return False
if hostname != vhostname:
- log.msg(
- "Open Directory (node=%s) /Computers/%s record hostname (%s) "
- "does not match this server (%s)"
- % (self.realmName, recordname, hostname, vhostname)
- )
+ # We can get false positives from the query - we ignore those.
return False
- # Get host details and create host templates
+ # 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:
- log.msg(
- "Open Directory (node=%s) /Computers/%s record does not have "
- "any host details in its ServiceInfo attribute value"
- % (self.realmName, recordname)
+ logging.err(
+ "Open Directory (node=%s) %s record does not have "
+ "any host details in its apple-serviceinfo attribute value"
+ % (self.realmName, recordlocation, ), system="OpenDirectoryService"
)
return False
- hostvariants = []
- for key, value in hostdetails.iteritems():
- if key in ("http", "https"):
- hostvariants.append((key, hostname, value["port"]))
# Look at the service data
serviceInfos = vhosts[hostguid].get("serviceInfo", None)
if not serviceInfos or not serviceInfos.has_key("calendar"):
- log.msg(
- "Open Directory (node=%s) /Computers/%s record does not have a "
- "calendar service in its ServiceInfo attribute value"
- % (self.realmName, recordname)
+ logging.err(
+ "Open Directory (node=%s) %s record does not have a "
+ "calendar service in its apple-serviceinfo attribute value"
+ % (self.realmName, recordlocation), system="OpenDirectoryService"
)
return False
serviceInfo = serviceInfos["calendar"]
# Check that this service is enabled
enabled = serviceInfo.get("enabled", True)
- if not enabled:
- log.msg(
- "Open Directory (node=%s) /Computers/%s record does not have an "
- "enabled calendar service in its ServiceInfo attribute value"
- % (self.realmName, recordname)
- )
- return False
# Create the string we will use to match users with accounts on this server
- self.servicetag = "%s:%s:calendar" % (recordguid, hostguid)
+ servicetag = "%s:%s:calendar" % (recordguid, hostguid)
- self.computerRecordName = recordname
+ self.computerRecords[recordlocation] = (recordname, enabled, servicetag,)
+ if enabled:
+ self.servicetags.add(servicetag)
+
return True
def _getCalendarUserAddresses(self, recordType, recordName, record):
@@ -431,8 +374,8 @@
def onError(f):
storage["status"] = "stale" # Keep trying
- log.err("Unable to load records of type %s from OpenDirectory due to unexpected error: %s"
- % (recordType, f))
+ 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)
@@ -470,8 +413,173 @@
return None
def reloadCache(self, recordType, shortName=None):
- log.msg("Reloading %s record cache" % (recordType,))
+
+ if shortName:
+ logging.info("Trying to add record %s to %s record cache" % (shortName, recordType,), system="OpenDirectoryService")
+ else:
+ logging.info("Reloading %s record cache" % (recordType,), system="OpenDirectoryService")
+ results = self._queryDirectory(recordType, shortName)
+
+ records = {}
+ guids = {}
+ disabled_names = set()
+ disabled_guids = set()
+
+ for (key, 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")
+ else:
+ logging.err("Directory (incorrectly) returned a record with no ServicesLocator attribute: %s" % (key,), system="OpenDirectoryService")
+ continue
+
+ # Now get useful record info.
+ recordShortName = key
+ guid = value.get(dsattributes.kDS1AttrGeneratedUID)
+ if not guid:
+ continue
+ realName = value.get(dsattributes.kDS1AttrDistinguishedName)
+
+ # Get calendar user addresses from directory record.
+ if enabledForCalendaring:
+ calendarUserAddresses = self._getCalendarUserAddresses(recordType, key, value)
+ else:
+ calendarUserAddresses = ()
+
+ # Special case for groups.
+ if recordType == DirectoryService.recordType_groups:
+ memberGUIDs = value.get(dsattributes.kDSNAttrGroupMembers)
+ if memberGUIDs is None:
+ memberGUIDs = ()
+ elif type(memberGUIDs) is str:
+ memberGUIDs = (memberGUIDs,)
+ nestedGUIDs = value.get(dsattributes.kDSNAttrNestedGroups)
+ if nestedGUIDs:
+ if type(nestedGUIDs) is str:
+ nestedGUIDs = (nestedGUIDs,)
+ memberGUIDs += tuple(nestedGUIDs)
+ else:
+ memberGUIDs = ()
+
+ # Special case for resources and locations
+ autoSchedule = False
+ proxyGUIDs = ()
+ if recordType in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
+ resourceInfo = value.get(dsattributes.kDSNAttrResourceInfo)
+ if resourceInfo is not None:
+ autoSchedule, proxy = self._parseResourceInfo(resourceInfo)
+ if proxy:
+ proxyGUIDs = (proxy,)
+
+ record = OpenDirectoryRecord(
+ service = self,
+ recordType = recordType,
+ guid = guid,
+ shortName = recordShortName,
+ fullName = realName,
+ calendarUserAddresses = calendarUserAddresses,
+ autoSchedule = autoSchedule,
+ enabledForCalendaring = enabledForCalendaring,
+ memberGUIDs = memberGUIDs,
+ proxyGUIDs = proxyGUIDs,
+ )
+
+ # 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")
+ 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 shortName is None:
+ #
+ # Replace the entire cache
+ #
+ storage = {
+ "status" : "new",
+ "records" : records,
+ "guids" : guids,
+ "disabled_names": disabled_names,
+ "disabled_guids": disabled_guids,
+ }
+
+ def rot():
+ storage["status"] = "stale"
+ removals = set()
+ for call in self._delayedCalls:
+ if not call.active():
+ removals.add(call)
+ for item in removals:
+ self._delayedCalls.remove(item)
+
+ self._delayedCalls.add(callLater(recordListCacheTimeout, rot))
+
+ 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
+
+ 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):
+
attrs = [
dsattributes.kDS1AttrGeneratedUID,
dsattributes.kDS1AttrDistinguishedName,
@@ -503,7 +611,7 @@
if self.requireComputerRecord:
if self.isWorkgroupServer and recordType == DirectoryService.recordType_users:
if shortName is None:
- results = opendirectory.queryRecordsWithAttribute(
+ results = opendirectory.queryRecordsWithAttribute_list(
self.directory,
dsattributes.kDSNAttrRecordName,
_saclGroup,
@@ -513,12 +621,16 @@
[dsattributes.kDSNAttrGroupMembers,
dsattributes.kDSNAttrNestedGroups])
- members = results.get(_saclGroup, {}).get(
- dsattributes.kDSNAttrGroupMembers, [])
+ if len(results) == 1:
+ members = results[0][1].get(
+ dsattributes.kDSNAttrGroupMembers, [])
+
+ nestedGroups = results[0][1].get(
+ dsattributes.kDSNAttrNestedGroups, [])
+ else:
+ members = []
+ nestedGroups = []
- nestedGroups = results.get(_saclGroup, {}).get(
- dsattributes.kDSNAttrNestedGroups, [])
-
guidQueries = []
for GUID in self._expandGroupMembership(members,
@@ -536,7 +648,13 @@
# have a services locator for this server.
#
elif recordType != DirectoryService.recordType_groups:
- subquery = dsquery.match(dsattributes.kDSNAttrServicesLocator, self.servicetag, dsattributes.eDSExact)
+ 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:
@@ -553,7 +671,7 @@
try:
if query:
if isinstance(query, dsquery.match):
- results = opendirectory.queryRecordsWithAttribute(
+ results = opendirectory.queryRecordsWithAttribute_list(
self.directory,
query.attribute,
query.value,
@@ -563,7 +681,7 @@
attrs,
)
else:
- results = opendirectory.queryRecordsWithAttributes(
+ results = opendirectory.queryRecordsWithAttributes_list(
self.directory,
query.generate(),
False,
@@ -571,117 +689,17 @@
attrs,
)
else:
- results = opendirectory.listAllRecordsWithAttributes(
+ results = opendirectory.listAllRecordsWithAttributes_list(
self.directory,
listRecordType,
attrs,
)
except opendirectory.ODError, ex:
- log.msg("Open Directory (node=%s) error: %s" % (self.realmName, str(ex)))
+ logging.err("Open Directory (node=%s) error: %s" % (self.realmName, str(ex)), system="OpenDirectoryService")
raise
- records = {}
- guids = {}
+ return results
- for (key, value) in results.iteritems():
- enabledForCalendaring = True
-
- if self.requireComputerRecord:
- if not value.get(dsattributes.kDSNAttrServicesLocator):
- if recordType == DirectoryService.recordType_groups:
- enabledForCalendaring = False
- #log.msg("Group %s is not enabled for calendaring but may be used in ACLs" % (key,))
- else:
- log.err("Directory (incorrectly) returned a record with no ServicesLocator attribute: %s" % (key,))
- continue
-
- # Now get useful record info.
- recordShortName = key
- guid = value.get(dsattributes.kDS1AttrGeneratedUID)
- if not guid:
- continue
- realName = value.get(dsattributes.kDS1AttrDistinguishedName)
-
- # Get calendar user addresses from directory record.
- if enabledForCalendaring:
- calendarUserAddresses = self._getCalendarUserAddresses(recordType, key, value)
- else:
- calendarUserAddresses = ()
-
- # Special case for groups.
- if recordType == DirectoryService.recordType_groups:
- memberGUIDs = value.get(dsattributes.kDSNAttrGroupMembers)
- if memberGUIDs is None:
- memberGUIDs = ()
- elif type(memberGUIDs) is str:
- memberGUIDs = (memberGUIDs,)
- nestedGUIDs = value.get(dsattributes.kDSNAttrNestedGroups)
- if nestedGUIDs:
- if type(nestedGUIDs) is str:
- nestedGUIDs = (nestedGUIDs,)
- memberGUIDs += tuple(nestedGUIDs)
- else:
- memberGUIDs = ()
-
- # Special case for resources and locations
- autoSchedule = False
- proxyGUIDs = ()
- if recordType in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
- resourceInfo = value.get(dsattributes.kDSNAttrResourceInfo)
- if resourceInfo is not None:
- autoSchedule, proxy = self._parseResourceInfo(resourceInfo)
- if proxy:
- proxyGUIDs = (proxy,)
-
- record = OpenDirectoryRecord(
- service = self,
- recordType = recordType,
- guid = guid,
- shortName = recordShortName,
- fullName = realName,
- calendarUserAddresses = calendarUserAddresses,
- autoSchedule = autoSchedule,
- enabledForCalendaring = enabledForCalendaring,
- memberGUIDs = memberGUIDs,
- proxyGUIDs = proxyGUIDs,
- )
- records[recordShortName] = guids[guid] = record
-
- #log.debug("Populated record: %s" % (records[recordShortName],))
-
- if shortName is None:
- #
- # Replace the entire cache
- #
- storage = {
- "status" : "new",
- "records": records,
- "guids" : guids,
- }
-
- def rot():
- storage["status"] = "stale"
- removals = set()
- for call in self._delayedCalls:
- if not call.active():
- removals.add(call)
- for item in removals:
- self._delayedCalls.remove(item)
-
- self._delayedCalls.add(callLater(recordListCacheTimeout, rot))
-
- self._records[recordType] = storage
-
- elif records:
- #
- # Update one record, if found
- #
- assert len(records) == 1, "shortName = %r, records = %r" % (shortName, len(records))
- storage = self._records[recordType]
- storage["records"][shortName] = record
- storage["guids"][record.guid] = record
-
-
class OpenDirectoryRecord(DirectoryRecord):
"""
Open Directory implementation of L{IDirectoryRecord}.
@@ -725,7 +743,7 @@
for guid in self._proxyGUIDs:
proxyRecord = self.service.recordWithGUID(guid)
if proxyRecord is None:
- log.err("No record for proxy in %s with GUID %s" % (self.shortName, guid))
+ logging.err("No record for proxy in %s with GUID %s" % (self.shortName, guid), system="OpenDirectoryService")
else:
yield proxyRecord
@@ -742,8 +760,8 @@
try:
return opendirectory.authenticateUserBasic(self.service.directory, self.guid, self.shortName, credentials.password)
except opendirectory.ODError, e:
- log.err("Open Directory (node=%s) error while performing basic authentication for user %s: %s"
- % (self.service.realmName, self.shortName, e))
+ logging.err("Open Directory (node=%s) error while performing basic authentication for user %s: %s"
+ % (self.service.realmName, self.shortName, e), system="OpenDirectoryService")
return False
elif isinstance(credentials, DigestedCredentials):
try:
@@ -759,8 +777,8 @@
'response="%(response)s",'
'algorithm=%(algorithm)s') % credentials.fields
except KeyError, e:
- log.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))
+ 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
return opendirectory.authenticateUserDigest(
@@ -772,8 +790,8 @@
credentials.method
)
except opendirectory.ODError, e:
- log.err("Open Directory (node=%s) error while performing digest authentication for user %s: %s"
- % (self.service.realmName, self.shortName, e))
+ 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 super(OpenDirectoryRecord, self).verifyCredentials(credentials)
Copied: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py (from rev 1924, CalendarServer/branches/users/cdaboo/multiple-computer-records-1911/twistedcaldav/directory/test/test_opendirectoryrecords.py)
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py (rev 0)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryrecords.py 2007-09-28 20:03:41 UTC (rev 1926)
@@ -0,0 +1,336 @@
+##
+# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# DRI: Wilfredo Sanchez, wsanchez at apple.com
+##
+
+import twisted.trial.unittest
+
+try:
+ from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
+ import dsattributes
+except ImportError:
+ pass
+else:
+ from twistedcaldav.directory.directory import DirectoryService
+
+ def _queryDirectory(dir, recordType, shortName=None):
+
+ if shortName:
+ for name, record in dir.fakerecords[recordType]:
+ if name == shortName:
+ return ((name, record),)
+ else:
+ return ()
+ else:
+ return dir.fakerecords[recordType]
+
+ 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:
+ call.cancel()
+
+ def _verifyRecords(self, recordType, expected):
+ expected = set(expected)
+ found = set(self._service._records[recordType]["records"].keys())
+
+ missing = expected.difference(found)
+ extras = found.difference(expected)
+
+ 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,)]
+
+ 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,))
+
+ 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",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ DirectoryService.recordType_groups: [
+ ["group01", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_group01",
+ dsattributes.kDS1AttrDistinguishedName: "Group 01",
+ dsattributes.kDSNAttrEMailAddress: "group01 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["group02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_group02",
+ dsattributes.kDS1AttrDistinguishedName: "Group 02",
+ dsattributes.kDSNAttrEMailAddress: "group02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ DirectoryService.recordType_resources: [
+ ["resource01", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_resource01",
+ dsattributes.kDS1AttrDistinguishedName: "Resource 01",
+ dsattributes.kDSNAttrEMailAddress: "resource01 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["resource02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_resource02",
+ dsattributes.kDS1AttrDistinguishedName: "Resource 02",
+ dsattributes.kDSNAttrEMailAddress: "resource02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ DirectoryService.recordType_locations: [
+ ["location01", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_location01",
+ dsattributes.kDS1AttrDistinguishedName: "Location 01",
+ dsattributes.kDSNAttrEMailAddress: "location01 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["location02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_location02",
+ dsattributes.kDS1AttrDistinguishedName: "Location 02",
+ dsattributes.kDSNAttrEMailAddress: "location02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ }
+
+ self._service.reloadCache(DirectoryService.recordType_users)
+ self._service.reloadCache(DirectoryService.recordType_groups)
+ 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_groups, ("group01", "group02",))
+ self._verifyDisabledRecords(DirectoryService.recordType_groups, "names", ())
+ self._verifyDisabledRecords(DirectoryService.recordType_groups, "guids", ())
+
+ self._verifyRecords(DirectoryService.recordType_resources, ("resource01", "resource02",))
+ self._verifyDisabledRecords(DirectoryService.recordType_resources, "names", ())
+ self._verifyDisabledRecords(DirectoryService.recordType_resources, "guids", ())
+
+ self._verifyRecords(DirectoryService.recordType_locations, ("location01", "location02",))
+ self._verifyDisabledRecords(DirectoryService.recordType_locations, "names", ())
+ self._verifyDisabledRecords(DirectoryService.recordType_locations, "guids", ())
+
+ 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",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ }
+
+ 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", ())
+
+
+ def test_DuplicateName(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",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02-1",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02-2",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ }
+
+ 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", ))
+
+ 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",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["user03", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ }
+
+ 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", ))
+
+ 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",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["user03", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02-2",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ }
+
+ 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"))
+
+ 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",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ }
+
+ 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._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",
+ }],
+ ["user02", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ["user03", {
+ dsattributes.kDS1AttrGeneratedUID: "GUID_user02",
+ dsattributes.kDS1AttrDistinguishedName: "User 02",
+ dsattributes.kDSNAttrEMailAddress: "user02 at example.com",
+ dsattributes.kDSNAttrServicesLocator: "12345:67890:calendar",
+ }],
+ ],
+ }
+
+ self._service.reloadCache(DirectoryService.recordType_users, "user03")
+
+ self._verifyRecords(DirectoryService.recordType_users, ("user01", "user02",))
+ self._verifyDisabledRecords(DirectoryService.recordType_users, "names", ("user03",))
+ self._verifyDisabledRecords(DirectoryService.recordType_users, "guids", ("GUID_user02", ))
+
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py 2007-09-28 20:01:21 UTC (rev 1925)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py 2007-09-28 20:03:41 UTC (rev 1926)
@@ -948,7 +948,10 @@
def test_plist_errors(self):
def _doParse(plist, title):
service = OpenDirectoryService(node="/Search", dosetup=False)
- if service._parseServiceInfo("calendar.apple.com", "recordit", plist, "GUIDIFY"):
+ 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 = (
@@ -964,16 +967,22 @@
def test_goodplist(self):
service = OpenDirectoryService(node="/Search", dosetup=False)
- if not service._parseServiceInfo("calendar.apple.com", "recordit", PlistParse.plist_good, "GUIDIFY"):
+ 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.servicetag, "GUIDIFY:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar")
+ 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, PlistParse.plist_good, "GUIDIFY"):
+ 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._getCalendarUserAddresses(DirectoryService.recordType_users, recordName, record)
@@ -1073,10 +1082,10 @@
pass
records = (
- ({}, "no records found"),
- ({
- ODRecordsParse.record_localod_good_other[0] : ODRecordsParse.record_localod_good_other[1],
- }, "non-matching record found"),
+ ((), "no records found"),
+ ((
+ (ODRecordsParse.record_localod_good_other[0], ODRecordsParse.record_localod_good_other[1]),
+ ), "non-matching record found"),
)
for recordlist, title in records:
@@ -1091,71 +1100,79 @@
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"),
+ ((
+ (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, guid):
+ def _doParseRecords(recordlist, title, tags):
service = OpenDirectoryService(node="/Search", dosetup=False)
service._parseComputersRecords(recordlist, "calendar.apple.com")
- gotGuid = service.servicetag.split(':', 1)[0]
- self.assertEquals(guid, gotGuid,
- "Got wrong guid, %s: Expected %s not %s" % (title, guid, gotGuid))
+ 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]},
- "Remote Record Preferred", "GUID2"),
- ({ODRecordsParse.record_localod_good[0] : ODRecordsParse.record_localod_good[1],
- ODRecordsParse.record_default_good[0] : ODRecordsParse.record_default_good[1]},
- "Local OD Preferred", "GUID1"),
- ({ODRecordsParse.record_default_good[0] : ODRecordsParse.record_default_good[1]},
- "Local Node Preferred", "GUID3"),
+ (((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, guid in records:
- _doParseRecords(recordlist, title, guid)
+ for recordlist, title, tags in records:
+ _doParseRecords(recordlist, title, tags)
def test_odrecords_duplicates(self):
- def _doParseRecords(recordlist, title, items):
+ def _doParseRecords(recordlist, title, items, tags):
service = OpenDirectoryService(node="/Search", dosetup=False)
- try:
- service._parseComputersRecords(recordlist, "calendar.apple.com")
- except OpenDirectoryInitError, ex:
- for item in items:
- if item not in str(ex):
- self.fail(msg="Record parse should have failed: \"%s\" with error: %s containing %s" % (title, ex, item))
- else:
- self.fail(msg="Record parse should have failed: \"%s\"" % (title, ))
+ 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",)),
- ({ODRecordsParse.record_localod_good[0] : ODRecordsParse.record_localod_good[1],
- ODRecordsParse.record_localod_duplicate[0] : ODRecordsParse.record_localod_duplicate[1],
- ODRecordsParse.record_default_good[0] : ODRecordsParse.record_default_good[1]},
- "Local OD Duplicated", ("computer1.apple.com", "computer1",)),
- ({ODRecordsParse.record_default_good[0] : ODRecordsParse.record_default_good[1],
- ODRecordsParse.record_default_duplicate[0] : ODRecordsParse.record_default_duplicate[1]},
- "Local Node Duplicated", ("computer4.apple.com", "computer4",)),
+ (((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 in records:
- _doParseRecords(recordlist, title, items)
+ for recordlist, title, items, tags in records:
+ _doParseRecords(recordlist, title, items, tags)
class ODResourceInfoParse (twisted.trial.unittest.TestCase):
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20070928/215666c4/attachment.html
More information about the calendarserver-changes
mailing list