From e1b0399ee018d217cd50267cef03c28dfdb32fbf Mon Sep 17 00:00:00 2001 From: Arthur de Jong Date: Fri, 26 Jul 2013 14:59:43 +0200 Subject: Rename nscd_invalidate option to reconnect_invalidate This also renames the internal nscd module to invalidator for both nslcd and pynslcd. The new invalidator module is now no longer nscd-specific. --- pynslcd/Makefile.am | 2 +- pynslcd/cfg.py | 8 ++-- pynslcd/invalidator.py | 112 +++++++++++++++++++++++++++++++++++++++++++++++++ pynslcd/nscd.py | 112 ------------------------------------------------- pynslcd/pynslcd.py | 8 ++-- pynslcd/search.py | 4 +- 6 files changed, 123 insertions(+), 123 deletions(-) create mode 100644 pynslcd/invalidator.py delete mode 100644 pynslcd/nscd.py (limited to 'pynslcd') diff --git a/pynslcd/Makefile.am b/pynslcd/Makefile.am index d0604f4..f96654b 100644 --- a/pynslcd/Makefile.am +++ b/pynslcd/Makefile.am @@ -20,7 +20,7 @@ pynslcddir = $(datadir)/pynslcd pynslcd_PYTHON = pynslcd.py attmap.py cache.py cfg.py common.py expr.py \ - mypidfile.py nscd.py search.py tio.py \ + mypidfile.py invalidator.py search.py tio.py \ alias.py ether.py group.py host.py netgroup.py network.py \ passwd.py protocol.py rpc.py service.py shadow.py pam.py \ usermod.py diff --git a/pynslcd/cfg.py b/pynslcd/cfg.py index 516eeb7..cf9c872 100644 --- a/pynslcd/cfg.py +++ b/pynslcd/cfg.py @@ -85,7 +85,7 @@ nss_nested_groups = False validnames = re.compile(r'^[a-z0-9._@$][a-z0-9._@$ \\~-]{0,98}[a-z0-9._@$~-]$', re.IGNORECASE) pam_authz_searches = [] pam_password_prohibit_message = None # FIXME: add support -nscd_invalidate = set() +reconnect_invalidate = set() # allowed boolean values @@ -311,15 +311,15 @@ def read(filename): flags = 0 | re.IGNORECASE if m.group('flags') == 'i' else 0 validnames = re.compile(m.group('value'), flags=flags) continue - # nscd_invalidate ,,... - m = re.match('nscd_invalidate\s+(?P\S.*)', + # reconnect_invalidate ,,... + m = re.match('reconnect_invalidate\s+(?P\S.*)', line, re.IGNORECASE) if m: dbs = re.split('[ ,]+', m.group('value').lower()) for db in dbs: if db not in maps.keys() + ['nfsidmap']: raise ParseError(filename, lineno, 'map %s unknown' % db) - nscd_invalidate.update(dbs) + reconnect_invalidate.update(dbs) continue # unrecognised line raise ParseError(filename, lineno, 'error parsing line %r' % line) diff --git a/pynslcd/invalidator.py b/pynslcd/invalidator.py new file mode 100644 index 0000000..98c0783 --- /dev/null +++ b/pynslcd/invalidator.py @@ -0,0 +1,112 @@ + +# invalidator.py - functions for invalidating external caches +# +# Copyright (C) 2013 Arthur de Jong +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA + +import fcntl +import logging +import os +import subprocess + +import cfg + + +# the file descriptor used for sending messages to the child process +signalfd = None + + +# mapping between map name and signal character +_db_to_char = dict( + aliases='A', ethers='E', group='G', hosts='H', netgroup='U', + networks='N', passwd='P', protocols='L', rpc='R', services='V', + shadow='S', nfsidmap='F', + ) +_char_to_db = dict((reversed(item) for item in _db_to_char.items())) + + +def exec_invalidate(*args): + cmd = ' '.join(args) + logging.debug('invalidator: %s', cmd) + try: + p = subprocess.Popen(args, bufsize=4096, close_fds=True, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + output, ignored = p.communicate() + if output: + output = ': %s' % output[:1024].strip() + if p.returncode == 0: + logging.debug('invalidator: %s (pid %d) success%s', + cmd, p.pid, output) + elif p.returncode > 0: + logging.debug('invalidator: %s (pid %d) failed (%d)%s', + cmd, p.pid, p.returncode, output) + else: # p.returncode < 0 + logging.error('invalidator: %s (pid %d) killed by signal %d%s', + cmd, p.pid, -p.returncode, output) + except: + logging.warn('invalidator: %s failed', cmd, exc_info=True) + + +def loop(fd): + # set process title + try: + import setproctitle + setproctitle.setproctitle('(invalidator)') + except ImportError: + pass + # set up clean environment + os.chdir('/') + os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' + while True: + db = os.read(fd, 1) + if db == '': + break # close process down + db = _char_to_db.get(db, None) + if db == 'nfsidmap': + exec_invalidate('nfsidmap', '-c') + else if db: + exec_invalidate('nscd', '-i', db) + + +def start_invalidator(): + r, w = os.pipe() + # mark write end as non-blocking + flags = fcntl.fcntl(w, fcntl.F_GETFL) + fcntl.fcntl(w, fcntl.F_SETFL, flags | os.O_NONBLOCK) + cpid = os.fork() + if cpid == 0: + # we are the child + os.close(w) + loop(r) + os._exit(1) + # we are the parent + global signalfd + signalfd = w + os.close(r) + + +def invalidate(db=None): + if signalfd is None: + return # nothing to do + if db: + db = _db_to_char.get(db, '') + else: + db = ''.join(_db_to_char[x] for x in cfg.reconnect_invalidate) + try: + os.write(signalfd, db) + except: + logging.warn('requesting invalidation (%s) failed', db, exc_info=True) diff --git a/pynslcd/nscd.py b/pynslcd/nscd.py deleted file mode 100644 index 1cc05cf..0000000 --- a/pynslcd/nscd.py +++ /dev/null @@ -1,112 +0,0 @@ - -# nscd.py - functions for invalidating the nscd cache -# -# Copyright (C) 2013 Arthur de Jong -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA - -import fcntl -import logging -import os -import subprocess - -import cfg - - -# the file descriptor used for sending messages to the child process -signalfd = None - - -# mapping between map name and signal character -_db_to_char = dict( - aliases='A', ethers='E', group='G', hosts='H', netgroup='U', - networks='N', passwd='P', protocols='L', rpc='R', services='V', - shadow='S', nfsidmap='F', - ) -_char_to_db = dict((reversed(item) for item in _db_to_char.items())) - - -def exec_invalidate(*args): - cmd = ' '.join(args) - logging.debug('nscd_invalidator: %s', cmd) - try: - p = subprocess.Popen(args, bufsize=4096, close_fds=True, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - output, ignored = p.communicate() - if output: - output = ': %s' % output[:1024].strip() - if p.returncode == 0: - logging.debug('nscd_invalidator: %s (pid %d) success%s', - cmd, p.pid, output) - elif p.returncode > 0: - logging.debug('nscd_invalidator: %s (pid %d) failed (%d)%s', - cmd, p.pid, p.returncode, output) - else: # p.returncode < 0 - logging.error('nscd_invalidator: %s (pid %d) killed by signal %d%s', - cmd, p.pid, -p.returncode, output) - except: - logging.warn('nscd_invalidator: %s failed', cmd, exc_info=True) - - -def loop(fd): - # set process title - try: - import setproctitle - setproctitle.setproctitle('(nscd invalidator)') - except ImportError: - pass - # set up clean environment - os.chdir('/') - os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' - while True: - db = os.read(fd, 1) - if db == '': - break # close process down - db = _char_to_db.get(db, None) - if db == 'nfsidmap': - exec_invalidate('nfsidmap', '-c') - else if db: - exec_invalidate('nscd', '-i', db) - - -def start_invalidator(): - r, w = os.pipe() - # mark write end as non-blocking - flags = fcntl.fcntl(w, fcntl.F_GETFL) - fcntl.fcntl(w, fcntl.F_SETFL, flags | os.O_NONBLOCK) - cpid = os.fork() - if cpid == 0: - # we are the child - os.close(w) - loop(r) - os._exit(1) - # we are the parent - global signalfd - signalfd = w - os.close(r) - - -def invalidate(db=None): - if signalfd is None: - return # nothing to do - if db: - db = _db_to_char.get(db, '') - else: - db = ''.join(_db_to_char[x] for x in cfg.nscd_invalidate) - try: - os.write(signalfd, db) - except: - logging.warn('requesting invalidation (%s) failed', db, exc_info=True) diff --git a/pynslcd/pynslcd.py b/pynslcd/pynslcd.py index df54bad..4a57155 100755 --- a/pynslcd/pynslcd.py +++ b/pynslcd/pynslcd.py @@ -35,7 +35,7 @@ import cfg import common import constants import mypidfile -import nscd +import invalidator import search @@ -323,9 +323,9 @@ if __name__ == '__main__': logging.getLogger().setLevel(min(level for method, level in cfg.logs)) logging.getLogger().removeHandler(stderrhandler) logging.info('version %s starting', constants.VERSION) - # start nscd sub-process if needed - if cfg.nscd_invalidate: - nscd.start_invalidator() + # start invalidator sub-process if needed + if cfg.invalidator_invalidate: + invalidator.start_invalidator() # create socket nslcd_serversocket = create_socket() # load supplementary groups diff --git a/pynslcd/search.py b/pynslcd/search.py index 3db6e9d..f8c82fb 100644 --- a/pynslcd/search.py +++ b/pynslcd/search.py @@ -55,9 +55,9 @@ class Connection(ldap.ldapobject.ReconnectLDAPObject): self.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_HARD) def reconnect_after_fail(self): - import nscd + import invalidator logging.info('connected to LDAP server %s', cfg.uri) - nscd.invalidate() + invalidator.invalidate() def search_s(self, *args, **kwargs): # wrapper function to keep the global server_error state -- cgit v1.2.3