Revision
1457
Author
dreid@apple.com
Date
2007-04-06 17:41:52 -0700 (Fri, 06 Apr 2007)

Log Message

Find the correct virtual host among multiple virtualhosts in different nodes, prefering the remote node, then the local od node, then the local node.

Modified Paths

Diff

Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py (1456 => 1457)


--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2007-04-06 15:29:20 UTC (rev 1456)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2007-04-07 00:41:52 UTC (rev 1457)
@@ -123,6 +123,7 @@
             dsattributes.kDS1AttrGeneratedUID,
             dsattributes.kDSNAttrRecordName,
             dsattributes.kDS1AttrXMLPlist,
+            dsattributes.kDSNAttrMetaNodeLocation,
         ]
 
         records = opendirectory.queryRecordsWithAttribute(
@@ -137,7 +138,9 @@
         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(
@@ -146,30 +149,59 @@
             )
 
         # Now find a single record that actually matches the hostname
-        found = False
+        # Prefering the remote OD node to the local OD Node and
+        # the local OD Node to the local node.
+
+        _localNode = None
+        _localODNode = None
+        _remoteNode = None
+
         for recordname, record in records.iteritems():
-            
             # Must have XMLPlist value
             plist = record.get(dsattributes.kDS1AttrXMLPlist, None)
             if not plist:
                 continue
-            
-            if not self._parseXMLPlist(vhostname, recordname, plist, record[dsattributes.kDS1AttrGeneratedUID]):
+
+            # 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
-            elif found:
-                raise OpenDirectoryInitError(
-                    "Open Directory (node=%s) multiple /Computers records found matching virtual hostname: %s"
-                    % (self.realmName, vhostname,)
-                )
+
+            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:
+                _localNode = (recordname, plist, record[dsattributes.kDS1AttrGeneratedUID])
+
+            elif record[dsattributes.kDSNAttrMetaNodeLocation] == localODNodePath:
+                _localODNode = (recordname, plist, record[dsattributes.kDS1AttrGeneratedUID])
+
             else:
-                found = True
-                
-        if not found:
+                _remoteNode = (recordname, plist, record[dsattributes.kDS1AttrGeneratedUID])
+
+        # XXX: These calls to self._parseXMLPlist will cause the plsit to be parsed _again_
+        #      refactor later so we only ever parse it once.
+
+        for node in (_remoteNode, _localODNode, _localNode):
+            if node and self._parseXMLPlist(vhostname, *node):
+                break
+
+        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 _parseXMLPlist(self, vhostname, recordname, plist, recordguid):
         # Parse the plist and look for our special entry
         plist = readPlistFromString(plist)