[CalendarServer-changes] [543] CalendarServer/branches/caladmin-tool/caladmin

source_changes at macosforge.org source_changes at macosforge.org
Tue Nov 21 15:04:21 PST 2006


Revision: 543
          http://trac.macosforge.org/projects/calendarserver/changeset/543
Author:   dreid at apple.com
Date:     2006-11-21 15:04:20 -0800 (Tue, 21 Nov 2006)

Log Message:
-----------
update commands to not import their actions until they're actually called, this will speed up loading of everything.  Have script.py read in the config file merge it with the default and do some magic stuff. (this is probably broken if you actually specify --config.)  make purge with the new script and commands.

Modified Paths:
--------------
    CalendarServer/branches/caladmin-tool/caladmin/commands.py
    CalendarServer/branches/caladmin-tool/caladmin/purge.py
    CalendarServer/branches/caladmin-tool/caladmin/script.py

Modified: CalendarServer/branches/caladmin-tool/caladmin/commands.py
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/commands.py	2006-11-21 20:16:55 UTC (rev 542)
+++ CalendarServer/branches/caladmin-tool/caladmin/commands.py	2006-11-21 23:04:20 UTC (rev 543)
@@ -38,12 +38,8 @@
         yield [command.name, command.shortcut, command, command.help]
 
 
-# Some common parameter definitions
+from twisted.python import reflect
 
-PARAM_DOCROOT = ['docroot', 'D', '/Library/CalendarServer/Documents', 
-                 'Document root for the calendar server data to back up.']
-
-
 class SubCommand(usage.Options):
     name = None
     shortcut = None
@@ -52,76 +48,96 @@
 
     params = ()
 
+    def __init__(self):
+        self._action = reflect.namedAny(self.action)
+        usage.Options.__init__(self)
+
     def parseArgs(self, *rest):
         self.params += rest
 
     def postOptions(self):
-        self.action(self).run()
+        self._action(self).run()
 
 
-from twisted.internet import reactor
-from twisted.internet.defer import maybeDeferred
-from twisted.python.failure import Failure
+class QuotaOptions(SubCommand):
+    name = 'quotas'
+    help = 'Retrieve quota information for principals'
+    action = 'caladmin.quotas.QuotaAction'
+         
+    def __init__(self):
+        SubCommand.__init__(self)
 
-class TwistedSubCommand(SubCommand):
-    """Subcommand subclass that calls it's action's run method from within a 
-    reactor."""
+        self['types'] = []
 
-    def postOptions(self):
+    def opt_users(self):
+        """Show Quotas for user calendars.
+        """
+        
+        self['types'].append('users')
+    opt_u = opt_users
 
-        def _log(failure):
-            failure.printTraceback()
+    def opt_groups(self):
+        """Show Quotas for group calendars.
+        """
+        
+        self['types'].append('groups')
+    opt_g = opt_groups
 
-        def _runRun():
-            try:
-                d = maybeDeferred(self.action(self).run)
-                d.addErrback(_log).addBoth(lambda _: reactor.stop())
-            except:
-                failure = Failure()
-                failure.printTraceback()
+    def opt_resources(self):
+        """Show Quotas for resource calendars.
+        """
+        
+        self['types'].append('resources')
+    opt_r = opt_resources
 
-                reactor.stop()
 
+registerCommand(QuotaOptions)
 
-        reactor.callLater(0, _runRun)
-        reactor.run()
 
-
-from caladmin.users import UserAction
-
-class UserOptions(TwistedSubCommand):
+class UserOptions(SubCommand):
     name = 'users'
     help = 'Retrieve information about and perform actions on users.'
-    action = UserAction
+    action = 'caladmin.users.UserAction'
 
     optFlags = [
         ['list', '1', 'List only usernames, one per line.'],
-        ['disabled', 'd', 'Limit display to disabled users.']
+        ['disabled', 'd', 'Limit display to disabled users.'],
+        ['detailed', None, 'Detailed statistics for each account.'],
         ]
 
-    optParameters = [
-        ['server', 's', 'http://localhost:8008/', 
-         'The url of the calendar server to query for user information.'],
-        ['username', 'u', None, 
-         'The username to connect to the calendar server'],
-        ['password', 'p', None,
-         'The password'],
-        ]
-
 registerCommand(UserOptions)
 
 
-from purge import PurgeAction
-
 class PurgeOptions(SubCommand):
     name = 'purge'
     help = ('Keep your store from becoming unnecessarily large by purging '
             'old events.')
-    action = PurgeAction
+    action = 'caladmin.purge.PurgeAction'
 
     optParameters = [
         ['days', 'n', 30, 'Age threshold for purging events.'],
-        PARAM_DOCROOT
         ]
 
 registerCommand(PurgeOptions)
+
+
+class StatsOptions(SubCommand):
+    name = 'stats'
+    help = ('Overall usage statistics.')
+    action = 'caladmin.stats.StatsAction'
+
+
+registerCommand(StatsOptions)
+
+
+class LogOptions(SubCommand):
+    name = 'logs'
+    help = ('Gather and report useful information from the logfiles.')
+    action = 'caladmin.logs.LogAction'
+
+    optParameters = [
+        ['logfile', 'L', '/var/caldavd/server.log', 
+         'Path to the log file to analyze'],
+        ]
+
+registerCommand(LogOptions)

Modified: CalendarServer/branches/caladmin-tool/caladmin/purge.py
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/purge.py	2006-11-21 20:16:55 UTC (rev 542)
+++ CalendarServer/branches/caladmin-tool/caladmin/purge.py	2006-11-21 23:04:20 UTC (rev 543)
@@ -20,7 +20,7 @@
 
 import datetime, dateutil.tz
 
-def purge(collection, purgeDate):
+def purgeEvents(collection, purgeDate):
     """
     Recursively purge all events older than purgeDate.
 
@@ -34,37 +34,29 @@
 
     from twistedcaldav import ical
 
-    collection = os.path.abspath(collection)
-
     files = []
     directories = []
 
-    for child in os.listdir(collection):
-        if child == '.db.sqlite':
+    for child in collection.children():
+        if child.basename() == '.db.sqlite':
             continue
 
-        child = os.path.join(collection, child)
-
-        if os.path.isdir(child):
+        if child.isdir():
             directories.append(child)
 
-        elif os.path.isfile(child):
+        elif child.isfile():
             files.append(child)
 
     for directory in directories:
-        purge(directory, purgeDate)
+        purgeEvents(directory, purgeDate)
 
-    for fname in files:
-        f = open(fname)
-
+    for f in files:
         try:
-            component = ical.Component.fromStream(f)
+            component = ical.Component.fromStream(f.open())
         except ValueError:
             # Not a calendar file?
             continue
 
-        f.close()
-
         endDate = component.mainComponent().getEndDateUTC()
         
         if component.resourceType() == 'VTODO':
@@ -81,35 +73,27 @@
                 print "Purging %s, %s, %s" % (component.resourceType(), 
                                                component.resourceUID(), 
                                                endDate.isoformat())
-                os.remove(fname)
+                f.remove()
 
 
 class PurgeAction(object):
     def __init__(self, config):
         self.config = config
+        self.calendarCollection = config.parent.calendarCollection
 
     def run(self):
-        assert os.path.exists(self.config['docroot'])
-
-        calendarCollectionRoot = os.path.join(
-            os.path.abspath(self.config['docroot']),
-            'calendars')
-
         if self.config.params:
-            collections = [os.path.join(calendarCollectionRoot, p) 
+            collections = [self.calendarCollection.child(p) 
                            for p in self.config.params]
             
         else:
             collections = []
-
-            for type in os.listdir(calendarCollectionRoot):
-                tRoot = os.path.join(calendarCollectionRoot, type)
-
-                for collection in os.listdir(tRoot):
-                    collections.append(os.path.join(tRoot, collection))
-
+            
+            for type in self.calendarCollection.children():
+                collections.extend(type.children())
+                    
         purgeDate = datetime.date.today()
         purgeDate = purgeDate - datetime.timedelta(self.config['days'])
 
         for collection in collections:
-            purge(collection, purgeDate)
+            purgeEvents(collection, purgeDate)

Modified: CalendarServer/branches/caladmin-tool/caladmin/script.py
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/script.py	2006-11-21 20:16:55 UTC (rev 542)
+++ CalendarServer/branches/caladmin-tool/caladmin/script.py	2006-11-21 23:04:20 UTC (rev 543)
@@ -31,7 +31,10 @@
 import sys, os
 
 from twisted.python import usage
+from twisted.python import filepath
 
+from plistlib import readPlist
+
 from caladmin import commands
 from caladmin import formatters
 
@@ -40,18 +43,55 @@
     params = ()
 
     optParameters = [
-        ['format', 'f', 'plain', "Select an appropriate output formatter: %s" % (formatters.listFormatters())]
+        ['format', 'f', 'plain', ("Select an appropriate output formatter: "
+                                  "%s" % (formatters.listFormatters(),))]
         ]
 
+    def __init__(self):
+        usage.Options.__init__(self)
+
+        self.config = readPlist('/etc/caldavd/caldavd.plist.default')
+
+        self['config'] = '/etc/caldavd/caldavd.plist'
+
+        self.config.update(readPlist(self['config']))
+
+        self['root'] = self.config['DocumentRoot']
+        self.opt_root(self['root'])
+
+    def opt_config(self, path):
+        """Path to the caldavd.plist config file
+        [default: %s] 
+        """ % (self['config'],)
+
+        self.config = readPlist(self['config'])
+
+    def opt_root(self, path):
+        """Path to the root of the calendar server document store.
+        [default: %s] 
+        """ % (self['root'],)
+
+        self['root'] = filepath.FilePath(path)
+
     def parseArgs(self, *rest):
         self.params += rest
 
-    def subCommands(self):
-        return commands.genSubCommandsDef()
+    def parseOptions(self, options=None):
+        if not options:
+            options = ['--help']
 
-    subCommands = property(subCommands)
+        if options == ['--help']:
+            self.subCommands = commands.genSubCommandsDef()
+
+        usage.Options.parseOptions(self, options)
     
     def postOptions(self):
+        if self.recursing:
+            return
+
+        self.calendarCollection = self['root'].child('calendars')
+        self.principalCollection = self['root'].child('principals')
+
         lf = formatters.listFormatters()
         lf.sort()
 
@@ -61,12 +101,25 @@
             raise usage.UsageError("Please specify a valid formatter: %s" % (
                     ', '.join(lf)))
 
+        sc = commands.listCommands()
+        sc.sort()
+
+        self.subCommands = commands.genSubCommandsDef()
+
+        self.recursing = 1
+
+        self.parseOptions(self.params)
+
+        if self.subCommand not in sc:
+            raise usage.UsageError("Please select one of: %s" % (
+                    ', '.join(sc)))
+
     
 def run():
     config = AdminOptions()
 
     try:
-        config.parseOptions()
+        config.parseOptions(sys.argv[1:])
 
     except usage.UsageError, ue:
         print config

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20061121/289b69d4/attachment.html


More information about the calendarserver-changes mailing list