[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