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

source_changes at macosforge.org source_changes at macosforge.org
Thu Nov 6 15:59:24 PST 2008


Revision: 3337
          http://trac.macosforge.org/projects/calendarserver/changeset/3337
Author:   wsanchez at apple.com
Date:     2008-11-06 15:59:24 -0800 (Thu, 06 Nov 2008)
Log Message:
-----------
Merge source:branches/users/cdaboo/upgrade-3301

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/trunk/twistedcaldav/tap.py

Added Paths:
-----------
    CalendarServer/trunk/twistedcaldav/test/test_upgrade.py
    CalendarServer/trunk/twistedcaldav/upgrade.py

Modified: CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py	2008-11-06 23:57:11 UTC (rev 3336)
+++ CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py	2008-11-06 23:59:24 UTC (rev 3337)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2008 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.
@@ -38,7 +38,7 @@
 from twistedcaldav.memcacher import Memcacher
 from twistedcaldav.resource import CalDAVComplianceMixIn
 from twistedcaldav.directory.util import NotFilePath
-from twistedcaldav.sql import AbstractSQLDatabase
+from twistedcaldav.sql import AbstractSQLDatabase, db_prefix
 
 import itertools
 import os
@@ -345,6 +345,7 @@
 
     dbType = "CALENDARUSERPROXY"
     dbFilename = "calendaruserproxy.sqlite"
+    dbOldFilename = db_prefix + "calendaruserproxy"
     dbFormatVersion = "4"
 
     class ProxyDBMemcacher(Memcacher):

Modified: CalendarServer/trunk/twistedcaldav/tap.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/tap.py	2008-11-06 23:57:11 UTC (rev 3336)
+++ CalendarServer/trunk/twistedcaldav/tap.py	2008-11-06 23:59:24 UTC (rev 3337)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2008 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.
@@ -15,7 +15,6 @@
 ##
 
 import os
-import stat
 
 from subprocess import Popen, PIPE
 from pwd import getpwnam
@@ -56,6 +55,7 @@
 from twistedcaldav.static import TimezoneServiceFile
 from twistedcaldav.static import IMIPInboxFile
 from twistedcaldav.timezones import TimezoneCache
+from twistedcaldav.upgrade import UpgradeTheServer
 from twistedcaldav import pdmonster
 from twistedcaldav import memcachepool
 from twistedcaldav.notify import installNotificationClient
@@ -699,6 +699,10 @@
     makeService_Single   = makeService_Slave
 
     def makeService(self, options):
+
+        # Now do any on disk upgrades we might need.
+        UpgradeTheServer.doUpgrade()
+
         serverType = config.ProcessType
 
         serviceMethod = getattr(self, "makeService_%s" % (serverType,), None)
@@ -706,7 +710,7 @@
         if not serviceMethod:
             raise UsageError(
                 "Unknown server type %s. "
-                "Please choose: Master, Slave or Combined"
+                "Please choose: Master, Slave, Single or Combined"
                 % (serverType,)
             )
         else:

Copied: CalendarServer/trunk/twistedcaldav/test/test_upgrade.py (from rev 3336, CalendarServer/branches/users/cdaboo/upgrade-3301/twistedcaldav/test/test_upgrade.py)
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_upgrade.py	                        (rev 0)
+++ CalendarServer/trunk/twistedcaldav/test/test_upgrade.py	2008-11-06 23:59:24 UTC (rev 3337)
@@ -0,0 +1,186 @@
+##
+# Copyright (c) 2008 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.
+##
+
+from twisted.trial.unittest import TestCase
+
+from twistedcaldav.config import config
+from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
+from twistedcaldav.upgrade import UpgradeError
+from twistedcaldav.upgrade import UpgradeTheServer
+
+import os
+
+class ProxyDBUpgradeTests(TestCase):
+    
+    def setUpInitialStates(self):
+        
+        self.setUpOldDocRoot()
+        self.setUpOldDocRootWithoutDB()
+        self.setUpNewDocRoot()
+        
+        self.setUpNewDataRoot()
+        self.setUpDataRootWithProxyDB()
+
+    def setUpOldDocRoot(self):
+        
+        # Set up doc root
+        self.olddocroot = self.mktemp()
+        os.mkdir(self.olddocroot)
+
+        principals = os.path.join(self.olddocroot, "principals")
+        os.mkdir(principals)
+        os.mkdir(os.path.join(principals, "__uids__"))
+        os.mkdir(os.path.join(principals, "users"))
+        os.mkdir(os.path.join(principals, "groups"))
+        os.mkdir(os.path.join(principals, "locations"))
+        os.mkdir(os.path.join(principals, "resources"))
+        os.mkdir(os.path.join(principals, "sudoers"))
+        os.mkdir(os.path.join(self.olddocroot, "calendars"))
+
+        proxyDB = CalendarUserProxyDatabase(principals)
+        proxyDB._db()
+        os.rename(
+            os.path.join(principals, CalendarUserProxyDatabase.dbFilename),
+            os.path.join(principals, CalendarUserProxyDatabase.dbOldFilename),
+        )
+
+    def setUpOldDocRootWithoutDB(self):
+        
+        # Set up doc root
+        self.olddocrootnodb = self.mktemp()
+        os.mkdir(self.olddocrootnodb)
+
+        principals = os.path.join(self.olddocrootnodb, "principals")
+        os.mkdir(principals)
+        os.mkdir(os.path.join(principals, "__uids__"))
+        os.mkdir(os.path.join(principals, "users"))
+        os.mkdir(os.path.join(principals, "groups"))
+        os.mkdir(os.path.join(principals, "locations"))
+        os.mkdir(os.path.join(principals, "resources"))
+        os.mkdir(os.path.join(principals, "sudoers"))
+        os.mkdir(os.path.join(self.olddocrootnodb, "calendars"))
+
+    def setUpNewDocRoot(self):
+        
+        # Set up doc root
+        self.newdocroot = self.mktemp()
+        os.mkdir(self.newdocroot)
+
+        os.mkdir(os.path.join(self.newdocroot, "calendars"))
+
+    def setUpNewDataRoot(self):
+        
+        # Set up data root
+        self.newdataroot = self.mktemp()
+        os.mkdir(self.newdataroot)
+
+    def setUpDataRootWithProxyDB(self):
+        
+        # Set up data root
+        self.existingdataroot = self.mktemp()
+        os.mkdir(self.existingdataroot)
+
+        proxyDB = CalendarUserProxyDatabase(self.existingdataroot)
+        proxyDB._db()
+
+    def test_normalUpgrade(self):
+        """
+        Test the behavior of normal upgrade from old server to new.
+        """
+
+        self.setUpInitialStates()
+
+        config.DocumentRoot = self.olddocroot
+        config.DataRoot = self.newdataroot
+        
+        # Check pre-conditions
+        self.assertTrue(os.path.exists(os.path.join(config.DocumentRoot, "principals")))
+        self.assertTrue(os.path.isdir(os.path.join(config.DocumentRoot, "principals")))
+        self.assertTrue(os.path.exists(os.path.join(config.DocumentRoot, "principals", CalendarUserProxyDatabase.dbOldFilename)))
+        self.assertFalse(os.path.exists(os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)))
+
+        UpgradeTheServer.doUpgrade()
+        
+        # Check post-conditions
+        self.assertFalse(os.path.exists(os.path.join(config.DocumentRoot, "principals",)))
+        self.assertTrue(os.path.exists(os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)))
+
+    def test_partialUpgrade(self):
+        """
+        Test the behavior of a partial upgrade (one where /principals exists but the proxy db does not) from old server to new.
+        """
+
+        self.setUpInitialStates()
+
+        config.DocumentRoot = self.olddocrootnodb
+        config.DataRoot = self.newdataroot
+        
+        # Check pre-conditions
+        self.assertTrue(os.path.exists(os.path.join(config.DocumentRoot, "principals")))
+        self.assertTrue(os.path.isdir(os.path.join(config.DocumentRoot, "principals")))
+        self.assertFalse(os.path.exists(os.path.join(config.DocumentRoot, "principals", CalendarUserProxyDatabase.dbOldFilename)))
+        self.assertFalse(os.path.exists(os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)))
+
+        UpgradeTheServer.doUpgrade()
+        
+        # Check post-conditions
+        self.assertFalse(os.path.exists(os.path.join(config.DocumentRoot, "principals",)))
+        self.assertFalse(os.path.exists(os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)))
+
+    def test_noUpgrade(self):
+        """
+        Test the behavior of running on a new server (i.e. no upgrade needed).
+        """
+
+        self.setUpInitialStates()
+
+        config.DocumentRoot = self.newdocroot
+        config.DataRoot = self.existingdataroot
+        
+        # Check pre-conditions
+        self.assertFalse(os.path.exists(os.path.join(config.DocumentRoot, "principals")))
+        self.assertTrue(os.path.exists(os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)))
+
+        UpgradeTheServer.doUpgrade()
+        
+        # Check post-conditions
+        self.assertFalse(os.path.exists(os.path.join(config.DocumentRoot, "principals",)))
+        self.assertTrue(os.path.exists(os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)))
+
+    def test_failedUpgrade(self):
+        """
+        Test the behavior of failed upgrade from old server to new where proxy DB exists in two locations.
+        """
+
+        self.setUpInitialStates()
+
+        config.DocumentRoot = self.olddocroot
+        config.DataRoot = self.existingdataroot
+        
+        # Check pre-conditions
+        self.assertTrue(os.path.exists(os.path.join(config.DocumentRoot, "principals")))
+        self.assertTrue(os.path.isdir(os.path.join(config.DocumentRoot, "principals")))
+        self.assertTrue(os.path.exists(os.path.join(config.DocumentRoot, "principals", CalendarUserProxyDatabase.dbOldFilename)))
+        self.assertTrue(os.path.exists(os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)))
+
+        self.assertRaises(UpgradeError, UpgradeTheServer.doUpgrade)
+        
+        # Check post-conditions
+        self.assertTrue(os.path.exists(os.path.join(config.DocumentRoot, "principals")))
+        self.assertTrue(os.path.isdir(os.path.join(config.DocumentRoot, "principals")))
+        self.assertTrue(os.path.exists(os.path.join(config.DocumentRoot, "principals", CalendarUserProxyDatabase.dbOldFilename)))
+        self.assertTrue(os.path.exists(os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)))
+        
\ No newline at end of file

Copied: CalendarServer/trunk/twistedcaldav/upgrade.py (from rev 3336, CalendarServer/branches/users/cdaboo/upgrade-3301/twistedcaldav/upgrade.py)
===================================================================
--- CalendarServer/trunk/twistedcaldav/upgrade.py	                        (rev 0)
+++ CalendarServer/trunk/twistedcaldav/upgrade.py	2008-11-06 23:59:24 UTC (rev 3337)
@@ -0,0 +1,85 @@
+##
+# Copyright (c) 2008 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.
+##
+
+from twisted.web2.dav.fileop import rmdir
+from twistedcaldav.config import config
+from twistedcaldav.directory.calendaruserproxy import CalendarUserProxyDatabase
+from twistedcaldav.log import Logger
+import os
+
+log = Logger()
+
+class UpgradeTheServer(object):
+    
+    @staticmethod
+    def doUpgrade():
+        
+        UpgradeTheServer._doPrincipalCollectionInMemoryUpgrade()
+    
+    @staticmethod
+    def _doPrincipalCollectionInMemoryUpgrade():
+        
+        # Look for the /principals/ directory on disk
+        old_principals = os.path.join(config.DocumentRoot, "principals")
+        if os.path.exists(old_principals):
+            # First move the proxy database and rename it
+            UpgradeTheServer._doProxyDatabaseMoveUpgrade()
+        
+            # Now delete the on disk representation of principals
+            rmdir(old_principals)
+            log.info(
+                "Removed the old principal directory at '%s'."
+                % (old_principals,)
+            )
+
+    @staticmethod
+    def _doProxyDatabaseMoveUpgrade():
+        
+        # See if the old DB is present
+        old_db_path = os.path.join(config.DocumentRoot, "principals", CalendarUserProxyDatabase.dbOldFilename)
+        if not os.path.exists(old_db_path):
+            # Nothing to be done
+            return
+        
+        # See if the new one is already present
+        new_db_path = os.path.join(config.DataRoot, CalendarUserProxyDatabase.dbFilename)
+        if os.path.exists(new_db_path):
+            # We have a problem - both the old and new ones exist. Stop the server from starting
+            # up and alert the admin to this condition
+            raise UpgradeError(
+                "Upgrade Error: unable to move the old calendar user proxy database at '%s' to '%s' because the new database already exists."
+                % (old_db_path, new_db_path,)
+            )
+        
+        # Now move the old one to the new location
+        try:
+            os.rename(old_db_path, new_db_path)
+        except Exception, e:
+            raise UpgradeError(
+                "Upgrade Error: unable to move the old calendar user proxy database at '%s' to '%s' due to %s."
+                % (old_db_path, new_db_path, str(e))
+            )
+            
+        log.info(
+            "Moved the calendar user proxy database from '%s' to '%s'."
+            % (old_db_path, new_db_path,)
+        )
+
+class UpgradeError(RuntimeError):
+    """
+    Generic upgrade error.
+    """
+    pass
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20081106/799c82b9/attachment-0001.html>


More information about the calendarserver-changes mailing list