[CalendarServer-changes] [4089] CalendarServer/trunk/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Mon Apr 27 09:13:04 PDT 2009


Revision: 4089
          http://trac.macosforge.org/projects/calendarserver/changeset/4089
Author:   sagen at apple.com
Date:     2009-04-27 09:13:04 -0700 (Mon, 27 Apr 2009)
Log Message:
-----------
Migrate calendar proxy assignments and auto-schedule settings from directory to database.  (XML directory implementation still honors values in the XML files for ease of use)

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/directory/aggregate.py
    CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/trunk/twistedcaldav/directory/cachingappleopendirectory.py
    CalendarServer/trunk/twistedcaldav/directory/directory.py
    CalendarServer/trunk/twistedcaldav/test/test_upgrade.py
    CalendarServer/trunk/twistedcaldav/upgrade.py

Modified: CalendarServer/trunk/twistedcaldav/directory/aggregate.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/aggregate.py	2009-04-27 15:04:19 UTC (rev 4088)
+++ CalendarServer/trunk/twistedcaldav/directory/aggregate.py	2009-04-27 16:13:04 UTC (rev 4089)
@@ -160,6 +160,14 @@
         
         raise UnauthorizedLogin("No such user: %s" % (credentials.credentials.username,))
 
+    def getResourceInfo(self):
+        results = []
+        for service in self._recordTypes.values():
+            for result in service.getResourceInfo():
+                if result:
+                    results.append(result)
+        return results
+
 class DuplicateRecordTypeError(DirectoryError):
     """
     Duplicate record type.

Modified: CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2009-04-27 15:04:19 UTC (rev 4088)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py	2009-04-27 16:13:04 UTC (rev 4089)
@@ -926,6 +926,46 @@
 
         return results
 
+    def getResourceInfo(self):
+        """
+        Resource information including proxy assignments for resource and
+        locations, as well as auto-schedule settings, used to live in the
+        directory.  This method fetches old resource info for migration
+        purposes.
+        """
+        attrs = [
+            dsattributes.kDS1AttrGeneratedUID,
+            dsattributes.kDSNAttrResourceInfo,
+        ]
+
+        for recordType in (dsattributes.kDSStdRecordTypePlaces, dsattributes.kDSStdRecordTypeResources):
+            try:
+                self.log_debug("opendirectory.listAllRecordsWithAttributes_list(%r,%r,%r)" % (
+                    self.directory,
+                    recordType,
+                    attrs,
+                ))
+                results = opendirectory.listAllRecordsWithAttributes_list(
+                    self.directory,
+                    recordType,
+                    attrs,
+                )
+            except opendirectory.ODError, ex:
+                self.log_error("Open Directory (node=%s) error: %s" % (self.realmName, str(ex)))
+                raise
+
+            for (recordShortName, value) in results:
+                recordGUID = value.get(dsattributes.kDS1AttrGeneratedUID)
+                resourceInfo = value.get(dsattributes.kDSNAttrResourceInfo)
+                if resourceInfo is not None:
+                    try:
+                        autoSchedule, proxy, readOnlyProxy = self._parseResourceInfo(resourceInfo,
+                            recordGUID, recordType, recordShortName)
+                    except ValueError:
+                        continue
+                    yield recordGUID, autoSchedule, proxy, readOnlyProxy
+
+
 class OpenDirectoryRecord(DirectoryRecord):
     """
     Open Directory implementation of L{IDirectoryRecord}.

Modified: CalendarServer/trunk/twistedcaldav/directory/cachingappleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/cachingappleopendirectory.py	2009-04-27 15:04:19 UTC (rev 4088)
+++ CalendarServer/trunk/twistedcaldav/directory/cachingappleopendirectory.py	2009-04-27 16:13:04 UTC (rev 4089)
@@ -191,33 +191,6 @@
                 
         return result
 
-    def _parseResourceInfo(self, plist, guid, recordType, shortname):
-        """
-        Parse OD ResourceInfo attribute and extract information that the server needs.
-
-        @param plist: the plist that is the attribute value.
-        @type plist: str
-        @param guid: the directory GUID of the record being parsed.
-        @type guid: str
-        @param shortname: the record shortname of the record being parsed.
-        @type shortname: str
-        @return: a C{tuple} of C{bool} for auto-accept, C{str} for proxy GUID, C{str} for read-only proxy GUID.
-        """
-        try:
-            plist = readPlistFromString(plist)
-            wpframework = plist.get("com.apple.WhitePagesFramework", {})
-            autoaccept = wpframework.get("AutoAcceptsInvitation", False)
-            proxy = wpframework.get("CalendaringDelegate", None)
-            read_only_proxy = wpframework.get("ReadOnlyCalendaringDelegate", None)
-        except (ExpatError, AttributeError), e:
-            self.log_error(
-                "Failed to parse ResourceInfo attribute of record (%s)%s (guid=%s): %s\n%s" %
-                (recordType, shortname, guid, e, plist,)
-            )
-            raise ValueError("Invalid ResourceInfo")
-
-        return (autoaccept, proxy, read_only_proxy,)
-
     def recordTypes(self):
         return (
             self.recordType_users,
@@ -676,7 +649,73 @@
             )
             self.recordCacheForType(recordType).addRecord(record)
 
+    def _parseResourceInfo(self, plist, guid, recordType, shortname):
+        """
+        Parse OD ResourceInfo attribute and extract information that the server needs.
 
+        @param plist: the plist that is the attribute value.
+        @type plist: str
+        @param guid: the directory GUID of the record being parsed.
+        @type guid: str
+        @param shortname: the record shortname of the record being parsed.
+        @type shortname: str
+        @return: a C{tuple} of C{bool} for auto-accept, C{str} for proxy GUID, C{str} for read-only proxy GUID.
+        """
+        try:
+            plist = readPlistFromString(plist)
+            wpframework = plist.get("com.apple.WhitePagesFramework", {})
+            autoaccept = wpframework.get("AutoAcceptsInvitation", False)
+            proxy = wpframework.get("CalendaringDelegate", None)
+            read_only_proxy = wpframework.get("ReadOnlyCalendaringDelegate", None)
+        except (ExpatError, AttributeError), e:
+            self.log_error(
+                "Failed to parse ResourceInfo attribute of record (%s)%s (guid=%s): %s\n%s" %
+                (recordType, shortname, guid, e, plist,)
+            )
+            raise ValueError("Invalid ResourceInfo")
+
+        return (autoaccept, proxy, read_only_proxy,)
+
+    def getResourceInfo(self):
+        """
+        Resource information including proxy assignments for resource and
+        locations, as well as auto-schedule settings, used to live in the
+        directory.  This method fetches old resource info for migration
+        purposes.
+        """
+        attrs = [
+            dsattributes.kDS1AttrGeneratedUID,
+            dsattributes.kDSNAttrResourceInfo,
+        ]
+
+        for recordType in (dsattributes.kDSStdRecordTypePlaces, dsattributes.kDSStdRecordTypeResources):
+            try:
+                self.log_debug("opendirectory.listAllRecordsWithAttributes_list(%r,%r,%r)" % (
+                    self.directory,
+                    recordType,
+                    attrs,
+                ))
+                results = opendirectory.listAllRecordsWithAttributes_list(
+                    self.directory,
+                    recordType,
+                    attrs,
+                )
+            except opendirectory.ODError, ex:
+                self.log_error("Open Directory (node=%s) error: %s" % (self.realmName, str(ex)))
+                raise
+
+            for (recordShortName, value) in results:
+                recordGUID = value.get(dsattributes.kDS1AttrGeneratedUID)
+                resourceInfo = value.get(dsattributes.kDSNAttrResourceInfo)
+                if resourceInfo is not None:
+                    try:
+                        autoSchedule, proxy, readOnlyProxy = self._parseResourceInfo(resourceInfo,
+                            recordGUID, recordType, recordShortName)
+                    except ValueError:
+                        continue
+                    yield recordGUID, autoSchedule, proxy, readOnlyProxy
+
+
 class OpenDirectoryRecord(CachingDirectoryRecord):
     """
     Open Directory implementation of L{IDirectoryRecord}.

Modified: CalendarServer/trunk/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/directory.py	2009-04-27 15:04:19 UTC (rev 4088)
+++ CalendarServer/trunk/twistedcaldav/directory/directory.py	2009-04-27 16:13:04 UTC (rev 4089)
@@ -251,6 +251,8 @@
 
         return succeed(yieldMatches(recordType))
 
+    def getResourceInfo(self):
+        return ()
 
 class DirectoryRecord(LoggingMixIn):
     implements(IDirectoryRecord)
@@ -363,7 +365,7 @@
 
 class DirectoryConfigurationError(DirectoryError):
     """
-    Invlid directory configuration.
+    Invalid directory configuration.
     """
 
 class UnknownRecordTypeError(DirectoryError):

Modified: CalendarServer/trunk/twistedcaldav/test/test_upgrade.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_upgrade.py	2009-04-27 15:04:19 UTC (rev 4088)
+++ CalendarServer/trunk/twistedcaldav/test/test_upgrade.py	2009-04-27 16:13:04 UTC (rev 4089)
@@ -16,6 +16,7 @@
 
 from twistedcaldav.config import config
 from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
+from twistedcaldav.directory.xmlfile import XMLDirectoryService
 from twistedcaldav.directory.resourceinfo import ResourceInfoDatabase
 from twistedcaldav.upgrade import UpgradeError, upgradeData, updateFreeBusySet
 from twistedcaldav.test.util import TestCase
@@ -788,8 +789,73 @@
         self.assertRaises(UpgradeError, upgradeData, config)
         self.assertTrue(self.verifyHierarchy(root, after))
 
+    def test_migrateResourceInfo(self):
+        # Fake getResourceInfo( )
 
+        assignments = {
+            'guid1' : (False, None, None),
+            'guid2' : (True, 'guid1', None),
+            'guid3' : (False, 'guid1', 'guid2'),
+            'guid4' : (True, None, 'guid3'),
+        }
 
+        def _getResourceInfo(ignored):
+            results = []
+            for guid, info in assignments.iteritems():
+                results.append( (guid, info[0], info[1], info[2]) )
+            return results
+
+        self.setUpInitialStates()
+        # Override the normal getResourceInfo method with our own:
+        XMLDirectoryService.getResourceInfo = _getResourceInfo
+
+        before = { }
+        after = {
+            ".calendarserver_version" :
+            {
+                "@contents" : "1",
+            },
+            CalendarUserProxyDatabase.dbFilename :
+            {
+                "@contents" : None,
+            },
+            ResourceInfoDatabase.dbFilename :
+            {
+                "@contents" : None,
+            }
+        }
+        root = self.createHierarchy(before)
+        config.DocumentRoot = root
+        config.DataRoot = root
+
+        upgradeData(config)
+        self.assertTrue(self.verifyHierarchy(root, after))
+
+        calendarUserProxyDatabase = CalendarUserProxyDatabase(root)
+        resourceInfoDatabase = ResourceInfoDatabase(root)
+
+        for guid, info in assignments.iteritems():
+
+            proxyGroup = "%s#calendar-proxy-write" % (guid,)
+            result = set([row[0] for row in calendarUserProxyDatabase._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", proxyGroup)])
+            if info[1]:
+                self.assertTrue(info[1] in result)
+            else:
+                self.assertTrue(not result)
+
+            readOnlyProxyGroup = "%s#calendar-proxy-read" % (guid,)
+            result = set([row[0] for row in calendarUserProxyDatabase._db_execute("select MEMBER from GROUPS where GROUPNAME = :1", readOnlyProxyGroup)])
+            if info[2]:
+                self.assertTrue(info[2] in result)
+            else:
+                self.assertTrue(not result)
+
+            autoSchedule = resourceInfoDatabase._db_value_for_sql("select AUTOSCHEDULE from RESOURCEINFO where GUID = :1", guid)
+            autoSchedule = autoSchedule == 1
+            self.assertEquals(info[0], autoSchedule)
+
+
+
 event01_before = """BEGIN:VCALENDAR
 VERSION:2.0
 PRODID:-//Apple Inc.//iCal 3.0//EN

Modified: CalendarServer/trunk/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/upgrade.py	2009-04-27 15:04:19 UTC (rev 4088)
+++ CalendarServer/trunk/twistedcaldav/upgrade.py	2009-04-27 16:13:04 UTC (rev 4089)
@@ -20,6 +20,7 @@
 from twisted.web2.dav import davxml
 from twistedcaldav.directory.directory import DirectoryService
 from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
+from twistedcaldav.directory.resourceinfo import ResourceInfoDatabase
 from twistedcaldav.log import Logger
 from twistedcaldav.ical import Component
 from twistedcaldav import caldavxml
@@ -243,12 +244,35 @@
         os.rename(oldHome, newHome)
 
 
+    def migrateResourceInfo(config, directory):
+        log.info("Fetching delegate assignments and auto-schedule settings from directory")
+        resourceInfoDatabase = ResourceInfoDatabase(config.DataRoot)
+        calendarUserProxyDatabase = CalendarUserProxyDatabase(config.DataRoot)
+        resourceInfo = directory.getResourceInfo()
+        for guid, autoSchedule, proxy, readOnlyProxy in resourceInfo:
+            resourceInfoDatabase.setAutoScheduleInDatabase(guid, autoSchedule)
+            if proxy:
+                calendarUserProxyDatabase.setGroupMembersInDatabase(
+                    "%s#calendar-proxy-write" % (guid,),
+                    [proxy]
+                )
+            if readOnlyProxy:
+                calendarUserProxyDatabase.setGroupMembersInDatabase(
+                    "%s#calendar-proxy-read" % (guid,),
+                    [readOnlyProxy]
+                )
 
+
+
     directory = getDirectory()
+
     docRoot = config.DocumentRoot
 
     uid, gid = getCalendarServerIDs(config)
 
+    if not os.path.exists(config.DataRoot):
+        makeDirsUserGroup(config.DataRoot, uid=uid, gid=gid)
+
     if os.path.exists(docRoot):
 
         # Look for the /principals/ directory on disk
@@ -344,6 +368,8 @@
 
                 log.warn("Done processing calendar homes")
 
+    migrateResourceInfo(config, directory)
+
     if errorOccurred:
         raise UpgradeError("Data upgrade failed, see error.log for details")
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090427/952eb93b/attachment-0001.html>


More information about the calendarserver-changes mailing list