[CalendarServer-changes] [7308] CalendarServer/branches/users/cdaboo/pods
source_changes at macosforge.org
source_changes at macosforge.org
Mon Apr 11 12:19:28 PDT 2011
Revision: 7308
http://trac.macosforge.org/projects/calendarserver/changeset/7308
Author: cdaboo at apple.com
Date: 2011-04-11 12:19:28 -0700 (Mon, 11 Apr 2011)
Log Message:
-----------
Checkpoint. Multi-server implementation in place and tested with single server.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/pods/calendarserver/provision/root.py
CalendarServer/branches/users/cdaboo/pods/calendarserver/tools/manageaugments.py
CalendarServer/branches/users/cdaboo/pods/conf/auth/augments.dtd
CalendarServer/branches/users/cdaboo/pods/conf/caldavd-partitioning-primary.plist
CalendarServer/branches/users/cdaboo/pods/conf/caldavd-partitioning-secondary.plist
CalendarServer/branches/users/cdaboo/pods/contrib/migration/calendarmigrator.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/augment.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/common.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/directory.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/idirectory.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/principal.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/resource.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/augments-test-default.xml
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/augments-test.xml
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/test_augment.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/xmlaugmentsparser.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/addressmapping.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/caldav.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/cuaddress.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/implicit.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/ischedule.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/scheduler.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/stdconfig.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/test/test_config.py
Added Paths:
-----------
CalendarServer/branches/users/cdaboo/pods/conf/servers-test.xml
CalendarServer/branches/users/cdaboo/pods/conf/servers.dtd
CalendarServer/branches/users/cdaboo/pods/conf/servers.xml
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/servers.py
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/test/test_servers.py
Removed Paths:
-------------
CalendarServer/branches/users/cdaboo/pods/calendarserver/tools/makepartition.py
CalendarServer/branches/users/cdaboo/pods/conf/partitions-test.plist
CalendarServer/branches/users/cdaboo/pods/conf/partitions.plist
CalendarServer/branches/users/cdaboo/pods/twistedcaldav/partitions.py
Modified: CalendarServer/branches/users/cdaboo/pods/calendarserver/provision/root.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/calendarserver/provision/root.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/calendarserver/provision/root.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -345,13 +345,12 @@
))
# Look for forwarding
- if config.Partitioning.Enabled:
- remote_ip = request.headers.getRawHeaders('x-forwarded-for')
- if remote_ip and len(remote_ip) == 1:
- request.forwarded_for = remote_ip[0]
- if not hasattr(request, "extendedLogItems"):
- request.extendedLogItems = {}
- request.extendedLogItems["xff"] = remote_ip[0]
+ remote_ip = request.headers.getRawHeaders('x-forwarded-for')
+ if remote_ip and len(remote_ip) == 1:
+ request.forwarded_for = remote_ip[0]
+ if not hasattr(request, "extendedLogItems"):
+ request.extendedLogItems = {}
+ request.extendedLogItems["xff"] = remote_ip[0]
if request.method == "PROPFIND" and not getattr(request, "notInCache", False) and len(segments) > 1:
try:
Deleted: CalendarServer/branches/users/cdaboo/pods/calendarserver/tools/makepartition.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/calendarserver/tools/makepartition.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/calendarserver/tools/makepartition.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -1,178 +0,0 @@
-#!/usr/bin/env python
-##
-# Copyright (c) 2010 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 optparse import OptionParser
-from twext.python.plistlib import readPlist, writePlist
-import os
-import sys
-from twistedcaldav.config import ConfigurationError, Config
-from twistedcaldav.stdconfig import PListConfigProvider, DEFAULT_CONFIG
-from urlparse import urlparse
-
-def error(s):
- print s
- sys.exit(1)
-
-def createPrimary(options):
- _createNode(options, True)
- print "Created primary partition with node id '%s' and uri '%s'" % (options.nodeid, options.nodeurl,)
-
-def createSecondary(options):
- _createNode(options, False)
- print "Created secondary partition with node id '%s' and uri '%s'" % (options.nodeid, options.nodeurl,)
-
-def _createNode(options, isPrimary):
-
- # Read in main plist
- try:
- dataDict = readPlist(options.conf)
- except (IOError, OSError):
- raise RuntimeError("Main plist file does not exist or is inaccessible: %s" % (options.conf,))
-
- # Look for includes
- includes = dataDict.setdefault("Includes", [])
-
- # Make sure partitioning plist is included
- primaryPlist = "caldavd-partitioning-primary.plist"
- secondaryPlist = "caldavd-partitioning-secondary.plist"
- partitioningPlistAdd = os.path.join(
- os.path.dirname(options.conf),
- primaryPlist if isPrimary else secondaryPlist,
- )
- partitioningPlistRemove = os.path.join(
- os.path.dirname(options.conf),
- secondaryPlist if isPrimary else primaryPlist,
- )
- if partitioningPlistAdd not in includes:
- includes.append(partitioningPlistAdd)
- if partitioningPlistRemove in includes:
- includes.remove(partitioningPlistRemove)
-
- # Push out main plist change
- try:
- writePlist(dataDict, options.conf)
- except (IOError, OSError):
- raise RuntimeError("Could not write main plist file: %s" % (options.conf,))
-
- # Now edit partitioning plist
- try:
- dataDict = readPlist(partitioningPlistAdd)
- except (IOError, OSError):
- raise RuntimeError("Partitioning plist file does not exist or is inaccessible: %s" % (partitioningPlistAdd,))
-
- # Need to adjust the node id, and host names
- dataDict["Partitioning"]["ServerPartitionID"] = options.nodeid
-
- if not isPrimary:
- _ignore_scheme, netloc, _ignore_path, _ignore_params, _ignore_query, _ignore_fragment = urlparse(options.primaryurl)
- if ':' in netloc:
- host = netloc.split(':')[0]
- else:
- host = netloc
- dataDict["ProxyDBService"]["params"]["host"] = host
- dataDict["Memcached"]["Pools"]["CommonToAllNodes"]["BindAddress"] = host
-
- # Push out partitioning plist change
- try:
- writePlist(dataDict, partitioningPlistAdd)
- except (IOError, OSError):
- raise RuntimeError("Could not write partitioning plist file: %s" % (partitioningPlistAdd,))
-
-def addOther(options):
- _addOther(options.conf, options.nodeid, options.nodeurl)
- print "Added partition with node id '%s' and uri '%s' to partitions plist" % (options.nodeid, options.nodeurl,)
-
-def _addOther(conf, nodeid, nodeurl):
-
- # Read main plist
- try:
- cfg = Config(PListConfigProvider(DEFAULT_CONFIG))
- cfg.load(conf)
- except ConfigurationError:
- raise RuntimeError("Could not parse as plist: '%s'" % (conf,))
-
- # Read in the partitions plist
- partitionsPlist = cfg.Partitioning.PartitionConfigFile
- try:
- dataDict = readPlist(partitionsPlist)
- except (IOError, OSError):
- raise RuntimeError("Partitions plist file does not exist or is inaccessible: %s" % (partitionsPlist,))
-
- # See if node id already exists
- if nodeid in [partition.get("uid", None) for partition in dataDict.get("partitions", ())]:
- raise RuntimeError("Node '%s' already in partitions plist '%s'" % (nodeid, partitionsPlist,))
-
- # Add new information and write it out
- dataDict.setdefault("partitions", []).append(
- {
- "uid": nodeid,
- "url": nodeurl,
- }
- )
- try:
- writePlist(dataDict, partitionsPlist)
- except (IOError, OSError):
- raise RuntimeError("Could not write partitions plist: %s" % (partitionsPlist,))
-
-def main():
-
- usage = "%prog [options] MODE"
- epilog = """
-MODE is one of primary|secondary|add
-
- primary: Create a new primary node (manages main DBs)
- secondary: Create a new secondary node
- add: Add information for a new partition node on another machine
-"""
- description = "Tool to setup CalendarServer partition node configuration files"
- version = "%prog v1.0"
- parser = OptionParser(usage=usage, description=description, version=version)
- parser.epilog = epilog
- parser.format_epilog = lambda _:epilog
-
- parser.add_option("-c", "--conf", dest="conf",
- help="Directory where .plist files are stored", metavar="CONF")
- parser.add_option("-n", "--nodeid", dest="nodeid",
- help="Node ID for this node", metavar="NODEID")
- parser.add_option("-u", "--url", dest="nodeurl",
- help="URL of node being added", metavar="NODEURL")
- parser.add_option("-p", "--primary", dest="primaryurl",
- help="URL of primary node", metavar="PRIMARYURL")
-
- (options, args) = parser.parse_args()
-
- if len(args) != 1:
- parser.error("incorrect number of arguments")
-
- # Make sure conf dir has the needed .plist files
- if not os.path.exists(options.conf):
- parser.error("Could not find '%s'" % (options.conf,))
- confdir = os.path.dirname(options.conf)
- if not os.path.exists(os.path.join(confdir, "caldavd-partitioning-primary.plist")):
- parser.error("Could not find caldavd-partitioning-primary.plist in '%s'" % (confdir,))
- if not os.path.exists(os.path.join(confdir, "caldavd-partitioning-secondary.plist")):
- parser.error("Could not find caldavd-partitioning-secondary.plist in '%s'" % (confdir,))
-
- # Handle each action
- {
- "primary" : createPrimary,
- "secondary": createSecondary,
- "add" : addOther,
- }[args[0]](options)
-
-if __name__ == '__main__':
- main()
Modified: CalendarServer/branches/users/cdaboo/pods/calendarserver/tools/manageaugments.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/calendarserver/tools/manageaugments.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/calendarserver/tools/manageaugments.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -1,6 +1,6 @@
#!/usr/bin/env python
##
-# Copyright (c) 2009-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2011 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.
@@ -57,13 +57,15 @@
help="OD GUID to manipulate", metavar="UID")
parser.add_option("-i", "--uidfile", dest="uidfile",
help="File containing a list of GUIDs to manipulate", metavar="UIDFILE")
- parser.add_option("-n", "--node", dest="node",
- help="Partition node to assign to UID", metavar="NODE")
+ parser.add_option("-s", "--server", dest="serverID",
+ help="Server id to assign to UID", metavar="SERVER")
+ parser.add_option("-p", "--partition", dest="partitionID",
+ help="Partition id to assign to UID", metavar="PARTITION")
parser.add_option("-c", "--enable-calendar", action="store_true", dest="enable_calendar",
default=True, help="Enable calendaring for this UID: %default")
parser.add_option("-a", "--enable-addressbooks", action="store_true", dest="enable_addressbook",
default=True, help="Enable calendaring for this UID: %default")
- parser.add_option("-s", "--auto-schedule", action="store_true", dest="auto_schedule",
+ parser.add_option("-x", "--auto-schedule", action="store_true", dest="auto_schedule",
default=False, help="Enable auto-schedule for this UID: %default")
(options, args) = parser.parse_args()
@@ -104,7 +106,8 @@
return AugmentRecord(
uid = uid,
enabled = True,
- hostedAt = options.node,
+ serverID = options.serverID,
+ partitionID = options.partitionID,
enabledForCalendaring = options.enable_calendar,
enabledForAddressBooks = options.enable_addressbook,
autoSchedule = options.auto_schedule,
@@ -125,8 +128,6 @@
uids.append(line[:-1])
if args[0] == "add":
- if not options.node:
- parser.error("Partition node must be specified when adding")
yield augment.AugmentService.addAugmentRecords([makeRecord(uid, options) for uid in uids])
for uid in uids:
print "Added uid '%s' to augment database" % (uid,)
Modified: CalendarServer/branches/users/cdaboo/pods/conf/auth/augments.dtd
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/conf/auth/augments.dtd 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/conf/auth/augments.dtd 2011-04-11 19:19:28 UTC (rev 7308)
@@ -16,12 +16,13 @@
<!ELEMENT augments (record*) >
- <!ELEMENT record (uid, enable, hosted-at?, enable-calendar?, enable-addressbook?, auto-schedule?)>
+ <!ELEMENT record (uid, enable, (server-id, partition-id?)?, enable-calendar?, enable-addressbook?, auto-schedule?)>
<!ATTLIST record repeat CDATA "1">
<!ELEMENT uid (#PCDATA)>
<!ELEMENT enable (#PCDATA)>
- <!ELEMENT hosted-at (#PCDATA)>
+ <!ELEMENT server-id (#PCDATA)>
+ <!ELEMENT partition-id (#PCDATA)>
<!ELEMENT enable-calendar (#PCDATA)>
<!ELEMENT enable-addressbook (#PCDATA)>
<!ELEMENT auto-schedule (#PCDATA)>
Modified: CalendarServer/branches/users/cdaboo/pods/conf/caldavd-partitioning-primary.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/conf/caldavd-partitioning-primary.plist 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/conf/caldavd-partitioning-primary.plist 2011-04-11 19:19:28 UTC (rev 7308)
@@ -20,18 +20,18 @@
<plist version="1.0">
<dict>
- <!-- Partitioning -->
- <key>Partitioning</key>
+ <!-- Servers -->
+ <key>Servers</key>
<dict>
<key>Enabled</key>
<true/>
- <key>ServerPartitionID</key>
- <string>00001</string>
- <key>PartitionConfigFile</key>
- <string>partitions.plist</string>
+ <key>ConfigFile</key>
+ <string>servers.xml</string>
<key>MaxClients</key>
<integer>5</integer>
</dict>
+ <key>ServerPartitionID</key>
+ <string>00001</string>
<!-- PostgreSQL ProxyDB Service -->
<key>ProxyDBService</key>
Modified: CalendarServer/branches/users/cdaboo/pods/conf/caldavd-partitioning-secondary.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/conf/caldavd-partitioning-secondary.plist 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/conf/caldavd-partitioning-secondary.plist 2011-04-11 19:19:28 UTC (rev 7308)
@@ -20,18 +20,18 @@
<plist version="1.0">
<dict>
- <!-- Partitioning -->
- <key>Partitioning</key>
+ <!-- Servers -->
+ <key>Servers</key>
<dict>
<key>Enabled</key>
<true/>
- <key>ServerPartitionID</key>
- <string>00002</string>
- <key>PartitionConfigFile</key>
- <string>partitions.plist</string>
+ <key>ConfigFile</key>
+ <string>servers.xml</string>
<key>MaxClients</key>
<integer>5</integer>
</dict>
+ <key>ServerPartitionID</key>
+ <string>00002</string>
<!-- PostgreSQL ProxyDB Service -->
<key>ProxyDBService</key>
Deleted: CalendarServer/branches/users/cdaboo/pods/conf/partitions-test.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/conf/partitions-test.plist 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/conf/partitions-test.plist 2011-04-11 19:19:28 UTC (rev 7308)
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- Copyright (c) 2009-2010 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.
- -->
-
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>partitions</key>
- <array>
- <dict>
- <key>uid</key>
- <string>00001</string>
- <key>url</key>
- <string>http://localhost:8008</string>
- </dict>
- <dict>
- <key>uid</key>
- <string>00002</string>
- <key>url</key>
- <string>http://localhost:8108</string>
- </dict>
- </array>
-</dict>
-</plist>
Deleted: CalendarServer/branches/users/cdaboo/pods/conf/partitions.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/conf/partitions.plist 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/conf/partitions.plist 2011-04-11 19:19:28 UTC (rev 7308)
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- Copyright (c) 2009-2010 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.
- -->
-
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>partitions</key>
- <array>
- <!--
- <dict>
- <key>uid</key>
- <string>00001</string>
- <key>url</key>
- <string>http://localhost:8008</string>
- </dict>
- -->
- </array>
-</dict>
-</plist>
Added: CalendarServer/branches/users/cdaboo/pods/conf/servers-test.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/conf/servers-test.xml (rev 0)
+++ CalendarServer/branches/users/cdaboo/pods/conf/servers-test.xml 2011-04-11 19:19:28 UTC (rev 7308)
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2011 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.
+ -->
+
+<!DOCTYPE servers SYSTEM "servers.dtd">
+
+<servers>
+ <server>
+ <id>00001</id>
+ <uri>http://localhost:8008</uri>
+ <partitions>
+ <partition>
+ <id>00001</id>
+ <uri>http://localhost:8008</uri>
+ </partition>
+ <partition>
+ <id>00002</id>
+ <uri>http://localhost:8108</uri>
+ </partition>
+ </partitions>
+ </server>
+</servers>
Added: CalendarServer/branches/users/cdaboo/pods/conf/servers.dtd
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/conf/servers.dtd (rev 0)
+++ CalendarServer/branches/users/cdaboo/pods/conf/servers.dtd 2011-04-11 19:19:28 UTC (rev 7308)
@@ -0,0 +1,25 @@
+<!--
+Copyright (c) 2011 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.
+-->
+
+<!ELEMENT servers (server*) >
+
+ <!ELEMENT server (id, uri, partitions?) >
+
+ <!ELEMENT id (#PCDATA) >
+ <!ELEMENT uri (#PCDATA) >
+
+ <!ELEMENT partitions (partition*) >
+ <!ELEMENT partition (id, uri) >
Added: CalendarServer/branches/users/cdaboo/pods/conf/servers.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/conf/servers.xml (rev 0)
+++ CalendarServer/branches/users/cdaboo/pods/conf/servers.xml 2011-04-11 19:19:28 UTC (rev 7308)
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2011 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.
+ -->
+
+<!DOCTYPE servers SYSTEM "servers.dtd">
+
+<servers>
+ <!--
+ <server>
+ <id>A</id>
+ <uri>https://caldav1.example.com:8843</uri>
+ </server>
+ <server>
+ <id>B</id>
+ <uri>https://caldav2.example.com:8843</uri>
+ <partitions>
+ <partition>
+ <id>00001</id>
+ <url>https://machine1.example.com:8443</url>
+ </partition>
+ <partition>
+ <id>00002</id>
+ <url>https://machine2.example.com:8443</url>
+ </partition>
+ </partitions>
+ </server>
+ -->
+</servers>
Modified: CalendarServer/branches/users/cdaboo/pods/contrib/migration/calendarmigrator.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/contrib/migration/calendarmigrator.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/contrib/migration/calendarmigrator.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -106,7 +106,6 @@
Memcached
MultiProcess
Notifications
-Partitioning
Postgres
ProcessType
Profiling
@@ -127,6 +126,8 @@
Scheduling
ServerHostName
ServerRoot
+Servers
+ServerPartitionID
Sharing
SudoersFile
Twisted
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/augment.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/augment.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/augment.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2009-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2011 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.
@@ -44,14 +44,16 @@
self,
uid,
enabled=False,
- hostedAt="",
+ serverID="",
+ partitionID="",
enabledForCalendaring=False,
autoSchedule=False,
enabledForAddressBooks=False,
):
self.uid = uid
self.enabled = enabled
- self.hostedAt = hostedAt
+ self.serverID = serverID
+ self.partitionID = partitionID
self.enabledForCalendaring = enabledForCalendaring
self.enabledForAddressBooks = enabledForAddressBooks
self.autoSchedule = autoSchedule
@@ -296,13 +298,7 @@
_ignore_etree, augments_node = newElementTreeWithRoot(xmlaugmentsparser.ELEMENT_AUGMENTS)
for record in self.db.itervalues():
- record_node = addSubElement(augments_node, xmlaugmentsparser.ELEMENT_RECORD)
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_UID, record.uid)
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLE, "true" if record.enabled else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_HOSTEDAT, record.hostedAt)
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLECALENDAR, "true" if record.enabledForCalendaring else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLEADDRESSBOOK, "true" if record.enabledForAddressBooks else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_AUTOSCHEDULE, "true" if record.autoSchedule else "false")
+ self._addRecordToXMLDB(record, augments_node)
writeXML(xmlfile, augments_node)
@@ -328,13 +324,7 @@
# Create new record
for record in records:
- record_node = addSubElement(augments_node, xmlaugmentsparser.ELEMENT_RECORD)
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_UID, record.uid)
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLE, "true" if record.enabled else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_HOSTEDAT, record.hostedAt)
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLECALENDAR, "true" if record.enabledForCalendaring else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLEADDRESSBOOK, "true" if record.enabledForAddressBooks else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_AUTOSCHEDULE, "true" if record.autoSchedule else "false")
+ self._addRecordToXMLDB(record, augments_node)
# Modify xmlfile
writeXML(xmlfile, augments_node)
@@ -360,16 +350,9 @@
if uid in recordMap:
# Modify record
record = recordMap[uid]
- del record_node.getchildren()[:]
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_UID, record.uid)
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLE, "true" if record.enabled else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_HOSTEDAT, record.hostedAt)
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLECALENDAR, "true" if record.enabledForCalendaring else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLEADDRESSBOOK, "true" if record.enabledForAddressBooks else "false")
- addSubElement(record_node, xmlaugmentsparser.ELEMENT_AUTOSCHEDULE, "true" if record.autoSchedule else "false")
+ self._updateRecordInXMLDB(record, record_node)
changed = True
-
-
+
# Modify xmlfile
if changed:
writeXML(xmlfile, augments_node)
@@ -416,6 +399,21 @@
if changed:
writeXML(xmlfile, augments_node)
+
+ def _addRecordToXMLDB(self, record, parentNode):
+ record_node = addSubElement(parentNode, xmlaugmentsparser.ELEMENT_RECORD)
+ self._updateRecordInXMLDB(record, record_node)
+
+ def _updateRecordInXMLDB(self, record, recordNode):
+ del recordNode.getchildren()[:]
+ addSubElement(recordNode, xmlaugmentsparser.ELEMENT_UID, record.uid)
+ addSubElement(recordNode, xmlaugmentsparser.ELEMENT_ENABLE, "true" if record.enabled else "false")
+ addSubElement(recordNode, xmlaugmentsparser.ELEMENT_SERVERID, record.serverID)
+ addSubElement(recordNode, xmlaugmentsparser.ELEMENT_PARTITIONID, record.partitionID)
+ addSubElement(recordNode, xmlaugmentsparser.ELEMENT_ENABLECALENDAR, "true" if record.enabledForCalendaring else "false")
+ addSubElement(recordNode, xmlaugmentsparser.ELEMENT_ENABLEADDRESSBOOK, "true" if record.enabledForAddressBooks else "false")
+ addSubElement(recordNode, xmlaugmentsparser.ELEMENT_AUTOSCHEDULE, "true" if record.autoSchedule else "false")
+
def refresh(self):
"""
Refresh any cached data.
@@ -493,9 +491,6 @@
def __init__(self, dbID, dbapiName, dbapiArgs, **kwargs):
AugmentDB.__init__(self)
- self.cachedPartitions = {}
- self.cachedHostedAt = {}
-
AbstractADBAPIDatabase.__init__(self, dbID, dbapiName, dbapiArgs, True, **kwargs)
@inlineCallbacks
@@ -522,16 +517,17 @@
"""
# Query for the record information
- results = (yield self.query("select UID, ENABLED, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE from AUGMENTS where UID = :1", (uid,)))
+ results = (yield self.query("select UID, ENABLED, SERVERID, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE from AUGMENTS where UID = :1", (uid,)))
if not results:
returnValue(None)
else:
- uid, enabled, partitionid, enabledForCalendaring, enabledForAddressBooks, autoSchedule = results[0]
+ uid, enabled, serverid, partitionid, enabledForCalendaring, enabledForAddressBooks, autoSchedule = results[0]
record = AugmentRecord(
uid = uid,
enabled = enabled == "T",
- hostedAt = (yield self._getPartition(partitionid)),
+ serverID = serverid,
+ partitionID = partitionid,
enabledForCalendaring = enabledForCalendaring == "T",
enabledForAddressBooks = enabledForAddressBooks == "T",
autoSchedule = autoSchedule == "T",
@@ -565,35 +561,6 @@
return self.execute("delete from AUGMENTS", ())
- @inlineCallbacks
- def _getPartitionID(self, hostedat, createIfMissing=True):
-
- # We will use a cache for these as we do not expect changes whilst running
- try:
- returnValue(self.cachedHostedAt[hostedat])
- except KeyError:
- pass
-
- partitionid = (yield self.queryOne("select PARTITIONID from PARTITIONS where HOSTEDAT = :1", (hostedat,)))
- if partitionid == None:
- yield self.execute("insert into PARTITIONS (HOSTEDAT) values (:1)", (hostedat,))
- partitionid = (yield self.queryOne("select PARTITIONID from PARTITIONS where HOSTEDAT = :1", (hostedat,)))
- self.cachedHostedAt[hostedat] = partitionid
- returnValue(partitionid)
-
- @inlineCallbacks
- def _getPartition(self, partitionid):
-
- # We will use a cache for these as we do not expect changes whilst running
- try:
- returnValue(self.cachedPartitions[partitionid])
- except KeyError:
- pass
-
- partition = (yield self.queryOne("select HOSTEDAT from PARTITIONS where PARTITIONID = :1", (partitionid,)))
- self.cachedPartitions[partitionid] = partition
- returnValue(partition)
-
def _db_version(self):
"""
@return: the schema version assigned to this index.
@@ -620,6 +587,7 @@
(
("UID", "text unique"),
("ENABLED", "text(1)"),
+ ("SERVERID", "text"),
("PARTITIONID", "text"),
("CALENDARING", "text(1)"),
("ADDRESSBOOKS", "text(1)"),
@@ -628,19 +596,9 @@
ifnotexists=True,
)
- yield self._create_table(
- "PARTITIONS",
- (
- ("PARTITIONID", "serial"),
- ("HOSTEDAT", "text"),
- ),
- ifnotexists=True,
- )
-
@inlineCallbacks
def _db_empty_data_tables(self):
yield self._db_execute("delete from AUGMENTS")
- yield self._db_execute("delete from PARTITIONS")
class AugmentSqliteDB(ADBAPISqliteMixin, AugmentADAPI):
"""
@@ -654,15 +612,15 @@
@inlineCallbacks
def _addRecord(self, record):
- partitionid = (yield self._getPartitionID(record.hostedAt))
yield self.execute(
"""insert or replace into AUGMENTS
- (UID, ENABLED, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE)
- values (:1, :2, :3, :4, :5, :6)""",
+ (UID, ENABLED, SERVERID, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE)
+ values (:1, :2, :3, :4, :5, :6, :7)""",
(
record.uid,
"T" if record.enabled else "F",
- partitionid,
+ record.serverID,
+ record.partitionID,
"T" if record.enabledForCalendaring else "F",
"T" if record.enabledForAddressBooks else "F",
"T" if record.autoSchedule else "F",
@@ -684,15 +642,15 @@
@inlineCallbacks
def _addRecord(self, record):
- partitionid = (yield self._getPartitionID(record.hostedAt))
yield self.execute(
"""insert into AUGMENTS
- (UID, ENABLED, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE)
- values (:1, :2, :3, :4, :5, :6)""",
+ (UID, ENABLED, SERVERID, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE)
+ values (:1, :2, :3, :4, :5, :6, :7)""",
(
record.uid,
"T" if record.enabled else "F",
- partitionid,
+ record.serverID,
+ record.partitionID,
"T" if record.enabledForCalendaring else "F",
"T" if record.enabledForAddressBooks else "F",
"T" if record.autoSchedule else "F",
@@ -701,15 +659,15 @@
@inlineCallbacks
def _modifyRecord(self, record):
- partitionid = (yield self._getPartitionID(record.hostedAt))
yield self.execute(
"""update AUGMENTS set
- (UID, ENABLED, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE) =
- (:1, :2, :3, :4, :5, :6) where UID = :7""",
+ (UID, ENABLED, SERVERID, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE) =
+ (:1, :2, :3, :4, :5, :6, :7) where UID = :8""",
(
record.uid,
"T" if record.enabled else "F",
- partitionid,
+ record.serverID,
+ record.partitionID,
"T" if record.enabledForCalendaring else "F",
"T" if record.enabledForAddressBooks else "F",
"T" if record.autoSchedule else "F",
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/common.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/common.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -81,8 +81,10 @@
if record.locallyHosted():
child = yield self.homeResourceCreator(record, transaction)
+ elif record.thisServer():
+ child = DirectoryReverseProxyResource(self, record)
else:
- child = DirectoryReverseProxyResource(self, record)
+ child = None # Use a redirect?
returnValue(child)
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/directory.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/directory.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -43,8 +43,8 @@
from twistedcaldav.config import config
from twistedcaldav.directory.idirectory import IDirectoryService, IDirectoryRecord
from twistedcaldav.directory.util import uuidFromName
-from twistedcaldav.partitions import partitions
from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
+from twistedcaldav import servers
class DirectoryService(LoggingMixIn):
implements(IDirectoryService, ICredentialsChecker)
@@ -339,7 +339,7 @@
implements(IDirectoryRecord)
def __repr__(self):
- return "<%s[%s@%s(%s)] %s(%s) %r @ %s>" % (
+ return "<%s[%s@%s(%s)] %s(%s) %r @ %s/#%s>" % (
self.__class__.__name__,
self.recordType,
self.service.guid,
@@ -347,7 +347,8 @@
self.guid,
",".join(self.shortNames),
self.fullName,
- self.hostedAt,
+ self.serverURI(),
+ self.partitionID,
)
def __init__(
@@ -377,7 +378,8 @@
self.guid = guid
self.uid = uid
self.enabled = False
- self.hostedAt = ""
+ self.serverID = ""
+ self.partitionID = ""
self.shortNames = shortNames
self.authIDs = authIDs
self.fullName = fullName
@@ -430,7 +432,8 @@
if augment:
self.enabled = augment.enabled
- self.hostedAt = augment.hostedAt
+ self.serverID = augment.serverID
+ self.partitionID = augment.partitionID
self.enabledForCalendaring = augment.enabledForCalendaring
self.enabledForAddressBooks = augment.enabledForAddressBooks
self.autoSchedule = augment.autoSchedule
@@ -447,8 +450,10 @@
else:
# Groups are by default always enabled
self.enabled = (self.recordType == self.service.recordType_groups)
- self.hostedAt = ""
+ self.serverID = ""
+ self.partitionID = ""
self.enabledForCalendaring = False
+ self.enabledForAddressBooks = False
def applySACLs(self):
@@ -495,12 +500,43 @@
return key
return None
+ def serverURI(self):
+ """
+ URL of the server hosting this record. Return None if hosted on this server.
+ """
+ if config.Servers.Enabled and self.serverID:
+ return servers.Servers.getServerURIById(self.serverID)
+ else:
+ return None
+
+ def partitionURI(self):
+ """
+ URL of the server hosting this record. Return None if hosted on this server.
+ """
+ if config.Servers.Enabled and self.serverID:
+ s = servers.Servers.getServerById(self.serverID)
+ if s:
+ return s.getPartitionURIForId(self.partitionID)
+ return None
+
def locallyHosted(self):
- return not self.hostedAt or not config.Partitioning.Enabled or self.hostedAt == config.Partitioning.ServerPartitionID
-
- def hostedURL(self):
- return partitions.getPartitionURL(self.hostedAt)
+ """
+ Hosted on this server/partition instance.
+ """
+
+ if config.Servers.Enabled and self.serverID:
+ s = servers.Servers.getServerById(self.serverID)
+ if s:
+ return s.thisServer and (not self.partitionID or self.partitionID == config.ServerPartitionID)
+ return True
+ def thisServer(self):
+ if config.Servers.Enabled and self.serverID:
+ s = servers.Servers.getServerById(self.serverID)
+ if s:
+ return s.thisServer
+ return True
+
class DirectoryError(RuntimeError):
"""
Generic directory error.
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/idirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/idirectory.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/idirectory.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -103,7 +103,8 @@
guid = Attribute("The GUID of this record.")
uid = Attribute("The UID of this record.")
enabled = Attribute("Determines whether this record should be provisioned as a principal.")
- hostedAt = Attribute("Identifies the server that actually hosts data for the record.")
+ serverID = Attribute("Identifies the server that actually hosts data for the record.")
+ partitionID = Attribute("Identifies the partition node that actually hosts data for the record.")
shortNames = Attribute("The names for this record.")
authIDs = Attribute("Alternative security identities for this record.")
fullName = Attribute("The full name of this record.")
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/principal.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/principal.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -608,7 +608,8 @@
"""---------------------\n"""
"""Directory GUID: %s\n""" % (self.record.service.guid,),
"""Realm: %s\n""" % (self.record.service.realmName,),
- """Hosted-At: %s\n""" % (self.record.hostedAt,) if config.Partitioning.Enabled else "",
+ """Hosted-At: %s\n""" % (self.record.serverURI(),) if config.Servers.Enabled else "",
+ """Partition: %s\n""" % (self.record.partitionID,) if config.Servers.Enabled and self.record.partitionID else "",
"""\n"""
"""Principal Information\n"""
"""---------------------\n"""
@@ -767,12 +768,18 @@
def principalUID(self):
return self.record.uid
+ def serverURI(self):
+ return self.record.serverURI()
+
+ def partitionURI(self):
+ return self.record.partitionURI()
+
def locallyHosted(self):
return self.record.locallyHosted()
- def hostedURL(self):
- return self.record.hostedURL()
-
+ def thisServer(self):
+ return self.record.thisServer()
+
##
# Extra resource info
##
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/resource.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/resource.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -30,7 +30,7 @@
self.parent = parent
self.record = record
- super(DirectoryReverseProxyResource, self).__init__(self.record.hostedAt)
+ super(DirectoryReverseProxyResource, self).__init__(self.record.partitionID)
def url(self):
return joinURL(self.parent.url(), self.record.uid)
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/augments-test-default.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/augments-test-default.xml 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/augments-test-default.xml 2011-04-11 19:19:28 UTC (rev 7308)
@@ -24,40 +24,40 @@
<enable>true</enable>
<enable-calendar>true</enable-calendar>
<enable-addressbook>true</enable-addressbook>
- <hosted-at>00001</hosted-at>
+ <partition-id>00001</partition-id>
</record>
<record>
<uid>Location-Default</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
- <hosted-at>00004</hosted-at>
+ <partition-id>00004</partition-id>
<auto-schedule>true</auto-schedule>
</record>
<record>
<uid>Location-AA*</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
- <hosted-at>00005</hosted-at>
+ <partition-id>00005</partition-id>
<auto-schedule>true</auto-schedule>
</record>
<record>
<uid>Resource-Default</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
- <hosted-at>00006</hosted-at>
+ <partition-id>00006</partition-id>
<auto-schedule>true</auto-schedule>
</record>
<record>
<uid>Resource-AA*</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
- <hosted-at>00007</hosted-at>
+ <partition-id>00007</partition-id>
<auto-schedule>true</auto-schedule>
</record>
<record>
<uid>AA*</uid>
<enable>true</enable>
- <hosted-at>00001</hosted-at>
+ <partition-id>00001</partition-id>
</record>
<record>
<uid>AB*</uid>
@@ -66,14 +66,14 @@
<record>
<uid>B*</uid>
<enable>true</enable>
- <hosted-at>00002</hosted-at>
+ <partition-id>00002</partition-id>
<enable-calendar>true</enable-calendar>
<enable-addressbook>true</enable-addressbook>
</record>
<record>
<uid>C*</uid>
<enable>true</enable>
- <hosted-at>00003</hosted-at>
+ <partition-id>00003</partition-id>
<enable-calendar>true</enable-calendar>
<enable-addressbook>true</enable-addressbook>
<auto-schedule>true</auto-schedule>
@@ -101,17 +101,17 @@
<record>
<uid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</uid>
<enable>true</enable>
- <hosted-at>00001</hosted-at>
+ <partition-id>00001</partition-id>
</record>
<record>
<uid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</uid>
<enable>true</enable>
- <hosted-at>00002</hosted-at>
+ <partition-id>00002</partition-id>
</record>
<record>
<uid>6A73326A-F781-47E7-A9F8-AF47364D4152</uid>
<enable>true</enable>
- <hosted-at>00002</hosted-at>
+ <partition-id>00002</partition-id>
<enable-calendar>true</enable-calendar>
<enable-addressbook>true</enable-addressbook>
<auto-schedule>true</auto-schedule>
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/augments-test.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/augments-test.xml 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/augments-test.xml 2011-04-11 19:19:28 UTC (rev 7308)
@@ -42,17 +42,17 @@
<record>
<uid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</uid>
<enable>true</enable>
- <hosted-at>00001</hosted-at>
+ <partition-id>00001</partition-id>
</record>
<record>
<uid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</uid>
<enable>true</enable>
- <hosted-at>00002</hosted-at>
+ <partition-id>00002</partition-id>
</record>
<record>
<uid>6A73326A-F781-47E7-A9F8-AF47364D4152</uid>
<enable>true</enable>
- <hosted-at>00002</hosted-at>
+ <partition-id>00002</partition-id>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
<enable-addressbook>true</enable-addressbook>
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/test_augment.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/test_augment.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/test/test_augment.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -28,41 +28,41 @@
xmlFileDefault = os.path.join(os.path.dirname(__file__), "augments-test-default.xml")
testRecords = (
- {"uid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "enabled":True, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"6423F94A-6B76-4A3A-815B-D52CFD77935D", "enabled":True, "hostedAt":"", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
- {"uid":"5A985493-EE2C-4665-94CF-4DFEA3A89500", "enabled":False, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"8B4288F6-CC82-491D-8EF9-642EF4F3E7D0", "enabled":True, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1", "enabled":True, "hostedAt":"00001", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"543D28BA-F74F-4D5F-9243-B3E3A61171E5", "enabled":True, "hostedAt":"00002", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"6A73326A-F781-47E7-A9F8-AF47364D4152", "enabled":True, "hostedAt":"00002", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":True},
+ {"uid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "enabled":True, "partitionID":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"6423F94A-6B76-4A3A-815B-D52CFD77935D", "enabled":True, "partitionID":"", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
+ {"uid":"5A985493-EE2C-4665-94CF-4DFEA3A89500", "enabled":False, "partitionID":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"8B4288F6-CC82-491D-8EF9-642EF4F3E7D0", "enabled":True, "partitionID":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1", "enabled":True, "partitionID":"00001", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"543D28BA-F74F-4D5F-9243-B3E3A61171E5", "enabled":True, "partitionID":"00002", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"6A73326A-F781-47E7-A9F8-AF47364D4152", "enabled":True, "partitionID":"00002", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":True},
)
testRecordWildcardDefault = (
- {"uid":"A4318887-F2C7-4A70-9056-B88CC8DB26F1", "enabled":True, "hostedAt":"00001", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
- {"uid":"AA5F935F-3358-4510-A649-B391D63279F2", "enabled":True, "hostedAt":"00001", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"ABF1A83B-1A29-4E04-BDC3-A6A66ECF27CA", "enabled":False, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"BC22A734-5E41-4FB7-B5C1-51DC0656DC2F", "enabled":True, "hostedAt":"00002", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
- {"uid":"C6DEEBB1-E14A-47F2-98BA-7E3BB4353E3A", "enabled":True, "hostedAt":"00003", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":True },
- {"uid":"AA859321-2C72-4974-ADCF-0CBA0C76F95D", "enabled":True, "hostedAt":"00001", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"AB7C488B-9ED2-4265-881C-7E2E38A63584", "enabled":False, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
- {"uid":"BB0C0DA1-0545-45F6-8D08-917C554D93A4", "enabled":True, "hostedAt":"00002", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
- {"uid":"CCD30AD3-582F-4682-8B65-2EDE92C5656E", "enabled":True, "hostedAt":"00003", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":True },
+ {"uid":"A4318887-F2C7-4A70-9056-B88CC8DB26F1", "enabled":True, "partitionID":"00001", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
+ {"uid":"AA5F935F-3358-4510-A649-B391D63279F2", "enabled":True, "partitionID":"00001", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"ABF1A83B-1A29-4E04-BDC3-A6A66ECF27CA", "enabled":False, "partitionID":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"BC22A734-5E41-4FB7-B5C1-51DC0656DC2F", "enabled":True, "partitionID":"00002", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
+ {"uid":"C6DEEBB1-E14A-47F2-98BA-7E3BB4353E3A", "enabled":True, "partitionID":"00003", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":True },
+ {"uid":"AA859321-2C72-4974-ADCF-0CBA0C76F95D", "enabled":True, "partitionID":"00001", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"AB7C488B-9ED2-4265-881C-7E2E38A63584", "enabled":False, "partitionID":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"BB0C0DA1-0545-45F6-8D08-917C554D93A4", "enabled":True, "partitionID":"00002", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
+ {"uid":"CCD30AD3-582F-4682-8B65-2EDE92C5656E", "enabled":True, "partitionID":"00003", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":True },
)
testRecordTypeDefault = (
- ("locations", {"uid":"A4318887-F2C7-4A70-9056-B88CC8DB26F1", "enabled":True, "hostedAt":"00004", "enabledForCalendaring":True, "enabledForAddressBooks":False, "autoSchedule":True}),
- ("locations", {"uid":"AA5F935F-3358-4510-A649-B391D63279F2", "enabled":True, "hostedAt":"00005", "enabledForCalendaring":True, "enabledForAddressBooks":False, "autoSchedule":True}),
- ("resources", {"uid":"A5318887-F2C7-4A70-9056-B88CC8DB26F1", "enabled":True, "hostedAt":"00006", "enabledForCalendaring":True, "enabledForAddressBooks":False, "autoSchedule":True}),
- ("resources", {"uid":"AA6F935F-3358-4510-A649-B391D63279F2", "enabled":True, "hostedAt":"00007", "enabledForCalendaring":True, "enabledForAddressBooks":False, "autoSchedule":True}),
+ ("locations", {"uid":"A4318887-F2C7-4A70-9056-B88CC8DB26F1", "enabled":True, "partitionID":"00004", "enabledForCalendaring":True, "enabledForAddressBooks":False, "autoSchedule":True}),
+ ("locations", {"uid":"AA5F935F-3358-4510-A649-B391D63279F2", "enabled":True, "partitionID":"00005", "enabledForCalendaring":True, "enabledForAddressBooks":False, "autoSchedule":True}),
+ ("resources", {"uid":"A5318887-F2C7-4A70-9056-B88CC8DB26F1", "enabled":True, "partitionID":"00006", "enabledForCalendaring":True, "enabledForAddressBooks":False, "autoSchedule":True}),
+ ("resources", {"uid":"AA6F935F-3358-4510-A649-B391D63279F2", "enabled":True, "partitionID":"00007", "enabledForCalendaring":True, "enabledForAddressBooks":False, "autoSchedule":True}),
)
testAddRecords = (
- {"uid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975767", "enabled":True, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975767", "enabled":True, "partitionID":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
)
testModifyRecords = (
- {"uid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975767", "enabled":True, "hostedAt":"", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
+ {"uid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975767", "enabled":True, "partitionID":"", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
)
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/xmlaugmentsparser.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/xmlaugmentsparser.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/directory/xmlaugmentsparser.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2009-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2009-2011 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.
@@ -35,7 +35,8 @@
ELEMENT_UID = "uid"
ELEMENT_ENABLE = "enable"
-ELEMENT_HOSTEDAT = "hosted-at"
+ELEMENT_SERVERID = "server-id"
+ELEMENT_PARTITIONID = "partition-id"
ELEMENT_ENABLECALENDAR = "enable-calendar"
ELEMENT_ENABLEADDRESSBOOK = "enable-addressbook"
ELEMENT_AUTOSCHEDULE = "auto-schedule"
@@ -48,7 +49,8 @@
ELEMENT_AUGMENTRECORD_MAP = {
ELEMENT_UID: "uid",
ELEMENT_ENABLE: "enabled",
- ELEMENT_HOSTEDAT: "hostedAt",
+ ELEMENT_SERVERID: "serverID",
+ ELEMENT_PARTITIONID: "partitionID",
ELEMENT_ENABLECALENDAR: "enabledForCalendaring",
ELEMENT_ENABLEADDRESSBOOK: "enabledForAddressBooks",
ELEMENT_AUTOSCHEDULE: "autoSchedule",
@@ -91,7 +93,8 @@
if node.tag in (
ELEMENT_UID,
- ELEMENT_HOSTEDAT,
+ ELEMENT_SERVERID,
+ ELEMENT_PARTITIONID,
):
fields[node.tag] = node.text if node.text else ""
elif node.tag in (
Deleted: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/partitions.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/partitions.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/partitions.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -1,72 +0,0 @@
-##
-# Copyright (c) 2009-2010 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 twext.python.log import Logger
-from twext.python.plistlib import readPlist
-
-from twistedcaldav.client.pool import installPool
-
-"""
-Collection of classes for managing partition information for a group of servers.
-"""
-
-log = Logger()
-
-class Partitions(object):
-
- def __init__(self):
-
- self.clear()
-
- def clear(self):
- self.partitions = {}
- self.ownUID = ""
- self.maxClients = 5
-
- def readConfig(self, plistpath):
- try:
- dataDict = readPlist(plistpath)
- except (IOError, OSError):
- log.error("Configuration file does not exist or is inaccessible: %s" % (self._configFileName,))
- return
-
- for partition in dataDict.get("partitions", ()):
- uid = partition.get("uid", None)
- url = partition.get("url", None)
- if uid and url:
- self.partitions[uid] = url
-
- def setSelfPartition(self, uid):
- self.ownUID = uid
-
- def setMaxClients(self, maxClients):
- self.maxClients = maxClients
-
- def getPartitionURL(self, uid):
- # When the UID matches this server return an empty string
- return self.partitions.get(uid, None) if uid != self.ownUID else ""
-
- def installReverseProxies(self):
-
- for partition, url in self.partitions.iteritems():
- if partition != self.ownUID:
- installPool(
- partition,
- url,
- self.maxClients,
- )
-
-partitions = Partitions()
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/addressmapping.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/addressmapping.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/addressmapping.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -24,9 +24,8 @@
from twistedcaldav.scheduling.delivery import DeliveryService
from twistedcaldav.scheduling.imip import ScheduleViaIMip
from twistedcaldav.scheduling.ischedule import ScheduleViaISchedule
-from twistedcaldav.scheduling.cuaddress import LocalCalendarUser,\
- RemoteCalendarUser, EmailCalendarUser, InvalidCalendarUser,\
- PartitionedCalendarUser
+from twistedcaldav.scheduling.cuaddress import RemoteCalendarUser, EmailCalendarUser, InvalidCalendarUser,\
+ calendarUserFromPrincipal
__all__ = [
"ScheduleAddressMapper",
@@ -54,7 +53,7 @@
# If we have a principal always treat the user as local or partitioned
if principal:
- returnValue(LocalCalendarUser(cuaddr, principal) if principal.locallyHosted() else PartitionedCalendarUser(cuaddr, principal))
+ returnValue(calendarUserFromPrincipal(cuaddr, principal))
# Get the type
cuaddr_type = (yield self.getCalendarUserServiceType(cuaddr))
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/caldav.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/caldav.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/caldav.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -39,7 +39,7 @@
from twistedcaldav.method import report_common
from twistedcaldav.resource import isCalendarCollectionResource
from twistedcaldav.scheduling.cuaddress import LocalCalendarUser, RemoteCalendarUser,\
- PartitionedCalendarUser
+ PartitionedCalendarUser, OtherServerCalendarUser
from twistedcaldav.scheduling.delivery import DeliveryService
from twistedcaldav.scheduling.itip import iTIPRequestStatus
from twistedcaldav.scheduling.processing import ImplicitProcessor, ImplicitProcessorException
@@ -99,7 +99,7 @@
uid = self.scheduler.calendar.resourceUID()
organizerPrincipal = None
- if type(self.scheduler.organizer) in (LocalCalendarUser, PartitionedCalendarUser,):
+ if type(self.scheduler.organizer) in (LocalCalendarUser, PartitionedCalendarUser, OtherServerCalendarUser,):
organizerPrincipal = davxml.Principal(davxml.HRef(self.scheduler.organizer.principal.principalURL()))
for recipient in self.recipients:
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/cuaddress.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/cuaddress.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/cuaddress.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -21,6 +21,7 @@
__all__ = [
"LocalCalendarUser",
"PartitionedCalendarUser",
+ "OtherServerCalendarUser",
"RemoteCalendarUser",
"EmailCalendarUser",
"InvalidCalendarUser",
@@ -54,6 +55,15 @@
def __str__(self):
return "Partitioned calendar user: %s" % (self.cuaddr,)
+class OtherServerCalendarUser(CalendarUser):
+ def __init__(self, cuaddr, principal):
+ self.cuaddr = cuaddr
+ self.principal = principal
+ self.serviceType = DeliveryService.serviceType_ischedule
+
+ def __str__(self):
+ return "Other server calendar user: %s" % (self.cuaddr,)
+
class RemoteCalendarUser(CalendarUser):
def __init__(self, cuaddr):
self.cuaddr = cuaddr
@@ -104,3 +114,15 @@
return addr.rstrip("/")
else:
return addr
+
+def calendarUserFromPrincipal(recipient, principal, inbox=None, inboxURL=None):
+ """
+ Get the appropriate calendar user address class for the provided principal.
+ """
+
+ if principal.locallyHosted():
+ return LocalCalendarUser(recipient, principal, inbox, inboxURL)
+ elif principal.thisServer():
+ return PartitionedCalendarUser(recipient, principal)
+ else:
+ return OtherServerCalendarUser(recipient, principal)
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/implicit.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/implicit.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -27,7 +27,7 @@
from twistedcaldav.ical import Property
from twistedcaldav.scheduling import addressmapping
from twistedcaldav.scheduling.cuaddress import InvalidCalendarUser,\
- LocalCalendarUser, PartitionedCalendarUser
+ LocalCalendarUser, PartitionedCalendarUser, OtherServerCalendarUser
from twistedcaldav.scheduling.icaldiff import iCalDiff
from twistedcaldav.scheduling.itip import iTipGenerator, iTIPRequestStatus
from twistedcaldav.scheduling.scheduler import CalDAVScheduler
@@ -943,7 +943,7 @@
calendar_resource, _ignore_name, _ignore_collection, _ignore_uri = (yield getCalendarObjectForPrincipals(self.request, self.organizerPrincipal, self.uid))
if calendar_resource:
self.organizer_calendar = (yield calendar_resource.iCalendarForUser(self.request))
- elif isinstance(self.organizerAddress, PartitionedCalendarUser):
+ elif type(self.organizerAddress) in (PartitionedCalendarUser, OtherServerCalendarUser,):
# For partitioning where the organizer is on a different node, we will assume that the attendee's copy
# of the event is up to date and "authoritative". So we pretend that is the organizer copy
self.organizer_calendar = self.oldcalendar
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/ischedule.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/ischedule.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/ischedule.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -42,8 +42,8 @@
from twistedcaldav.scheduling.ischeduleservers import IScheduleServerRecord
from twistedcaldav.scheduling.itip import iTIPRequestStatus
from twistedcaldav.util import utf8String
-from twistedcaldav.scheduling.cuaddress import RemoteCalendarUser
-from twistedcaldav.scheduling.cuaddress import PartitionedCalendarUser
+from twistedcaldav.scheduling.cuaddress import PartitionedCalendarUser, RemoteCalendarUser,\
+ OtherServerCalendarUser
import OpenSSL
@@ -86,6 +86,8 @@
server = servermgr.mapDomain(recipient.domain)
elif isinstance(recipient, PartitionedCalendarUser):
server = self._getServerForPartitionedUser(recipient)
+ elif isinstance(recipient, OtherServerCalendarUser):
+ server = self._getServerForOtherServerUser(recipient)
else:
assert False, "Incorrect calendar user address class"
if not server:
@@ -132,13 +134,25 @@
if not hasattr(self, "partitionedServers"):
self.partitionedServers = {}
- partition = recipient.principal.hostedURL()
+ partition = recipient.principal.partitionURI()
if partition not in self.partitionedServers:
self.partitionedServers[partition] = IScheduleServerRecord(uri=joinURL(partition, "/ischedule"))
self.partitionedServers[partition].unNormalizeAddresses = False
return self.partitionedServers[partition]
+ def _getServerForOtherServerUser(self, recipient):
+
+ if not hasattr(self, "otherServers"):
+ self.otherServers = {}
+
+ server = recipient.principal.serverURI()
+ if server not in self.otherServers:
+ self.otherServers[server] = IScheduleServerRecord(uri=joinURL(server, "/ischedule"))
+ self.otherServers[server].unNormalizeAddresses = False
+
+ return self.otherServers[server]
+
class IScheduleRequest(object):
def __init__(self, scheduler, server, recipients, responses, refreshOnly=False):
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/scheduler.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/scheduler.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/scheduling/scheduler.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -38,7 +38,8 @@
from twistedcaldav.ical import Component
from twistedcaldav.scheduling import addressmapping
from twistedcaldav.scheduling.caldav import ScheduleViaCalDAV
-from twistedcaldav.scheduling.cuaddress import InvalidCalendarUser
+from twistedcaldav.scheduling.cuaddress import InvalidCalendarUser,\
+ calendarUserFromPrincipal, OtherServerCalendarUser
from twistedcaldav.scheduling.cuaddress import LocalCalendarUser
from twistedcaldav.scheduling.cuaddress import RemoteCalendarUser
from twistedcaldav.scheduling.cuaddress import EmailCalendarUser
@@ -451,6 +452,7 @@
# Loop over each recipient and aggregate into lists by service types.
caldav_recipients = []
partitioned_recipients = []
+ otherserver_recipients = []
remote_recipients = []
imip_recipients = []
for ctr, recipient in enumerate(self.recipients):
@@ -474,6 +476,9 @@
elif isinstance(recipient, PartitionedCalendarUser):
partitioned_recipients.append(recipient)
+ elif isinstance(recipient, OtherServerCalendarUser):
+ otherserver_recipients.append(recipient)
+
elif isinstance(recipient, RemoteCalendarUser):
remote_recipients.append(recipient)
@@ -496,6 +501,10 @@
if partitioned_recipients:
yield self.generateRemoteSchedulingResponses(partitioned_recipients, responses, freebusy, getattr(self.request, 'doing_attendee_refresh', False))
+ # Now process other server recipients
+ if otherserver_recipients:
+ yield self.generateRemoteSchedulingResponses(otherserver_recipients, responses, freebusy, getattr(self.request, 'doing_attendee_refresh', False))
+
# To reduce chatter, we suppress certain messages
if not getattr(self.request, 'suppressRefresh', False):
@@ -610,13 +619,11 @@
results.append(address)
else:
# Map recipient to their inbox
- inbox = None
inboxURL = principal.scheduleInboxURL()
- if inboxURL:
- inbox = (yield self.request.locateResource(inboxURL)) if principal.locallyHosted() else "dummy"
+ inbox = (yield self.request.locateResource(inboxURL)) if principal.locallyHosted() else "dummy"
if inbox:
- results.append(LocalCalendarUser(recipient, principal, inbox, inboxURL) if principal.locallyHosted() else PartitionedCalendarUser(recipient, principal))
+ results.append(calendarUserFromPrincipal(recipient, principal, inbox, inboxURL))
else:
log.err("No schedule inbox for principal: %s" % (principal,))
results.append(InvalidCalendarUser(recipient))
@@ -783,13 +790,11 @@
results.append(InvalidCalendarUser(recipient))
else:
# Map recipient to their inbox
- inbox = None
inboxURL = principal.scheduleInboxURL()
- if inboxURL:
- inbox = (yield self.request.locateResource(inboxURL)) if principal.locallyHosted() else "dummy"
+ inbox = (yield self.request.locateResource(inboxURL)) if principal.locallyHosted() else "dummy"
if inbox:
- results.append(LocalCalendarUser(recipient, principal, inbox, inboxURL) if principal.locallyHosted() else PartitionedCalendarUser(recipient, principal))
+ results.append(calendarUserFromPrincipal(recipient, principal, inbox, inboxURL))
else:
log.err("No schedule inbox for principal: %s" % (principal,))
results.append(InvalidCalendarUser(recipient))
@@ -835,8 +840,8 @@
"Originator cannot be local to server",
))
else:
- self.originator = PartitionedCalendarUser(self.originator, originatorPrincipal)
- #self._validPartitionServer()
+ self.originator = calendarUserFromPrincipal(self.originator, originatorPrincipal)
+ self._validAlternateServer(originatorPrincipal)
else:
self.originator = RemoteCalendarUser(self.originator)
self._validiScheduleServer()
@@ -897,13 +902,13 @@
"Originator not allowed to send to this server",
))
- def _validPartitionServer(self, principal):
+ def _validAlternateServer(self, principal):
"""
Check the validity of the partitioned host.
"""
# Extract expected host/port
- expected_uri = principal.hostedURL()
+ expected_uri = principal.partitionURI() if principal.thisServer() else principal.serverURI()
expected_uri = urlparse.urlparse(expected_uri)
# Get the request IP and map to hostname.
@@ -953,8 +958,8 @@
))
else:
# Check that the origin server is the correct partition
- self.organizer = PartitionedCalendarUser(organizer, organizerPrincipal)
- self._validPartitionServer(self.organizer.principal)
+ self.organizer = calendarUserFromPrincipal(organizer, organizerPrincipal)
+ self._validAlternateServer(self.organizer.principal)
else:
localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(organizer))
if localUser:
@@ -992,7 +997,7 @@
"Local attendee cannot send to this server",
))
else:
- self._validPartitionServer(attendeePrincipal)
+ self._validAlternateServer(attendeePrincipal)
else:
localUser = (yield addressmapping.mapper.isCalendarUserInMyDomain(self.attendee))
if localUser:
Added: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/servers.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/servers.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/servers.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -0,0 +1,201 @@
+##
+# Copyright (c) 2011 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 twext.python.filepath import CachingFilePath as FilePath
+
+from twext.python.log import Logger
+
+from twistedcaldav.client.pool import installPool
+from twistedcaldav.config import config, fullServerPath
+from twistedcaldav.xmlutil import readXML
+import urlparse
+
+"""
+XML based server configuration file handling.
+
+This is used in an environment where more than one server is being used within a single domain. i.e., all
+the principals across the whole domain need to be able to directly schedule each other and know of each others
+existence. A common scenario would be a production server and a development/test server.
+
+Each server is identified by an id and url. The id is used when assigning principals to a specific server. Each
+server can also support multiple partitions, and each of those is identified by an id and url, with the id also
+being used to assign principals to a specific partition.
+"""
+
+__all__ = [
+ "Servers",
+]
+
+log = Logger()
+
+class ServersDB(object):
+ """
+ Represents the set of servers within the same domain.
+ """
+
+ def __init__(self):
+
+ self._servers = {}
+ self._xmlFile = None
+ self._thisServer = None
+
+ def load(self, xmlFile=None):
+ if self._xmlFile is None or xmlFile is not None:
+ self._servers = {}
+ if xmlFile:
+ self._xmlFile = xmlFile
+ else:
+ self._xmlFile = FilePath(
+ fullServerPath(
+ config.ConfigRoot,
+ config.Servers.ConfigFile
+ )
+ )
+ self._servers = ServersParser.parse(self._xmlFile)
+ for server in self._servers.values():
+ if server.thisServer:
+ self._thisServer = server
+ break
+ else:
+ raise ValueError("No server in self._xmlFile matches this server.")
+
+ def clear(self):
+ self._servers = {}
+ self._xmlFile = None
+ self._thisServer = None
+
+ def getServerById(self, id):
+ return self._servers.get(id)
+
+ def getServerURIById(self, id):
+ try:
+ return self._servers.get[id].uri
+ except KeyError:
+ return None
+
+ def getThisServer(self):
+ return self._thisServer
+
+Servers = ServersDB() # Global server DB
+
+class Server(object):
+ """
+ Represents a server which may itself be partitioned.
+ """
+
+ def __init__(self):
+ self.id = None
+ self.uri = None
+ self.thisServer = False
+ self.partitions = {}
+
+ def check(self):
+ # Check whether this matches the current server
+ parsed_uri = urlparse.urlparse(self.uri)
+ if parsed_uri.hostname == config.ServerHostName:
+ if parsed_uri.scheme == "http":
+ if config.HTTPPort:
+ self.thisServer = parsed_uri.port in (config.HTTPPort,) + tuple(config.BindHTTPPorts)
+ elif parsed_uri.scheme == "https":
+ if config.SSLPort:
+ self.thisServer = parsed_uri.port in (config.SSLPort,) + tuple(config.BindSSLPorts)
+
+ def addPartition(self, id, uri):
+ self.partitions[id] = uri
+
+ def getPartitionURIForId(self, id):
+ return self.partitions.get(id)
+
+ def installReverseProxies(self, ownUID, maxClients):
+
+ for partition, url in self.partitions.iteritems():
+ if partition != ownUID:
+ installPool(
+ partition,
+ url,
+ maxClients,
+ )
+
+
+
+ELEMENT_SERVERS = "servers"
+ELEMENT_SERVER = "server"
+ELEMENT_ID = "id"
+ELEMENT_URI = "uri"
+ELEMENT_PARTITIONS = "partitions"
+ELEMENT_PARTITION = "partition"
+
+class ServersParser(object):
+ """
+ Servers configuration file parser.
+ """
+ @staticmethod
+ def parse(xmlFile):
+
+ results = {}
+
+ # Read in XML
+ try:
+ _ignore_tree, servers_node = readXML(xmlFile, ELEMENT_SERVERS)
+ except ValueError, e:
+ log.error("XML parse error for '%s' because: %s" % (xmlFile, e,), raiseException=RuntimeError)
+
+ for child in servers_node.getchildren():
+
+ if child.tag != ELEMENT_SERVER:
+ log.error("Unknown server type: '%s' in servers file: '%s'" % (child.tag, xmlFile,), raiseException=RuntimeError)
+
+ server = Server()
+ for node in child.getchildren():
+ if node.tag == ELEMENT_ID:
+ server.id = node.text
+ elif node.tag == ELEMENT_URI:
+ server.uri = node.text
+ elif node.tag == ELEMENT_PARTITIONS:
+ ServersParser._parsePartition(xmlFile, node, server)
+ else:
+ log.error("Invalid element '%s' in servers file: '%s'" % (node.tag, xmlFile,), raiseException=RuntimeError)
+
+ if server.id is None or server.uri is None:
+ log.error("Invalid partition '%s' in servers file: '%s'" % (child.tag, xmlFile,), raiseException=RuntimeError)
+
+ server.check()
+ results[server.id] = server
+
+ return results
+
+ @staticmethod
+ def _parsePartition(xmlFile, partitions, server):
+
+ for child in partitions.getchildren():
+
+ if child.tag != ELEMENT_PARTITION:
+ log.error("Unknown partition type: '%s' in servers file: '%s'" % (child.tag, xmlFile,), raiseException=RuntimeError)
+
+ id = None
+ uri = None
+ for node in child.getchildren():
+ if node.tag == ELEMENT_ID:
+ id = node.text
+ elif node.tag == ELEMENT_URI:
+ uri = node.text
+ else:
+ log.error("Invalid element '%s' in augment file: '%s'" % (node.tag, xmlFile,), raiseException=RuntimeError)
+
+ if id is None or uri is None:
+ log.error("Invalid partition '%s' in servers file: '%s'" % (child.tag, xmlFile,), raiseException=RuntimeError)
+
+ server.addPartition(id, uri)
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/stdconfig.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/stdconfig.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -15,8 +15,10 @@
# limitations under the License.
##
+from socket import getfqdn
+from socket import gethostbyname
+import copy
import os
-import copy
import re
from twext.web2.dav import davxml
@@ -29,7 +31,6 @@
from twistedcaldav import caldavxml, customxml, carddavxml
from twistedcaldav.config import ConfigProvider, ConfigurationError
from twistedcaldav.config import config, _mergeData, fullServerPath
-from twistedcaldav.partitions import partitions
from twistedcaldav.util import getPasswordFromKeychain
from twistedcaldav.util import KeychainAccessError, KeychainPasswordNotFound
@@ -587,14 +588,14 @@
},
#
- # Partitioning
+ # Support multiple hosts within a domain
#
- "Partitioning" : {
- "Enabled": False, # Partitioning enabled or not
- "ServerPartitionID": "", # Unique ID for this server's partition instance.
- "PartitionConfigFile": "partitions.plist", # File path for partition information
+ "Servers" : {
+ "Enabled": False, # Multiple servers/partitions enabled or not
+ "ConfigFile": "servers.xml", # File path for server information
"MaxClients": 5, # Pool size for connections to each partition
},
+ "ServerPartitionID": "", # Unique ID for this server's partition instance.
#
# Performance tuning
@@ -758,10 +759,14 @@
if "Includes" in configDict:
configRoot = os.path.join(configDict.ServerRoot, configDict.ConfigRoot)
for include in configDict.Includes:
-
- additionalDict = self._parseConfigFromFile(fullServerPath(configRoot, include))
+ path = fullServerPath(configRoot, include)
+ if '$' in path:
+ path = path.replace('$', getfqdn())
+ if '#' in path:
+ path = path.replace('#', gethostbyname(getfqdn()))
+ additionalDict = self._parseConfigFromFile(path)
if additionalDict:
- log.info("Adding configuration from file: '%s'" % (include,))
+ log.info("Adding configuration from file: '%s'" % (path,))
configDict.update(additionalDict)
return configDict
@@ -849,7 +854,6 @@
def _updateHostName(configDict):
if not configDict.ServerHostName:
- from socket import getfqdn
hostname = getfqdn()
if not hostname:
hostname = "localhost"
@@ -1116,14 +1120,16 @@
log.info("iMIP %s password not found in keychain" %
(direction,))
-def _updatePartitions(configDict):
- if configDict.Partitioning.Enabled:
- partitions.setSelfPartition(configDict.Partitioning.ServerPartitionID)
- partitions.setMaxClients(configDict.Partitioning.MaxClients)
- partitions.readConfig(fullServerPath(configDict.ConfigRoot, configDict.Partitioning.PartitionConfigFile))
- partitions.installReverseProxies()
+def _updateServers(configDict):
+ import servers
+ if configDict.Servers.Enabled:
+ servers.Servers.load()
+ servers.Servers.getThisServer().installReverseProxies(
+ configDict.ServerPartitionID,
+ configDict.Servers.MaxClients,
+ )
else:
- partitions.clear()
+ servers.Servers.clear()
def _updateCompliance(configDict):
@@ -1169,7 +1175,7 @@
_updateLogLevels,
_updateNotifications,
_updateScheduling,
- _updatePartitions,
+ _updateServers,
_updateCompliance,
)
Modified: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/test/test_config.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/test/test_config.py 2011-04-08 22:22:17 UTC (rev 7307)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/test/test_config.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -22,6 +22,7 @@
from twistedcaldav.stdconfig import DEFAULT_CONFIG, PListConfigProvider,\
RELATIVE_PATHS
from twistedcaldav.test.util import TestCase
+import socket
testConfig = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -325,3 +326,194 @@
# But attr syntax is OK
configDict._x = "X"
self.assertEquals(configDict._x, "X")
+
+ def test_SimpleInclude(self):
+
+ testConfigMaster = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+
+ <key>ResponseCompression</key>
+ <false/>
+
+ <key>ServerRoot</key>
+ <string></string>
+
+ <key>ConfigRoot</key>
+ <string></string>
+
+ <key>HTTPPort</key>
+ <integer>8008</integer>
+
+ <key>SSLPort</key>
+ <integer>8443</integer>
+
+ <key>DefaultLogLevel</key>
+ <string>info</string>
+ <key>LogLevels</key>
+ <dict>
+ <key>some.namespace</key>
+ <string>debug</string>
+ </dict>
+
+ <key>Includes</key>
+ <array>
+ <string>%s</string>
+ </array>
+
+</dict>
+</plist>
+"""
+
+ testConfigInclude = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+
+ <key>HTTPPort</key>
+ <integer>9008</integer>
+
+</dict>
+</plist>
+"""
+
+ config.setProvider(PListConfigProvider(DEFAULT_CONFIG))
+
+ self.testInclude = self.mktemp()
+ open(self.testInclude, "w").write(testConfigInclude)
+
+ self.testMaster = self.mktemp()
+ open(self.testMaster, "w").write(testConfigMaster % (self.testInclude,))
+
+ config.load(self.testMaster)
+ self.assertEquals(config.HTTPPort, 9008)
+ self.assertEquals(config.SSLPort, 8443)
+
+ def test_FQDNInclude(self):
+
+ testConfigMaster = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+
+ <key>ResponseCompression</key>
+ <false/>
+
+ <key>ServerRoot</key>
+ <string></string>
+
+ <key>ConfigRoot</key>
+ <string></string>
+
+ <key>HTTPPort</key>
+ <integer>8008</integer>
+
+ <key>SSLPort</key>
+ <integer>8443</integer>
+
+ <key>DefaultLogLevel</key>
+ <string>info</string>
+ <key>LogLevels</key>
+ <dict>
+ <key>some.namespace</key>
+ <string>debug</string>
+ </dict>
+
+ <key>Includes</key>
+ <array>
+ <string>%s.$</string>
+ </array>
+
+</dict>
+</plist>
+"""
+
+ testConfigInclude = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+
+ <key>HTTPPort</key>
+ <integer>9008</integer>
+
+</dict>
+</plist>
+"""
+
+ config.setProvider(PListConfigProvider(DEFAULT_CONFIG))
+
+ self.testIncludeRoot = self.mktemp()
+ self.testInclude = self.testIncludeRoot + "." + socket.getfqdn()
+ open(self.testInclude, "w").write(testConfigInclude)
+
+ self.testMaster = self.mktemp()
+ open(self.testMaster, "w").write(testConfigMaster % (self.testIncludeRoot,))
+
+ config.load(self.testMaster)
+ self.assertEquals(config.HTTPPort, 9008)
+ self.assertEquals(config.SSLPort, 8443)
+
+ def test_HostnameInclude(self):
+
+ testConfigMaster = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+
+ <key>ResponseCompression</key>
+ <false/>
+
+ <key>ServerRoot</key>
+ <string></string>
+
+ <key>ConfigRoot</key>
+ <string></string>
+
+ <key>HTTPPort</key>
+ <integer>8008</integer>
+
+ <key>SSLPort</key>
+ <integer>8443</integer>
+
+ <key>DefaultLogLevel</key>
+ <string>info</string>
+ <key>LogLevels</key>
+ <dict>
+ <key>some.namespace</key>
+ <string>debug</string>
+ </dict>
+
+ <key>Includes</key>
+ <array>
+ <string>%s.#</string>
+ </array>
+
+</dict>
+</plist>
+"""
+
+ testConfigInclude = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+
+ <key>HTTPPort</key>
+ <integer>9008</integer>
+
+</dict>
+</plist>
+"""
+
+ config.setProvider(PListConfigProvider(DEFAULT_CONFIG))
+
+ self.testIncludeRoot = self.mktemp()
+ self.testInclude = self.testIncludeRoot + "." + socket.gethostbyname(socket.getfqdn())
+ open(self.testInclude, "w").write(testConfigInclude)
+
+ self.testMaster = self.mktemp()
+ open(self.testMaster, "w").write(testConfigMaster % (self.testIncludeRoot,))
+
+ config.load(self.testMaster)
+ self.assertEquals(config.HTTPPort, 9008)
+ self.assertEquals(config.SSLPort, 8443)
Added: CalendarServer/branches/users/cdaboo/pods/twistedcaldav/test/test_servers.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pods/twistedcaldav/test/test_servers.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/pods/twistedcaldav/test/test_servers.py 2011-04-11 19:19:28 UTC (rev 7308)
@@ -0,0 +1,89 @@
+##
+# Copyright (c) 2009-2010 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 twistedcaldav.servers import Servers
+from twistedcaldav.test.util import TestCase
+import StringIO as StringIO
+from twistedcaldav.config import config
+
+class ServerTests(TestCase):
+
+ data1 = """<?xml version="1.0" encoding="utf-8"?>
+<servers>
+ <server>
+ <id>00001</id>
+ <uri>http://caldav1.example.com:8008</uri>
+ </server>
+ <server>
+ <id>00002</id>
+ <uri>https://caldav2.example.com:8843</uri>
+ <partitions>
+ <partition>
+ <id>A</id>
+ <uri>https://machine1.example.com:8443</uri>
+ </partition>
+ <partition>
+ <id>B</id>
+ <uri>https://machine2.example.com:8443</uri>
+ </partition>
+ </partitions>
+ </server>
+</servers>
+"""
+
+ def test_read_ok(self):
+
+ self.patch(config, "ServerHostName", "caldav1.example.com")
+ self.patch(config, "HTTPPort", 8008)
+
+ xmlFile = StringIO.StringIO(ServerTests.data1)
+ servers = Servers
+ servers.load(xmlFile)
+
+ self.assertTrue(servers.getServerById("00001") is not None)
+ self.assertTrue(servers.getServerById("00002") is not None)
+
+ self.assertEqual(servers.getServerById("00001").uri, "http://caldav1.example.com:8008")
+ self.assertEqual(servers.getServerById("00002").uri, "https://caldav2.example.com:8843")
+
+ self.assertEqual(len(servers.getServerById("00001").partitions), 0)
+ self.assertEqual(len(servers.getServerById("00002").partitions), 2)
+
+ self.assertEqual(servers.getServerById("00002").getPartitionURIForId("A"), "https://machine1.example.com:8443")
+ self.assertEqual(servers.getServerById("00002").getPartitionURIForId("B"), "https://machine2.example.com:8443")
+
+ def test_this_server(self):
+
+ self.patch(config, "ServerHostName", "caldav1.example.com")
+ self.patch(config, "HTTPPort", 8008)
+
+ xmlFile = StringIO.StringIO(ServerTests.data1)
+ servers = Servers
+ servers.load(xmlFile)
+
+ self.assertTrue(servers.getServerById("00001").thisServer)
+ self.assertFalse(servers.getServerById("00002").thisServer)
+
+ self.patch(config, "ServerHostName", "caldav2.example.com")
+ self.patch(config, "SSLPort", 8443)
+ self.patch(config, "BindSSLPorts", [8843])
+
+ xmlFile = StringIO.StringIO(ServerTests.data1)
+ servers = Servers
+ servers.load(xmlFile)
+
+ self.assertFalse(servers.getServerById("00001").thisServer)
+ self.assertTrue(servers.getServerById("00002").thisServer)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110411/d6760f50/attachment-0001.html>
More information about the calendarserver-changes
mailing list