|
1 | 1 | """
|
2 |
| -ldapobject.py - wraps class _ldap.LDAPObject |
| 2 | +ldap.ldapobject - wraps class _ldap.LDAPObject |
3 | 3 |
|
4 | 4 | See https://www.python-ldap.org/ for details.
|
5 | 5 | """
|
@@ -1091,226 +1091,8 @@ def get_naming_contexts(self):
|
1091 | 1091 | ).get('namingContexts', [])
|
1092 | 1092 |
|
1093 | 1093 |
|
1094 |
| -class ReconnectLDAPObject(SimpleLDAPObject): |
1095 |
| - """ |
1096 |
| - In case of server failure (ldap.SERVER_DOWN) the implementations |
1097 |
| - of all synchronous operation methods (search_s() etc.) are doing |
1098 |
| - an automatic reconnect and rebind and will retry the very same |
1099 |
| - operation. |
1100 |
| -
|
1101 |
| - This is very handy for broken LDAP server implementations |
1102 |
| - (e.g. in Lotus Domino) which drop connections very often making |
1103 |
| - it impossible to have a long-lasting control flow in the |
1104 |
| - application. |
1105 |
| - """ |
1106 |
| - |
1107 |
| - __transient_attrs__ = set([ |
1108 |
| - '_l', |
1109 |
| - '_ldap_object_lock', |
1110 |
| - '_trace_file', |
1111 |
| - '_reconnect_lock', |
1112 |
| - '_last_bind', |
1113 |
| - ]) |
1114 |
| - |
1115 |
| - def __init__( |
1116 |
| - self, |
1117 |
| - uri, |
1118 |
| - trace_level=0, trace_file=None, trace_stack_limit=5, |
1119 |
| - retry_max=1, retry_delay=60.0 |
1120 |
| - ): |
1121 |
| - """ |
1122 |
| - Parameters like SimpleLDAPObject.__init__() with these |
1123 |
| - additional arguments: |
1124 |
| -
|
1125 |
| - retry_max |
1126 |
| - Maximum count of reconnect trials |
1127 |
| - retry_delay |
1128 |
| - Time span to wait between two reconnect trials |
1129 |
| - """ |
1130 |
| - self._uri = uri |
1131 |
| - self._options = [] |
1132 |
| - self._last_bind = None |
1133 |
| - SimpleLDAPObject.__init__(self, uri, trace_level, trace_file, trace_stack_limit) |
1134 |
| - self._reconnect_lock = ldap.LDAPLock(desc='reconnect lock within %r' % self) |
1135 |
| - self._retry_max = retry_max |
1136 |
| - self._retry_delay = retry_delay |
1137 |
| - self._start_tls = 0 |
1138 |
| - self._reconnects_done = 0L |
1139 |
| - |
1140 |
| - def __getstate__(self): |
1141 |
| - """ |
1142 |
| - return data representation for pickled object |
1143 |
| - """ |
1144 |
| - state = dict([ |
1145 |
| - (key, val) |
1146 |
| - for key, val in self.__dict__.items() |
1147 |
| - if key not in self.__transient_attrs__ |
1148 |
| - ]) |
1149 |
| - state['_last_bind'] = ( |
1150 |
| - self._last_bind[0].__name__, |
1151 |
| - self._last_bind[1], |
1152 |
| - self._last_bind[2], |
1153 |
| - ) |
1154 |
| - return state |
1155 |
| - |
1156 |
| - def __setstate__(self, data): |
1157 |
| - """ |
1158 |
| - set up the object from pickled data |
1159 |
| - """ |
1160 |
| - self.__dict__.update(data) |
1161 |
| - self._last_bind = ( |
1162 |
| - getattr(SimpleLDAPObject, self._last_bind[0]), |
1163 |
| - self._last_bind[1], |
1164 |
| - self._last_bind[2], |
1165 |
| - ) |
1166 |
| - self._ldap_object_lock = self._ldap_lock() |
1167 |
| - self._reconnect_lock = ldap.LDAPLock(desc='reconnect lock within %r' % (self)) |
1168 |
| - self._trace_file = sys.stdout |
1169 |
| - self.reconnect(self._uri) |
1170 |
| - |
1171 |
| - def _store_last_bind(self, method, *args, **kwargs): |
1172 |
| - self._last_bind = (method, args, kwargs) |
1173 |
| - |
1174 |
| - def _apply_last_bind(self): |
1175 |
| - if self._last_bind != None: |
1176 |
| - func, args, kwargs = self._last_bind |
1177 |
| - func(self, *args, **kwargs) |
1178 |
| - else: |
1179 |
| - # Send explicit anon simple bind request to provoke |
1180 |
| - # ldap.SERVER_DOWN in method reconnect() |
1181 |
| - SimpleLDAPObject.simple_bind_s(self, '', '') |
1182 |
| - |
1183 |
| - def _restore_options(self): |
1184 |
| - """Restore all recorded options""" |
1185 |
| - for key, val in self._options: |
1186 |
| - SimpleLDAPObject.set_option(self, key, val) |
1187 |
| - |
1188 |
| - def passwd_s(self, *args, **kwargs): |
1189 |
| - return self._apply_method_s(SimpleLDAPObject.passwd_s, *args, **kwargs) |
1190 |
| - |
1191 |
| - def reconnect(self, uri, retry_max=1, retry_delay=60.0): |
1192 |
| - # Drop and clean up old connection completely |
1193 |
| - # Reconnect |
1194 |
| - self._reconnect_lock.acquire() |
1195 |
| - try: |
1196 |
| - reconnect_counter = retry_max |
1197 |
| - while reconnect_counter: |
1198 |
| - counter_text = '%d. (of %d)' % (retry_max-reconnect_counter+1, retry_max) |
1199 |
| - if __debug__ and self._trace_level >= 1: |
1200 |
| - self._trace_file.write('*** Trying %s reconnect to %s...\n' % ( |
1201 |
| - counter_text, uri |
1202 |
| - )) |
1203 |
| - try: |
1204 |
| - # Do the connect |
1205 |
| - self._l = ldap.functions._ldap_function_call( |
1206 |
| - ldap._ldap_module_lock, |
1207 |
| - _ldap.initialize, |
1208 |
| - uri |
1209 |
| - ) |
1210 |
| - self._restore_options() |
1211 |
| - # StartTLS extended operation in case this was called before |
1212 |
| - if self._start_tls: |
1213 |
| - SimpleLDAPObject.start_tls_s(self) |
1214 |
| - # Repeat last simple or SASL bind |
1215 |
| - self._apply_last_bind() |
1216 |
| - except (ldap.SERVER_DOWN, ldap.TIMEOUT), e: |
1217 |
| - if __debug__ and self._trace_level >= 1: |
1218 |
| - self._trace_file.write('*** %s reconnect to %s failed\n' % ( |
1219 |
| - counter_text, uri |
1220 |
| - )) |
1221 |
| - reconnect_counter = reconnect_counter-1 |
1222 |
| - if not reconnect_counter: |
1223 |
| - raise e |
1224 |
| - if __debug__ and self._trace_level >= 1: |
1225 |
| - self._trace_file.write('=> delay %s...\n' % (retry_delay)) |
1226 |
| - time.sleep(retry_delay) |
1227 |
| - SimpleLDAPObject.unbind_s(self) |
1228 |
| - else: |
1229 |
| - if __debug__ and self._trace_level >= 1: |
1230 |
| - self._trace_file.write( |
1231 |
| - '*** %s reconnect to %s successful => repeat last operation\n' % ( |
1232 |
| - counter_text, |
1233 |
| - uri, |
1234 |
| - ) |
1235 |
| - ) |
1236 |
| - self._reconnects_done = self._reconnects_done + 1L |
1237 |
| - break |
1238 |
| - finally: |
1239 |
| - self._reconnect_lock.release() |
1240 |
| - return # reconnect() |
1241 |
| - |
1242 |
| - def _apply_method_s(self, func, *args, **kwargs): |
1243 |
| - if not hasattr(self, '_l'): |
1244 |
| - self.reconnect(self._uri, retry_max=self._retry_max, retry_delay=self._retry_delay) |
1245 |
| - try: |
1246 |
| - return func(self, *args, **kwargs) |
1247 |
| - except ldap.SERVER_DOWN: |
1248 |
| - SimpleLDAPObject.unbind_s(self) |
1249 |
| - # Try to reconnect |
1250 |
| - self.reconnect(self._uri, retry_max=self._retry_max, retry_delay=self._retry_delay) |
1251 |
| - # Re-try last operation |
1252 |
| - return func(self, *args, **kwargs) |
1253 |
| - |
1254 |
| - def set_option(self, option, invalue): |
1255 |
| - self._options.append((option, invalue)) |
1256 |
| - return SimpleLDAPObject.set_option(self, option, invalue) |
1257 |
| - |
1258 |
| - def bind_s(self, *args, **kwargs): |
1259 |
| - res = self._apply_method_s(SimpleLDAPObject.bind_s, *args, **kwargs) |
1260 |
| - self._store_last_bind(SimpleLDAPObject.bind_s, *args, **kwargs) |
1261 |
| - return res |
1262 |
| - |
1263 |
| - def simple_bind_s(self, *args, **kwargs): |
1264 |
| - res = self._apply_method_s(SimpleLDAPObject.simple_bind_s, *args, **kwargs) |
1265 |
| - self._store_last_bind(SimpleLDAPObject.simple_bind_s, *args, **kwargs) |
1266 |
| - return res |
1267 |
| - |
1268 |
| - def start_tls_s(self, *args, **kwargs): |
1269 |
| - res = self._apply_method_s(SimpleLDAPObject.start_tls_s, *args, **kwargs) |
1270 |
| - self._start_tls = 1 |
1271 |
| - return res |
1272 |
| - |
1273 |
| - def sasl_interactive_bind_s(self, *args, **kwargs): |
1274 |
| - """ |
1275 |
| - sasl_interactive_bind_s(who, auth) -> None |
1276 |
| - """ |
1277 |
| - res = self._apply_method_s(SimpleLDAPObject.sasl_interactive_bind_s, *args, **kwargs) |
1278 |
| - self._store_last_bind(SimpleLDAPObject.sasl_interactive_bind_s, *args, **kwargs) |
1279 |
| - return res |
1280 |
| - |
1281 |
| - def sasl_bind_s(self, *args, **kwargs): |
1282 |
| - res = self._apply_method_s(SimpleLDAPObject.sasl_bind_s, *args, **kwargs) |
1283 |
| - self._store_last_bind(SimpleLDAPObject.sasl_bind_s, *args, **kwargs) |
1284 |
| - return res |
1285 |
| - |
1286 |
| - def add_ext_s(self, *args, **kwargs): |
1287 |
| - return self._apply_method_s(SimpleLDAPObject.add_ext_s, *args, **kwargs) |
1288 |
| - |
1289 |
| - def cancel_s(self, *args, **kwargs): |
1290 |
| - return self._apply_method_s(SimpleLDAPObject.cancel_s, *args, **kwargs) |
1291 |
| - |
1292 |
| - def compare_ext_s(self, *args, **kwargs): |
1293 |
| - return self._apply_method_s(SimpleLDAPObject.compare_ext_s, *args, **kwargs) |
1294 |
| - |
1295 |
| - def delete_ext_s(self, *args, **kwargs): |
1296 |
| - return self._apply_method_s(SimpleLDAPObject.delete_ext_s, *args, **kwargs) |
1297 |
| - |
1298 |
| - def extop_s(self, *args, **kwargs): |
1299 |
| - return self._apply_method_s(SimpleLDAPObject.extop_s, *args, **kwargs) |
1300 |
| - |
1301 |
| - def modify_ext_s(self, *args, **kwargs): |
1302 |
| - return self._apply_method_s(SimpleLDAPObject.modify_ext_s, *args, **kwargs) |
1303 |
| - |
1304 |
| - def rename_s(self, *args, **kwargs): |
1305 |
| - return self._apply_method_s(SimpleLDAPObject.rename_s, *args, **kwargs) |
1306 |
| - |
1307 |
| - def search_ext_s(self, *args, **kwargs): |
1308 |
| - return self._apply_method_s(SimpleLDAPObject.search_ext_s, *args, **kwargs) |
1309 |
| - |
1310 |
| - def whoami_s(self, *args, **kwargs): |
1311 |
| - return self._apply_method_s(SimpleLDAPObject.whoami_s, *args, **kwargs) |
1312 |
| - |
1313 |
| - |
1314 | 1094 | # The class called LDAPObject will be used as default for
|
1315 | 1095 | # ldap.open() and ldap.initialize()
|
1316 | 1096 | LDAPObject = SimpleLDAPObject
|
| 1097 | + |
| 1098 | +from reconnect import ReconnectLDAPObject |
0 commit comments