[CalendarServer-changes] [8637] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Feb 8 22:15:55 PST 2012
Revision: 8637
http://trac.macosforge.org/projects/calendarserver/changeset/8637
Author: sagen at apple.com
Date: 2012-02-08 22:15:53 -0800 (Wed, 08 Feb 2012)
Log Message:
-----------
Adds command line tool to inspect APN subscriptions
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/push/test/test_applepush.py
CalendarServer/trunk/txdav/common/datastore/file.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/common/icommondatastore.py
Added Paths:
-----------
CalendarServer/trunk/bin/calendarserver_manage_push
CalendarServer/trunk/calendarserver/tools/push.py
Added: CalendarServer/trunk/bin/calendarserver_manage_push
===================================================================
--- CalendarServer/trunk/bin/calendarserver_manage_push (rev 0)
+++ CalendarServer/trunk/bin/calendarserver_manage_push 2012-02-09 06:15:53 UTC (rev 8637)
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+
+##
+# Copyright (c) 2006-2012 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.
+##
+
+import sys
+
+#PYTHONPATH
+
+if __name__ == "__main__":
+ if "PYTHONPATH" in globals():
+ sys.path.insert(0, PYTHONPATH)
+ else:
+ try:
+ import _calendarserver_preamble
+ except ImportError:
+ sys.exc_clear()
+
+ from calendarserver.tools.push import main
+ main()
Property changes on: CalendarServer/trunk/bin/calendarserver_manage_push
___________________________________________________________________
Added: svn:executable
+ *
Modified: CalendarServer/trunk/calendarserver/push/test/test_applepush.py
===================================================================
--- CalendarServer/trunk/calendarserver/push/test/test_applepush.py 2012-02-09 00:42:41 UTC (rev 8636)
+++ CalendarServer/trunk/calendarserver/push/test/test_applepush.py 2012-02-09 06:15:53 UTC (rev 8637)
@@ -84,6 +84,11 @@
key2 = "/CalDAV/calendars.example.com/user02/calendar/"
timestamp2 = 3000
yield txn.addAPNSubscription(token, key2, timestamp2, uid)
+
+ subscriptions = (yield txn.apnSubscriptionsBySubscriber(uid))
+ self.assertTrue([token, key1, timestamp1] in subscriptions)
+ self.assertTrue([token, key2, timestamp2] in subscriptions)
+
yield txn.commit()
# Set up the service
Added: CalendarServer/trunk/calendarserver/tools/push.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/push.py (rev 0)
+++ CalendarServer/trunk/calendarserver/tools/push.py 2012-02-09 06:15:53 UTC (rev 8637)
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+##
+# Copyright (c) 2012 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 calendarserver.tap.util import getRootResource
+from calendarserver.tools.cmdline import utilityMain
+from errno import ENOENT, EACCES
+from getopt import getopt, GetoptError
+from twext.python.log import Logger
+from twisted.application.service import Service
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks
+from twistedcaldav.config import config, ConfigurationError
+import os
+import sys
+import time
+
+log = Logger()
+
+def usage(e=None):
+
+ name = os.path.basename(sys.argv[0])
+ print "usage: %s [options] [user ...]" % (name,)
+ print ""
+ print " Display Apple Push Notification subscriptions"
+ print ""
+ print "options:"
+ print " -h --help: print this help and exit"
+ print " -f --config <path>: Specify caldavd.plist configuration path"
+ print ""
+
+ if e:
+ sys.stderr.write("%s\n" % (e,))
+ sys.exit(64)
+ else:
+ sys.exit(0)
+
+
+class WorkerService(Service):
+
+ def __init__(self, store):
+ self._store = store
+
+ def rootResource(self):
+ try:
+ rootResource = getRootResource(config, self._store)
+ except OSError, e:
+ if e.errno == ENOENT:
+ # Trying to re-write resources.xml but its parent directory does
+ # not exist. The server's never been started, so we're missing
+ # state required to do any work. (Plus, what would be the point
+ # of purging stuff from a server that's completely empty?)
+ raise ConfigurationError(
+ "It appears that the server has never been started.\n"
+ "Please start it at least once before purging anything.")
+ elif e.errno == EACCES:
+ # Trying to re-write resources.xml but it is not writable by the
+ # current user. This most likely means we're in a system
+ # configuration and the user doesn't have sufficient privileges
+ # to do the other things the tool might need to do either.
+ raise ConfigurationError("You must run this tool as root.")
+ else:
+ raise
+ return rootResource
+
+
+ @inlineCallbacks
+ def startService(self):
+ try:
+ yield self.doWork()
+ except ConfigurationError, ce:
+ sys.stderr.write("Error: %s\n" % (str(ce),))
+ except Exception, e:
+ sys.stderr.write("Error: %s\n" % (e,))
+ raise
+ finally:
+ reactor.stop()
+
+
+class DisplayAPNSubscriptions(WorkerService):
+
+ users = []
+
+ def doWork(self):
+ rootResource = self.rootResource()
+ directory = rootResource.getDirectory()
+ return displayAPNSubscriptions(self._store, directory, rootResource,
+ self.users)
+
+
+def main():
+
+ try:
+ (optargs, args) = getopt(
+ sys.argv[1:], "f:h", [
+ "config=",
+ "help",
+ ],
+ )
+ except GetoptError, e:
+ usage(e)
+
+ #
+ # Get configuration
+ #
+ configFileName = None
+
+ for opt, arg in optargs:
+ if opt in ("-h", "--help"):
+ usage()
+
+ elif opt in ("-f", "--config"):
+ configFileName = arg
+
+ else:
+ raise NotImplementedError(opt)
+
+ if not args:
+ usage("Not enough arguments")
+
+
+ DisplayAPNSubscriptions.users = args
+
+ utilityMain(
+ configFileName,
+ DisplayAPNSubscriptions,
+ )
+
+
+
+
+ at inlineCallbacks
+def displayAPNSubscriptions(store, directory, root, users):
+ for user in users:
+ print
+ record = directory.recordWithShortName("users", user)
+ if record is not None:
+ print "User %s (%s)..." % (user, record.uid)
+ txn = store.newTransaction(label="Display APN Subscriptions")
+ subscriptions = (yield txn.apnSubscriptionsBySubscriber(record.uid))
+ (yield txn.commit())
+ if subscriptions:
+ byKey = { }
+ for token, key, timestamp in subscriptions:
+ byKey.setdefault(key, []).append((token, timestamp))
+ for key, tokens in byKey.iteritems():
+ print
+ protocol, host, path = key.strip("/").split("/", 2)
+ resource = {
+ "CalDAV" : "calendar",
+ "CardDAV" : "addressbook",
+ }[protocol]
+ if "/" in path:
+ uid, collection = path.split("/")
+ else:
+ uid = path
+ collection = None
+ record = directory.recordWithUID(uid)
+ user = record.shortNames[0]
+ if collection:
+ print "...is subscribed to a share from %s's %s home" % (user, resource),
+ else:
+ print "...is subscribed to %s's %s home" % (user, resource),
+ # print " (key: %s)\n" % (key,)
+ print "with %d device(s):" % (len(tokens),)
+ for token, timestamp in tokens:
+ print " %s %ss ago" % (token, int(time.time()) - timestamp)
+ else:
+ print " ...is not subscribed to anything."
+ else:
+ print "User %s not found" % (user,)
Property changes on: CalendarServer/trunk/calendarserver/tools/push.py
___________________________________________________________________
Added: svn:executable
+ *
Modified: CalendarServer/trunk/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/file.py 2012-02-09 00:42:41 UTC (rev 8636)
+++ CalendarServer/trunk/txdav/common/datastore/file.py 2012-02-09 06:15:53 UTC (rev 8637)
@@ -262,6 +262,9 @@
def apnSubscriptionsByKey(self, key):
return NotImplementedError
+ def apnSubscriptionsBySubscriber(self, guid):
+ return NotImplementedError
+
def isNotifiedAlready(self, obj):
return obj in self._notifiedAlready
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2012-02-09 00:42:41 UTC (rev 8636)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2012-02-09 06:15:53 UTC (rev 8637)
@@ -432,6 +432,17 @@
return self._apnSubscriptionsByKeyQuery.on(self, resourceKey=key)
+ @classproperty
+ def _apnSubscriptionsBySubscriberQuery(cls): #@NoSelf
+ apn = schema.APN_SUBSCRIPTIONS
+ return Select([apn.TOKEN, apn.RESOURCE_KEY, apn.MODIFIED],
+ From=apn, Where=apn.SUBSCRIBER_GUID == Parameter("subscriberGUID"))
+
+
+ def apnSubscriptionsBySubscriber(self, guid):
+ return self._apnSubscriptionsBySubscriberQuery.on(self, subscriberGUID=guid)
+
+
def postCommit(self, operation):
"""
Run things after C{commit}.
Modified: CalendarServer/trunk/txdav/common/icommondatastore.py
===================================================================
--- CalendarServer/trunk/txdav/common/icommondatastore.py 2012-02-09 00:42:41 UTC (rev 8636)
+++ CalendarServer/trunk/txdav/common/icommondatastore.py 2012-02-09 06:15:53 UTC (rev 8637)
@@ -215,6 +215,17 @@
@return: tuples of (token, guid)
"""
+ def apnSubscriptionsBySubscriber(guid):
+ """
+ Retrieve all subscription entries for the subscriber.
+
+ @param guid: The GUID of the subscribed principal
+ @type guid: C{str}
+
+ @return: tuples of (token, key, timestamp)
+ """
+
+
class IShareableCollection(Interface):
"""
A collection resource which may be shared.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120208/e851628f/attachment-0001.html>
More information about the calendarserver-changes
mailing list