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 =