Hello community,
here is the log from the commit of package python-oslo.service for
openSUSE:Factory checked in at 2015-09-09 20:20:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-oslo.service (Old)
and /work/SRC/openSUSE:Factory/.python-oslo.service.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-oslo.service"
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-oslo.service/python-oslo.service.changes
2015-09-02 07:54:10.000000000 +0200
+++
/work/SRC/openSUSE:Factory/.python-oslo.service.new/python-oslo.service.changes
2015-09-09 20:20:55.000000000 +0200
@@ -1,0 +2,10 @@
+Thu Sep 3 19:33:04 UTC 2015 - [email protected]
+
+- update to 0.9.0:
+ * Handling corner cases in dynamic looping call
+ * Change DEBUG log in loopingcall to TRACE level log
+ * Updated from global requirements
+ * Added wsgi functionality
+- Adjust Requires according to requirements.txt
+
+-------------------------------------------------------------------
Old:
----
oslo.service-0.7.0.tar.gz
New:
----
oslo.service-0.9.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-oslo.service.spec ++++++
--- /var/tmp/diff_new_pack.oDP1Dr/_old 2015-09-09 20:20:55.000000000 +0200
+++ /var/tmp/diff_new_pack.oDP1Dr/_new 2015-09-09 20:20:55.000000000 +0200
@@ -17,7 +17,7 @@
Name: python-oslo.service
-Version: 0.7.0
+Version: 0.9.0
Release: 0
Summary: Oslo service library
License: Apache-2.0
@@ -28,14 +28,20 @@
BuildRequires: python-devel
BuildRequires: python-pbr
Requires: python-Babel >= 1.3
+Requires: python-Paste
+Requires: python-PasteDeploy >= 1.5.0
+Requires: python-Routes >= 1.12.3
+Requires: python-WebOb >= 1.2.3
Requires: python-eventlet >= 0.17.4
Requires: python-greenlet >= 0.3.2
Requires: python-monotonic >= 0.3
Requires: python-oslo.concurrency >= 2.3.0
-Requires: python-oslo.config >= 2.1.0
+Requires: python-oslo.config >= 2.3.0
Requires: python-oslo.i18n >= 1.5.0
+Requires: python-oslo.log >= 1.8.0
Requires: python-oslo.utils >= 2.0.0
Requires: python-six >= 1.9.0
+
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%if 0%{?suse_version} && 0%{?suse_version} <= 1110
%{!?python_sitelib: %global python_sitelib %(python -c "from
distutils.sysconfig import get_python_lib; print get_python_lib()")}
++++++ oslo.service-0.7.0.tar.gz -> oslo.service-0.9.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/AUTHORS
new/oslo.service-0.9.0/AUTHORS
--- old/oslo.service-0.7.0/AUTHORS 2015-08-18 22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/AUTHORS 2015-09-01 20:39:42.000000000 +0200
@@ -73,6 +73,7 @@
Soren Hansen <[email protected]>
Steve Martinelli <[email protected]>
Steven Hardy <[email protected]>
+Surojit Pathak <[email protected]>
Thomas Herve <[email protected]>
Tianhua Huang <[email protected]>
Tom Cammann <[email protected]>
@@ -81,6 +82,7 @@
Zhongyue Luo <[email protected]>
fujioka yuuichi <[email protected]>
gongysh <[email protected]>
+liu-sheng <[email protected]>
liyingjun <[email protected]>
ravikumar-venkatesan <[email protected]>
stanzgy <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/ChangeLog
new/oslo.service-0.9.0/ChangeLog
--- old/oslo.service-0.7.0/ChangeLog 2015-08-18 22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/ChangeLog 2015-09-01 20:39:41.000000000 +0200
@@ -1,6 +1,18 @@
CHANGES
=======
+0.9.0
+-----
+
+* Handling corner cases in dynamic looping call
+* Change DEBUG log in loopingcall to TRACE level log
+* Updated from global requirements
+
+0.8.0
+-----
+
+* Added wsgi functionality
+
0.7.0
-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/PKG-INFO
new/oslo.service-0.9.0/PKG-INFO
--- old/oslo.service-0.7.0/PKG-INFO 2015-08-18 22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/PKG-INFO 2015-09-01 20:39:42.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: oslo.service
-Version: 0.7.0
+Version: 0.9.0
Summary: oslo.service library
Home-page: http://launchpad.net/oslo
Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/doc/source/usage.rst
new/oslo.service-0.9.0/doc/source/usage.rst
--- old/oslo.service-0.7.0/doc/source/usage.rst 2015-08-18 22:23:15.000000000
+0200
+++ new/oslo.service-0.9.0/doc/source/usage.rst 2015-09-01 20:39:05.000000000
+0200
@@ -58,6 +58,9 @@
* :func:`oslo.service.sslutils <oslo_service.sslutils.list_opts>`
The options from the sslutils module for the [ssl] section.
+* :func:`oslo.service.wsgi <oslo_service.wsgi.list_opts>`
+ The options from the wsgi module for the [DEFAULT] section.
+
**ATTENTION:** The library doesn't provide an oslo.service entry point.
.. code-block:: bash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/oslo.service.egg-info/PKG-INFO
new/oslo.service-0.9.0/oslo.service.egg-info/PKG-INFO
--- old/oslo.service-0.7.0/oslo.service.egg-info/PKG-INFO 2015-08-18
22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/oslo.service.egg-info/PKG-INFO 2015-09-01
20:39:42.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: oslo.service
-Version: 0.7.0
+Version: 0.9.0
Summary: oslo.service library
Home-page: http://launchpad.net/oslo
Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/oslo.service.egg-info/SOURCES.txt
new/oslo.service-0.9.0/oslo.service.egg-info/SOURCES.txt
--- old/oslo.service-0.7.0/oslo.service.egg-info/SOURCES.txt 2015-08-18
22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/oslo.service.egg-info/SOURCES.txt 2015-09-01
20:39:42.000000000 +0200
@@ -51,6 +51,7 @@
oslo_service/sslutils.py
oslo_service/systemd.py
oslo_service/threadgroup.py
+oslo_service/wsgi.py
oslo_service/tests/__init__.py
oslo_service/tests/base.py
oslo_service/tests/eventlet_service.py
@@ -59,4 +60,9 @@
oslo_service/tests/test_periodic.py
oslo_service/tests/test_service.py
oslo_service/tests/test_systemd.py
-oslo_service/tests/test_threadgroup.py
\ No newline at end of file
+oslo_service/tests/test_threadgroup.py
+oslo_service/tests/test_wsgi.py
+oslo_service/tests/ssl_cert/ca.crt
+oslo_service/tests/ssl_cert/ca.key
+oslo_service/tests/ssl_cert/certificate.crt
+oslo_service/tests/ssl_cert/privatekey.key
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.service-0.7.0/oslo.service.egg-info/entry_points.txt
new/oslo.service-0.9.0/oslo.service.egg-info/entry_points.txt
--- old/oslo.service-0.7.0/oslo.service.egg-info/entry_points.txt
2015-08-18 22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/oslo.service.egg-info/entry_points.txt
2015-09-01 20:39:42.000000000 +0200
@@ -2,4 +2,5 @@
oslo.service.periodic_task = oslo_service.periodic_task:list_opts
oslo.service.service = oslo_service.service:list_opts
oslo.service.sslutils = oslo_service.sslutils:list_opts
+oslo.service.wsgi = oslo_service.wsgi:list_opts
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/oslo.service.egg-info/pbr.json
new/oslo.service-0.9.0/oslo.service.egg-info/pbr.json
--- old/oslo.service-0.7.0/oslo.service.egg-info/pbr.json 2015-08-18
22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/oslo.service.egg-info/pbr.json 2015-09-01
20:39:42.000000000 +0200
@@ -1 +1 @@
-{"is_release": true, "git_version": "ae46422"}
\ No newline at end of file
+{"is_release": true, "git_version": "fad5b04"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.service-0.7.0/oslo.service.egg-info/requires.txt
new/oslo.service-0.9.0/oslo.service.egg-info/requires.txt
--- old/oslo.service-0.7.0/oslo.service.egg-info/requires.txt 2015-08-18
22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/oslo.service.egg-info/requires.txt 2015-09-01
20:39:42.000000000 +0200
@@ -1,9 +1,19 @@
Babel>=1.3
+WebOb>=1.2.3
eventlet>=0.17.4
greenlet>=0.3.2
-monotonic>=0.3 # Apache-2.0
-oslo.utils>=2.0.0 # Apache-2.0
-oslo.concurrency>=2.3.0 # Apache-2.0
-oslo.config>=2.1.0 # Apache-2.0
+monotonic>=0.3
+oslo.utils>=2.0.0
+oslo.concurrency>=2.3.0
+oslo.config>=2.3.0
+oslo.log>=1.8.0
six>=1.9.0
-oslo.i18n>=1.5.0 # Apache-2.0
+oslo.i18n>=1.5.0
+PasteDeploy>=1.5.0
+Paste
+
+[:(python_version!='2.7')]
+Routes!=2.0,>=1.12.3
+
+[:(python_version=='2.7')]
+Routes!=2.0,!=2.1,>=1.12.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/oslo_service/_options.py
new/oslo.service-0.9.0/oslo_service/_options.py
--- old/oslo.service-0.7.0/oslo_service/_options.py 2015-08-18
22:23:15.000000000 +0200
+++ new/oslo.service-0.9.0/oslo_service/_options.py 2015-09-01
20:39:05.000000000 +0200
@@ -41,6 +41,42 @@
'options when starting a service (at DEBUG level).'),
]
+wsgi_opts = [
+ cfg.StrOpt('api_paste_config',
+ default="api-paste.ini",
+ help='File name for the paste.deploy config for api service'),
+ cfg.StrOpt('wsgi_log_format',
+ default='%(client_ip)s "%(request_line)s" status: '
+ '%(status_code)s len: %(body_length)s time:'
+ ' %(wall_seconds).7f',
+ help='A python format string that is used as the template to '
+ 'generate log lines. The following values can be'
+ 'formatted into it: client_ip, date_time, request_line, '
+ 'status_code, body_length, wall_seconds.'),
+ cfg.IntOpt('tcp_keepidle',
+ default=600,
+ help="Sets the value of TCP_KEEPIDLE in seconds for each "
+ "server socket. Not supported on OS X."),
+ cfg.IntOpt('wsgi_default_pool_size',
+ default=1000,
+ help="Size of the pool of greenthreads used by wsgi"),
+ cfg.IntOpt('max_header_line',
+ default=16384,
+ help="Maximum line size of message headers to be accepted. "
+ "max_header_line may need to be increased when using "
+ "large tokens (typically those generated by the "
+ "Keystone v3 API with big service catalogs)."),
+ cfg.BoolOpt('wsgi_keep_alive',
+ default=True,
+ help="If False, closes the client socket connection "
+ "explicitly."),
+ cfg.IntOpt('client_socket_timeout', default=900,
+ help="Timeout for client connections' socket operations. "
+ "If an incoming connection is idle for this number of "
+ "seconds it will be closed. A value of '0' means "
+ "wait forever."),
+ ]
+
ssl_opts = [
cfg.StrOpt('ca_file',
help="CA certificate file to use to verify "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/oslo_service/loopingcall.py
new/oslo.service-0.9.0/oslo_service/loopingcall.py
--- old/oslo.service-0.7.0/oslo_service/loopingcall.py 2015-08-18
22:23:15.000000000 +0200
+++ new/oslo.service-0.9.0/oslo_service/loopingcall.py 2015-09-01
20:39:05.000000000 +0200
@@ -15,11 +15,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import logging
import sys
from eventlet import event
from eventlet import greenthread
+from oslo_log import log as logging
from oslo_utils import excutils
from oslo_utils import reflection
from oslo_utils import timeutils
@@ -115,7 +115,7 @@
if not self._running:
break
idle = idle_for_func(result, watch.elapsed())
- LOG.debug('%(kind)s %(func_name)r sleeping '
+ LOG.trace('%(kind)s %(func_name)r sleeping '
'for %(idle).02f seconds',
{'func_name': func_name, 'idle': idle,
'kind': kind})
@@ -166,6 +166,10 @@
_RUN_ONLY_ONE_MESSAGE = _("A dynamic interval looping call can only run"
" one function at a time")
+ _TASK_MISSING_SLEEP_VALUE_MESSAGE = _(
+ "A dynamic interval looping call should supply either an"
+ " interval or periodic_interval_max"
+ )
_KIND = _('Dynamic interval looping call')
@@ -173,9 +177,20 @@
stop_on_exception=True):
def _idle_for(suggested_delay, elapsed):
delay = suggested_delay
- if periodic_interval_max is not None:
- delay = min(delay, periodic_interval_max)
+ if delay is None:
+ if periodic_interval_max is not None:
+ delay = periodic_interval_max
+ else:
+ # Note(suro-patz): An application used to receive a
+ # TypeError thrown from eventlet layer, before
+ # this RuntimeError was introduced.
+ raise RuntimeError(
+ self._TASK_MISSING_SLEEP_VALUE_MESSAGE)
+ else:
+ if periodic_interval_max is not None:
+ delay = min(delay, periodic_interval_max)
return delay
+
return self._start(_idle_for, initial_delay=initial_delay,
stop_on_exception=stop_on_exception)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.service-0.7.0/oslo_service/tests/ssl_cert/ca.crt
new/oslo.service-0.9.0/oslo_service/tests/ssl_cert/ca.crt
--- old/oslo.service-0.7.0/oslo_service/tests/ssl_cert/ca.crt 1970-01-01
01:00:00.000000000 +0100
+++ new/oslo.service-0.9.0/oslo_service/tests/ssl_cert/ca.crt 2015-09-01
20:39:05.000000000 +0200
@@ -0,0 +1,40 @@
+-----BEGIN CERTIFICATE-----
+MIIHADCCBOigAwIBAgIJAOjPGLL9VDhjMA0GCSqGSIb3DQEBDQUAMIGwMQswCQYD
+VQQGEwJVUzEOMAwGA1UECBMFVGV4YXMxDzANBgNVBAcTBkF1c3RpbjEdMBsGA1UE
+ChMUT3BlblN0YWNrIEZvdW5kYXRpb24xHTAbBgNVBAsTFE9wZW5TdGFjayBEZXZl
+bG9wZXJzMRAwDgYDVQQDEwdUZXN0IENBMTAwLgYJKoZIhvcNAQkBFiFvcGVuc3Rh
+Y2stZGV2QGxpc3RzLm9wZW5zdGFjay5vcmcwHhcNMTUwMTA4MDIyOTEzWhcNMjUw
+MTA4MDIyOTEzWjCBsDELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYD
+VQQHEwZBdXN0aW4xHTAbBgNVBAoTFE9wZW5TdGFjayBGb3VuZGF0aW9uMR0wGwYD
+VQQLExRPcGVuU3RhY2sgRGV2ZWxvcGVyczEQMA4GA1UEAxMHVGVzdCBDQTEwMC4G
+CSqGSIb3DQEJARYhb3BlbnN0YWNrLWRldkBsaXN0cy5vcGVuc3RhY2sub3JnMIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwILIMebpHYK1E1zhyi6713GG
+TQ9DFeLOE1T25+XTJqAkO7efQzZfB8QwCXy/8bmbhmKgQQ7APuuDci8SKCkYeWCx
+qJRGmg0tZVlj5gCfrV2u+olwS+XyaOGCFkYScs6D34BaE2rGD2GDryoSPc2feAt6
+X4+ZkDPZnvaHQP6j9Ofq/4WmsECEas0IO5X8SDF8afA47U9ZXFkcgQK6HCHDcokL
+aaZxEyZFSaPex6ZAESNthkGOxEThRPxAkJhqYCeMl3Hff98XEUcFNzuAOmcnQJJg
+RemwJO2hS5KS3Y3p9/nBRlh3tSAG1nbY5kXSpyaq296D9x/esnXlt+9JUmn1rKyv
+maFBC/SbzyyQoO3MT5r8rKte0bulLw1bZOZNlhxSv2KCg5RD6vlNrnpsZszw4nj2
+8fBroeFp0JMeT8jcqGs3qdm8sXLcBgiTalLYtiCNV9wZjOduQotuFN6mDwZvfa6h
+zZjcBNfqeLyTEnFb5k6pIla0wydWx/jvBAzoxOkEcVjak747A+p/rriD5hVUBH0B
+uNaWcEgKe9jcHnLvU8hUxFtgPxUHOOR+eMa+FS3ApKf9sJ/zVUq0uxyA9hUnsvnq
+v/CywLSvaNKBiKQTL0QLEXnw6EQb7g/XuwC5mmt+l30wGh9M1U/QMaU/+YzT4sVL
+TXIHJ7ExRTbEecbNbjsCAwEAAaOCARkwggEVMB0GA1UdDgQWBBQTWz2WEB0sJg9c
+xfM5JeJMIAJq0jCB5QYDVR0jBIHdMIHagBQTWz2WEB0sJg9cxfM5JeJMIAJq0qGB
+tqSBszCBsDELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZB
+dXN0aW4xHTAbBgNVBAoTFE9wZW5TdGFjayBGb3VuZGF0aW9uMR0wGwYDVQQLExRP
+cGVuU3RhY2sgRGV2ZWxvcGVyczEQMA4GA1UEAxMHVGVzdCBDQTEwMC4GCSqGSIb3
+DQEJARYhb3BlbnN0YWNrLWRldkBsaXN0cy5vcGVuc3RhY2sub3JnggkA6M8Ysv1U
+OGMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOCAgEAIfAD6uVorT5WomG1
+2DWRm3kuwa+EDimgVF6VRvxCzyHx7e/6KJQj149KpMQ6e0ZPjqQw+pZ+jJSgq6TP
+MEjCHgIDwdKhi9LmQWIlo8xdzgfZW2VQkVLvwkqAnWWhCy9oGc/Ypk8pjiZfCx+/
+DSJBbFnopI9f8epAKMq7N3jJyEMoTctzmI0KckrZnJ1Gq4MZpoxGmkJiGhWoUk8p
+r8apXZ6B1DzO1XxpGw2BIcrUC3bQS/vPrg5/XbyaAu2BSgu6iF7ULqkBsEd0yK/L
+i2gO9eTacaX3zJBQOlMJFsIAgIiVw6Rq6BuhU9zxDoopY4feta/NDOpk1OjY3MV7
+4rcLTU6XYaItMDRe+dmjBOK+xspsaCU4kHEkA7mHL5YZhEEWLHj6QY8tAiIQMVQZ
+RuTpQIbNkjLW8Ls+CbwL2LkUFB19rKu9tFpzEJ1IIeFmt5HZsL5ri6W2qkSPIbIe
+Qq15kl/a45jgBbgn2VNA5ecjW20hhXyaS9AKWXK+AeFBaFIFDUrB2UP4YSDbJWUJ
+0LKe+QuumXdl+iRdkgb1Tll7qme8gXAeyzVGHK2AsaBg+gkEeSyVLRKIixceyy+3
+6yqlKJhk2qeV3ceOfVm9ZdvRlzWyVctaTcGIpDFqf4y8YyVhL1e2KGKcmYtbLq+m
+rtku4CM3HldxcM4wqSB1VcaTX8o=
+-----END CERTIFICATE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.service-0.7.0/oslo_service/tests/ssl_cert/ca.key
new/oslo.service-0.9.0/oslo_service/tests/ssl_cert/ca.key
--- old/oslo.service-0.7.0/oslo_service/tests/ssl_cert/ca.key 1970-01-01
01:00:00.000000000 +0100
+++ new/oslo.service-0.9.0/oslo_service/tests/ssl_cert/ca.key 2015-09-01
20:39:05.000000000 +0200
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.service-0.7.0/oslo_service/tests/ssl_cert/certificate.crt
new/oslo.service-0.9.0/oslo_service/tests/ssl_cert/certificate.crt
--- old/oslo.service-0.7.0/oslo_service/tests/ssl_cert/certificate.crt
1970-01-01 01:00:00.000000000 +0100
+++ new/oslo.service-0.9.0/oslo_service/tests/ssl_cert/certificate.crt
2015-09-01 20:39:05.000000000 +0200
@@ -0,0 +1,41 @@
+-----BEGIN CERTIFICATE-----
+MIIHHjCCBQagAwIBAgIBATANBgkqhkiG9w0BAQ0FADCBsDELMAkGA1UEBhMCVVMx
+DjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4xHTAbBgNVBAoTFE9wZW5T
+dGFjayBGb3VuZGF0aW9uMR0wGwYDVQQLExRPcGVuU3RhY2sgRGV2ZWxvcGVyczEQ
+MA4GA1UEAxMHVGVzdCBDQTEwMC4GCSqGSIb3DQEJARYhb3BlbnN0YWNrLWRldkBs
+aXN0cy5vcGVuc3RhY2sub3JnMB4XDTE1MDEwODAyNTQzNVoXDTI1MDEwODAyNTQz
+NVoweDELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0
+aW4xHTAbBgNVBAoTFE9wZW5TdGFjayBGb3VuZGF0aW9uMR0wGwYDVQQLExRPcGVu
+U3RhY2sgRGV2ZWxvcGVyczEKMAgGA1UEAxQBKjCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBANBJtvyhMKBn397hE7x9Ce/Ny+4ENQfr9VrHuvGNCR3W/uUb
+QafdNdZCYNAGPrq2T3CEYK0IJxZjr2HuTcSK9StBMFauTeIPqVUVkO3Tjq1Rkv+L
+np/e6DhHkjCU6Eq/jIw3ic0QoxLygTybGxXgJgVoBzGsJufzOQ14tfkzGeGyE3L5
+z5DpCNQqWLWF7soMx3kM5hBm+LWeoiBPjmsEXQY+UYiDlSLW/6I855X/wwDW5+Ot
+P6/1lWUfcyAyIqj3t0pmxZeY7xQnabWjhXT2dTK+dlwRjb77w665AgeF1R5lpTvU
+yT1aQwgH1kd9GeQbkBDwWSVLH9boPPgdMLtX2ipUgQAAEhIOUWXOYZVHVNXhV6Cr
+jAgvfdF39c9hmuXovPP24ikW4L+d5RPE7Vq9KJ4Uzijw9Ghu4lQQCRZ8SCNZIYJn
+Tz53+6fs93WwnnEPto9tFRKeNWt3jx/wjluDFhhBTZO4snNIq9xnCYSEQAIsRBVW
+Ahv7LqWLigUy7a9HMIyi3tQEZN9NCDy4BNuJDu33XWLLVMwNrIiR5mdCUFoRKt/E
++YPj7bNlzZMTSGLoBFPM71Lnfym9HazHDE1KxvT4gzYMubK4Y07meybiL4QNvU08
+ITgFU6DAGob+y/GHqw+bmez5y0F/6FlyV+SiSrbVEEtzp9Ewyrxb85OJFK0tAgMB
+AAGjggF4MIIBdDBLBgNVHREERDBCgglsb2NhbGhvc3SCDWlwNi1sb2NhbGhvc3SC
+CTEyNy4wLjAuMYIDOjoxhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMB0GA1UdDgQW
+BBSjWxD0qedj9eeGUWyGphy5PU67dDCB5QYDVR0jBIHdMIHagBQTWz2WEB0sJg9c
+xfM5JeJMIAJq0qGBtqSBszCBsDELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFz
+MQ8wDQYDVQQHEwZBdXN0aW4xHTAbBgNVBAoTFE9wZW5TdGFjayBGb3VuZGF0aW9u
+MR0wGwYDVQQLExRPcGVuU3RhY2sgRGV2ZWxvcGVyczEQMA4GA1UEAxMHVGVzdCBD
+QTEwMC4GCSqGSIb3DQEJARYhb3BlbnN0YWNrLWRldkBsaXN0cy5vcGVuc3RhY2su
+b3JnggkA6M8Ysv1UOGMwCQYDVR0TBAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAN
+BgkqhkiG9w0BAQ0FAAOCAgEAIGx/acXQEiGYFBJUduE6/Y6LBuHEVMcj0yfbLzja
+Eb35xKWHuX7tgQPwXy6UGlYM8oKIptIp/9eEuYXte6u5ncvD7e/JldCUVd0fW8hm
+fBOhfqVstcTmlfZ6WqTJD6Bp/FjUH+8qf8E+lsjNy7i0EsmcQOeQm4mkocHG1AA4
+MEeuDg33lV6XCjW450BoZ/FTfwZSuTlGgFlEzUUrAe/ETdajF9G9aJ+0OvXzE1tU
+pvbvkU8eg4pLXxrzboOhyQMEmCikdkMYjo/0ZQrXrrJ1W8mCinkJdz6CToc7nUkU
+F8tdAY0rKMEM8SYHngMJU2943lpGbQhE5B4oms8I+SMTyCVz2Vu5I43Px68Y0GUN
+Bn5qu0w2Vj8eradoPF8pEAIVICIvlbiRepPbNZ7FieSsY2TEfLtxBd2DLE1YWeE5
+p/RDBxqcDrGQuSg6gFSoLEhYgQcGnYgD75EIE8f/LrHFOAeSYEOhibFbK5G8p/2h
+EHcKZ9lvTgqwHn0FiTqZ3LWxVFsZiTsiyXErpJ2Nu2WTzo0k1xJMUpJqHuUZraei
+N5fA5YuDp2ShXRoZyVieRvp0TCmm6sHL8Pn0K8weJchYrvV1yvPKeuISN/fVCQev
+88yih5Rh5R2szwoY3uVImpd99bMm0e1bXrQug43ZUz9rC4ABN6+lZvuorDWRVI7U
+I1M=
+-----END CERTIFICATE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.service-0.7.0/oslo_service/tests/ssl_cert/privatekey.key
new/oslo.service-0.9.0/oslo_service/tests/ssl_cert/privatekey.key
--- old/oslo.service-0.7.0/oslo_service/tests/ssl_cert/privatekey.key
1970-01-01 01:00:00.000000000 +0100
+++ new/oslo.service-0.9.0/oslo_service/tests/ssl_cert/privatekey.key
2015-09-01 20:39:05.000000000 +0200
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/oslo.service-0.7.0/oslo_service/tests/test_loopingcall.py
new/oslo.service-0.9.0/oslo_service/tests/test_loopingcall.py
--- old/oslo.service-0.7.0/oslo_service/tests/test_loopingcall.py
2015-08-18 22:23:15.000000000 +0200
+++ new/oslo.service-0.9.0/oslo_service/tests/test_loopingcall.py
2015-09-01 20:39:05.000000000 +0200
@@ -192,6 +192,30 @@
timer = loopingcall.DynamicLoopingCall(self._wait_for_zero)
self.assertFalse(timer.start().wait())
+ def _timeout_task_without_any_return(self):
+ pass
+
+ def test_timeout_task_without_return_and_max_periodic(self):
+ timer = loopingcall.DynamicLoopingCall(
+ self._timeout_task_without_any_return
+ )
+ self.assertRaises(RuntimeError, timer.start().wait)
+
+ def _timeout_task_without_return_but_with_done(self):
+ if self.num_runs == 0:
+ raise loopingcall.LoopingCallDone(False)
+ else:
+ self.num_runs = self.num_runs - 1
+
+ @mock.patch('eventlet.greenthread.sleep')
+ def test_timeout_task_without_return(self, sleep_mock):
+ self.num_runs = 1
+ timer = loopingcall.DynamicLoopingCall(
+ self._timeout_task_without_return_but_with_done
+ )
+ timer.start(periodic_interval_max=5).wait()
+ sleep_mock.assert_has_calls([mock.call(5)])
+
@mock.patch('eventlet.greenthread.sleep')
def test_interval_adjustment(self, sleep_mock):
self.num_runs = 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/oslo_service/tests/test_wsgi.py
new/oslo.service-0.9.0/oslo_service/tests/test_wsgi.py
--- old/oslo.service-0.7.0/oslo_service/tests/test_wsgi.py 1970-01-01
01:00:00.000000000 +0100
+++ new/oslo.service-0.9.0/oslo_service/tests/test_wsgi.py 2015-09-01
20:39:05.000000000 +0200
@@ -0,0 +1,369 @@
+# Copyright 2011 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# 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.
+
+"""Unit tests for `wsgi`."""
+
+import os.path
+import platform
+import socket
+import tempfile
+import testtools
+
+import eventlet
+import eventlet.wsgi
+import mock
+import requests
+import webob
+
+from oslo_config import cfg
+from oslo_config import fixture as config
+from oslo_service import _options
+from oslo_service import sslutils
+from oslo_service import wsgi
+from oslo_utils import netutils
+from oslotest import base as test_base
+from oslotest import moxstubout
+
+
+SSL_CERT_DIR = os.path.normpath(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ 'ssl_cert'))
+CONF = cfg.CONF
+
+
+class WsgiTestCase(test_base.BaseTestCase):
+ """Base class for WSGI tests."""
+
+ def setUp(self):
+ super(WsgiTestCase, self).setUp()
+ self.conf_fixture = self.useFixture(config.Config())
+ self.conf_fixture.register_opts(_options.wsgi_opts)
+ self.conf = self.conf_fixture.conf
+ self.config = self.conf_fixture.config
+ self.conf(args=[], default_config_files=[])
+
+
+class TestLoaderNothingExists(WsgiTestCase):
+ """Loader tests where os.path.exists always returns False."""
+
+ def setUp(self):
+ super(TestLoaderNothingExists, self).setUp()
+ mox_fixture = self.useFixture(moxstubout.MoxStubout())
+ self.stubs = mox_fixture.stubs
+ self.stubs.Set(os.path, 'exists', lambda _: False)
+
+ def test_relpath_config_not_found(self):
+ self.config(api_paste_config='api-paste.ini')
+ self.assertRaises(
+ wsgi.ConfigNotFound,
+ wsgi.Loader,
+ self.conf
+ )
+
+ def test_asbpath_config_not_found(self):
+ self.config(api_paste_config='/etc/openstack-srv/api-paste.ini')
+ self.assertRaises(
+ wsgi.ConfigNotFound,
+ wsgi.Loader,
+ self.conf
+ )
+
+
+class TestLoaderNormalFilesystem(WsgiTestCase):
+ """Loader tests with normal filesystem (unmodified os.path module)."""
+
+ _paste_config = """
+[app:test_app]
+use = egg:Paste#static
+document_root = /tmp
+ """
+
+ def setUp(self):
+ super(TestLoaderNormalFilesystem, self).setUp()
+ self.paste_config = tempfile.NamedTemporaryFile(mode="w+t")
+ self.paste_config.write(self._paste_config.lstrip())
+ self.paste_config.seek(0)
+ self.paste_config.flush()
+
+ self.config(api_paste_config=self.paste_config.name)
+ self.loader = wsgi.Loader(CONF)
+
+ def test_config_found(self):
+ self.assertEqual(self.paste_config.name, self.loader.config_path)
+
+ def test_app_not_found(self):
+ self.assertRaises(
+ wsgi.PasteAppNotFound,
+ self.loader.load_app,
+ "nonexistent app",
+ )
+
+ def test_app_found(self):
+ url_parser = self.loader.load_app("test_app")
+ self.assertEqual("/tmp", url_parser.directory)
+
+ def tearDown(self):
+ self.paste_config.close()
+ super(TestLoaderNormalFilesystem, self).tearDown()
+
+
+class TestWSGIServer(WsgiTestCase):
+ """WSGI server tests."""
+
+ def setUp(self):
+ super(TestWSGIServer, self).setUp()
+
+ def test_no_app(self):
+ server = wsgi.Server(self.conf, "test_app", None)
+ self.assertEqual("test_app", server.name)
+
+ def test_custom_max_header_line(self):
+ self.config(max_header_line=4096) # Default value is 16384
+ wsgi.Server(self.conf, "test_custom_max_header_line", None)
+ self.assertEqual(self.conf.max_header_line,
+ eventlet.wsgi.MAX_HEADER_LINE)
+
+ def test_start_random_port(self):
+ server = wsgi.Server(self.conf, "test_random_port", None,
+ host="127.0.0.1", port=0)
+ server.start()
+ self.assertNotEqual(0, server.port)
+ server.stop()
+ server.wait()
+
+ @testtools.skipIf(not netutils.is_ipv6_enabled(), "no ipv6 support")
+ def test_start_random_port_with_ipv6(self):
+ server = wsgi.Server(self.conf, "test_random_port", None,
+ host="::1", port=0)
+ server.start()
+ self.assertEqual("::1", server.host)
+ self.assertNotEqual(0, server.port)
+ server.stop()
+ server.wait()
+
+ @testtools.skipIf(platform.mac_ver()[0] != '',
+ 'SO_REUSEADDR behaves differently '
+ 'on OSX, see bug 1436895')
+ def test_socket_options_for_simple_server(self):
+ # test normal socket options has set properly
+ self.config(tcp_keepidle=500)
+ server = wsgi.Server(self.conf, "test_socket_options", None,
+ host="127.0.0.1", port=0)
+ server.start()
+ sock = server._socket
+ self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
+ socket.SO_REUSEADDR))
+ self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
+ socket.SO_KEEPALIVE))
+ if hasattr(socket, 'TCP_KEEPIDLE'):
+ self.assertEqual(self.conf.tcp_keepidle,
+ sock.getsockopt(socket.IPPROTO_TCP,
+ socket.TCP_KEEPIDLE))
+ self.assertFalse(server._server.dead)
+ server.stop()
+ server.wait()
+ self.assertTrue(server._server.dead)
+
+ def test_server_pool_waitall(self):
+ # test pools waitall method gets called while stopping server
+ server = wsgi.Server(self.conf, "test_server", None, host="127.0.0.1")
+ server.start()
+ with mock.patch.object(server._pool,
+ 'waitall') as mock_waitall:
+ server.stop()
+ server.wait()
+ mock_waitall.assert_called_once_with()
+
+ def test_uri_length_limit(self):
+ eventlet.monkey_patch(os=False, thread=False)
+ server = wsgi.Server(self.conf, "test_uri_length_limit", None,
+ host="127.0.0.1", max_url_len=16384, port=33337)
+ server.start()
+ self.assertFalse(server._server.dead)
+
+ uri = "http://127.0.0.1:%d/%s" % (server.port, 10000 * 'x')
+ resp = requests.get(uri, proxies={"http": ""})
+ eventlet.sleep(0)
+ self.assertNotEqual(resp.status_code,
+ requests.codes.REQUEST_URI_TOO_LARGE)
+
+ uri = "http://127.0.0.1:%d/%s" % (server.port, 20000 * 'x')
+ resp = requests.get(uri, proxies={"http": ""})
+ eventlet.sleep(0)
+ self.assertEqual(resp.status_code,
+ requests.codes.REQUEST_URI_TOO_LARGE)
+ server.stop()
+ server.wait()
+
+ def test_reset_pool_size_to_default(self):
+ server = wsgi.Server(self.conf, "test_resize", None,
+ host="127.0.0.1", max_url_len=16384)
+ server.start()
+
+ # Stopping the server, which in turn sets pool size to 0
+ server.stop()
+ self.assertEqual(server._pool.size, 0)
+
+ # Resetting pool size to default
+ server.reset()
+ server.start()
+ self.assertEqual(server._pool.size, CONF.wsgi_default_pool_size)
+
+ def test_client_socket_timeout(self):
+ self.config(client_socket_timeout=5)
+
+ # mocking eventlet spawn method to check it is called with
+ # configured 'client_socket_timeout' value.
+ with mock.patch.object(eventlet,
+ 'spawn') as mock_spawn:
+ server = wsgi.Server(self.conf, "test_app", None,
+ host="127.0.0.1", port=0)
+ server.start()
+ _, kwargs = mock_spawn.call_args
+ self.assertEqual(self.conf.client_socket_timeout,
+ kwargs['socket_timeout'])
+ server.stop()
+
+ def test_wsgi_keep_alive(self):
+ self.config(wsgi_keep_alive=False)
+
+ # mocking eventlet spawn method to check it is called with
+ # configured 'wsgi_keep_alive' value.
+ with mock.patch.object(eventlet,
+ 'spawn') as mock_spawn:
+ server = wsgi.Server(self.conf, "test_app", None,
+ host="127.0.0.1", port=0)
+ server.start()
+ _, kwargs = mock_spawn.call_args
+ self.assertEqual(self.conf.wsgi_keep_alive,
+ kwargs['keepalive'])
+ server.stop()
+
+
+class TestWSGIServerWithSSL(WsgiTestCase):
+ """WSGI server with SSL tests."""
+
+ def setUp(self):
+ super(TestWSGIServerWithSSL, self).setUp()
+ self.conf_fixture.register_opts(_options.ssl_opts,
+ sslutils.config_section)
+ cert_file_name = os.path.join(SSL_CERT_DIR, 'certificate.crt')
+ key_file_name = os.path.join(SSL_CERT_DIR, 'privatekey.key')
+ eventlet.monkey_patch(os=False, thread=False)
+
+ self.config(cert_file=cert_file_name,
+ key_file=key_file_name,
+ group=sslutils.config_section)
+
+ def test_ssl_server(self):
+ def test_app(env, start_response):
+ start_response('200 OK', {})
+ return ['PONG']
+
+ fake_ssl_server = wsgi.Server(self.conf, "fake_ssl", test_app,
+ host="127.0.0.1", port=0, use_ssl=True)
+ fake_ssl_server.start()
+ self.assertNotEqual(0, fake_ssl_server.port)
+
+ cli = eventlet.connect(("localhost", fake_ssl_server.port))
+ ca_certs_name = os.path.join(SSL_CERT_DIR, 'ca.crt')
+ cli = eventlet.wrap_ssl(cli, ca_certs=ca_certs_name)
+
+ cli.write('POST / HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nContent-length:4\r\n\r\nPING')
+ response = cli.read(8192)
+ self.assertEqual(response[-4:], "PONG")
+
+ fake_ssl_server.stop()
+ fake_ssl_server.wait()
+
+ def test_two_servers(self):
+ def test_app(env, start_response):
+ start_response('200 OK', {})
+ return ['PONG']
+
+ fake_ssl_server = wsgi.Server(self.conf, "fake_ssl", test_app,
+ host="127.0.0.1", port=0, use_ssl=True)
+ fake_ssl_server.start()
+ self.assertNotEqual(0, fake_ssl_server.port)
+
+ fake_server = wsgi.Server(self.conf, "fake", test_app,
+ host="127.0.0.1", port=0)
+ fake_server.start()
+ self.assertNotEqual(0, fake_server.port)
+
+ cli = eventlet.connect(("localhost", fake_ssl_server.port))
+ cli = eventlet.wrap_ssl(cli,
+ ca_certs=os.path.join(SSL_CERT_DIR, 'ca.crt'))
+
+ cli.write('POST / HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nContent-length:4\r\n\r\nPING')
+ response = cli.read(8192)
+ self.assertEqual(response[-4:], "PONG")
+
+ cli = eventlet.connect(("localhost", fake_server.port))
+
+ cli.sendall('POST / HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nContent-length:4\r\n\r\nPING')
+ response = cli.recv(8192)
+ self.assertEqual(response[-4:], "PONG")
+
+ fake_ssl_server.stop()
+ fake_ssl_server.wait()
+
+ @testtools.skipIf(platform.mac_ver()[0] != '',
+ 'SO_REUSEADDR behaves differently '
+ 'on OSX, see bug 1436895')
+ def test_socket_options_for_ssl_server(self):
+ # test normal socket options has set properly
+ self.config(tcp_keepidle=500)
+ server = wsgi.Server(self.conf, "test_socket_options", None,
+ host="127.0.0.1", port=0, use_ssl=True)
+ server.start()
+ sock = server._socket
+ self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
+ socket.SO_REUSEADDR))
+ self.assertEqual(1, sock.getsockopt(socket.SOL_SOCKET,
+ socket.SO_KEEPALIVE))
+ if hasattr(socket, 'TCP_KEEPIDLE'):
+ self.assertEqual(CONF.tcp_keepidle,
+ sock.getsockopt(socket.IPPROTO_TCP,
+ socket.TCP_KEEPIDLE))
+ server.stop()
+ server.wait()
+
+ @testtools.skipIf(not netutils.is_ipv6_enabled(), "no ipv6 support")
+ def test_app_using_ipv6_and_ssl(self):
+ greetings = 'Hello, World!!!'
+
+ @webob.dec.wsgify
+ def hello_world(req):
+ return greetings
+
+ server = wsgi.Server(self.conf, "fake_ssl",
+ hello_world,
+ host="::1",
+ port=0,
+ use_ssl=True)
+
+ server.start()
+
+ response = requests.get('https://[::1]:%d/' % server.port,
+ verify=os.path.join(SSL_CERT_DIR, 'ca.crt'))
+ self.assertEqual(greetings, response.text)
+
+ server.stop()
+ server.wait()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/oslo_service/wsgi.py
new/oslo.service-0.9.0/oslo_service/wsgi.py
--- old/oslo.service-0.7.0/oslo_service/wsgi.py 1970-01-01 01:00:00.000000000
+0100
+++ new/oslo.service-0.9.0/oslo_service/wsgi.py 2015-09-01 20:39:05.000000000
+0200
@@ -0,0 +1,318 @@
+# Copyright 2010 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# Copyright 2010 OpenStack Foundation
+# 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.
+
+"""Utility methods for working with WSGI servers."""
+
+from __future__ import print_function
+
+import copy
+import os
+import socket
+
+import eventlet
+import eventlet.wsgi
+import greenlet
+from paste import deploy
+import routes.middleware
+import webob.dec
+import webob.exc
+
+from oslo_log import log as logging
+from oslo_service import _options
+from oslo_service import sslutils
+from oslo_service._i18n import _, _LE, _LI
+
+
+LOG = logging.getLogger(__name__)
+
+
+def list_opts():
+ """Entry point for oslo-config-generator."""
+ return [(None, copy.deepcopy(_options.wsgi_opts))]
+
+
+class InvalidInput(Exception):
+ message = _("Invalid input received: "
+ "Unexpected argument for periodic task creation: %(arg)s.")
+
+
+class Server(object):
+ """Server class to manage a WSGI server, serving a WSGI application."""
+
+ def __init__(self, conf, name, app, host='0.0.0.0', port=0, pool_size=None,
+ protocol=eventlet.wsgi.HttpProtocol, backlog=128,
+ use_ssl=False, max_url_len=None):
+ """Initialize, but do not start, a WSGI server.
+
+ :param name: Pretty name for logging.
+ :param app: The WSGI application to serve.
+ :param host: IP address to serve the application.
+ :param port: Port number to server the application.
+ :param pool_size: Maximum number of eventlets to spawn concurrently.
+ :param backlog: Maximum number of queued connections.
+ :param max_url_len: Maximum length of permitted URLs.
+ :returns: None
+ :raises: InvalidInput
+ """
+
+ self.conf = conf
+ self.conf.register_opts(_options.wsgi_opts)
+
+ self.default_pool_size = self.conf.wsgi_default_pool_size
+
+ # Allow operators to customize http requests max header line size.
+ eventlet.wsgi.MAX_HEADER_LINE = conf.max_header_line
+ self.name = name
+ self.app = app
+ self._server = None
+ self._protocol = protocol
+ self.pool_size = pool_size or self.default_pool_size
+ self._pool = eventlet.GreenPool(self.pool_size)
+ self._logger = logging.getLogger("eventlet.wsgi.server")
+ self._use_ssl = use_ssl
+ self._max_url_len = max_url_len
+ self.client_socket_timeout = conf.client_socket_timeout or None
+ self.default_pool_size = conf.wsgi_default_pool_size
+
+ if backlog < 1:
+ raise InvalidInput(reason='The backlog must be more than 0')
+
+ bind_addr = (host, port)
+ # TODO(dims): eventlet's green dns/socket module does not actually
+ # support IPv6 in getaddrinfo(). We need to get around this in the
+ # future or monitor upstream for a fix
+ try:
+ info = socket.getaddrinfo(bind_addr[0],
+ bind_addr[1],
+ socket.AF_UNSPEC,
+ socket.SOCK_STREAM)[0]
+ family = info[0]
+ bind_addr = info[-1]
+ except Exception:
+ family = socket.AF_INET
+
+ if self._use_ssl:
+ sslutils.is_enabled(conf)
+
+ try:
+ self._socket = eventlet.listen(bind_addr, family, backlog=backlog)
+ except EnvironmentError:
+ LOG.error(_LE("Could not bind to %(host)s:%(port)s"),
+ {'host': host, 'port': port})
+ raise
+
+ (self.host, self.port) = self._socket.getsockname()[0:2]
+ LOG.info(_LI("%(name)s listening on %(host)s:%(port)s"),
+ {'name': self.name, 'host': self.host, 'port': self.port})
+
+ def start(self):
+ """Start serving a WSGI application.
+
+ :returns: None
+ """
+ # The server socket object will be closed after server exits,
+ # but the underlying file descriptor will remain open, and will
+ # give bad file descriptor error. So duplicating the socket object,
+ # to keep file descriptor usable.
+
+ self.dup_socket = self._socket.dup()
+
+ self.dup_socket = self._set_socket_opts(self.dup_socket)
+
+ if self._use_ssl:
+ self.dup_socket = sslutils.wrap(self.conf, self.dup_socket)
+
+ wsgi_kwargs = {
+ 'func': eventlet.wsgi.server,
+ 'sock': self.dup_socket,
+ 'site': self.app,
+ 'protocol': self._protocol,
+ 'custom_pool': self._pool,
+ 'log': self._logger,
+ 'log_format': self.conf.wsgi_log_format,
+ 'debug': False,
+ 'keepalive': self.conf.wsgi_keep_alive,
+ 'socket_timeout': self.client_socket_timeout
+ }
+
+ if self._max_url_len:
+ wsgi_kwargs['url_length_limit'] = self._max_url_len
+
+ self._server = eventlet.spawn(**wsgi_kwargs)
+
+ def _set_socket_opts(self, _socket):
+ _socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ # sockets can hang around forever without keepalive
+ _socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
+
+ # This option isn't available in the OS X version of eventlet
+ if hasattr(socket, 'TCP_KEEPIDLE'):
+ _socket.setsockopt(socket.IPPROTO_TCP,
+ socket.TCP_KEEPIDLE,
+ self.conf.tcp_keepidle)
+
+ return _socket
+
+ def reset(self):
+ """Reset server greenpool size to default.
+
+ :returns: None
+
+ """
+ self._pool.resize(self.pool_size)
+
+ def stop(self):
+ """Stops eventlet server. Doesn't allow accept new connecting.
+
+ :returns: None
+
+ """
+ LOG.info(_LI("Stopping WSGI server."))
+
+ if self._server is not None:
+ # let eventlet close socket
+ self._pool.resize(0)
+ self._server.kill()
+
+ def wait(self):
+ """Block, until the server has stopped.
+
+ Waits on the server's eventlet to finish, then returns.
+
+ :returns: None
+
+ """
+ try:
+ if self._server is not None:
+ num = self._pool.running()
+ LOG.debug("Waiting WSGI server to finish %d requests.", num)
+ self._pool.waitall()
+ except greenlet.GreenletExit:
+ LOG.info(_LI("WSGI server has stopped."))
+
+
+class Request(webob.Request):
+ pass
+
+
+class Router(object):
+ """WSGI middleware that maps incoming requests to WSGI apps."""
+
+ def __init__(self, mapper):
+ """Create a router for the given routes.Mapper.
+
+ Each route in `mapper` must specify a 'controller', which is a
+ WSGI app to call. You'll probably want to specify an 'action' as
+ well and have your controller be an object that can route
+ the request to the action-specific method.
+
+ Examples:
+ mapper = routes.Mapper()
+ sc = ServerController()
+
+ # Explicit mapping of one route to a controller+action
+ mapper.connect(None, '/svrlist', controller=sc, action='list')
+
+ # Actions are all implicitly defined
+ mapper.resource('server', 'servers', controller=sc)
+
+ # Pointing to an arbitrary WSGI app. You can specify the
+ # {path_info:.*} parameter so the target app can be handed just that
+ # section of the URL.
+ mapper.connect(None, '/v1.0/{path_info:.*}', controller=BlogApp())
+
+ """
+ self.map = mapper
+ self._router = routes.middleware.RoutesMiddleware(self._dispatch,
+ self.map)
+
+ @webob.dec.wsgify(RequestClass=Request)
+ def __call__(self, req):
+ """Route the incoming request to a controller based on self.map.
+
+ If no match, return a 404.
+
+ """
+ return self._router
+
+ @staticmethod
+ @webob.dec.wsgify(RequestClass=Request)
+ def _dispatch(req):
+ """Dispatch the request to the appropriate controller.
+
+ Called by self._router after matching the incoming request to a route
+ and putting the information into req.environ. Either returns 404
+ or the routed WSGI app's response.
+
+ """
+ match = req.environ['wsgiorg.routing_args'][1]
+ if not match:
+ return webob.exc.HTTPNotFound()
+ app = match['controller']
+ return app
+
+
+class ConfigNotFound(Exception):
+ def __init__(self, path):
+ msg = _('Could not find config at %(path)s') % {'path': path}
+ super(ConfigNotFound, self).__init__(msg)
+
+
+class PasteAppNotFound(Exception):
+ def __init__(self, name, path):
+ msg = (_("Could not load paste app '%(name)s' from %(path)s") %
+ {'name': name, 'path': path})
+ super(PasteAppNotFound, self).__init__(msg)
+
+
+class Loader(object):
+ """Used to load WSGI applications from paste configurations."""
+
+ def __init__(self, conf):
+ """Initialize the loader, and attempt to find the config.
+
+ :param conf
+ :returns: None
+
+ """
+ conf.register_opts(_options.wsgi_opts)
+ self.config_path = None
+
+ config_path = conf.api_paste_config
+ if not os.path.isabs(config_path):
+ self.config_path = conf.find_file(config_path)
+ elif os.path.exists(config_path):
+ self.config_path = config_path
+
+ if not self.config_path:
+ raise ConfigNotFound(path=config_path)
+
+ def load_app(self, name):
+ """Return the paste URLMap wrapped WSGI application.
+
+ :param name: Name of the application to load.
+ :returns: Paste URLMap object wrapping the requested application.
+ :raises: `PasteAppNotFound`
+
+ """
+ try:
+ LOG.debug("Loading app %(name)s from %(path)s",
+ {'name': name, 'path': self.config_path})
+ return deploy.loadapp("config:%s" % self.config_path, name=name)
+ except LookupError:
+ LOG.exception(_LE("Couldn't lookup app: %s"), name)
+ raise PasteAppNotFound(name=name, path=self.config_path)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/requirements.txt
new/oslo.service-0.9.0/requirements.txt
--- old/oslo.service-0.7.0/requirements.txt 2015-08-18 22:23:15.000000000
+0200
+++ new/oslo.service-0.9.0/requirements.txt 2015-09-01 20:39:05.000000000
+0200
@@ -3,11 +3,17 @@
# process, which may cause wedges in the gate later.
Babel>=1.3
+WebOb>=1.2.3
eventlet>=0.17.4
greenlet>=0.3.2
monotonic>=0.3 # Apache-2.0
oslo.utils>=2.0.0 # Apache-2.0
oslo.concurrency>=2.3.0 # Apache-2.0
-oslo.config>=2.1.0 # Apache-2.0
+oslo.config>=2.3.0 # Apache-2.0
+oslo.log>=1.8.0 # Apache-2.0
six>=1.9.0
oslo.i18n>=1.5.0 # Apache-2.0
+PasteDeploy>=1.5.0
+Routes!=2.0,!=2.1,>=1.12.3;python_version=='2.7'
+Routes!=2.0,>=1.12.3;python_version!='2.7'
+Paste
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/setup.cfg
new/oslo.service-0.9.0/setup.cfg
--- old/oslo.service-0.7.0/setup.cfg 2015-08-18 22:23:58.000000000 +0200
+++ new/oslo.service-0.9.0/setup.cfg 2015-09-01 20:39:42.000000000 +0200
@@ -32,6 +32,7 @@
oslo.service.periodic_task = oslo_service.periodic_task:list_opts
oslo.service.service = oslo_service.service:list_opts
oslo.service.sslutils = oslo_service.sslutils:list_opts
+ oslo.service.wsgi = oslo_service.wsgi:list_opts
[build_sphinx]
source-dir = doc/source
@@ -59,7 +60,7 @@
universal = true
[egg_info]
+tag_build =
tag_svn_revision = 0
tag_date = 0
-tag_build =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/oslo.service-0.7.0/tox.ini
new/oslo.service-0.9.0/tox.ini
--- old/oslo.service-0.7.0/tox.ini 2015-08-18 22:23:15.000000000 +0200
+++ new/oslo.service-0.9.0/tox.ini 2015-09-01 20:39:05.000000000 +0200
@@ -19,6 +19,16 @@
[testenv:pep8]
commands = flake8
+[testenv:py34]
+commands =
+ python -m testtools.run \
+ oslo_service.tests.test_eventlet_backdoor \
+ oslo_service.tests.test_loopingcall \
+ oslo_service.tests.test_periodic \
+ oslo_service.tests.test_service \
+ oslo_service.tests.test_systemd \
+ oslo_service.tests.test_threadgroup
+
[testenv:venv]
commands = {posargs}