diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..0042673 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,8 @@ +[MESSAGES CONTROL] +disable=line-too-long, + missing-docstring, + invalid-name, + locally-disabled, + too-many-arguments, + too-many-branches, + redefined-outer-name, diff --git a/check_syncrepl_extended b/check_syncrepl_extended index 26d136f..11f12ea 100755 --- a/check_syncrepl_extended +++ b/check_syncrepl_extended @@ -26,483 +26,556 @@ # # This script could be use as Nagios plugin (-n argument) # -# Requirement : -# A single couple of DN and password able to connect to both server +# Requirement: +# A single couple of DN and password able to connect to both server # and without restriction to retrieve objects from servers. # -# Author : Benjamin Renard -# Date : Mon, 10 Dec 2012 18:04:24 +0100 -# Source : http://git.zionetrix.net/check_syncrepl_extended +# Author: Benjamin Renard +# Date: Mon, 10 Dec 2012 18:04:24 +0100 +# Source: http://git.zionetrix.net/check_syncrepl_extended # -import ldap -from ldap.controls import SimplePagedResultsControl -import ldap.modlist as modlist +import argparse import logging import sys + import getpass -from optparse import OptionParser +import ldap +from ldap import LDAPError # pylint: disable=no-name-in-module +from ldap.controls import SimplePagedResultsControl +import ldap.modlist as modlist -TOUCH_VALUE='%%TOUCH%%' +TOUCH_VALUE = '%%TOUCH%%' -parser = OptionParser(version="%prog version 1.0\n\nDate : Mon, 10 Dec 2012 18:04:24 +0100\nAuthor : Benjamin Renard \nSource : http://git.zionetrix.net/check_syncrepl_extended") +parser = argparse.ArgumentParser( + version="""%prog version 1.1 -parser.add_option( "-p", "--provider", - dest="provider", - action="store", - type='string', - help="LDAP provider URI (example : ldaps://ldapmaster.foo:636)") +Date: Fri, 18 Dec 2020 10:48:45 +0100 +Author: Benjamin Renard +Source: https://gogs.zionetrix.net/bn8/check_syncrepl_extended +""" +) -parser.add_option( "-c", "--consumer", - dest="consumer", - action="store", - type='string', - help="LDAP consumer URI (example : ldaps://ldapslave.foo:636)") +parser.add_argument( + "-p", "--provider", + dest="provider", + action="store", + type=str, + help="LDAP provider URI (example: ldaps://ldapmaster.foo:636)" +) -parser.add_option( "-i", "--serverID", - dest="serverid", - action="store", - type='int', - help="Compare contextCSN of a specific master. Useful in MultiMaster setups where each master has a unique ID and a contextCSN for each replicated master exists. A valid serverID is a integer value from 0 to 4095 (limited to 3 hex digits, example: '12' compares the contextCSN matching '#00C#')", - default=False) +parser.add_argument( + "-c", "--consumer", + dest="consumer", + action="store", + type=str, + help="LDAP consumer URI (example: ldaps://ldapslave.foo:636)" +) -parser.add_option( "-T", "--starttls", - dest="starttls", - action="store_true", - help="Start TLS on LDAP provider/consumers connections", - default=False) +parser.add_argument( + "-i", "--serverID", + dest="serverid", + action="store", + type=int, + help="Compare contextCSN of a specific master. Useful in MultiMaster setups where each master has a unique ID and a contextCSN for each replicated master exists. A valid serverID is a integer value from 0 to 4095 (limited to 3 hex digits, example: '12' compares the contextCSN matching '#00C#')", + default=False +) -parser.add_option( "-D", "--dn", - dest="dn", - action="store", - type='string', - help="LDAP bind DN (example : uid=nagios,ou=sysaccounts,o=example") +parser.add_argument( + "-T", "--starttls", + dest="starttls", + action="store_true", + help="Start TLS on LDAP provider/consumers connections", + default=False +) -parser.add_option( "-P", "--pwd", - dest="pwd", - action="store", - type='string', - help="LDAP bind password", - default=None) +parser.add_argument( + "-D", "--dn", + dest="dn", + action="store", + type=str, + help="LDAP bind DN (example: uid=nagios,ou=sysaccounts,o=example" +) -parser.add_option( "-b", "--basedn", - dest="basedn", - action="store", - type='string', - help="LDAP base DN (example : o=example)") +parser.add_argument( + "-P", "--pwd", + dest="pwd", + action="store", + type=str, + help="LDAP bind password", + default=None +) -parser.add_option( "-f", "--filter", - dest="filter", - action="store", - type='string', - help="LDAP filter (default : (objectClass=*))", - default='(objectClass=*)') +parser.add_argument( + "-b", "--basedn", + dest="basedn", + action="store", + type=str, + help="LDAP base DN (example: o=example)" +) -parser.add_option( "-d", "--debug", - dest="debug", - action="store_true", - help="Debug mode", - default=False) +parser.add_argument( + "-f", "--filter", + dest="filterstr", + action="store", + type=str, + help="LDAP filter (default: (objectClass=*))", + default='(objectClass=*)' +) -parser.add_option( "-n", "--nagios", - dest="nagios", - action="store_true", - help="Nagios check plugin mode", - default=False) +parser.add_argument( + "-d", "--debug", + dest="debug", + action="store_true", + help="Debug mode", + default=False +) -parser.add_option( "-q", "--quiet", - dest="quiet", - action="store_true", - help="Quiet mode", - default=False) +parser.add_argument( + "-n", "--nagios", + dest="nagios", + action="store_true", + help="Nagios check plugin mode", + default=False +) -parser.add_option( "--no-check-certificate", - dest="nocheckcert", - action="store_true", - help="Don't check the server certificate (Default : False)", - default=False) +parser.add_argument( + "-q", "--quiet", + dest="quiet", + action="store_true", + help="Quiet mode", + default=False +) -parser.add_option( "--no-check-contextCSN", - dest="nocheckcontextcsn", - action="store_true", - help="Don't check servers contextCSN (Default : False)", - default=False) +parser.add_argument( + "--no-check-certificate", + dest="nocheckcert", + action="store_true", + help="Don't check the server certificate (Default: False)", + default=False +) -parser.add_option( "-a", "--attributes", - dest="attrs", - action="store_true", - help="Check attributes values (Default : check only entryCSN)", - default=False) +parser.add_argument( + "--no-check-contextCSN", + dest="nocheckcontextcsn", + action="store_true", + help="Don't check servers contextCSN (Default: False)", + default=False +) -parser.add_option( "--exclude-attributes", - dest="excl_attrs", - action="store", - type='string', - help="Don't check this attribut (only in attribute check mode)", - default=None) +parser.add_argument( + "-a", "--attributes", + dest="attrs", + action="store_true", + help="Check attributes values (Default: check only entryCSN)", + default=False +) -parser.add_option( "--touch", - dest="touch", - action="store", - type='string', - help="Touch attribute giving in parameter to force resync a this LDAP object from provider. A value '%s' will be add to this attribute and remove after. The user use to connect to the LDAP directory must have write permission on this attribute on each object." % TOUCH_VALUE, - default=None) +parser.add_argument( + "--exclude-attributes", + dest="excl_attrs", + action="store", + type=str, + help="Don't check this attribut (only in attribute check mode)", + default=None +) -parser.add_option( "--replace-touch", - dest="replacetouch", - action="store_true", - help="In touch mode, replace value instead of adding.", - default=False) +parser.add_argument( + "--touch", + dest="touch", + action="store", + type=str, + help="Touch attribute giving in parameter to force resync a this LDAP object from provider. A value '%s' will be add to this attribute and remove after. The user use to connect to the LDAP directory must have write permission on this attribute on each object." % TOUCH_VALUE, + default=None +) -parser.add_option( "--remove-touch-value", - dest="removetouchvalue", - action="store_true", - help="In touch mode, remove touch value if present.", - default=False) +parser.add_argument( + "--replace-touch", + dest="replacetouch", + action="store_true", + help="In touch mode, replace value instead of adding.", + default=False +) -parser.add_option( "--page-size", - dest="page_size", - action="store", - type='int', - help="Page size : if defined, paging control using LDAP v3 extended control will be enabled.", - default=None) +parser.add_argument( + "--remove-touch-value", + dest="removetouchvalue", + action="store_true", + help="In touch mode, remove touch value if present.", + default=False +) -(options, args) = parser.parse_args() +parser.add_argument( + "--page-size", + dest="page_size", + action="store", + type=int, + help="Page size: if defined, paging control using LDAP v3 extended control will be enabled.", + default=None +) + +options = parser.parse_args() if not options.provider or not options.consumer: - print "You must provide provider and customer URI" - if options.nagios: - sys.exit(3) - sys.exit(1) + print "You must provide provider and customer URI" + if options.nagios: + sys.exit(3) + sys.exit(1) if not options.basedn: - print "You must provide base DN of connection to LDAP servers" - if options.nagios: - sys.exit(3) - sys.exit(1) + print "You must provide base DN of connection to LDAP servers" + if options.nagios: + sys.exit(3) + sys.exit(1) if not 0 <= options.serverid <= 4095: - print "ServerID should be a integer value from 0 to 4095 (limited to 3 hexadecimal digits)." - if options.nagios: - sys.exit(3) - sys.exit(1) + print "ServerID should be a integer value from 0 to 4095 (limited to 3 hexadecimal digits)." + if options.nagios: + sys.exit(3) + sys.exit(1) if options.touch and not options.attrs: - logging.info('Force option attrs on touch mode') - options.attrs=True + logging.info('Force option attrs on touch mode') + options.attrs = True if options.dn and options.pwd is None: - options.pwd=getpass.getpass() + options.pwd = getpass.getpass() -excl_attrs=[] +excl_attrs = [] if options.excl_attrs: - for ex in options.excl_attrs.split(','): - excl_attrs.append(ex.strip()) + for ex in options.excl_attrs.split(','): + excl_attrs.append(ex.strip()) -FORMAT="%(asctime)s - %(levelname)s : %(message)s" +FORMAT = "%(asctime)s - %(levelname)s: %(message)s" if options.debug: - logging.basicConfig(level=logging.DEBUG,format=FORMAT) - ldap.set_option(ldap.OPT_DEBUG_LEVEL,0) - ldapmodule_trace_level = 1 - ldapmodule_trace_file = sys.stderr + logging.basicConfig(level=logging.DEBUG, format=FORMAT) + ldap.set_option(ldap.OPT_DEBUG_LEVEL, 0) # pylint: disable=no-member + ldapmodule_trace_level = 1 + ldapmodule_trace_file = sys.stderr elif options.nagios: - logging.basicConfig(level=logging.ERROR,format=FORMAT) + logging.basicConfig(level=logging.ERROR, format=FORMAT) elif options.quiet: - logging.basicConfig(level=logging.WARNING,format=FORMAT) + logging.basicConfig(level=logging.WARNING, format=FORMAT) else: - logging.basicConfig(level=logging.INFO,format=FORMAT) + logging.basicConfig(level=logging.INFO, format=FORMAT) class LdapServer(object): - uri = "" - dn = "" - pwd = "" - start_tls = False + uri = "" + dn = "" + pwd = "" + start_tls = False - con = 0 + con = 0 - def __init__(self,uri,dn,pwd, start_tls=False, page_size=None): - self.uri = uri - self.dn = dn - self.pwd = pwd - self.start_tls = start_tls - self.page_size = page_size + def __init__(self, uri, dn, pwd, start_tls=False, page_size=None): + self.uri = uri + self.dn = dn + self.pwd = pwd + self.start_tls = start_tls + self.page_size = page_size - def connect(self): - if self.con == 0: - try: - con = ldap.initialize(self.uri) - con.protocol_version = ldap.VERSION3 - if self.start_tls: - con.start_tls_s() - if self.dn: - con.simple_bind_s(self.dn,self.pwd) - self.con = con - return True - except ldap.LDAPError, e: - logging.error("LDAP Error : %s" % e) - return + def connect(self): + if self.con == 0: + try: + con = ldap.initialize(self.uri) + con.protocol_version = ldap.VERSION3 # pylint: disable=no-member + if self.start_tls: + con.start_tls_s() + if self.dn: + con.simple_bind_s(self.dn, self.pwd) + self.con = con + except LDAPError: + logging.error("LDAP Error", exc_info=True) + return False + return True - def getContextCSN(self,basedn=False,serverid=False): - if not basedn: - basedn=self.dn - data=self.search(basedn,'(objectclass=*)',['contextCSN']) - if len(data)>0: - contextCSNs=data[0][0][1]['contextCSN'] - logging.debug('Found contextCSNs %s' % contextCSNs) - if serverid is False: - return contextCSNs[0] - else: - csnid=str(format(serverid, 'X')).zfill(3) - sub='#%s#' % csnid - CSN=[s for s in contextCSNs if sub in s] - if not CSN: - logging.error("No contextCSN matching with ServerID %s (=%s) could be found." % (serverid,sub)) - return False - else: - return CSN[0] - else: - return False + def getContextCSN(self, basedn=False, serverid=False): + if not basedn: + basedn = self.dn + data = self.search(basedn, '(objectclass=*)', ['contextCSN']) + if data: + contextCSNs = data[0][0][1]['contextCSN'] + logging.debug('Found contextCSNs %s', contextCSNs) + if serverid is False: + return contextCSNs[0] + csnid = str(format(serverid, 'X')).zfill(3) + sub = '#%s#' % csnid + CSN = [s for s in contextCSNs if sub in s] + if not CSN: + logging.error( + "No contextCSN matching with ServerID %s (=%s) could be found.", + serverid, sub + ) + return False + return CSN[0] + return False - def search(self,basedn,filter,attrs): - if self.page_size: - return self.paged_search(basedn,filter,attrs) - res_id = self.con.search(basedn,ldap.SCOPE_SUBTREE,filter,attrs) - ret = [] - while 1: - res_type, res_data = self.con.result(res_id,0) - if res_data == []: - break - else: - if res_type == ldap.RES_SEARCH_ENTRY: - ret.append(res_data) - return ret + def search(self, basedn, filterstr, attrs): + if self.page_size: + return self.paged_search(basedn, filterstr, attrs) + res_id = self.con.search(basedn, ldap.SCOPE_SUBTREE, filterstr, attrs) # pylint: disable=no-member + ret = [] + while 1: + res_type, res_data = self.con.result(res_id, 0) + if res_data == []: + break + else: + if res_type == ldap.RES_SEARCH_ENTRY: # pylint: disable=no-member + ret.append(res_data) + return ret - def paged_search(self,basedn,filter,attrs): - ret = [] - page = 0 - pg_ctrl = SimplePagedResultsControl(True, self.page_size, '') - pg_oid = SimplePagedResultsControl.controlType - while page == 0 or pg_ctrl.cookie: - page += 1 - logging.debug('Page search : loading page %d' % page) - res_id = self.con.search_ext(basedn,ldap.SCOPE_SUBTREE,filter,attrs,serverctrls=[pg_ctrl]) - res_type, res_data, res_id, serverctrls = self.con.result3(res_id) - for serverctrl in serverctrls: - if serverctrl.controlType == pg_oid: - pg_ctrl.cookie = serverctrl.cookie - for item in res_data: - ret.append([item]) - return ret + def paged_search(self, basedn, filterstr, attrs): + ret = [] + page = 0 + pg_ctrl = SimplePagedResultsControl(True, self.page_size, '') + while page == 0 or pg_ctrl.cookie: + page += 1 + logging.debug('Page search: loading page %d', page) + res_id = self.con.search_ext( + basedn, ldap.SCOPE_SUBTREE, # pylint: disable=no-member + filterstr, attrs, + serverctrls=[pg_ctrl] + ) + res_type, res_data, res_id, serverctrls = self.con.result3(res_id) # pylint: disable=unused-variable + for serverctrl in serverctrls: + if serverctrl.controlType == SimplePagedResultsControl.controlType: + pg_ctrl.cookie = serverctrl.cookie + break + for item in res_data: + ret.append([item]) + return ret - def update_object(self,dn,old,new): - ldif = modlist.modifyModlist(old,new) - if ldif == []: - return True - try: - logging.debug('Update object %s : %s' % (dn,ldif)) - self.con.modify_s(dn,ldif) - return True - except ldap.LDAPError, e: - logging.error('Error updating object %s : %s' % (dn,e)) - return False + def update_object(self, dn, old, new): + ldif = modlist.modifyModlist(old, new) + if ldif == []: + return True + try: + logging.debug('Update object %s: %s', dn, ldif) + self.con.modify_s(dn, ldif) + return True + except LDAPError: + logging.error('Error updating object %s', dn, exc_info=True) + return False - def get_attr(self,obj,attr): - if attr in obj[0][1]: - return obj[0][1][attr] - return [] + @staticmethod + def get_attr(obj, attr): + if attr in obj[0][1]: + return obj[0][1][attr] + return [] - def touch_object(self,dn,attr,orig_value): - old = {} - if orig_value: - old[attr] = orig_value - new = {} + def touch_object(self, dn, attr, orig_value): + old = {} + if orig_value: + old[attr] = orig_value + new = {} - if options.replacetouch: - if not orig_value or TOUCH_VALUE not in orig_value: - new[attr] = [TOUCH_VALUE] - else: - new[attr] = list(orig_value) - if orig_value or TOUCH_VALUE in orig_value: - new[attr].remove(TOUCH_VALUE) - else: - new[attr].append(TOUCH_VALUE) - try: - logging.info('Touch object "%s" on attribute "%s" : %s => %s', dn, attr, old, new) - if self.update_object(dn, old, new): - logging.info('Restore original value of attribute "%s" of object "%s"', attr, dn) - if options.removetouchvalue and TOUCH_VALUE in old[attr]: - old[attr].remove(TOUCH_VALUE) - self.update_object(dn, new, old) - return True - except ldap.LDAPError: - logging.error('Error touching object "%s"', dn, exc_info=True) - return False + if options.replacetouch: + if not orig_value or TOUCH_VALUE not in orig_value: + new[attr] = [TOUCH_VALUE] + else: + new[attr] = list(orig_value) + if orig_value or TOUCH_VALUE in orig_value: + new[attr].remove(TOUCH_VALUE) + else: + new[attr].append(TOUCH_VALUE) + try: + logging.info( + 'Touch object "%s" on attribute "%s": %s => %s', + dn, attr, old, new + ) + if self.update_object(dn, old, new): + logging.info('Restore original value of attribute "%s" of object "%s"', attr, dn) + if options.removetouchvalue and TOUCH_VALUE in old[attr]: + old[attr].remove(TOUCH_VALUE) + self.update_object(dn, new, old) + return True + except LDAPError: + logging.error('Error touching object "%s"', dn, exc_info=True) + return False if options.nocheckcert: - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER) + ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) # pylint: disable=no-member -servers=[options.provider,options.consumer] +servers = [options.provider, options.consumer] -LdapServers={} -LdapObjects={} -LdapServersCSN={} +LdapServers = {} +LdapObjects = {} +LdapServersCSN = {} for srv in servers: - logging.info('Connect to %s' % srv) - LdapServers[srv]=LdapServer(srv, options.dn, options.pwd, options.starttls, page_size=options.page_size) + logging.info('Connect to %s', srv) + LdapServers[srv] = LdapServer(srv, options.dn, options.pwd, options.starttls, page_size=options.page_size) - if not LdapServers[srv].connect(): - if options.nagios: - print "UNKWNON - Failed to connect to %s" % srv - sys.exit(3) - else: - sys.exit(1) + if not LdapServers[srv].connect(): + if options.nagios: + print "UNKWNON - Failed to connect to %s" % srv + sys.exit(3) + else: + sys.exit(1) - if not options.nocheckcontextcsn: - LdapServersCSN[srv]=LdapServers[srv].getContextCSN(options.basedn,options.serverid) - logging.info('ContextCSN of %s : %s' % (srv, LdapServersCSN[srv])) + if not options.nocheckcontextcsn: + LdapServersCSN[srv] = LdapServers[srv].getContextCSN(options.basedn, options.serverid) + logging.info('ContextCSN of %s: %s', srv, LdapServersCSN[srv]) - logging.info('List objects from %s' % srv) - LdapObjects[srv]={} + logging.info('List objects from %s', srv) + LdapObjects[srv] = {} - if options.attrs: - for obj in LdapServers[srv].search(options.basedn,options.filter,[]): - logging.debug('Found on %s : %s' % (srv,obj[0][0])) - LdapObjects[srv][obj[0][0]]=obj[0][1] - else: - for obj in LdapServers[srv].search(options.basedn,options.filter,['entryCSN']): - logging.debug('Found on %s : %s / %s' % (srv,obj[0][0],obj[0][1]['entryCSN'][0])) - LdapObjects[srv][obj[0][0]]=obj[0][1]['entryCSN'][0] + if options.attrs: + for obj in LdapServers[srv].search(options.basedn, options.filterstr, []): + logging.debug('Found on %s: %s', srv, obj[0][0]) + LdapObjects[srv][obj[0][0]] = obj[0][1] + else: + for obj in LdapServers[srv].search(options.basedn, options.filterstr, ['entryCSN']): + logging.debug( + 'Found on %s: %s / %s', + srv, obj[0][0], obj[0][1]['entryCSN'][0] + ) + LdapObjects[srv][obj[0][0]] = obj[0][1]['entryCSN'][0] - logging.info('%s objects founds' % len(LdapObjects[srv])) + logging.info('%s objects founds', len(LdapObjects[srv])) -not_found={} -not_sync={} +not_found = {} +not_sync = {} for srv in servers: - not_found[srv]=[] - not_sync[srv]=[] + not_found[srv] = [] + not_sync[srv] = [] if options.attrs: - logging.info("Check if objects a are synchronized (by comparing attributes's values)") + logging.info("Check if objects a are synchronized (by comparing attributes's values)") else: - logging.info('Check if objets are synchronized (by comparing entryCSN)') + logging.info('Check if objets are synchronized (by comparing entryCSN)') for obj in LdapObjects[options.provider]: - logging.debug('Check obj %s' % (obj)) - for srv in LdapObjects: - if srv == options.provider: - continue - if obj in LdapObjects[srv]: - touch=False - if LdapObjects[options.provider][obj] != LdapObjects[srv][obj]: - if options.attrs: - attrs_list=[] - for attr in LdapObjects[options.provider][obj]: - if attr in excl_attrs: - continue - if attr not in LdapObjects[srv][obj]: - attrs_list.append(attr) - logging.debug("Obj %s not synchronized : %s not present on %s" % (obj,','.join(attrs_list),srv)) - touch=True - else: - LdapObjects[srv][obj][attr].sort() - LdapObjects[options.provider][obj][attr].sort() - if LdapObjects[srv][obj][attr]!=LdapObjects[options.provider][obj][attr]: - attrs_list.append(attr) - logging.debug("Obj %s not synchronized : %s not same value(s)" % (obj,','.join(attrs_list))) - touch=True - if len(attrs_list)>0: - not_sync[srv].append("%s (%s)" % (obj,','.join(attrs_list))) - else: - logging.debug("Obj %s not synchronized : %s <-> %s" % (obj,LdapObjects[options.provider][obj],LdapObjects[srv][obj])) - not_sync[srv].append(obj) - if touch and options.touch: - orig_value=[] - if options.touch in LdapObjects[options.provider][obj]: - orig_value=LdapObjects[options.provider][obj][options.touch] - LdapServers[options.provider].touch_object(obj,options.touch,orig_value) - else: - logging.debug('Obj %s : not found on %s' % (obj,srv)) - not_found[srv].append(obj) - if options.touch: - orig_value=[] - if options.touch in LdapObjects[options.provider][obj]: - orig_value=LdapObjects[options.provider][obj][options.touch] - LdapServers[options.provider].touch_object(obj,options.touch,orig_value) + logging.debug('Check obj %s', obj) + for srv in LdapObjects: + if srv == options.provider: + continue + if obj in LdapObjects[srv]: + touch = False + if LdapObjects[options.provider][obj] != LdapObjects[srv][obj]: + if options.attrs: + attrs_list = [] + for attr in LdapObjects[options.provider][obj]: + if attr in excl_attrs: + continue + if attr not in LdapObjects[srv][obj]: + attrs_list.append(attr) + logging.debug( + "Obj %s not synchronized: %s not present on %s", + obj, ','.join(attrs_list), srv + ) + touch = True + else: + LdapObjects[srv][obj][attr].sort() + LdapObjects[options.provider][obj][attr].sort() + if LdapObjects[srv][obj][attr] != LdapObjects[options.provider][obj][attr]: + attrs_list.append(attr) + logging.debug( + "Obj %s not synchronized: %s not same value(s)", + obj, ','.join(attrs_list) + ) + touch = True + if attrs_list: + not_sync[srv].append("%s (%s)" % (obj, ','.join(attrs_list))) + else: + logging.debug( + "Obj %s not synchronized: %s <-> %s", + obj, LdapObjects[options.provider][obj], LdapObjects[srv][obj] + ) + not_sync[srv].append(obj) + if touch and options.touch: + orig_value = [] + if options.touch in LdapObjects[options.provider][obj]: + orig_value = LdapObjects[options.provider][obj][options.touch] + LdapServers[options.provider].touch_object(obj, options.touch, orig_value) + else: + logging.debug('Obj %s: not found on %s', obj, srv) + not_found[srv].append(obj) + if options.touch: + orig_value = [] + if options.touch in LdapObjects[options.provider][obj]: + orig_value = LdapObjects[options.provider][obj][options.touch] + LdapServers[options.provider].touch_object(obj, options.touch, orig_value) for obj in LdapObjects[options.consumer]: - logging.debug('Check obj %s of consumer' % obj) - if obj not in LdapObjects[options.provider]: - logging.debug('Obj %s : not found on provider' % obj) - not_found[options.provider].append(obj) + logging.debug('Check obj %s of consumer', obj) + if obj not in LdapObjects[options.provider]: + logging.debug('Obj %s: not found on provider', obj) + not_found[options.provider].append(obj) if options.nagios: - errors=[] - long_output=[] + errors = [] + long_output = [] - if not options.nocheckcontextcsn: - if not LdapServersCSN[options.provider]: - errors.append('ContextCSN of LDAP server provider could not be found') - else: - long_output.append('ContextCSN on LDAP server provider = %s' % LdapServersCSN[options.provider]) - for srv in LdapServersCSN: - if srv==options.provider: - continue - if not LdapServersCSN[srv]: - errors.append('ContextCSN of %s not found' % srv) - elif LdapServersCSN[srv]!=LdapServersCSN[options.provider]: - errors.append('ContextCSN of %s not the same of provider' % srv) - long_output.append('ContextCSN on LDAP server %s = %s' % (srv, LdapServersCSN[srv])) + if not options.nocheckcontextcsn: + if not LdapServersCSN[options.provider]: + errors.append('ContextCSN of LDAP server provider could not be found') + else: + long_output.append('ContextCSN on LDAP server provider = %s' % LdapServersCSN[options.provider]) + for srv in LdapServersCSN: + if srv == options.provider: + continue + if not LdapServersCSN[srv]: + errors.append('ContextCSN of %s not found' % srv) + elif LdapServersCSN[srv] != LdapServersCSN[options.provider]: + errors.append('ContextCSN of %s not the same of provider' % srv) + long_output.append('ContextCSN on LDAP server %s = %s' % (srv, LdapServersCSN[srv])) - if len(not_found[options.consumer])>0: - errors.append("%s not found object(s) on consumer" % len(not_found[options.consumer])) - long_output.append("Object(s) not found on server %s (consumer) :" % options.consumer) - for obj in not_found[options.consumer]: - long_output.append(" - %s" % obj) - if len(not_found[options.provider])>0: - errors.append("%s not found object(s) on provider" % len(not_found[options.provider])) - long_output.append("Object(s) not found on server %s (provider) :" % options.provider) - for obj in not_found[options.provider]: - long_output.append(" - %s" % obj) - if len(not_sync[options.consumer])>0: - errors.append("%s not synchronized object(s) on consumer" % len(not_sync[options.consumer])) - long_output.append("Object(s) not synchronized on server %s (consumer) :" % options.consumer) - for obj in not_sync[options.consumer]: - long_output.append(" - %s" % obj) - if len(errors)>0: - print "CRITICAL : " + ', '.join(errors) + "\n\n" + "\n".join(long_output) - sys.exit(2) - else: - print 'OK : consumer and provider are synchronized' - sys.exit(0) + if not_found[options.consumer]: + errors.append("%s not found object(s) on consumer" % len(not_found[options.consumer])) + long_output.append("Object(s) not found on server %s (consumer) :" % options.consumer) + for obj in not_found[options.consumer]: + long_output.append(" - %s" % obj) + if not_found[options.provider]: + errors.append("%s not found object(s) on provider" % len(not_found[options.provider])) + long_output.append("Object(s) not found on server %s (provider) :" % options.provider) + for obj in not_found[options.provider]: + long_output.append(" - %s" % obj) + if not_sync[options.consumer]: + errors.append("%s not synchronized object(s) on consumer" % len(not_sync[options.consumer])) + long_output.append("Object(s) not synchronized on server %s (consumer) :" % options.consumer) + for obj in not_sync[options.consumer]: + long_output.append(" - %s" % obj) + if errors: + print "CRITICAL: " + ', '.join(errors) + "\n\n" + "\n".join(long_output) + sys.exit(2) + else: + print 'OK: consumer and provider are synchronized' + sys.exit(0) else: - noerror=True - for srv in servers: - if not options.nocheckcontextcsn: - if not LdapServersCSN[options.provider]: - logging.warning('ContextCSN of LDAP server provider could not be found') - noerror=False - else: - for srv in LdapServersCSN: - if srv==options.provider: - continue - if not LdapServersCSN[srv]: - logging.warning('ContextCSN of %s not found' % srv) - noerror=False - elif LdapServersCSN[srv]!=LdapServersCSN[options.provider]: - logging.warning('ContextCSN of %s not the same of provider' % srv) - noerror=False + noerror = True + for srv in servers: + if not options.nocheckcontextcsn: + if not LdapServersCSN[options.provider]: + logging.warning('ContextCSN of LDAP server provider could not be found') + noerror = False + else: + for srv in LdapServersCSN: + if srv == options.provider: + continue + if not LdapServersCSN[srv]: + logging.warning('ContextCSN of %s not found', srv) + noerror = False + elif LdapServersCSN[srv] != LdapServersCSN[options.provider]: + logging.warning('ContextCSN of %s not the same of provider', srv) + noerror = False - if len(not_found[srv])>0: - logging.warning('Not found objects on %s :\n - %s' % (srv,'\n - '.join(not_found[srv]))) - noerror=False - if len(not_sync[srv])>0: - logging.warning('Not sync objects on %s : %s' % (srv,'\n - '.join(not_sync[srv]))) - noerror=False - - if noerror: - logging.info('No sync problem detected') + if not_found[srv]: + logging.warning( + 'Not found objects on %s :\n - %s', + srv, '\n - '.join(not_found[srv]) + ) + noerror = False + if not_sync[srv]: + logging.warning( + 'Not sync objects on %s: %s', + srv, '\n - '.join(not_sync[srv]) + ) + noerror = False + + if noerror: + logging.info('No sync problem detected')