Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
restartable.py261 linesDownload Raw Back to strategy
1"""2"""3 4# Created on 2014.03.045#6# Author: Giovanni Cannata7#8# Copyright 2014 - 2020 Giovanni Cannata9#10# This file is part of ldap3.11#12# ldap3 is free software: you can redistribute it and/or modify13# it under the terms of the GNU Lesser General Public License as published14# by the Free Software Foundation, either version 3 of the License, or15# (at your option) any later version.16#17# ldap3 is distributed in the hope that it will be useful,18# but WITHOUT ANY WARRANTY; without even the implied warranty of19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the20# GNU Lesser General Public License for more details.21#22# You should have received a copy of the GNU Lesser General Public License23# along with ldap3 in the COPYING and COPYING.LESSER files.24# If not, see <http://www.gnu.org/licenses/>.25 26from time import sleep27import socket28 29from .. import get_config_parameter30from .sync import SyncStrategy31from ..core.exceptions import LDAPSocketOpenError, LDAPOperationResult, LDAPMaximumRetriesError, LDAPStartTLSError32from ..utils.log import log, log_enabled, ERROR, BASIC33 34 35# noinspection PyBroadException,PyProtectedMember36class RestartableStrategy(SyncStrategy):37    def __init__(self, ldap_connection):38        SyncStrategy.__init__(self, ldap_connection)39        self.sync = True40        self.no_real_dsa = False41        self.pooled = False42        self.can_stream = False43        self.restartable_sleep_time = get_config_parameter('RESTARTABLE_SLEEPTIME')44        self.restartable_tries = get_config_parameter('RESTARTABLE_TRIES')45        self._restarting = False46        self._last_bind_controls = None47        self._current_message_type = None48        self._current_request = None49        self._current_controls = None50        self._restart_tls = None51        self.exception_history = []52 53    def open(self, reset_usage=False, read_server_info=True):54        SyncStrategy.open(self, reset_usage, read_server_info)55 56    def _open_socket(self, address, use_ssl=False, unix_socket=False):57        """58        Try to open and connect a socket to a Server59        raise LDAPExceptionError if unable to open or connect socket60        if connection is restartable tries for the number of restarting requested or forever61        """62        try:63            SyncStrategy._open_socket(self, address, use_ssl, unix_socket)  # try to open socket using SyncWait64            self._reset_exception_history()65            return66        except Exception as e:  # machinery for restartable connection67            if log_enabled(ERROR):68                log(ERROR, '<%s> while restarting <%s>', e, self.connection)69                self._add_exception_to_history(type(e)(str(e)))70 71        if not self._restarting:  # if not already performing a restart72            self._restarting = True73            counter = self.restartable_tries74            while counter > 0:  # includes restartable_tries == True75                if log_enabled(BASIC):76                    log(BASIC, 'try #%d to open Restartable connection <%s>', self.restartable_tries - counter, self.connection)77                sleep(self.restartable_sleep_time)78                if not self.connection.closed:79                    try:  # resetting connection80                        self.connection.unbind()81                    except (socket.error, LDAPSocketOpenError):  # don't trace catch socket errors because socket could already be closed82                        pass83                    except Exception as e:84                        if log_enabled(ERROR):85                            log(ERROR, '<%s> while restarting <%s>', e, self.connection)86                        self._add_exception_to_history(type(e)(str(e)))87                try:  # reissuing same operation88                    if self.connection.server_pool:89                        new_server = self.connection.server_pool.get_server(self.connection)  # get a server from the server_pool if available90                        if self.connection.server != new_server:91                            self.connection.server = new_server92                            if self.connection.usage:93                                self.connection._usage.servers_from_pool += 194                    SyncStrategy._open_socket(self, address, use_ssl, unix_socket)  # calls super (not restartable) _open_socket()95                    if self.connection.usage:96                        self.connection._usage.restartable_successes += 197                    self.connection.closed = False98                    self._restarting = False99                    self._reset_exception_history()100                    return101                except Exception as e:102                    if log_enabled(ERROR):103                        log(ERROR, '<%s> while restarting <%s>', e, self.connection)104                    self._add_exception_to_history(type(e)(str(e)))105                    if self.connection.usage:106                        self.connection._usage.restartable_failures += 1107                if not isinstance(self.restartable_tries, bool):108                    counter -= 1109            self._restarting = False110            self.connection.last_error = 'restartable connection strategy failed while opening socket'111            if log_enabled(ERROR):112                log(ERROR, '<%s> for <%s>', self.connection.last_error, self.connection)113            raise LDAPMaximumRetriesError(self.connection.last_error, self.exception_history, self.restartable_tries)114 115    def send(self, message_type, request, controls=None):116        self._current_message_type = message_type117        self._current_request = request118        self._current_controls = controls119        if not self._restart_tls:  # RFCs doesn't define how to stop tls once started120            self._restart_tls = self.connection.tls_started121        if message_type == 'bindRequest':  # stores controls used in bind operation to be used again when restarting the connection122            self._last_bind_controls = controls123 124        try:125            message_id = SyncStrategy.send(self, message_type, request, controls)  # tries to send using SyncWait126            self._reset_exception_history()127            return message_id128        except Exception as e:129            if log_enabled(ERROR):130                log(ERROR, '<%s> while restarting <%s>', e, self.connection)131            self._add_exception_to_history(type(e)(str(e)))132        if not self._restarting:  # machinery for restartable connection133            self._restarting = True134            counter = self.restartable_tries135            while counter > 0:136                if log_enabled(BASIC):137                    log(BASIC, 'try #%d to send in Restartable connection <%s>', self.restartable_tries - counter, self.connection)138                sleep(self.restartable_sleep_time)139                if not self.connection.closed:140                    try:  # resetting connection141                        self.connection.unbind()142                    except (socket.error, LDAPSocketOpenError):  # don't trace socket errors because socket could already be closed143                        pass144                    except Exception as e:145                        if log_enabled(ERROR):146                            log(ERROR, '<%s> while restarting <%s>', e, self.connection)147                        self._add_exception_to_history(type(e)(str(e)))148                failure = False149                try:  # reopening connection150                    self.connection.open(reset_usage=False, read_server_info=False)151                    if self._restart_tls:  # restart tls if start_tls was previously used152                        if not self.connection.start_tls(read_server_info=False):153                            error = 'restart tls in restartable not successful' + (' - ' + self.connection.last_error if self.connection.last_error else '')154                            if log_enabled(ERROR):155                                log(ERROR, '%s for <%s>', error, self)156                            self.connection.unbind()157                            raise LDAPStartTLSError(error)158                    if message_type != 'bindRequest':159                        self.connection.bind(read_server_info=False, controls=self._last_bind_controls)  # binds with previously used controls unless the request is already a bindRequest160                    if not self.connection.server.schema and not self.connection.server.info:161                        self.connection.refresh_server_info()162                    else:163                        self.connection._fire_deferred(read_info=False)   # in case of lazy connection, not open by the refresh_server_info164                except Exception as e:165                    if log_enabled(ERROR):166                        log(ERROR, '<%s> while restarting <%s>', e, self.connection)167                    self._add_exception_to_history(type(e)(str(e)))168                    failure = True169 170                if not failure:171                    try:  # reissuing same operation172                        ret_value = self.connection.send(message_type, request, controls)173                        if self.connection.usage:174                            self.connection._usage.restartable_successes += 1175                        self._restarting = False176                        self._reset_exception_history()177                        return ret_value  # successful send178                    except Exception as e:179                        if log_enabled(ERROR):180                            log(ERROR, '<%s> while restarting <%s>', e, self.connection)181                        self._add_exception_to_history(type(e)(str(e)))182                        failure = True183 184                if failure and self.connection.usage:185                    self.connection._usage.restartable_failures += 1186 187                if not isinstance(self.restartable_tries, bool):188                    counter -= 1189 190            self._restarting = False191 192        self.connection.last_error = 'restartable connection failed to send'193        if log_enabled(ERROR):194            log(ERROR, '<%s> for <%s>', self.connection.last_error, self.connection)195        raise LDAPMaximumRetriesError(self.connection.last_error, self.exception_history, self.restartable_tries)196 197    def post_send_single_response(self, message_id):198        try:199            ret_value = SyncStrategy.post_send_single_response(self, message_id)200            self._reset_exception_history()201            return ret_value202        except Exception as e:203            if log_enabled(ERROR):204                log(ERROR, '<%s> while restarting <%s>', e, self.connection)205            self._add_exception_to_history(type(e)(str(e)))206 207        # if an LDAPExceptionError is raised then resend the request208        try:209            ret_value = SyncStrategy.post_send_single_response(self, self.send(self._current_message_type, self._current_request, self._current_controls))210            self._reset_exception_history()211            return ret_value212        except Exception as e:213            if log_enabled(ERROR):214                log(ERROR, '<%s> while restarting <%s>', e, self.connection)215            self._add_exception_to_history(type(e)(str(e)))216            if not isinstance(e, LDAPOperationResult):217                self.connection.last_error = 'restartable connection strategy failed in post_send_single_response'218            if log_enabled(ERROR):219                log(ERROR, '<%s> for <%s>', self.connection.last_error, self.connection)220            raise221 222    def post_send_search(self, message_id):223        try:224            ret_value = SyncStrategy.post_send_search(self, message_id)225            self._reset_exception_history()226            return ret_value227        except Exception as e:228            if log_enabled(ERROR):229                log(ERROR, '<%s> while restarting <%s>', e, self.connection)230            self._add_exception_to_history(type(e)(str(e)))231 232        # if an LDAPExceptionError is raised then resend the request233        try:234            ret_value = SyncStrategy.post_send_search(self, self.connection.send(self._current_message_type, self._current_request, self._current_controls))235            self._reset_exception_history()236            return ret_value237        except Exception as e:238            if log_enabled(ERROR):239                log(ERROR, '<%s> while restarting <%s>', e, self.connection)240            self._add_exception_to_history(type(e)(str(e)))241            if not isinstance(e, LDAPOperationResult):242                self.connection.last_error = e.args243            if log_enabled(ERROR):244                log(ERROR, '<%s> for <%s>', self.connection.last_error, self.connection)245            raise e246 247    def _add_exception_to_history(self, exc):248        if not isinstance(self.restartable_tries, bool):  # doesn't accumulate when restarting forever249            if not isinstance(exc, LDAPMaximumRetriesError):  # doesn't add the LDAPMaximumRetriesError exception250                self.exception_history.append(exc)251 252    def _reset_exception_history(self):253        if self.exception_history:254            self.exception_history = []255 256    def get_stream(self):257        raise NotImplementedError258 259    def set_stream(self, value):260        raise NotImplementedError261 
codekingpro/portable-devtools · Team Ai