Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-oslo.privsep for 
openSUSE:Factory checked in at 2021-12-12 00:57:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-oslo.privsep (Old)
 and      /work/SRC/openSUSE:Factory/.python-oslo.privsep.new.2520 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-oslo.privsep"

Sun Dec 12 00:57:35 2021 rev:16 rq:939537 version:2.6.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-oslo.privsep/python-oslo.privsep.changes  
2021-05-10 15:39:51.477446894 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-oslo.privsep.new.2520/python-oslo.privsep.changes
        2021-12-12 00:57:44.150589581 +0100
@@ -1,0 +2,16 @@
+Tue Oct 26 22:10:01 UTC 2021 - cloud-de...@suse.de
+
+- update to version 2.6.2
+  - Fix requirements issues.
+  - Allow finer grained log levels
+  - Changed minversion in tox to 3.18.0
+  - Use TOX_CONSTRAINTS_FILE
+  - Add Python3 xena unit tests
+  - Add except path with exception debug to send_recv
+  - Add timeout to PrivContext and entrypoint_with_timeout decorator
+  - Use py3 as the default runtime for tox
+  - setup.cfg: Replace dashes with underscores
+  - Upgrade the pre-commit-hooks version
+  - Update master for stable/wallaby
+
+-------------------------------------------------------------------

Old:
----
  oslo.privsep-2.5.0.tar.gz

New:
----
  oslo.privsep-2.6.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-oslo.privsep.spec ++++++
--- /var/tmp/diff_new_pack.dSDDln/_old  2021-12-12 00:57:45.598590575 +0100
+++ /var/tmp/diff_new_pack.dSDDln/_new  2021-12-12 00:57:45.602590578 +0100
@@ -17,13 +17,13 @@
 
 
 Name:           python-oslo.privsep
-Version:        2.5.0
+Version:        2.6.2
 Release:        0
 Summary:        OpenStack library for privilege separation
 License:        Apache-2.0
 Group:          Development/Languages/Python
 URL:            https://docs.openstack.org/oslo.privsep
-Source0:        
https://files.pythonhosted.org/packages/source/o/oslo.privsep/oslo.privsep-2.5.0.tar.gz
+Source0:        
https://files.pythonhosted.org/packages/source/o/oslo.privsep/oslo.privsep-2.6.2.tar.gz
 BuildRequires:  openstack-macros
 BuildRequires:  python3-cffi >= 1.14.0
 BuildRequires:  python3-eventlet >= 0.21.0
@@ -69,7 +69,7 @@
 Documentation for oslo.privsep
 
 %prep
-%autosetup -p1 -n oslo.privsep-2.5.0
+%autosetup -p1 -n oslo.privsep-2.6.2
 %py_req_cleanup
 
 %build

++++++ _service ++++++
--- /var/tmp/diff_new_pack.dSDDln/_old  2021-12-12 00:57:45.626590594 +0100
+++ /var/tmp/diff_new_pack.dSDDln/_new  2021-12-12 00:57:45.626590594 +0100
@@ -1,8 +1,8 @@
 <services>
   <service mode="disabled" name="renderspec">
-    <param 
name="input-template">https://opendev.org/openstack/rpm-packaging/raw/branch/stable/wallaby/openstack/oslo.privsep/oslo.privsep.spec.j2</param>
+    <param 
name="input-template">https://opendev.org/openstack/rpm-packaging/raw/master/openstack/oslo.privsep/oslo.privsep.spec.j2</param>
     <param name="output-name">python-oslo.privsep.spec</param>
-    <param 
name="requirements">https://opendev.org/openstack/oslo.privsep/raw/branch/stable/wallaby/requirements.txt</param>
+    <param 
name="requirements">https://opendev.org/openstack/oslo.privsep/raw/master/requirements.txt</param>
     <param name="changelog-email">cloud-de...@suse.de</param>
     <param name="changelog-provider">gh,openstack,oslo.privsep</param>
   </service>

++++++ oslo.privsep-2.5.0.tar.gz -> oslo.privsep-2.6.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/.pre-commit-config.yaml 
new/oslo.privsep-2.6.2/.pre-commit-config.yaml
--- old/oslo.privsep-2.5.0/.pre-commit-config.yaml      2021-03-11 
21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/.pre-commit-config.yaml      2021-08-26 
17:49:16.000000000 +0200
@@ -9,7 +9,7 @@
 
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: ebc15addedad713c86ef18ae9632c88e187dd0af  # v3.1.0
+    rev: 9136088a246768144165fcc3ecc3d31bb686920a # v3.3.0
     hooks:
       - id: trailing-whitespace
       # Replaces or checks mixed line ending
@@ -27,9 +27,13 @@
       - id: debug-statements
       - id: check-yaml
         files: .*\.(yaml|yml)$
-  - repo: https://gitlab.com/pycqa/flake8
-    rev: 181bb46098dddf7e2d45319ea654b4b4d58c2840 # 3.8.3
+  - repo: local
     hooks:
       - id: flake8
+        name: flake8
         additional_dependencies:
           - hacking>=3.0.1,<3.1.0
+        language: python
+        entry: flake8
+        files: '^.*\.py$'
+        exclude: '^(doc|releasenotes|tools)/.*$'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/.zuul.yaml 
new/oslo.privsep-2.6.2/.zuul.yaml
--- old/oslo.privsep-2.5.0/.zuul.yaml   2021-03-11 21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/.zuul.yaml   2021-08-26 17:49:16.000000000 +0200
@@ -2,8 +2,7 @@
     templates:
       - check-requirements
       - lib-forward-testing-python3
-      - openstack-lower-constraints-jobs
-      - openstack-python3-wallaby-jobs
+      - openstack-python3-xena-jobs
       - periodic-stable-jobs
       - publish-openstack-docs-pti
       - release-notes-jobs-python3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/AUTHORS 
new/oslo.privsep-2.6.2/AUTHORS
--- old/oslo.privsep-2.5.0/AUTHORS      2021-03-11 21:28:21.000000000 +0100
+++ new/oslo.privsep-2.6.2/AUTHORS      2021-08-26 17:49:51.000000000 +0200
@@ -8,6 +8,7 @@
 Claudiu Belu <cb...@cloudbasesolutions.com>
 Corey Bryant <corey.bry...@canonical.com>
 C??dric Jeanneret <cjean...@redhat.com>
+Daniel Bengtsson <dbe...@redhat.com>
 Darragh O'Reilly <dorei...@suse.com>
 Davanum Srinivas <dava...@gmail.com>
 Dirk Mueller <d...@dmllr.de>
@@ -17,6 +18,7 @@
 Eric Harney <ehar...@redhat.com>
 Flavio Percoco <flape...@gmail.com>
 Ghanshyam Mann <gm...@ghanshyammann.com>
+Gorka Eguileor <gegui...@redhat.com>
 Herv?? Beraud <hber...@redhat.com>
 Hongbin Lu <hongbin...@huawei.com>
 Javier Pena <jp...@redhat.com>
@@ -27,6 +29,7 @@
 Mois??s Guimar??es de Medeiros <mogui...@redhat.com>
 OpenStack Release Bot <infra-r...@openstack.org>
 Pavlo Shchelokovskyy <shchelokovs...@gmail.com>
+Rodolfo Alonso <ralon...@redhat.com>
 Rodolfo Alonso Hernandez <ralon...@redhat.com>
 Sam Wan <sam....@emc.com>
 Sean McGinnis <sean.mcgin...@gmail.com>
@@ -43,6 +46,7 @@
 ZhongShengping <chd...@163.com>
 avnish <avnish....@nectechnologies.in>
 caoyuan <cao.y...@99cloud.net>
+elajkat <lajos.kat...@est.tech>
 jacky06 <zhang....@99cloud.net>
 liangcui <liang...@fiberhome.com>
 loooosy <syluo5...@fiberhome.com>
@@ -52,5 +56,7 @@
 shupeng <15050873...@163.com>
 sonu.kumar <sonu.ku...@nectechnologies.in>
 wangqi <wang...@99cloud.net>
+wu.shiming <wushim...@yovole.com>
 xgwang5843 <xgwang5...@fiberhome.com>
+yangyawei <yangya...@inspur.com>
 zhangboye <zhangb...@inspur.com>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/ChangeLog 
new/oslo.privsep-2.6.2/ChangeLog
--- old/oslo.privsep-2.5.0/ChangeLog    2021-03-11 21:28:21.000000000 +0100
+++ new/oslo.privsep-2.6.2/ChangeLog    2021-08-26 17:49:51.000000000 +0200
@@ -1,6 +1,29 @@
 CHANGES
 =======
 
+2.6.2
+-----
+
+
+2.6.1
+-----
+
+* Add except path with exception debug to send\_recv
+
+2.6.0
+-----
+
+* Add timeout to PrivContext and entrypoint\_with\_timeout decorator
+* Changed minversion in tox to 3.18.0
+* Upgrade the pre-commit-hooks version
+* setup.cfg: Replace dashes with underscores
+* Allow finer grained log levels
+* Add Python3 xena unit tests
+* Update master for stable/wallaby
+* Fix requirements issues
+* Use TOX\_CONSTRAINTS\_FILE
+* Use py3 as the default runtime for tox
+
 2.5.0
 -----
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/PKG-INFO 
new/oslo.privsep-2.6.2/PKG-INFO
--- old/oslo.privsep-2.5.0/PKG-INFO     2021-03-11 21:28:21.683663800 +0100
+++ new/oslo.privsep-2.6.2/PKG-INFO     2021-08-26 17:49:51.674757700 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: oslo.privsep
-Version: 2.5.0
+Version: 2.6.2
 Summary: OpenStack library for privilege separation
 Home-page: https://docs.openstack.org/oslo.privsep/latest/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/doc/source/user/index.rst 
new/oslo.privsep-2.6.2/doc/source/user/index.rst
--- old/oslo.privsep-2.5.0/doc/source/user/index.rst    2021-03-11 
21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/doc/source/user/index.rst    2021-08-26 
17:49:16.000000000 +0200
@@ -30,6 +30,31 @@
                     capabilities.CAP_SYS_ADMIN],
   )
 
+Defining a context with timeout
+-------------------------------
+
+It is possible to initialize PrivContext with timeout::
+
+  from oslo_privsep import capabilities
+  from oslo_privsep import priv_context
+
+  dhcp_release_cmd = priv_context.PrivContext(
+      __name__,
+      cfg_section='privsep_dhcp_release',
+      pypath=__name__ + '.dhcp_release_cmd',
+      capabilities=[caps.CAP_SYS_ADMIN,
+                    caps.CAP_NET_ADMIN],
+      timeout=5
+  )
+
+``PrivsepTimeout`` is raised if timeout is reached.
+
+.. warning::
+
+   The daemon (the root process) task won't stop when timeout
+   is reached. That means we'll have less available threads if the related
+   thread never finishes.
+
 Defining a privileged function
 ==============================
 
@@ -51,6 +76,36 @@
 overwrite any file in the filesystem, allowing easy escalation to root
 rights. That would defeat the whole purpose of oslo.privsep.
 
+Defining a privileged function with timeout
+-------------------------------------------
+
+It is possible to use ``entrypoint_with_timeout`` decorator::
+
+  from oslo_privsep import daemon
+
+  from neutron import privileged
+
+  @privileged.default.entrypoint_with_timeout(timeout=5)
+  def get_link_devices(namespace, **kwargs):
+      try:
+          with get_iproute(namespace) as ip:
+              return make_serializable(ip.get_links(**kwargs))
+      except OSError as e:
+          if e.errno == errno.ENOENT:
+              raise NetworkNamespaceNotFound(netns_name=namespace)
+          raise
+      except daemon.FailedToDropPrivileges:
+          raise
+      except daemon.PrivsepTimeout:
+          raise
+
+``PrivsepTimeout`` is raised if timeout is reached.
+
+.. warning::
+
+   The daemon (the root process) task won't stop when timeout
+   is reached. That means we'll have less available threads if the related
+   thread never finishes.
 
 Using a privileged function
 ===========================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/lower-constraints.txt 
new/oslo.privsep-2.6.2/lower-constraints.txt
--- old/oslo.privsep-2.5.0/lower-constraints.txt        2021-03-11 
21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/lower-constraints.txt        1970-01-01 
01:00:00.000000000 +0100
@@ -1,54 +0,0 @@
-alabaster==0.7.10
-appdirs==1.3.0
-Babel==2.3.4
-bandit==1.1.0
-cffi==1.14.0
-debtcollector==1.2.0
-docutils==0.11
-dulwich==0.15.0
-eventlet==0.21.0
-extras==1.0.0
-fixtures==3.0.0
-gitdb==0.6.4
-GitPython==1.0.1
-greenlet==0.4.14
-imagesize==0.7.1
-iso8601==0.1.11
-Jinja2==2.10
-keystoneauth1==3.4.0
-linecache2==1.0.0
-MarkupSafe==1.0
-mox3==0.20.0
-msgpack==0.6.0
-netaddr==0.7.18
-netifaces==0.10.4
-os-client-config==1.28.0
-oslo.config==5.2.0
-oslo.context==2.19.2
-oslo.i18n==3.15.3
-oslo.log==3.36.0
-oslo.serialization==2.24.0
-oslo.utils==3.33.0
-oslotest==3.2.0
-pbr==2.0.0
-pycparser==2.18
-Pygments==2.2.0
-pyinotify==0.9.6
-pyparsing==2.1.0
-python-dateutil==2.5.3
-python-mimeparse==1.6.0
-python-subunit==1.0.0
-pytz==2013.6
-PyYAML==3.13
-requests==2.14.2
-requestsexceptions==1.2.0
-rfc3986==0.3.1
-six==1.10.0
-smmap==0.9.0
-snowballstemmer==1.2.1
-stestr==2.0.0
-stevedore==1.20.0
-testtools==2.2.0
-traceback2==1.4.0
-unittest2==1.1.0
-wrapt==1.7.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/oslo.privsep.egg-info/PKG-INFO 
new/oslo.privsep-2.6.2/oslo.privsep.egg-info/PKG-INFO
--- old/oslo.privsep-2.5.0/oslo.privsep.egg-info/PKG-INFO       2021-03-11 
21:28:21.000000000 +0100
+++ new/oslo.privsep-2.6.2/oslo.privsep.egg-info/PKG-INFO       2021-08-26 
17:49:51.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: oslo.privsep
-Version: 2.5.0
+Version: 2.6.2
 Summary: OpenStack library for privilege separation
 Home-page: https://docs.openstack.org/oslo.privsep/latest/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/oslo.privsep.egg-info/SOURCES.txt 
new/oslo.privsep-2.6.2/oslo.privsep.egg-info/SOURCES.txt
--- old/oslo.privsep-2.5.0/oslo.privsep.egg-info/SOURCES.txt    2021-03-11 
21:28:21.000000000 +0100
+++ new/oslo.privsep-2.6.2/oslo.privsep.egg-info/SOURCES.txt    2021-08-26 
17:49:51.000000000 +0200
@@ -9,7 +9,6 @@
 HACKING.rst
 LICENSE
 README.rst
-lower-constraints.txt
 requirements.txt
 setup.cfg
 setup.py
@@ -50,9 +49,11 @@
 oslo_privsep/tests/test_daemon.py
 oslo_privsep/tests/test_priv_context.py
 oslo_privsep/tests/testctx.py
+releasenotes/notes/add_entrypoint_with_timeout_decorator-9aab5a74153b3632.yaml
 releasenotes/notes/add_reno-3b4ae0789e9c45b4.yaml
 releasenotes/notes/add_thread_pool_size-a54e6f27ab019f96.yaml
 releasenotes/notes/auto-restart-client-channel-619545294557bf2b.yaml
+releasenotes/notes/context-logger-06b475357bebadc7.yaml
 releasenotes/notes/drop-python27-support-6da3028c1cf099eb.yaml
 releasenotes/notes/un-monkey-patch-privileged-daemon-160e00296549df3d.yaml
 releasenotes/source/conf.py
@@ -67,6 +68,7 @@
 releasenotes/source/unreleased.rst
 releasenotes/source/ussuri.rst
 releasenotes/source/victoria.rst
+releasenotes/source/wallaby.rst
 releasenotes/source/_static/.placeholder
 releasenotes/source/_templates/.placeholder
 releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/oslo.privsep.egg-info/pbr.json 
new/oslo.privsep-2.6.2/oslo.privsep.egg-info/pbr.json
--- old/oslo.privsep-2.5.0/oslo.privsep.egg-info/pbr.json       2021-03-11 
21:28:21.000000000 +0100
+++ new/oslo.privsep-2.6.2/oslo.privsep.egg-info/pbr.json       2021-08-26 
17:49:51.000000000 +0200
@@ -1 +1 @@
-{"git_version": "83870bd", "is_release": true}
\ No newline at end of file
+{"git_version": "a3256ac", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/oslo_privsep/comm.py 
new/oslo.privsep-2.6.2/oslo_privsep/comm.py
--- old/oslo.privsep-2.5.0/oslo_privsep/comm.py 2021-03-11 21:27:45.000000000 
+0100
+++ new/oslo.privsep-2.6.2/oslo_privsep/comm.py 2021-08-26 17:49:16.000000000 
+0200
@@ -20,30 +20,35 @@
 converted to tuples during serialization/deserialization.
 """
 
+import datetime
+import enum
 import logging
 import socket
+import sys
 import threading
 
 import msgpack
 import six
 
 from oslo_privsep._i18n import _
-
+from oslo_utils import uuidutils
 
 LOG = logging.getLogger(__name__)
 
 
-try:
-    import greenlet
+@enum.unique
+class Message(enum.IntEnum):
+    """Types of messages sent across the communication channel"""
+    PING = 1
+    PONG = 2
+    CALL = 3
+    RET = 4
+    ERR = 5
+    LOG = 6
+
 
-    def _get_thread_ident():
-        # This returns something sensible, even if the current thread
-        # isn't a greenthread
-        return id(greenlet.getcurrent())
-
-except ImportError:
-    def _get_thread_ident():
-        return threading.current_thread().ident
+class PrivsepTimeout(Exception):
+    pass
 
 
 class Serializer(object):
@@ -89,10 +94,11 @@
 class Future(object):
     """A very simple object to track the return of a function call"""
 
-    def __init__(self, lock):
+    def __init__(self, lock, timeout=None):
         self.condvar = threading.Condition(lock)
         self.error = None
         self.data = None
+        self.timeout = timeout
 
     def set_result(self, data):
         """Must already be holding lock used in constructor"""
@@ -106,7 +112,16 @@
 
     def result(self):
         """Must already be holding lock used in constructor"""
-        self.condvar.wait()
+        before = datetime.datetime.now()
+        if not self.condvar.wait(timeout=self.timeout):
+            now = datetime.datetime.now()
+            LOG.warning('Timeout while executing a command, timeout: %s, '
+                        'time elapsed: %s', self.timeout,
+                        (now - before).total_seconds())
+            return (Message.ERR.value,
+                    '%s.%s' % (PrivsepTimeout.__module__,
+                               PrivsepTimeout.__name__),
+                    '')
         if self.error is not None:
             raise self.error
         return self.data
@@ -138,8 +153,9 @@
             else:
                 with self.lock:
                     if msgid not in self.outstanding_msgs:
-                        raise AssertionError("msgid should in "
-                                             "outstanding_msgs.")
+                        LOG.warning("msgid should be in oustanding_msgs, it is"
+                                    "possible that timeout is reached!")
+                        continue
                     self.outstanding_msgs[msgid].set_result(data)
 
         # EOF.  Perhaps the privileged process exited?
@@ -158,18 +174,22 @@
         """Received OOB message. Subclasses might want to override this."""
         pass
 
-    def send_recv(self, msg):
-        myid = _get_thread_ident()
-        future = Future(self.lock)
+    def send_recv(self, msg, timeout=None):
+        myid = uuidutils.generate_uuid()
+        while myid in self.outstanding_msgs:
+            LOG.warning("myid shoudn't be in outstanding_msgs.")
+            myid = uuidutils.generate_uuid()
+        future = Future(self.lock, timeout)
 
         with self.lock:
-            if myid in self.outstanding_msgs:
-                raise AssertionError("myid shoudn't be in outstanding_msgs.")
             self.outstanding_msgs[myid] = future
             try:
                 self.writer.send((myid, msg))
 
                 reply = future.result()
+            except Exception:
+                LOG.warning("Unexpected error: {}".format(sys.exc_info()[0]))
+                raise
             finally:
                 del self.outstanding_msgs[myid]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/oslo_privsep/daemon.py 
new/oslo.privsep-2.6.2/oslo_privsep/daemon.py
--- old/oslo.privsep-2.5.0/oslo_privsep/daemon.py       2021-03-11 
21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/oslo_privsep/daemon.py       2021-08-26 
17:49:16.000000000 +0200
@@ -109,17 +109,6 @@
     STDERR = 2
 
 
-@enum.unique
-class Message(enum.IntEnum):
-    """Types of messages sent across the communication channel"""
-    PING = 1
-    PONG = 2
-    CALL = 3
-    RET = 4
-    ERR = 5
-    LOG = 6
-
-
 class FailedToDropPrivileges(Exception):
     pass
 
@@ -187,35 +176,38 @@
         data['msg'] = record.getMessage()
         data['args'] = ()
 
-        self.channel.send((None, (Message.LOG, data)))
+        self.channel.send((None, (comm.Message.LOG, data)))
 
 
 class _ClientChannel(comm.ClientChannel):
     """Our protocol, layered on the basic primitives in comm.ClientChannel"""
 
-    def __init__(self, sock):
+    def __init__(self, sock, context):
+        self.log = logging.getLogger(context.conf.logger_name)
         super(_ClientChannel, self).__init__(sock)
         self.exchange_ping()
 
     def exchange_ping(self):
         try:
             # exchange "ready" messages
-            reply = self.send_recv((Message.PING.value,))
-            success = reply[0] == Message.PONG
+            reply = self.send_recv((comm.Message.PING.value,))
+            success = reply[0] == comm.Message.PONG
         except Exception as e:
-            LOG.exception('Error while sending initial PING to privsep: %s', e)
+            self.log.exception('Error while sending initial PING to privsep: '
+                               '%s', e)
             success = False
         if not success:
             msg = _('Privsep daemon failed to start')
-            LOG.critical(msg)
+            self.log.critical(msg)
             raise FailedToDropPrivileges(msg)
 
-    def remote_call(self, name, args, kwargs):
-        result = self.send_recv((Message.CALL.value, name, args, kwargs))
-        if result[0] == Message.RET:
+    def remote_call(self, name, args, kwargs, timeout):
+        result = self.send_recv((comm.Message.CALL.value, name, args, kwargs),
+                                timeout)
+        if result[0] == comm.Message.RET:
             # (RET, return value)
             return result[1]
-        elif result[0] == Message.ERR:
+        elif result[0] == comm.Message.ERR:
             # (ERR, exc_type, args)
             #
             # TODO(gus): see what can be done to preserve traceback
@@ -226,16 +218,16 @@
             raise ProtocolError(_('Unexpected response: %r') % result)
 
     def out_of_band(self, msg):
-        if msg[0] == Message.LOG:
+        if msg[0] == comm.Message.LOG:
             # (LOG, LogRecord __dict__)
             message = {encodeutils.safe_decode(k): v
                        for k, v in msg[1].items()}
             record = pylogging.makeLogRecord(message)
-            if LOG.isEnabledFor(record.levelno):
-                LOG.logger.handle(record)
+            if self.log.isEnabledFor(record.levelno):
+                self.log.logger.handle(record)
         else:
-            LOG.warning('Ignoring unexpected OOB message from privileged '
-                        'process: %r', msg)
+            self.log.warning('Ignoring unexpected OOB message from privileged '
+                             'process: %r', msg)
 
 
 def fdopen(fd, *args, **kwargs):
@@ -330,7 +322,7 @@
         # parent
 
         sock_b.close()
-        super(ForkingClientChannel, self).__init__(sock_a)
+        super(ForkingClientChannel, self).__init__(sock_a, context)
 
 
 class RootwrapClientChannel(_ClientChannel):
@@ -380,7 +372,7 @@
                     raise
             os.rmdir(tmpdir)
 
-        super(RootwrapClientChannel, self).__init__(sock)
+        super(RootwrapClientChannel, self).__init__(sock, context)
 
 
 class Daemon(object):
@@ -468,11 +460,11 @@
         :return: A tuple of the return status, optional call output, and
                  optional error information.
         """
-        if cmd == Message.PING:
-            return (Message.PONG.value,)
+        if cmd == comm.Message.PING:
+            return (comm.Message.PONG.value,)
 
         try:
-            if cmd != Message.CALL:
+            if cmd != comm.Message.CALL:
                 raise ProtocolError(_('Unknown privsep cmd: %s') % cmd)
 
             # Extract the callable and arguments
@@ -483,14 +475,14 @@
                 raise NameError(msg)
 
             ret = func(*f_args, **f_kwargs)
-            return (Message.RET.value, ret)
+            return (comm.Message.RET.value, ret)
         except Exception as e:
             LOG.debug(
                 'privsep: Exception during request[%(msgid)s]: '
                 '%(err)s', {'msgid': msgid, 'err': e}, exc_info=True)
             cls = e.__class__
             cls_name = '%s.%s' % (cls.__module__, cls.__name__)
-            return (Message.ERR.value, cls_name, e.args)
+            return (comm.Message.ERR.value, cls_name, e.args)
 
     def _create_done_callback(self, msgid):
         """Creates a future callback to receive command execution results.
@@ -518,7 +510,7 @@
                     '%(err)s', {'msgid': msgid, 'err': e}, exc_info=True)
                 cls = e.__class__
                 cls_name = '%s.%s' % (cls.__module__, cls.__name__)
-                reply = (Message.ERR.value, cls_name, e.args)
+                reply = (comm.Message.ERR.value, cls_name, e.args)
                 try:
                     channel.send((msgid, reply))
                 except IOError:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.privsep-2.5.0/oslo_privsep/functional/test_daemon.py 
new/oslo.privsep-2.6.2/oslo_privsep/functional/test_daemon.py
--- old/oslo.privsep-2.5.0/oslo_privsep/functional/test_daemon.py       
2021-03-11 21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/oslo_privsep/functional/test_daemon.py       
2021-08-26 17:49:16.000000000 +0200
@@ -20,6 +20,7 @@
 from oslo_config import fixture as config_fixture
 from oslotest import base
 
+from oslo_privsep import comm
 from oslo_privsep import priv_context
 
 
@@ -30,6 +31,14 @@
     capabilities=[],
 )
 
+test_context_with_timeout = priv_context.PrivContext(
+    __name__,
+    cfg_section='privsep',
+    pypath=__name__ + '.test_context_with_timeout',
+    capabilities=[],
+    timeout=0.03
+)
+
 
 @test_context.entrypoint
 def sleep():
@@ -37,6 +46,18 @@
     time.sleep(.001)
 
 
+@test_context.entrypoint_with_timeout(0.03)
+def sleep_with_timeout(long_timeout=0.04):
+    time.sleep(long_timeout)
+    return 42
+
+
+@test_context_with_timeout.entrypoint
+def sleep_with_t_context(long_timeout=0.04):
+    time.sleep(long_timeout)
+    return 42
+
+
 @test_context.entrypoint
 def one():
     return 1
@@ -65,6 +86,28 @@
         # Make sure the daemon is still working
         self.assertEqual(1, one())
 
+    def test_entrypoint_with_timeout(self):
+        thread_pool_size = self.cfg_fixture.conf.privsep.thread_pool_size
+        for _ in range(thread_pool_size + 1):
+            self.assertRaises(comm.PrivsepTimeout, sleep_with_timeout)
+
+    def test_entrypoint_with_timeout_pass(self):
+        thread_pool_size = self.cfg_fixture.conf.privsep.thread_pool_size
+        for _ in range(thread_pool_size + 1):
+            res = sleep_with_timeout(0.01)
+            self.assertEqual(42, res)
+
+    def test_context_with_timeout(self):
+        thread_pool_size = self.cfg_fixture.conf.privsep.thread_pool_size
+        for _ in range(thread_pool_size + 1):
+            self.assertRaises(comm.PrivsepTimeout, sleep_with_t_context)
+
+    def test_context_with_timeout_pass(self):
+        thread_pool_size = self.cfg_fixture.conf.privsep.thread_pool_size
+        for _ in range(thread_pool_size + 1):
+            res = sleep_with_t_context(0.01)
+            self.assertEqual(42, res)
+
     def test_logging(self):
         logs()
         self.assertIn('foo', self.log_fixture.logger.output)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/oslo_privsep/priv_context.py 
new/oslo.privsep-2.6.2/oslo_privsep/priv_context.py
--- old/oslo.privsep-2.5.0/oslo_privsep/priv_context.py 2021-03-11 
21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/oslo_privsep/priv_context.py 2021-08-26 
17:49:16.000000000 +0200
@@ -65,6 +65,10 @@
                       'recreate the current configuration. '
                       'This command must accept suitable --privsep_context '
                       'and --privsep_sock_path arguments.')),
+    cfg.StrOpt('logger_name',
+               help=_('Logger name to use for this privsep context.  By '
+                      'default all contexts log with oslo_privsep.daemon.'),
+               default='oslo_privsep.daemon'),
 ]
 
 _ENTRYPOINT_ATTR = 'privsep_entrypoint'
@@ -124,7 +128,8 @@
 
 class PrivContext(object):
     def __init__(self, prefix, cfg_section='privsep', pypath=None,
-                 capabilities=None):
+                 capabilities=None, logger_name='oslo_privsep.daemon',
+                 timeout=None):
 
         # Note that capabilities=[] means retaining no capabilities
         # and leaves even uid=0 with no powers except being able to
@@ -150,6 +155,9 @@
         cfg.CONF.register_opts(OPTS, group=cfg_section)
         cfg.CONF.set_default('capabilities', group=cfg_section,
                              default=capabilities)
+        cfg.CONF.set_default('logger_name', group=cfg_section,
+                             default=logger_name)
+        self.timeout = timeout
 
     @property
     def conf(self):
@@ -215,7 +223,22 @@
 
     def entrypoint(self, func):
         """This is intended to be used as a decorator."""
+        return self._entrypoint(func)
 
+    def entrypoint_with_timeout(self, timeout):
+        """This is intended to be used as a decorator with timeout."""
+
+        def wrap(func):
+
+            @functools.wraps(func)
+            def inner(*args, **kwargs):
+                f = self._entrypoint(func)
+                return f(*args, _wrap_timeout=timeout, **kwargs)
+            setattr(inner, _ENTRYPOINT_ATTR, self)
+            return inner
+        return wrap
+
+    def _entrypoint(self, func):
         if not func.__module__.startswith(self.prefix):
             raise AssertionError('%r entrypoints must be below "%s"' %
                                  (self, self.prefix))
@@ -236,7 +259,7 @@
     def is_entrypoint(self, func):
         return getattr(func, _ENTRYPOINT_ATTR, None) is self
 
-    def _wrap(self, func, *args, **kwargs):
+    def _wrap(self, func, *args, _wrap_timeout=None, **kwargs):
         if self.client_mode:
             name = '%s.%s' % (func.__module__, func.__name__)
             if self.channel is not None and not self.channel.running:
@@ -244,7 +267,9 @@
                 self.stop()
             if self.channel is None:
                 self.start()
-            return self.channel.remote_call(name, args, kwargs)
+            r_call_timeout = _wrap_timeout or self.timeout
+            return self.channel.remote_call(name, args, kwargs,
+                                            r_call_timeout)
         else:
             return func(*args, **kwargs)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/oslo_privsep/tests/test_daemon.py 
new/oslo.privsep-2.6.2/oslo_privsep/tests/test_daemon.py
--- old/oslo.privsep-2.5.0/oslo_privsep/tests/test_daemon.py    2021-03-11 
21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/oslo_privsep/tests/test_daemon.py    2021-08-26 
17:49:16.000000000 +0200
@@ -45,6 +45,20 @@
     pass
 
 
+def get_fake_context(conf_attrs=None, **context_attrs):
+    conf_attrs = conf_attrs or {}
+    context = mock.NonCallableMock()
+    context.conf.user = 42
+    context.conf.group = 84
+    context.conf.thread_pool_size = 10
+    context.conf.capabilities = [
+        capabilities.CAP_SYS_ADMIN, capabilities.CAP_NET_ADMIN]
+    context.conf.logger_name = 'oslo_privsep.daemon'
+    vars(context).update(context_attrs)
+    vars(context.conf).update(conf_attrs)
+    return context
+
+
 @testctx.context.entrypoint
 def logme(level, msg, exc_info=False):
     # We want to make sure we log everything from the priv side for
@@ -152,12 +166,7 @@
     def test_drop_privs(self, mock_dropcaps, mock_keepcaps,
                         mock_setgroups, mock_setgid, mock_setuid):
         channel = mock.NonCallableMock()
-        context = mock.NonCallableMock()
-        context.conf.user = 42
-        context.conf.group = 84
-        context.conf.thread_pool_size = 10
-        context.conf.capabilities = [
-            capabilities.CAP_SYS_ADMIN, capabilities.CAP_NET_ADMIN]
+        context = get_fake_context()
 
         d = daemon.Daemon(channel, context)
         d._drop_privs()
@@ -200,23 +209,51 @@
 
     def setUp(self):
         super(ClientChannelTestCase, self).setUp()
+        context = get_fake_context()
         with mock.patch.object(comm.ClientChannel, '__init__'), \
                 mock.patch.object(daemon._ClientChannel, 'exchange_ping'):
-            self.client_channel = daemon._ClientChannel(mock.ANY)
+            self.client_channel = daemon._ClientChannel(mock.ANY, context)
 
-    def test_out_of_band_log_message(self):
-        message = [daemon.Message.LOG, self.DICT]
+    @mock.patch.object(daemon.LOG.logger, 'handle')
+    def test_out_of_band_log_message(self, handle_mock):
+        message = [comm.Message.LOG, self.DICT]
+        self.assertEqual(self.client_channel.log, daemon.LOG)
         with mock.patch.object(pylogging, 'makeLogRecord') as mock_make_log, \
                 mock.patch.object(daemon.LOG, 'isEnabledFor',
-                                  return_value=False):
+                                  return_value=True) as mock_enabled:
             self.client_channel.out_of_band(message)
             mock_make_log.assert_called_once_with(self.EXPECTED)
+            handle_mock.assert_called_once_with(mock_make_log.return_value)
+            mock_enabled.assert_called_once_with(
+                mock_make_log.return_value.levelno)
 
     def test_out_of_band_not_log_message(self):
         with mock.patch.object(daemon.LOG, 'warning') as mock_warning:
-            self.client_channel.out_of_band([daemon.Message.PING])
+            self.client_channel.out_of_band([comm.Message.PING])
             mock_warning.assert_called_once()
 
+    @mock.patch.object(daemon.logging, 'getLogger')
+    @mock.patch.object(pylogging, 'makeLogRecord')
+    def test_out_of_band_log_message_context_logger(self, make_log_mock,
+                                                    get_logger_mock):
+        logger_name = 'os_brick.privileged'
+        context = get_fake_context(conf_attrs={'logger_name': logger_name})
+        with mock.patch.object(comm.ClientChannel, '__init__'), \
+                mock.patch.object(daemon._ClientChannel, 'exchange_ping'):
+            channel = daemon._ClientChannel(mock.ANY, context)
+
+        get_logger_mock.assert_called_once_with(logger_name)
+        self.assertEqual(get_logger_mock.return_value, channel.log)
+
+        message = [comm.Message.LOG, self.DICT]
+        channel.out_of_band(message)
+
+        make_log_mock.assert_called_once_with(self.EXPECTED)
+        channel.log.isEnabledFor.assert_called_once_with(
+            make_log_mock.return_value.levelno)
+        channel.log.logger.handle.assert_called_once_with(
+            make_log_mock.return_value)
+
 
 class UnMonkeyPatch(base.BaseTestCase):
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.privsep-2.5.0/oslo_privsep/tests/test_priv_context.py 
new/oslo.privsep-2.6.2/oslo_privsep/tests/test_priv_context.py
--- old/oslo.privsep-2.5.0/oslo_privsep/tests/test_priv_context.py      
2021-03-11 21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/oslo_privsep/tests/test_priv_context.py      
2021-08-26 17:49:16.000000000 +0200
@@ -19,10 +19,12 @@
 import platform
 import sys
 import tempfile
+import time
 from unittest import mock
 
 import testtools
 
+from oslo_privsep import comm
 from oslo_privsep import daemon
 from oslo_privsep import priv_context
 from oslo_privsep.tests import testctx
@@ -40,6 +42,12 @@
     return arg + 1
 
 
+@testctx.context.entrypoint_with_timeout(0.2)
+def do_some_long(long_timeout=0.4):
+    time.sleep(long_timeout)
+    return 42
+
+
 class CustomError(Exception):
     def __init__(self, code, msg):
         super(CustomError, self).__init__(code, msg)
@@ -188,6 +196,16 @@
         priv_pid = priv_getpid()
         self.assertNotMyPid(priv_pid)
 
+    def test_long_call_with_timeout(self):
+        self.assertRaises(
+            comm.PrivsepTimeout,
+            do_some_long
+        )
+
+    def test_long_call_within_timeout(self):
+        res = do_some_long(0.001)
+        self.assertEqual(42, res)
+
 
 @testtools.skipIf(platform.system() != 'Linux',
                   'works only on Linux platform.')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.privsep-2.5.0/releasenotes/notes/add_entrypoint_with_timeout_decorator-9aab5a74153b3632.yaml
 
new/oslo.privsep-2.6.2/releasenotes/notes/add_entrypoint_with_timeout_decorator-9aab5a74153b3632.yaml
--- 
old/oslo.privsep-2.5.0/releasenotes/notes/add_entrypoint_with_timeout_decorator-9aab5a74153b3632.yaml
       1970-01-01 01:00:00.000000000 +0100
+++ 
new/oslo.privsep-2.6.2/releasenotes/notes/add_entrypoint_with_timeout_decorator-9aab5a74153b3632.yaml
       2021-08-26 17:49:16.000000000 +0200
@@ -0,0 +1,11 @@
+---
+features:
+  - |
+    Add ``timeout`` as parameter to ``PrivContext`` and add
+    ``entrypoint_with_timeout`` decorator to cover the issues with
+    commands which take random time to finish.
+    ``PrivsepTimeout`` is raised if timeout is reached.
+
+    ``Warning``: The daemon (the root process) task won't stop when timeout
+    is reached. That means we'll have less available threads if the related
+    thread never finishes.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/oslo.privsep-2.5.0/releasenotes/notes/context-logger-06b475357bebadc7.yaml 
new/oslo.privsep-2.6.2/releasenotes/notes/context-logger-06b475357bebadc7.yaml
--- 
old/oslo.privsep-2.5.0/releasenotes/notes/context-logger-06b475357bebadc7.yaml  
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/oslo.privsep-2.6.2/releasenotes/notes/context-logger-06b475357bebadc7.yaml  
    2021-08-26 17:49:16.000000000 +0200
@@ -0,0 +1,15 @@
+---
+features:
+  - |
+    ``PrivContext`` accepts a new string parameter called ``logger_name`` to
+    define the logger we want to use for the daemon logs of this context.
+
+    By default all contexts use ``oslo_privsep.daemon``, but in some cases we
+    may need finer grained log levels, for example nova running in debug mode
+    could log its own privsep calls on INFO level regardless, but leave all
+    libraries' privsep calls, such as os-brick's, to be logged in the normal
+    DEBUG level.
+
+    See `bug 1922052`_.
+
+    .. _`bug 1922052`: https://bugs.launchpad.net/nova/+bug/1922052
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/releasenotes/source/index.rst 
new/oslo.privsep-2.6.2/releasenotes/source/index.rst
--- old/oslo.privsep-2.5.0/releasenotes/source/index.rst        2021-03-11 
21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/releasenotes/source/index.rst        2021-08-26 
17:49:16.000000000 +0200
@@ -6,6 +6,7 @@
     :maxdepth: 1
 
     unreleased
+    wallaby
     victoria
     ussuri
     train
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/releasenotes/source/wallaby.rst 
new/oslo.privsep-2.6.2/releasenotes/source/wallaby.rst
--- old/oslo.privsep-2.5.0/releasenotes/source/wallaby.rst      1970-01-01 
01:00:00.000000000 +0100
+++ new/oslo.privsep-2.6.2/releasenotes/source/wallaby.rst      2021-08-26 
17:49:16.000000000 +0200
@@ -0,0 +1,6 @@
+============================
+Wallaby Series Release Notes
+============================
+
+.. release-notes::
+   :branch: stable/wallaby
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/setup.cfg 
new/oslo.privsep-2.6.2/setup.cfg
--- old/oslo.privsep-2.5.0/setup.cfg    2021-03-11 21:28:21.687663800 +0100
+++ new/oslo.privsep-2.6.2/setup.cfg    2021-08-26 17:49:51.674757700 +0200
@@ -1,12 +1,12 @@
 [metadata]
 name = oslo.privsep
 summary = OpenStack library for privilege separation
-description-file = 
+description_file = 
        README.rst
 author = OpenStack
-author-email = openstack-disc...@lists.openstack.org
-home-page = https://docs.openstack.org/oslo.privsep/latest/
-python-requires = >=3.6
+author_email = openstack-disc...@lists.openstack.org
+home_page = https://docs.openstack.org/oslo.privsep/latest/
+python_requires = >=3.6
 classifier = 
        Environment :: OpenStack
        Intended Audience :: Information Technology
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/oslo.privsep-2.5.0/tox.ini 
new/oslo.privsep-2.6.2/tox.ini
--- old/oslo.privsep-2.5.0/tox.ini      2021-03-11 21:27:45.000000000 +0100
+++ new/oslo.privsep-2.6.2/tox.ini      2021-08-26 17:49:16.000000000 +0200
@@ -1,12 +1,12 @@
 [tox]
-minversion = 3.1.1
-envlist = py38,pypy,pep8
+minversion = 3.18.0
+envlist = py3,pypy,pep8
 ignore_basepython_conflict = true
 
 [testenv]
 basepython = python3
 deps =
-  
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+  
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
   -r{toxinidir}/test-requirements.txt
   -r{toxinidir}/requirements.txt
 commands = stestr run --slowest {posargs}
@@ -23,7 +23,7 @@
 commands = {posargs}
 
 [testenv:docs]
-whitelist_externals =
+allowlist_externals =
   rm
 deps =
   {[testenv]deps}
@@ -57,21 +57,15 @@
   oslo_privsep._i18n
 
 [testenv:releasenotes]
-whitelist_externals =
+allowlist_externals =
   rm
 deps =
-  
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+  
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
   -r{toxinidir}/doc/requirements.txt
 commands =
   rm -rf releasenotes/build
   sphinx-build -a -E -W -d releasenotes/build/doctrees --keep-going -b html 
releasenotes/source releasenotes/build/html
 
-[testenv:lower-constraints]
-deps =
-  -c{toxinidir}/lower-constraints.txt
-  -r{toxinidir}/test-requirements.txt
-  -r{toxinidir}/requirements.txt
-
 [testenv:functional]
 basepython = python3
 setenv =

Reply via email to