Benjamin Renard commited on 2013-05-15 15:32:27
Showing 1 changed files, with 55 additions and 0 deletions.
| ... | ... |
@@ -24,11 +24,14 @@ |
| 24 | 24 |
# |
| 25 | 25 |
|
| 26 | 26 |
import ldap |
| 27 |
+import ldap.modlist as modlist |
|
| 27 | 28 |
import logging |
| 28 | 29 |
import sys |
| 29 | 30 |
|
| 30 | 31 |
from optparse import OptionParser |
| 31 | 32 |
|
| 33 |
+TOUCH_VALUE='%%TOUCH%%' |
|
| 34 |
+ |
|
| 32 | 35 |
parser = OptionParser(version="%prog version 1.0\n\nDate : Mon, 10 Dec 2012 18:04:24 +0100\nAuthor : Benjamin Renard <brenard@easter-eggs.com>\nSource : http://git.zionetrix.net/check_syncrepl_extended") |
| 33 | 36 |
|
| 34 | 37 |
parser.add_option( "-p", "--provider", |
| ... | ... |
@@ -111,6 +114,13 @@ parser.add_option( "--exclude-attributes", |
| 111 | 114 |
help="Don't check this attribut (only in attribute check mode)", |
| 112 | 115 |
default=None) |
| 113 | 116 |
|
| 117 |
+parser.add_option( "--touch", |
|
| 118 |
+ dest="touch", |
|
| 119 |
+ action="store", |
|
| 120 |
+ type='string', |
|
| 121 |
+ 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, |
|
| 122 |
+ default=None) |
|
| 123 |
+ |
|
| 114 | 124 |
|
| 115 | 125 |
(options, args) = parser.parse_args() |
| 116 | 126 |
|
| ... | ... |
@@ -126,6 +136,13 @@ if not options.basedn: |
| 126 | 136 |
print "You must provide base DN of connection to LDAP servers" |
| 127 | 137 |
sys.exit(1) |
| 128 | 138 |
|
| 139 |
+if options.touch and not options.attrs: |
|
| 140 |
+ logging.info('Force option attrs on touch mode')
|
|
| 141 |
+ options.attrs=True |
|
| 142 |
+elif options.touch and options.nagios: |
|
| 143 |
+ logging.error('Touch mode and Nagios mode not compatible')
|
|
| 144 |
+ sys.exit(1) |
|
| 145 |
+ |
|
| 129 | 146 |
excl_attrs=[] |
| 130 | 147 |
if options.excl_attrs: |
| 131 | 148 |
for ex in options.excl_attrs.split(','):
|
| ... | ... |
@@ -190,6 +207,36 @@ class LdapServer(object): |
| 190 | 207 |
ret.append(res_data) |
| 191 | 208 |
return ret |
| 192 | 209 |
|
| 210 |
+ def update_object(self,dn,old,new): |
|
| 211 |
+ ldif = modlist.modifyModlist(old,new) |
|
| 212 |
+ if ldif == []: |
|
| 213 |
+ return True |
|
| 214 |
+ try: |
|
| 215 |
+ logging.debug('Update object %s : %s' % (dn,ldif))
|
|
| 216 |
+ self.con.modify_s(dn,ldif) |
|
| 217 |
+ return True |
|
| 218 |
+ except ldap.LDAPError, e: |
|
| 219 |
+ logging.error('Error updating object %s : %s' % (dn,e))
|
|
| 220 |
+ return False |
|
| 221 |
+ |
|
| 222 |
+ def get_attr(self,obj,attr): |
|
| 223 |
+ if attr in obj[0][1]: |
|
| 224 |
+ return obj[0][1][attr] |
|
| 225 |
+ return [] |
|
| 226 |
+ |
|
| 227 |
+ def touch_object(self,dn,attr,orig_value): |
|
| 228 |
+ new_value=list(orig_value) |
|
| 229 |
+ new_value.append(TOUCH_VALUE) |
|
| 230 |
+ try: |
|
| 231 |
+ logging.info('Add value "%s" to attribute %s of object %s' % (TOUCH_VALUE,attr,dn))
|
|
| 232 |
+ if self.update_object(dn,{attr: orig_value}, {attr: new_value}):
|
|
| 233 |
+ logging.info('Remove value "%s" to attribute %s of object %s' % (TOUCH_VALUE,attr,dn))
|
|
| 234 |
+ self.update_object(dn,{attr: new_value}, {attr: orig_value})
|
|
| 235 |
+ return True |
|
| 236 |
+ except ldap.LDAPError, e: |
|
| 237 |
+ logging.error('Error touching object %s : %s' % (dn,e))
|
|
| 238 |
+ return False |
|
| 239 |
+ |
|
| 193 | 240 |
if options.nocheckcert: |
| 194 | 241 |
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER) |
| 195 | 242 |
|
| ... | ... |
@@ -246,6 +293,7 @@ for obj in LdapObjects[options.provider]: |
| 246 | 293 |
if srv == options.provider: |
| 247 | 294 |
continue |
| 248 | 295 |
if obj in LdapObjects[srv]: |
| 296 |
+ touch=False |
|
| 249 | 297 |
if LdapObjects[options.provider][obj] != LdapObjects[srv][obj]: |
| 250 | 298 |
if options.attrs: |
| 251 | 299 |
attrs_list=[] |
| ... | ... |
@@ -255,17 +303,24 @@ for obj in LdapObjects[options.provider]: |
| 255 | 303 |
if attr not in LdapObjects[srv][obj]: |
| 256 | 304 |
attrs_list.append(attr) |
| 257 | 305 |
logging.debug("Obj %s not synchronized : %s not present on %s" % (obj,','.join(attrs_list),srv))
|
| 306 |
+ touch=True |
|
| 258 | 307 |
else: |
| 259 | 308 |
LdapObjects[srv][obj][attr].sort() |
| 260 | 309 |
LdapObjects[options.provider][obj][attr].sort() |
| 261 | 310 |
if LdapObjects[srv][obj][attr]!=LdapObjects[options.provider][obj][attr]: |
| 262 | 311 |
attrs_list.append(attr) |
| 263 | 312 |
logging.debug("Obj %s not synchronized : %s not same value(s)" % (obj,','.join(attrs_list)))
|
| 313 |
+ touch=True |
|
| 264 | 314 |
if len(attrs_list)>0: |
| 265 | 315 |
not_sync[srv].append("%s (%s)" % (obj,','.join(attrs_list)))
|
| 266 | 316 |
else: |
| 267 | 317 |
logging.debug("Obj %s not synchronized : %s <-> %s" % (obj,LdapObjects[options.provider][obj],LdapObjects[srv][obj]))
|
| 268 | 318 |
not_sync[srv].append(obj) |
| 319 |
+ if touch and options.touch: |
|
| 320 |
+ orig_value=[] |
|
| 321 |
+ if options.touch in LdapObjects[options.provider][obj]: |
|
| 322 |
+ orig_value=LdapObjects[options.provider][obj][options.touch] |
|
| 323 |
+ LdapServers[options.provider].touch_object(obj,options.touch,orig_value) |
|
| 269 | 324 |
else: |
| 270 | 325 |
logging.debug('Obj %s : not found on %s' % (obj,srv))
|
| 271 | 326 |
not_found[srv].append(obj) |
| 272 | 327 |