[CalendarServer-changes] [6071] CalendarServer/branches/users/glyph/sql-store/txdav/datastore/ subpostgres.py
source_changes at macosforge.org
source_changes at macosforge.org
Wed Aug 11 18:11:03 PDT 2010
Revision: 6071
http://trac.macosforge.org/projects/calendarserver/changeset/6071
Author: sagen at apple.com
Date: 2010-08-11 18:11:00 -0700 (Wed, 11 Aug 2010)
Log Message:
-----------
Use spawnProcess + CapturingProcessProtocol so we can specify the uid/gid for initdb to run as.
Modified Paths:
--------------
CalendarServer/branches/users/glyph/sql-store/txdav/datastore/subpostgres.py
Modified: CalendarServer/branches/users/glyph/sql-store/txdav/datastore/subpostgres.py
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txdav/datastore/subpostgres.py 2010-08-12 00:25:05 UTC (rev 6070)
+++ CalendarServer/branches/users/glyph/sql-store/txdav/datastore/subpostgres.py 2010-08-12 01:11:00 UTC (rev 6071)
@@ -22,8 +22,8 @@
from hashlib import md5
from twisted.python.procutils import which
-from twisted.internet.utils import getProcessOutput
from twisted.internet.protocol import ProcessProtocol
+from twisted.internet.error import ProcessDone
from twisted.python.reflect import namedAny
from twisted.python import log
from twext.python.filepath import CachingFilePath
@@ -154,7 +154,77 @@
self.completionDeferred.callback(None)
+class ErrorOutput(Exception):
+ """
+ The process produced some error output and exited with a non-zero exit
+ code.
+ """
+
+class CapturingProcessProtocol(ProcessProtocol):
+ """
+ A L{ProcessProtocol} that captures its output and error.
+
+ @ivar output: a C{list} of all C{str}s received to stderr.
+
+ @ivar error: a C{list} of all C{str}s received to stderr.
+ """
+
+ def __init__(self, deferred, inputData):
+ """
+ Initialize a L{CapturingProcessProtocol}.
+
+ @param deferred: the L{Deferred} to fire when the process is complete.
+
+ @param inputData: a C{str} to feed to the subprocess's stdin.
+ """
+ self.deferred = deferred
+ self.input = inputData
+ self.output = []
+ self.error = []
+
+
+ def connectionMade(self):
+ """
+ The process started; feed its input on stdin.
+ """
+ if self.input is not None:
+ self.transport.write(self.input)
+ self.transport.closeStdin()
+
+
+ def outReceived(self, data):
+ """
+ Some output was received on stdout.
+ """
+ self.output.append(data)
+
+
+ def errReceived(self, data):
+ """
+ Some output was received on stderr.
+ """
+ self.error.append(data)
+ # Attempt to exit promptly if a traceback is displayed, so we don't
+ # deal with timeouts.
+ lines = ''.join(self.error).split("\n")
+ if len(lines) > 1:
+ errorReportLine = lines[-2].split(": ", 1)
+ if len(errorReportLine) == 2 and ' ' not in errorReportLine[0] and '\t' not in errorReportLine[0]:
+ self.transport.signalProcess("TERM")
+
+
+ def processEnded(self, why):
+ """
+ The process is over, fire the Deferred with the output.
+ """
+ if why.check(ProcessDone) and not self.error:
+ self.deferred.callback(''.join(self.output))
+ else:
+ self.deferred.errback(ErrorOutput(''.join(self.error)))
+
+
+
class PostgresService(MultiService):
def __init__(self, dataStoreDirectory, subServiceFactory,
@@ -333,17 +403,21 @@
initdb = which("initdb")[0]
if not self.socketDir.isdir():
self.socketDir.createDirectory()
- if clusterDir.isdir():
+ if self.uid and self.gid:
+ os.chown(self.socketDir.path, self.uid, self.gid)
+ if self.dataStoreDirectory.isdir():
self.startDatabase()
else:
- if not self.dataStoreDirectory.isdir():
- self.dataStoreDirectory.createDirectory()
- if not clusterDir.isdir():
- clusterDir.createDirectory()
- if not workingDir.isdir():
- workingDir.createDirectory()
- dbInited = getProcessOutput(
- initdb, [], env, workingDir.path, errortoo=True
+ self.dataStoreDirectory.createDirectory()
+ workingDir.createDirectory()
+ if self.uid and self.gid:
+ os.chown(self.dataStoreDirectory.path, self.uid, self.gid)
+ os.chown(workingDir.path, self.uid, self.gid)
+ dbInited = Deferred()
+ reactor.spawnProcess(
+ CapturingProcessProtocol(dbInited, None),
+ initdb, [], env, workingDir.path,
+ uid=self.uid, gid=self.gid,
)
def doCreate(result):
self.startDatabase()
@@ -362,7 +436,8 @@
pg_ctl = which("pg_ctl")[0]
reactor.spawnProcess(monitor, pg_ctl,
[pg_ctl, '-l', 'logfile', 'stop'],
- self.env
+ self.env,
+ uid=self.uid, gid=self.gid,
)
return monitor.completionDeferred
return d.addCallback(superStopped)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100811/0b31b6b5/attachment.html>
More information about the calendarserver-changes
mailing list