Added "Touch attribute" feature
Benjamin Renard

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