summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2009-05-03 15:35:29 -0400
committerBarry Warsaw2009-05-03 15:35:29 -0400
commite920c98c72fc9674316ae32c26a81fe571964ea5 (patch)
tree905de48fe2f08c939b77e13f0fcf35ad1b6e8efa
parent443aba66658347d0b747ff84ec1750cfb8c71924 (diff)
downloadmailman-e920c98c72fc9674316ae32c26a81fe571964ea5.tar.gz
mailman-e920c98c72fc9674316ae32c26a81fe571964ea5.tar.zst
mailman-e920c98c72fc9674316ae32c26a81fe571964ea5.zip
-rw-r--r--src/mailman/bin/qrunner.py16
-rw-r--r--src/mailman/config/mailman.cfg3
-rw-r--r--src/mailman/config/schema.cfg3
-rw-r--r--src/mailman/queue/rest.py50
-rw-r--r--src/mailman/rest/configure.zcml8
-rw-r--r--src/mailman/rest/urls.py34
-rw-r--r--src/mailman/rest/webservice.py20
7 files changed, 111 insertions, 23 deletions
diff --git a/src/mailman/bin/qrunner.py b/src/mailman/bin/qrunner.py
index 62e943aad..0016d082b 100644
--- a/src/mailman/bin/qrunner.py
+++ b/src/mailman/bin/qrunner.py
@@ -202,12 +202,16 @@ def main():
options.initialize()
if options.options.list:
- prefixlen = max(len(shortname)
- for shortname in config.qrunner_shortcuts)
- for shortname in sorted(config.qrunner_shortcuts):
- runnername = config.qrunner_shortcuts[shortname]
- shortname = (' ' * (prefixlen - len(shortname))) + shortname
- print _('$shortname runs $runnername')
+ descriptions = {}
+ for section in config.qrunner_configs:
+ shortname = section.name.rsplit('.', 1)[-1]
+ classname = getattr(section, 'class').rsplit('.', 1)[-1]
+ descriptions[shortname] = classname
+ longest = max(len(name) for name in descriptions)
+ for shortname in sorted(descriptions):
+ classname = descriptions[shortname]
+ name = (' ' * (longest - len(shortname))) + shortname
+ print _('$name runs $classname')
sys.exit(0)
# Fast track for one infinite runner
diff --git a/src/mailman/config/mailman.cfg b/src/mailman/config/mailman.cfg
index d68099ca3..58dcdd4e8 100644
--- a/src/mailman/config/mailman.cfg
+++ b/src/mailman/config/mailman.cfg
@@ -54,6 +54,9 @@ class: mailman.queue.outgoing.OutgoingRunner
[qrunner.pipeline]
class: mailman.queue.pipeline.PipelineRunner
+[qrunner.rest]
+class: mailman.queue.rest.RESTRunner
+
[qrunner.retry]
class: mailman.queue.retry.RetryRunner
sleep_time: 15m
diff --git a/src/mailman/config/schema.cfg b/src/mailman/config/schema.cfg
index a2003d034..73a2ff34e 100644
--- a/src/mailman/config/schema.cfg
+++ b/src/mailman/config/schema.cfg
@@ -211,6 +211,9 @@ failure: $msgid delivery to $recip failed with code $smtpcode, $smtpmsg
# The hostname at which admin web service resources are exposed.
hostname: localhost
+# The port at which the admin web service resources are exposed.
+port: 8001
+
# Whether or not requests to the web service are secured through SSL.
use_https: no
diff --git a/src/mailman/queue/rest.py b/src/mailman/queue/rest.py
new file mode 100644
index 000000000..3d0eb3bae
--- /dev/null
+++ b/src/mailman/queue/rest.py
@@ -0,0 +1,50 @@
+# Copyright (C) 2009 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Start the administrative HTTP server."""
+
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'RESTRunner',
+ ]
+
+
+import sys
+import errno
+import select
+import signal
+import logging
+
+from mailman.queue import Runner
+from mailman.rest.webservice import start
+
+
+
+class RESTRunner(Runner):
+ def run(self):
+ try:
+ start()
+ except KeyboardInterrupt:
+ sys.exit(signal.SIGTERM)
+ except select.error as (errcode, message):
+ if errcode == errno.EINTR:
+ sys.exit(signal.SIGTERM)
+ raise
+ except:
+ raise
diff --git a/src/mailman/rest/configure.zcml b/src/mailman/rest/configure.zcml
index edd444d0d..70155bf67 100644
--- a/src/mailman/rest/configure.zcml
+++ b/src/mailman/rest/configure.zcml
@@ -10,11 +10,11 @@
<webservice:register module="mailman.interfaces.system" />
- <adapter factory="mailman.rest.urls.AbsoluteURLMapper" />
-
<adapter
- factory="mailman.rest.root.AdminWebServiceRootAbsoluteURL"
- name="absolute_url"
+ for="zope.interface.Interface
+ mailman.rest.webservice.AdminWebServiceRequest"
+ provides="zope.traversing.browser.interfaces.IAbsoluteURL"
+ factory="mailman.rest.urls.AbsoluteURLMapper"
/>
<utility
diff --git a/src/mailman/rest/urls.py b/src/mailman/rest/urls.py
index 0cd51e5f6..8d82fe2c6 100644
--- a/src/mailman/rest/urls.py
+++ b/src/mailman/rest/urls.py
@@ -29,25 +29,49 @@ from zope.component import adapts
from zope.interface import implements, Interface
from zope.traversing.browser.interfaces import IAbsoluteURL
+from mailman.config import config
+from mailman.core.system import system
+from mailman.rest.configuration import AdminWebServiceConfiguration
+from mailman.rest.webservice import AdminWebServiceApplication
+
class AbsoluteURLMapper:
"""Generic absolute url mapper."""
implements(IAbsoluteURL)
- adapts(Interface, IAbsoluteURL)
def __init__(self, context, request):
"""Initialize with respect to a context and request."""
- # Avoid circular imports.
- from mailman.rest.configuration import AdminWebServiceConfiguration
+ self.context = context
+ self.request = request
self.webservice_config = AdminWebServiceConfiguration()
- self.version = webservice_config.service_version_uri_prefix
+ self.version = self.webservice_config.service_version_uri_prefix
self.schema = ('https' if self.webservice_config.use_https else 'http')
self.hostname = config.webservice.hostname
+ self.port = int(config.webservice.port)
def __str__(self):
"""Return the semi-hard-coded URL to the service root."""
- return '{0.schema}://{0.hostname}/{0.version}'.format(self)
+ path = self[self.context]
+ return '{0.schema}://{0.hostname}:{0.port}/{0.version}/{1}'.format(
+ self, path)
__call__ = __str__
+
+ def __getitem__(self, ob):
+ """Return the path component for the object.
+
+ :param ob: The object we're looking for.
+ :type ob: anything
+ :return: The path component.
+ :rtype: string
+ :raises KeyError: if no path component can be found.
+ """
+ # Special cases.
+ if isinstance(ob, AdminWebServiceApplication):
+ return ''
+ urls = {
+ system: 'sys',
+ }
+ return urls[ob]
diff --git a/src/mailman/rest/webservice.py b/src/mailman/rest/webservice.py
index 8203b0439..fe14513b9 100644
--- a/src/mailman/rest/webservice.py
+++ b/src/mailman/rest/webservice.py
@@ -36,6 +36,7 @@ from zope.interface import implements
from zope.publisher.browser import BrowserRequest
from zope.publisher.publish import publish
+from mailman.config import config
from mailman.core.system import system
from mailman.interfaces.rest import IResolvePathNames
from mailman.rest.publication import AdminWebServicePublication
@@ -52,6 +53,11 @@ class AdminWebServiceApplication:
implements(IResolvePathNames)
def __init__(self, environ, start_response):
+ self.environ = environ
+ self.start_response = start_response
+
+ def __iter__(self):
+ environ = self.environ
# Create the request based on the HTTP method used.
method = environ.get('REQUEST_METHOD', 'GET').upper()
request = AdminWebServiceRequest(environ['wsgi.input'], environ)
@@ -63,9 +69,9 @@ class AdminWebServiceApplication:
request = publish(request, handle_errors=handle_errors)
# Start the WSGI server response.
response = request.response
- start_response(response.getStatusString(), response.getHeaders())
+ self.start_response(response.getStatusString(), response.getHeaders())
# Return the result body iterable.
- return response.consumeBodyIter()
+ return iter(response.consumeBodyIter())
def get(self, name):
"""Maps root names to resources."""
@@ -80,9 +86,7 @@ def start():
"""Start the WSGI admin REST service."""
zcml = resource_string('mailman.rest', 'configure.zcml')
xmlconfig.string(zcml)
- server = make_server('', 8001, AdminWebServiceApplication)
- return server
-
-
-if __name__ == '__main__':
- start().serve_forever()
+ host = config.webservice.hostname
+ port = int(config.webservice.port)
+ server = make_server(host, port, AdminWebServiceApplication)
+ server.serve_forever()