Skip to content

Fix reconnection handling #287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 29, 2020
Merged

Conversation

spaceone
Copy link
Contributor

@spaceone spaceone commented May 10, 2019

Considering the following code:

import ldap
import subprocess

bind_dn = 'uid=Administrator,cn=users,l=school,l=dev'
bind_pw = 'univention'
ldap_addr = 'ldap://localhost:7389'


lo = ldap.ldapobject.ReconnectLDAPObject(ldap_addr, retry_max=2, retry_delay=1)
lo.bind_s(bind_dn, bind_pw)
subprocess.check_call(['systemctl', 'stop', 'slapd'])
try:
    _ = lo.search_s('l=school,l=dev', ldap.SCOPE_SUBTREE, '(uid=Administrator)')
except ldap.LDAPError as exc:
    print('Exception raised as expected')
    print(exc)
else:
    assert False, 'cannot happen'
finally:
    subprocess.check_call(['systemctl', 'start', 'slapd'])
print('\n######################')
print('Unexpected exception')
_ = lo.search_s('l=school,l=dev', ldap.SCOPE_SUBTREE, '(uid=Administrator)')
print(_)

which currently results in:

# python reproduce.py
Exception raised as expected
{'desc': "Can't contact LDAP server"}

######################
Unexpected exception
Traceback (most recent call last):
  File "reproduce.py", line 23, in <module>
    _ = lo.search_s('l=school,l=dev', ldap.SCOPE_SUBTREE, '(uid=Administrator)')
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 597, in search_s
    return self.search_ext_s(base,scope,filterstr,attrlist,attrsonly,None,None,timeout=self.timeout)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 997, in search_ext_s
    return self._apply_method_s(SimpleLDAPObject.search_ext_s,*args,**kwargs)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 935, in _apply_method_s
    return func(self,*args,**kwargs)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 591, in search_ext_s
    return self.result(msgid,all=1,timeout=timeout)[1]
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 503, in result
    resp_type, resp_data, resp_msgid = self.result2(msgid,all,timeout)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 507, in result2
    resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all,timeout)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 514, in result3
    resp_ctrl_classes=resp_ctrl_classes
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 521, in result4
    ldap_result = self._ldap_call(self._l.result4,msgid,all,timeout,add_ctrls,add_intermediates,add_extop)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 106, in _ldap_call
    result = func(*args,**kwargs)
ldap.INSUFFICIENT_ACCESS: {'desc': 'Insufficient access'}

But it just should regulary do the reconnection.
I added a test case for the issue, let's see via Travis if the test is implemented well.

@codecov
Copy link

codecov bot commented May 10, 2019

Codecov Report

Merging #287 into master will increase coverage by 1.16%.
The diff coverage is 77.77%.

@@            Coverage Diff             @@
##           master     #287      +/-   ##
==========================================
+ Coverage    70.1%   71.27%   +1.16%     
==========================================
  Files          49       49              
  Lines        4797     4821      +24     
  Branches      804      812       +8     
==========================================
+ Hits         3363     3436      +73     
+ Misses       1085     1052      -33     
+ Partials      349      333      -16
Impacted Files Coverage Δ
Lib/ldap/ldapobject.py 77.9% <77.77%> (+5.29%) ⬆️
Lib/ldap/dn.py 94.23% <0%> (-3.85%) ⬇️
Lib/ldap/controls/deref.py 57.14% <0%> (ø) ⬆️
Modules/message.c 32.54% <0%> (+0.4%) ⬆️
Modules/functions.c 62.06% <0%> (+0.4%) ⬆️
Modules/LDAPObject.c 66.71% <0%> (+0.5%) ⬆️
Modules/options.c 86.66% <0%> (+1.06%) ⬆️
Modules/ldapcontrol.c 58.88% <0%> (+1.51%) ⬆️
Lib/ldap/sasl.py 86.11% <0%> (+5.55%) ⬆️
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update da432d7...daf266a. Read the comment docs.

If the timeout is reached and a reconnection was not successfull in that time, a ldap.SERVER_DOWN exception is raised.
If later on, when it's assured that the ldap server is running again, the connection is used again, the reconnection
is not performed and the ldap connection in an incosistent unbind state.

Traceback (most recent call last):
  File "reproduce.py", line 23, in <module>
    _ = lo.search_s('l=school,l=dev', ldap.SCOPE_SUBTREE, '(uid=Administrator)')
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 597, in search_s
    return self.search_ext_s(base,scope,filterstr,attrlist,attrsonly,None,None,timeout=self.timeout)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 997, in search_ext_s
    return self._apply_method_s(SimpleLDAPObject.search_ext_s,*args,**kwargs)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 935, in _apply_method_s
    return func(self,*args,**kwargs)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 591, in search_ext_s
    return self.result(msgid,all=1,timeout=timeout)[1]
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 503, in result
    resp_type, resp_data, resp_msgid = self.result2(msgid,all,timeout)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 507, in result2
    resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all,timeout)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 514, in result3
    resp_ctrl_classes=resp_ctrl_classes
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 521, in result4
    ldap_result = self._ldap_call(self._l.result4,msgid,all,timeout,add_ctrls,add_intermediates,add_extop)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 106, in _ldap_call
    result = func(*args,**kwargs)
ldap.INSUFFICIENT_ACCESS: {'desc': 'Insufficient access'}
@encukou
Copy link
Member

encukou commented Sep 20, 2019

Rebased to squash the fixup! commit.

@encukou encukou merged commit 5c2e3ce into python-ldap:master Jan 29, 2020
@tiran tiran added this to the 3.3 milestone May 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy