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-----
+MIIJKAIBAAKCAgEA0Em2/KEwoGff3uETvH0J783L7gQ1B+v1Wse68Y0JHdb+5RtB
+p9011kJg0AY+urZPcIRgrQgnFmOvYe5NxIr1K0EwVq5N4g+pVRWQ7dOOrVGS/4ue
+n97oOEeSMJToSr+MjDeJzRCjEvKBPJsbFeAmBWgHMawm5/M5DXi1+TMZ4bITcvnP
+kOkI1CpYtYXuygzHeQzmEGb4tZ6iIE+OawRdBj5RiIOVItb/ojznlf/DANbn460/
+r/WVZR9zIDIiqPe3SmbFl5jvFCdptaOFdPZ1Mr52XBGNvvvDrrkCB4XVHmWlO9TJ
+PVpDCAfWR30Z5BuQEPBZJUsf1ug8+B0wu1faKlSBAAASEg5RZc5hlUdU1eFXoKuM
+CC990Xf1z2Ga5ei88/biKRbgv53lE8TtWr0onhTOKPD0aG7iVBAJFnxII1khgmdP
+Pnf7p+z3dbCecQ+2j20VEp41a3ePH/COW4MWGEFNk7iyc0ir3GcJhIRAAixEFVYC
+G/supYuKBTLtr0cwjKLe1ARk300IPLgE24kO7fddYstUzA2siJHmZ0JQWhEq38T5
+g+Pts2XNkxNIYugEU8zvUud/Kb0drMcMTUrG9PiDNgy5srhjTuZ7JuIvhA29TTwh
+OAVToMAahv7L8YerD5uZ7PnLQX/oWXJX5KJKttUQS3On0TDKvFvzk4kUrS0CAwEA
+AQKCAgAkdpMrPMi3fBfL+9kpqTYhHgTyYRgrj9o/DzIh8U/EQowS7aebzHUNUkeC
+g2Vd6GaVywblo8S7/a2JVl+U5cKv1NSyiAcoaRd6xrC9gci7fMlgJUAauroqiBUG
+njrgQxJGxb5BAQWbXorTYk/mj3v4fFKuFnYlKwY03on020ZPpY4UFbmJo9Ig2lz3
+QkAgbQZKocBw5KXrnZ7CS0siXvwuCKDbZjWoiLzt2P2t2712myizSfQZSMPjlRLh
+cwVwURVsV/uFY4ePHqs52iuV40N3I7KywXvwEEEciFTbnklF7gN0Kvcj33ZWpJCV
+qUfsEAsze/APQEyNodBymyGZ2nJdn9PqaQYnVhE9xpjiXejQHZsuMnrA3jYr8Mtx
+j0EZiX4ICI4Njt9oI/EtWhQtcDt86hTEtBlyFRU6jhW8O5Ai7hzxCYgUJ7onWVOE
+PtCC9FoOwumXWgdZNz/hMqQSn91O8trferccdUGIfx8N/G4QkyzOLI0Hc6Mubby7
++GGRwVXnLsIGxpFc+VBHY/J6offCkXx3MPbfn57x0LGZu1GtHoep391yLUrBs9jx
+nJrUI9OuwaeOG0iesTuGT+PbZWxDrJEtA7DRM1FBMNMvn5BTTg7yx8EqUM35hnFf
+5J1XEf0DW5nUPH1Qadgi1LZjCAhiD5OuNooFsTmN7dSdleF+PQKCAQEA7jq7drTu
+O1ePCO+dQeECauy1qv9SO2LIHfLZ/L4OwcEtEnE8xBbvrZfUqkbUITCS6rR8UITp
+6ru0MyhUEsRsk4FHIJV2P1pB2Zy+8tV4Dm3aHh4bCoECqAPHMgXUkP+9kIOn2QsE
+uRXnsEiQAl0SxSTcduy5F+WIWLVl4A72ry3cSvrEGwMEz0sjaEMmCZ2B8X8EJt64
+uWUSHDaAMSg80bADy3p+OhmWMGZTDl/KRCz9pJLyICMxsotfbvE0BadAZr+UowSe
+ldqKlgRYlYL3pAhwjeMO/QxmMfRxjvG09romqe0Bcs8BDNII/ShAjjHQUwxcEszQ
+P14g8QwmTQVm5wKCAQEA39M3GveyIhX6vmyR4DUlxE5+yloTACdlCZu6wvFlRka8
+3FEw8DWKVfnmYYFt/RPukYeBRmXwqLciGSly7PnaBXeNFqNXiykKETzS2UISZoqT
+Dur06GmcI+Lk1my9v5gLB1LT/D8XWjwmjA5hNO1J1UYmp+X4dgaYxWzOKBsTTJ8j
+SVaEaxBUwLHy58ehoQm+G5+QqL5yU/n1hPwXx1XYvd33OscSGQRbALrH2ZxsqxMZ
+yvNa2NYt3TnihXcF36Df5861DTNI7NDqpY72C4U8RwaqgTdDkD+t8zrk/r3LUa5d
+NGkGQF+59spBcb64IPZ4DuJ9//GaEsyj0jPF/FTMywKCAQEA1DiB83eumjKf+yfq
+AVv/GV2RYKleigSvnO5QfrSY1MXP7xPtPAnqrcwJ6T57jq2E04zBCcG92BwqpUAR
+1T4iMy0BPeenlTxEWSUnfY/pCYGWwymykSLoSOBEvS0wdZM9PdXq2pDUPkVjRkj9
+8P0U0YbK1y5+nOkfE1dVT8pEuz2xdyH5PM7to/SdsC3RXtNvhMDP5AiYqp99CKEM
+hb4AoBOa7dNLS1qrzqX4618uApnJwqgdBcAUb6d09pHs8/RQjLeyI57j3z72Ijnw
+6A/pp7jU+7EAEzDOgUXvO5Xazch61PmLRsldeBxLYapQB9wcZz8lbqICCdFCqzlV
+jVt4lQKCAQA9CYxtfj7FrNjENTdSvSufbQiGhinIUPXsuNslbk7/6yp1qm5+Exu2
+dn+s927XJShZ52oJmKMYX1idJACDP1+FPiTrl3+4I2jranrVZH9AF2ojF0/SUXqT
+Drz4/I6CQSRAywWkNFBZ+y1H5GP92vfXgVnpT32CMipXLGTL6xZIPt2QkldqGvoB
+0oU7T+Vz1QRS5CC+47Cp1fBuY5DYe0CwBmf1T3RP/jAS8tytK0s3G+5cuiB8IWxA
+eBid7OddJLHqtSQKhYHNkutqWqIeYicd92Nn+XojTDpTqivojDl1/ObN9BYQWAqO
+knlmW2w7EPuMk5doxKoPll7WY+gJ99YhAoIBAHf5HYRh4ZuYkx+R1ow8/Ahp7N4u
+BGFRNnCpMG358Zws95wvBg5dkW8VU0M3256M0kFkw2AOyyyNsHqIhMNakzHesGo/
+TWhqCh23p1xBLY5p14K8K6iOc1Jfa1LqGsL2TZ06TeNNyONMGqq0yOyD62CdLRDj
+0ACL/z2j494LmfqhV45hYuqjQbrLizjrr6ln75g2WJ32U+zwl7KUHnBL7IEwb4Be
+KOl1bfVwZAs0GtHuaiScBYRLUaSC/Qq7YPjTh1nmg48DQC/HUCNGMqhoZ950kp9k
+76HX+MpwUi5y49moFmn/3qDvefGFpX1td8vYMokx+eyKTXGFtxBUwPnMUSQ=
+-----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}
 


Reply via email to