[CalendarServer-changes] [4020] CalendarServer/branches/users/sagen/deployment/bin/ caldav_addresschange
source_changes at macosforge.org
source_changes at macosforge.org
Tue Apr 14 15:22:23 PDT 2009
Revision: 4020
http://trac.macosforge.org/projects/calendarserver/changeset/4020
Author: sagen at apple.com
Date: 2009-04-14 15:22:22 -0700 (Tue, 14 Apr 2009)
Log Message:
-----------
CUA renaming tool (in progress)
Added Paths:
-----------
CalendarServer/branches/users/sagen/deployment/bin/caldav_addresschange
Added: CalendarServer/branches/users/sagen/deployment/bin/caldav_addresschange
===================================================================
--- CalendarServer/branches/users/sagen/deployment/bin/caldav_addresschange (rev 0)
+++ CalendarServer/branches/users/sagen/deployment/bin/caldav_addresschange 2009-04-14 22:22:22 UTC (rev 4020)
@@ -0,0 +1,334 @@
+#!/usr/bin/env python
+
+##
+# Copyright (c) 2006-2009 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.
+##
+
+"""
+This tool trawls through the server's data store, reading data.
+
+This is useful for ensuring that any on-demand data format upgrades
+are done.
+
+This tool requires access to the calendar server's configuration and
+data storage.
+"""
+
+from __future__ import with_statement
+
+import sys
+
+sys.path.insert(0, "/usr/share/caldavd/lib/python")
+
+import os
+import sqlite3
+import itertools
+
+from getopt import getopt, GetoptError
+from os.path import dirname, abspath
+
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, returnValue, succeed
+from twisted.python import log
+from twisted.python.reflect import namedClass
+from twisted.web2.dav import davxml
+
+from twistedcaldav import ical
+from twistedcaldav import caldavxml
+from twistedcaldav.resource import isPseudoCalendarCollectionResource
+from twistedcaldav.static import CalDAVFile, CalendarHomeFile
+from twistedcaldav.config import config, defaultConfigFile
+from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
+from twistedcaldav.method.put_common import storeCalendarObjectResource
+
+
+
+from twistedcaldav import memcachepool
+from twistedcaldav.notify import installNotificationClient
+from twisted.internet.address import IPv4Address
+
+
+def loadConfig(configFileName):
+ if configFileName is None:
+ configFileName = defaultConfigFile
+
+ if not os.path.isfile(configFileName):
+ sys.stderr.write("No config file: %s\n" % (configFileName,))
+ sys.exit(1)
+
+ config.loadConfig(configFileName)
+
+ return config
+
+def getDirectory():
+ BaseDirectoryService = namedClass(config.DirectoryService["type"])
+
+ class MyDirectoryService (BaseDirectoryService):
+ def getPrincipalCollection(self):
+ if not hasattr(self, "_principalCollection"):
+ #
+ # Instantiating a CalendarHomeProvisioningResource with a directory
+ # will register it with the directory (still smells like a hack).
+ #
+ # We need that in order to locate calendar homes via the directory.
+ #
+ from twistedcaldav.static import CalendarHomeProvisioningFile
+ CalendarHomeProvisioningFile(os.path.join(config.DocumentRoot, "calendars"), self, "/calendars/")
+
+ from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
+ self._principalCollection = DirectoryPrincipalProvisioningResource("/principals/", self)
+
+ return self._principalCollection
+
+ def setPrincipalCollection(self, coll):
+ # See principal.py line 237: self.directory.principalCollection = self
+ pass
+
+ principalCollection = property(getPrincipalCollection, setPrincipalCollection)
+
+ def calendarHomeForRecord(self, record):
+ principal = self.principalCollection.principalForRecord(record)
+ if principal:
+ try:
+ return principal._calendarHome()
+ except AttributeError:
+ pass
+ return None
+
+ def calendarHomeForShortName(self, recordType, shortName):
+ principal = self.principalCollection.principalForShortName(recordType, shortName)
+ if principal:
+ try:
+ return principal._calendarHome()
+ except AttributeError:
+ pass
+ return None
+
+ def principalForCalendarUserAddress(self, cua):
+ return self.principalCollection.principalForCalendarUserAddress(cua)
+
+
+ return MyDirectoryService(**config.DirectoryService["params"])
+
+class DummyDirectoryService (DirectoryService):
+ realmName = ""
+ baseGUID = "51856FD4-5023-4890-94FE-4356C4AAC3E4"
+ def recordTypes(self): return ()
+ def listRecords(self): return ()
+ def recordWithShortName(self): return None
+
+dummyDirectoryRecord = DirectoryRecord(
+ service = DummyDirectoryService(),
+ recordType = "dummy",
+ guid = "8EF0892F-7CB6-4B8E-B294-7C5A5321136A",
+ shortName = "dummy",
+ fullName = "Dummy McDummerson",
+ calendarUserAddresses = set(),
+ autoSchedule = False,
+)
+
+class UsageError (StandardError):
+ pass
+
+def usage(e=None):
+ if e:
+ print e
+ print ""
+
+ name = os.path.basename(sys.argv[0])
+ print "usage: %s [options] [input_specifiers]" % (name,)
+ print ""
+ print "Change calendar user addresses"
+ print __doc__
+ print "options:"
+ print " -h --help: print this help and exit"
+ print " -f --config: Specify caldavd.plist configuration path"
+ print ""
+ print "input specifiers:"
+ print " -c --changes: add all calendar homes"
+ print " --dry-run: Don't actually change the data"
+
+ if e:
+ sys.exit(64)
+ else:
+ sys.exit(0)
+
+def loadChanges(fileName):
+ addresses = {}
+ with open(fileName) as input:
+ count = 1
+ for line in input:
+ line = line.strip()
+ if line and not line.startswith("#"):
+ try:
+ oldAddr, newAddr = line.split()
+ addresses[oldAddr] = newAddr
+ except Exception, e:
+ print "Could not parse line %d: %s" % (count, line)
+ sys.exit(2)
+ count += 1
+ return addresses
+
+def main():
+ try:
+ (optargs, args) = getopt(
+ sys.argv[1:], "hf:c:", [
+ "config=",
+ "help",
+ "changes=",
+ "dry-run",
+ ],
+ )
+ except GetoptError, e:
+ usage(e)
+
+ configFileName = None
+ logFileName = "/dev/stdout"
+ modifyData = True
+ changesFile = None
+
+ directory = None
+ calendarHomePaths = set()
+ calendarHomes = set()
+
+ def checkExists(resource):
+ if not resource.exists():
+ sys.stderr.write("No such file: %s\n" % (resource.fp.path,))
+ sys.exit(1)
+
+ for opt, arg in optargs:
+ if opt in ("-h", "--help"):
+ usage()
+
+ elif opt in ("-f", "--config"):
+ configFileName = arg
+
+ elif opt in ("-c", "--changes"):
+ changesFile = arg
+
+ elif opt in ("--dry-run",):
+ modifyData = False
+
+ if args:
+ usage("Too many arguments: %s" % (" ".join(args),))
+
+ observer = log.FileLogObserver(open(logFileName, "a"))
+ log.addObserver(observer.emit)
+
+ if changesFile:
+ loadConfig(configFileName)
+ addresses = loadChanges(changesFile)
+ print addresses
+
+ directory = getDirectory()
+ if config.Memcached["ClientEnabled"]:
+ memcachepool.installPool(
+ IPv4Address(
+ 'TCP',
+ config.Memcached["BindAddress"],
+ config.Memcached["Port"]
+ ),
+ config.Memcached["MaxClients"]
+ )
+ if config.Notifications["Enabled"]:
+ installNotificationClient(
+ config.Notifications["InternalNotificationHost"],
+ config.Notifications["InternalNotificationPort"],
+ )
+
+
+ homesToFix = { }
+ homesFixed = { }
+
+ for oldAddress, newAddress in addresses.iteritems():
+ record = directory.recordWithCalendarUserAddress(newAddress)
+ if record is None:
+ # New address is not in the directory, perhaps the old one
+ # still is
+ record = directory.recordWithCalendarUserAddress(oldAddress)
+ if record is None:
+ print "Neither %s nor %s are in the directory" % (
+ oldAddress, newAddress
+ )
+ sys.exit(2)
+ else:
+ print "Found *old* address %s in the directory. Be sure to update the directory soon." % (oldAddress,)
+
+ print record
+ home = directory.calendarHomeForRecord(record)
+ homesToFix[record.guid] = home
+
+ print homesToFix
+
+ reactor.callLater(1, replaceAddresses, homesToFix, directory, addresses)
+ reactor.run()
+
+
+
+ at inlineCallbacks
+def replaceAddresses(homesToFix, directory, addresses):
+ for guid, home in homesToFix.iteritems():
+ try:
+ yield processCalendarHome(home, directory, addresses)
+ except Exception, e:
+ print "Failed to process calendar home", home
+ sys.exit(1)
+
+ reactor.stop()
+
+
+
+ at inlineCallbacks
+def processCalendarHome(calendarHome, directory, addresses):
+ print "Processing calendar home:", calendarHome
+
+ for childName in calendarHome.listChildren():
+ child = calendarHome.getChild(childName)
+ yield processCalendar(child, directory, addresses)
+
+ at inlineCallbacks
+def processCalendar(calendarCollection, directory, addresses):
+ print "Processing calendar collection:", calendarCollection
+
+ for name in calendarCollection.listChildren():
+ child = calendarCollection.getChild(name)
+ yield processEvent(child, directory, addresses)
+
+def processEvent(ics, directory, addresses):
+ event = ical.Component.fromString(ics.iCalendarText())
+
+ needsWriting = False
+ for component in event.subcomponents():
+ if component.name() == "VTIMEZONE":
+ continue
+ for prop in itertools.chain(
+ component.properties("ORGANIZER"),
+ component.properties("ATTENDEE"),
+ ):
+ cuaddr = prop.value()
+ if cuaddr in addresses:
+ prop.setValue(addresses[cuaddr])
+ print "Changing:", cuaddr, addresses[cuaddr]
+ needsWriting = True
+
+ if needsWriting:
+ # return storeCalendarObjectResource( ) # a deferred
+ returnValue(succeed)
+ else:
+ returnValue(succeed)
+
+
+if __name__ == "__main__":
+ main()
Property changes on: CalendarServer/branches/users/sagen/deployment/bin/caldav_addresschange
___________________________________________________________________
Added: svn:executable
+ *
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090414/a2619adc/attachment-0001.html>
More information about the calendarserver-changes
mailing list