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

source_changes at macosforge.org source_changes at macosforge.org
Wed Nov 22 09:38:15 PST 2006


Revision: 551
          http://trac.macosforge.org/projects/calendarserver/changeset/551
Author:   dreid at apple.com
Date:     2006-11-22 09:38:15 -0800 (Wed, 22 Nov 2006)

Log Message:
-----------
Rename commands.py to options.py so we can use the commands module in the stdlib.  Add a bunch of stats gathering stuff.  Move prepareValue to util.prepareByteValue and add support for -g

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

Added Paths:
-----------
    CalendarServer/branches/caladmin-tool/caladmin/options.py
    CalendarServer/branches/caladmin-tool/caladmin/stats.py
    CalendarServer/branches/caladmin-tool/caladmin/util.py

Removed Paths:
-------------
    CalendarServer/branches/caladmin-tool/caladmin/commands.py

Deleted: CalendarServer/branches/caladmin-tool/caladmin/commands.py
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/commands.py	2006-11-22 17:37:40 UTC (rev 550)
+++ CalendarServer/branches/caladmin-tool/caladmin/commands.py	2006-11-22 17:38:15 UTC (rev 551)
@@ -1,162 +0,0 @@
-##
-# Copyright (c) 2006 Apple Computer, 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.
-#
-# DRI: David Reid, dreid at apple.com
-##
-
-""" "pluggable" subcommands for the caladmin script
-"""
-
-from twisted.python import usage
-
-COMMANDS = {}
-
-def registerCommand(command):
-    COMMANDS[command.name] = command
-
-def listCommands():
-    return COMMANDS.keys()
-
-def genSubCommandsDef():
-    sc = listCommands()
-    sc.sort()
-
-    for name in sc:
-        command = COMMANDS[name]
-        yield [command.name, command.shortcut, command, command.help]
-
-
-from twisted.python import reflect
-
-class SubCommand(usage.Options):
-    name = None
-    shortcut = None
-    help = "FIXME"
-    action = None
-
-    params = ()
-
-    def parseArgs(self, *rest):
-        self.params += rest
-
-    def postOptions(self):
-        reflect.namedAny(self.action)(self).run()
-
-
-class QuotaOptions(SubCommand):
-    name = 'quotas'
-    help = 'Retrieve quota information for principals'
-    action = 'caladmin.quotas.QuotaAction'
-
-    optFlags = [
-        ['human', 'h', 'Display quota values in a human readable form.'],
-        ['megabytes', 'm', 'Display quota values in megabytes'],
-        ['kilobytes', 'k', 'Display quota values in kilobytes'],
-        ]
-         
-    def __init__(self):
-        SubCommand.__init__(self)
-
-        self['types'] = []
-
-    def opt_users(self):
-        """Show Quotas for user calendars.
-        """
-        
-        self['types'].append('users')
-    opt_u = opt_users
-
-    def opt_groups(self):
-        """Show Quotas for group calendars.
-        """
-        
-        self['types'].append('groups')
-    opt_g = opt_groups
-
-    def opt_resources(self):
-        """Show Quotas for resource calendars.
-        """
-        
-        self['types'].append('resources')
-    opt_r = opt_resources
-
-
-registerCommand(QuotaOptions)
-
-
-class UserOptions(SubCommand):
-    name = 'users'
-    help = 'Retrieve information about and perform actions on users.'
-    action = 'caladmin.users.UserAction'
-
-    optFlags = [
-        ['list', '1', 'List only usernames, one per line.'],
-        ['disabled', 'd', 'Limit display to disabled users.'],
-        ['detailed', None, 'Detailed statistics for each account.'],
-        ]
-
-registerCommand(UserOptions)
-
-
-class PurgeOptions(SubCommand):
-    name = 'purge'
-    help = ('Keep your store from becoming unnecessarily large by purging '
-            'old events.')
-    action = 'caladmin.purge.PurgeAction'
-
-    optParameters = [
-        ['days', 'n', 30, 'Age threshold for purging events.'],
-        ]
-
-registerCommand(PurgeOptions)
-
-
-class StatsOptions(SubCommand):
-    name = 'stats'
-    help = ('Overall usage statistics.')
-    action = 'caladmin.stats.StatsAction'
-
-
-registerCommand(StatsOptions)
-
-from twisted.python import filepath
-
-class LogOptions(SubCommand):
-    name = 'logs'
-    help = ('Gather and report useful information from the logfiles.')
-    action = 'caladmin.logs.LogAction'
-
-    def __init__(self):
-        SubCommand.__init__(self)
-
-        self['logfile'] = None
-
-    def opt_logfile(self, logfile):
-        """Path to the log file to be analyzed.
-        [default: /var/log/caldavd/server.log]
-        """ 
-
-        self['logfile'] = filepath.FilePath(logfile)
-
-    opt_l = opt_logfile
-
-    def postOptions(self):
-        if not self['logfile']:
-            self['logfile'] = filepath.FilePath(
-                self.parent.config['ServerLogFile'])
-
-        SubCommand.postOptions(self)
-
-registerCommand(LogOptions)

Copied: CalendarServer/branches/caladmin-tool/caladmin/options.py (from rev 549, CalendarServer/branches/caladmin-tool/caladmin/commands.py)
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/options.py	                        (rev 0)
+++ CalendarServer/branches/caladmin-tool/caladmin/options.py	2006-11-22 17:38:15 UTC (rev 551)
@@ -0,0 +1,175 @@
+##
+# Copyright (c) 2006 Apple Computer, 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.
+#
+# DRI: David Reid, dreid at apple.com
+##
+
+""" "pluggable" subcommands for the caladmin script
+"""
+
+from twisted.python import usage
+
+COMMANDS = {}
+
+def registerCommand(command):
+    COMMANDS[command.name] = command
+
+def listCommands():
+    return COMMANDS.keys()
+
+def genSubCommandsDef():
+    sc = listCommands()
+    sc.sort()
+
+    for name in sc:
+        command = COMMANDS[name]
+        yield [command.name, command.shortcut, command, command.help]
+
+
+from twisted.python import reflect
+
+class SubCommand(usage.Options):
+    name = None
+    shortcut = None
+    help = "FIXME"
+    action = None
+
+    params = ()
+
+    def parseArgs(self, *rest):
+        self.params += rest
+
+    def postOptions(self):
+        reflect.namedAny(self.action)(self).run()
+
+
+PARAM_HUMAN = ['human', 'h', 'Display byte values in a human readable form.']
+PARAM_MEGA = ['megabytes', 'm', 'Display byte values in megabytes']
+PARAM_KILO = ['kilobytes', 'k', 'Display byte values in kilobytes']
+PARAM_GIGA = ['gigabytes', 'g', 'Display byte values in gigabytes']
+
+
+class QuotaOptions(SubCommand):
+    name = 'quotas'
+    help = 'Retrieve quota information for principals'
+    action = 'caladmin.quotas.QuotaAction'
+
+    optFlags = [
+        PARAM_HUMAN,
+        PARAM_KILO,
+        PARAM_MEGA,
+        PARAM_GIGA,
+        ]
+         
+    def __init__(self):
+        SubCommand.__init__(self)
+
+        self['types'] = []
+
+    def opt_users(self):
+        """Show Quotas for user calendars.
+        """
+        
+        self['types'].append('users')
+    opt_u = opt_users
+
+    def opt_groups(self):
+        """Show Quotas for group calendars.
+        """
+        
+        self['types'].append('groups')
+    opt_g = opt_groups
+
+    def opt_resources(self):
+        """Show Quotas for resource calendars.
+        """
+        
+        self['types'].append('resources')
+    opt_r = opt_resources
+
+
+registerCommand(QuotaOptions)
+
+
+class UserOptions(SubCommand):
+    name = 'users'
+    help = 'Retrieve information about and perform actions on users.'
+    action = 'caladmin.users.UserAction'
+
+    optFlags = [
+        ['list', '1', 'List only usernames, one per line.'],
+        ['disabled', 'd', 'Limit display to disabled users.'],
+        ['detailed', None, 'Detailed statistics for each account.'],
+        ]
+
+registerCommand(UserOptions)
+
+
+class PurgeOptions(SubCommand):
+    name = 'purge'
+    help = ('Keep your store from becoming unnecessarily large by purging '
+            'old events.')
+    action = 'caladmin.purge.PurgeAction'
+
+    optParameters = [
+        ['days', 'n', 30, 'Age threshold for purging events.'],
+        ]
+
+registerCommand(PurgeOptions)
+
+
+class StatsOptions(SubCommand):
+    name = 'stats'
+    help = ('Overall usage statistics.')
+    action = 'caladmin.stats.StatsAction'
+
+    optFlags = [
+        PARAM_HUMAN,
+        PARAM_KILO,
+        PARAM_MEGA,
+        PARAM_GIGA,
+        ]
+
+registerCommand(StatsOptions)
+
+from twisted.python import filepath
+
+class LogOptions(SubCommand):
+    name = 'logs'
+    help = ('Gather and report useful information from the logfiles.')
+    action = 'caladmin.logs.LogAction'
+
+    def __init__(self):
+        SubCommand.__init__(self)
+
+        self['logfile'] = None
+
+    def opt_logfile(self, logfile):
+        """Path to the log file to be analyzed.
+        [default: /var/log/caldavd/server.log]
+        """ 
+
+        self['logfile'] = filepath.FilePath(logfile)
+
+    opt_l = opt_logfile
+
+    def postOptions(self):
+        if not self['logfile']:
+            self['logfile'] = filepath.FilePath(
+                self.parent.config['ServerLogFile'])
+
+        SubCommand.postOptions(self)
+
+registerCommand(LogOptions)

Modified: CalendarServer/branches/caladmin-tool/caladmin/quotas.py
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/quotas.py	2006-11-22 17:37:40 UTC (rev 550)
+++ CalendarServer/branches/caladmin-tool/caladmin/quotas.py	2006-11-22 17:38:15 UTC (rev 551)
@@ -21,6 +21,8 @@
 from twisted.web2.dav.resource import TwistedQuotaRootProperty, TwistedQuotaUsedProperty
 from twisted.web import microdom
 
+from caladmin.util import prepareByteValue
+
 quotaRoot = "WebDAV:" + TwistedQuotaRootProperty.sname().replace("/", "%2F")
 quotaUsed = "WebDAV:" + TwistedQuotaUsedProperty.sname().replace("/", "%2F")
 
@@ -56,29 +58,6 @@
         self.principalCollection = config.parent.principalCollection
         self.formatter = config.parent.formatter
 
-    def prepareValue(self, value):
-        if self.config['human']:
-            h = value/1024.0
-            if h < 1:
-                return '%d' % (value,)
-
-            h2 = h/1024.0
-            if h2 < 1:
-                return '%5.2fKB' % (h,)
-
-            return '%5.2fMB' % (h2,)
-
-        elif self.config['megabytes']:
-            M = value/1024.0/1024.0
-
-            return '%5.2fMB' % (M,)
-
-        elif self.config['kilobytes']:
-            K = value/1024.0
-            return '%5.2fKB' % (K,)
-
-        return value
-
     def getQuotaStats(self):
 
         defaultQuota = getQuotaRoot(self.calendarCollection)
@@ -116,9 +95,9 @@
 
                 yield (child.basename(),
                        type,
-                       self.prepareValue(childQuota),
-                       self.prepareValue(childUsed),
-                       self.prepareValue(childAvailable))
+                       prepareByteValue(self.config, childQuota),
+                       prepareByteValue(self.config, childUsed),
+                       prepareByteValue(self.config, childAvailable))
     
     def run(self):
         if not self.config['types']:

Modified: CalendarServer/branches/caladmin-tool/caladmin/script.py
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/script.py	2006-11-22 17:37:40 UTC (rev 550)
+++ CalendarServer/branches/caladmin-tool/caladmin/script.py	2006-11-22 17:38:15 UTC (rev 551)
@@ -35,7 +35,7 @@
 
 from plistlib import readPlist
 
-from caladmin import commands
+from caladmin import options
 from caladmin import formatters
 
 from twistedcaldav.caldavd import caldavd_defaults, caldavd
@@ -63,7 +63,7 @@
             options = ['--help']
 
         if options == ['--help']:
-            self.subCommands = commands.genSubCommandsDef()
+            self.subCommands = options.genSubCommandsDef()
 
         usage.Options.parseOptions(self, options)
     
@@ -96,10 +96,10 @@
             raise usage.UsageError("Please specify a valid formatter: %s" % (
                     ', '.join(lf)))
 
-        sc = commands.listCommands()
+        sc = options.listCommands()
         sc.sort()
 
-        self.subCommands = commands.genSubCommandsDef()
+        self.subCommands = options.genSubCommandsDef()
 
         self.recursing = 1
 

Added: CalendarServer/branches/caladmin-tool/caladmin/stats.py
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/stats.py	                        (rev 0)
+++ CalendarServer/branches/caladmin-tool/caladmin/stats.py	2006-11-22 17:38:15 UTC (rev 551)
@@ -0,0 +1,140 @@
+##
+# Copyright (c) 2006 Apple Computer, 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.
+#
+# DRI: David Reid, dreid at apple.com
+##
+
+"""
+Statisitcs Types:
+
+ Account Stats: 
+  # of calendars
+  # of events
+  # storage used (including things that don't count against quota?)
+  Last login?
+
+ Overall Stats:
+  # of accounts
+  # of calendars
+  # of events
+
+ Log Stats:
+  # Invitations sent per day/week/month
+  # bytes i/o
+  # requests
+  user agents
+
+"""
+import os
+import xattr
+import commands
+
+from twisted.web import microdom
+
+from caladmin.util import prepareByteValue
+
+def getResourceType(fp):
+    rt = 'WebDAV:{DAV:}resourcetype'
+    x = xattr.xattr(fp.path)
+    if not x.has_key(rt):
+        return None
+    
+    collection = False
+
+    type = None
+
+    dom = microdom.parseString(x[rt])
+    rt = microdom.getElementsByTagName(dom, 'resourcetype')
+
+    for child in rt[0].childNodes:
+        if child.tagName == 'collection':
+            collection = True
+        else:
+            type = child.tagName
+
+    return (collection, type)
+        
+
+class StatsAction(object):
+    def __init__(self, config):
+        self.config = config
+        self.formatter = self.config.parent.formatter
+        self.root = self.config.parent.root
+        self.calendarCollection = self.config.parent.calendarCollection
+        self.principalCollection = self.config.parent.principalCollection
+        
+        self.gatherers = [
+            self.getAccountCount,
+            self.getGroupCount,
+            self.getResourceCount,
+            self.getCalendarCount,
+            self.getEventCount,
+            self.getDiskUsage]
+
+    def getDiskUsage(self):
+        output = commands.getoutput(' '.join(
+                ['/usr/bin/du', '-s', self.root.path]))
+
+        return ("Disk Usage", prepareByteValue(self.config,
+                                               int(output.split()[0])))
+
+    def _getPrincipalList(self, type):
+        typeRoot = self.principalCollection.child(type)
+        assert typeRoot.exists()
+        
+        pl = []
+        
+        for child in typeRoot.listdir():
+            if child not in ['.db.sqlite']:
+                pl.append(child)
+
+        return pl
+
+    def getAccountCount(self):
+        return ("# Accounts", len(self._getPrincipalList('users')))
+
+    def getGroupCount(self):
+        return ("# Groups", len(self._getPrincipalList('groups')))
+
+    def getResourceCount(self):
+        return ("# Resources", len(self._getPrincipalList('resources')))
+
+    def getEventCount(self):
+        return ("# Events", 0)
+
+    def getCalendarCount(self):
+        count = 0
+        for child in self.calendarCollection.walk():
+            if child.isdir():
+                if getResourceType(child) == (True, 'calendar'):
+                    count += 1
+
+        return ("# Calendars", count)
+
+    def printStatistics(self, head, stats):
+        self.formatter.printRow([head], 16)
+
+        for stat in stats:
+            self.formatter.printRow(stat, 16)
+
+    def run(self):
+        assert self.root.exists()
+        stats = []
+
+        for gatherer in self.gatherers:
+            stats.append(gatherer())
+
+        self.printStatistics("Overall Statistics", stats)
+

Added: CalendarServer/branches/caladmin-tool/caladmin/util.py
===================================================================
--- CalendarServer/branches/caladmin-tool/caladmin/util.py	                        (rev 0)
+++ CalendarServer/branches/caladmin-tool/caladmin/util.py	2006-11-22 17:38:15 UTC (rev 551)
@@ -0,0 +1,49 @@
+##
+# Copyright (c) 2006 Apple Computer, 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.
+#
+# DRI: David Reid, dreid at apple.com
+##
+
+def prepareByteValue(config, value):
+    if config['human']:
+        KB = value/1024.0
+        if KB < 1:
+            return '%d' % (value,)
+
+        MB = KB/1024.0
+        if MB < 1:
+            return '%5.2fKB' % (KB,)
+
+        GB = MB/1024.0
+        if GB < 1:
+            return '%5.2fMB' % (MB,)
+
+        return '%5.2fGB' % (GB,)
+
+    elif config['gigabytes']:
+        G = value/1024.0/1024.0/1024.0
+
+        return '%5.2fGB' % (G,)
+
+    elif config['megabytes']:
+        M = value/1024.0/1024.0
+
+        return '%5.2fMB' % (M,)
+
+    elif config['kilobytes']:
+        K = value/1024.0
+        return '%5.2fKB' % (K,)
+
+    return value

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20061122/80a13007/attachment.html


More information about the calendarserver-changes mailing list