Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

changeip_calendar now uses calendarserver_config to do its bidding

  • Loading branch information
m0rgen committed Apr 10, 2014
1 parent f9bc8ee commit 59a4b8fb67e25a447bba32b4fe510a9f235524b8
Showing with 137 additions and 81 deletions.
  1. +111 −36 calendarserver/tools/changeip_calendar.py
  2. +26 −45 calendarserver/tools/test/test_changeip.py
@@ -12,26 +12,59 @@
from __future__ import print_function
from __future__ import with_statement


import datetime
from getopt import getopt, GetoptError
import os
import plistlib
import subprocess
import sys
from getopt import getopt, GetoptError

from plistlib import readPlist, writePlist

SERVER_APP_ROOT = "/Applications/Server.app/Contents/ServerRoot"
CALENDARSERVER_CONFIG = "%s/usr/sbin/calendarserver_config" % (SERVER_APP_ROOT,)


def serverRootLocation():
"""
Return the ServerRoot value from the servermgr_calendar.plist. If not
present, return the default.
"""
plist = "/Library/Preferences/com.apple.servermgr_calendar.plist"
serverRoot = u"/Library/Server/Calendar and Contacts"
if os.path.exists(plist):
serverRoot = plistlib.readPlist(plist).get("ServerRoot", serverRoot)
return serverRoot



def usage():
name = os.path.basename(sys.argv[0])
print("Usage: %s [-hv] old-ip new-ip [old-hostname new-hostname]" % (name,))
print(" Options:")
print(" -h - print this message and exit")
print(" -v - print additional information when running")
print(" -f <file> - path to config file")
print(" Arguments:")
print(" old-ip - current IPv4 address of the server")
print(" new-ip - new IPv4 address of the server")
print(" old-hostname - current FQDN for the server")
print(" new-hostname - new FQDN for the server")


def log(msg):
serverRoot = serverRootLocation()
logDir = os.path.join(serverRoot, "Logs")
logFile = os.path.join(logDir, "changeip.log")

try:
timestamp = datetime.datetime.now().strftime("%b %d %H:%M:%S")
msg = "changeip_calendar: %s %s" % (timestamp, msg)
with open(logFile, 'a') as output:
output.write("%s\n" % (msg,))
except IOError:
# Could not write to log
pass


def main():

@@ -44,27 +77,22 @@ def main():

try:
(optargs, args) = getopt(
sys.argv[1:], "hvf:", [
sys.argv[1:], "hf:", [
"help",
"verbose",
"config=",
]
)
except GetoptError:
usage()
sys.exit(1)

verbose = False
configFile = "/Library/Server/Calendar and Contacts/Config/caldavd-system.plist"
configFile = None

for opt, arg in optargs:
if opt in ("-h", "--help"):
usage()
sys.exit(1)

elif opt in ("-v", "--verbose"):
verbose = True

elif opt in ("-f", "--config"):
configFile = arg

@@ -74,33 +102,79 @@ def main():
except ValueError:
oldHostname = newHostname = None

if verbose:
print("Calendar Server: updating %s" % (configFile,))
log("args: {}".format(args))

try:
plist = readPlist(configFile)
except IOError:
print("Error: could not open %s" % (configFile,))
sys.exit(1)
except Exception, e:
print("Error: could not parse %s" % (configFile,))
raise e
config = readConfig(configFile=configFile)

writePlist(plist, "%s.changeip.bak" % (configFile,))
updateConfig(
config,
oldIP, newIP,
oldHostname, newHostname
)
writeConfig(config)



def sendCommand(commandDict, configFile=None):

args = [CALENDARSERVER_CONFIG]
if configFile is not None:
args.append("-f {}".format(configFile))

child = subprocess.Popen(
args=args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)

updatePlist(plist, oldIP, newIP, oldHostname, newHostname, verbose=verbose)
writePlist(plist, configFile)
commandString = plistlib.writePlistToString(commandDict)
log("Sending to calendarserver_config: {}".format(commandString))

if verbose:
print("Calendar Server: done")
output, error = child.communicate(input=commandString)
log("Output from calendarserver_config: {}".format(output))
if child.returncode:
log(
"Error from calendarserver_config: {}, {}".format(
child.returncode, error
)
)
return None
else:
return plistlib.readPlistFromString(output)["result"]


def readConfig(configFile=None):
"""
Ask calendarserver_config for the current configuration
"""

command = {
"command": "readConfig"
}
return sendCommand(command)



def updatePlist(plist, oldIP, newIP, oldHostname, newHostname, verbose=False):
def writeConfig(valuesDict, configFile=None):
"""
Ask calendarserver_config to update the configuration
"""
command = {
"command": "writeConfig",
"Values": valuesDict,
}
return sendCommand(command)


def updateConfig(
config,
oldIP, newIP,
oldHostname, newHostname,
configFile=None
):

keys = (
("Authentication", "Wiki", "Hostname"),
("BindAddresses",),
("Scheduling", "iMIP", "Receiving", "Server"),
("Scheduling", "iMIP", "Sending", "Server"),
("Scheduling", "iMIP", "Sending", "Address"),
@@ -111,12 +185,12 @@ def _replace(value, oldIP, newIP, oldHostname, newHostname):
newValue = value.replace(oldIP, newIP)
if oldHostname and newHostname:
newValue = newValue.replace(oldHostname, newHostname)
if verbose and value != newValue:
print("Changed %s -> %s" % (value, newValue))
if value != newValue:
log("Changed %s -> %s" % (value, newValue))
return newValue

for keyPath in keys:
parent = plist
parent = config
path = keyPath[:-1]
key = keyPath[-1]

@@ -133,16 +207,17 @@ def _replace(value, oldIP, newIP, oldHostname, newHostname):
if isinstance(value, list):
newValue = []
for item in value:
item = _replace(item, oldIP, newIP, oldHostname,
newHostname)
item = _replace(
item, oldIP, newIP, oldHostname, newHostname
)
newValue.append(item)
else:
newValue = _replace(value, oldIP, newIP, oldHostname,
newHostname)
newValue = _replace(
value, oldIP, newIP, oldHostname, newHostname
)

parent[key] = newValue



if __name__ == '__main__':
main()
@@ -15,65 +15,46 @@
##

from twistedcaldav.test.util import TestCase
from calendarserver.tools.changeip_calendar import updatePlist
from calendarserver.tools.changeip_calendar import updateConfig


class ChangeIPTestCase(TestCase):

def test_updatePlist(self):
def test_updateConfig(self):

plist = {
"Authentication" : {
"Wiki" : {
"Hostname" : "original_hostname",
"Other" : "should_be_untouched",
},
},
"Untouched" : "dont_change_me",
"BindAddresses" : [
"10.1.1.1",
"192.168.1.1",
"original_hostname",
],
"ServerHostName" : "",
"Scheduling" : {
"iMIP" : {
"Receiving" : {
"Server" : "original_hostname",
"Untouched": "dont_change_me",
"ServerHostName": "",
"Scheduling": {
"iMIP": {
"Receiving": {
"Server": "original_hostname",
},
"Sending" : {
"Server" : "original_hostname",
"Address" : "user@original_hostname",
"Sending": {
"Server": "original_hostname",
"Address": "user@original_hostname",
},
},
},
}

updatePlist(plist, "10.1.1.1", "10.1.1.2", "original_hostname",
"new_hostname")
updateConfig(
plist, "10.1.1.1", "10.1.1.2", "original_hostname", "new_hostname"
)

self.assertEquals(plist,
self.assertEquals(
plist,
{
"Authentication" : {
"Wiki" : {
"Hostname" : "new_hostname",
"Other" : "should_be_untouched",
},
},
"Untouched" : "dont_change_me",
"BindAddresses" : [
"10.1.1.2",
"192.168.1.1",
"new_hostname",
],
"ServerHostName" : "",
"Scheduling" : {
"iMIP" : {
"Receiving" : {
"Server" : "new_hostname",
"Untouched": "dont_change_me",
"ServerHostName": "",
"Scheduling": {
"iMIP": {
"Receiving": {
"Server": "new_hostname",
},
"Sending" : {
"Server" : "new_hostname",
"Address" : "user@new_hostname",
"Sending": {
"Server": "new_hostname",
"Address": "user@new_hostname",
},
},
},

0 comments on commit 59a4b8f

Please sign in to comment.
You can’t perform that action at this time.