Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bareos/python-bareos.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Steffens <joerg.steffens@bareos.com>2015-11-15 15:14:41 +0300
committerJoerg Steffens <joerg.steffens@bareos.com>2015-11-15 15:14:41 +0300
commitf29e76c928f79dd3b140fdfb5a267c98bf9c96a5 (patch)
tree46cea55ac79b732c545c3e2cb93dca8cf5345cb3
parentbc9ba63080de46937e4b521887ef4d626129d307 (diff)
do network reconnect
-rw-r--r--bareos/bsock/bsock.py23
-rwxr-xr-xbareos/bsock/bsockjson.py19
-rw-r--r--bareos/bsock/lowlevel.py53
-rw-r--r--bareos/exceptions.py6
4 files changed, 81 insertions, 20 deletions
diff --git a/bareos/bsock/bsock.py b/bareos/bsock/bsock.py
index 746c270..60a220b 100644
--- a/bareos/bsock/bsock.py
+++ b/bareos/bsock/bsock.py
@@ -2,8 +2,9 @@
Communicates with the bareos-director
"""
-from bareos.bsock.lowlevel import LowLevel
-import sys
+from bareos.bsock.lowlevel import LowLevel
+from bareos.exceptions import *
+import sys
class BSock(LowLevel):
'''use to send and receive the response from director'''
@@ -24,9 +25,23 @@ class BSock(LowLevel):
'''
call a bareos-director user agent command
'''
- self.send(str(command))
- return self.recv_msg()
+ return self.__call(command, 0)
+ def __call(self, command, count):
+ '''
+ Call a bareos-director user agent command.
+ If connection is lost, try to reconnect.
+ '''
+ result = ''
+ try:
+ self.send(str(command))
+ result = self.recv_msg()
+ except (SocketEmptyHeader, ConnectionLostError) as e:
+ self.logger.error("connection problem (%s): %s" % (type(e).__name__, str(e)))
+ if count == 0:
+ if self.reconnect():
+ return self.__call(command, count+1)
+ return result
def send_command(self, commamd):
return self.call(command)
diff --git a/bareos/bsock/bsockjson.py b/bareos/bsock/bsockjson.py
index 9fd67c0..a14622c 100755
--- a/bareos/bsock/bsockjson.py
+++ b/bareos/bsock/bsockjson.py
@@ -20,11 +20,6 @@ class BSockJson(BSock):
super(BSockJson, self).__init__(
address, port, dirname, name,
password)
- # older version did not support compact mode,
- # therfore first set api mode to json (which should always work in bareos >= 15.2.0)
- # and then set api mode json compact (which should work with bareos >= 15.2.2)
- self.call(".api json")
- self.call(".api json compact=yes")
def call(self, command):
@@ -39,7 +34,6 @@ class BSockJson(BSock):
return result
-
def call_fullresult(self, command):
resultstring = super(BSockJson, self).call(command)
data = None
@@ -56,7 +50,6 @@ class BSockJson(BSock):
'data': resultstring
},
}
-
return data
@@ -71,3 +64,15 @@ class BSockJson(BSock):
if command:
pprint(self.call(command))
return True
+
+
+ def _set_state_director_prompt(self):
+ result = False
+ if super(BSockJson, self)._set_state_director_prompt():
+ # older version did not support compact mode,
+ # therfore first set api mode to json (which should always work in bareos >= 15.2.0)
+ # and then set api mode json compact (which should work with bareos >= 15.2.2)
+ self.call(".api json")
+ self.call(".api json compact=yes")
+ result = True
+ return result
diff --git a/bareos/bsock/lowlevel.py b/bareos/bsock/lowlevel.py
index 4838715..dc63417 100644
--- a/bareos/bsock/lowlevel.py
+++ b/bareos/bsock/lowlevel.py
@@ -31,6 +31,7 @@ class LowLevel(object):
self.port = None
self.dirname = None
self.socket = None
+ self.auth_credentials_valid = False
def connect(self, address="localhost", port=9101, dirname=None):
@@ -43,6 +44,10 @@ class LowLevel(object):
self.dirname = dirname
else:
self.dirname = address
+ return self.__connect()
+
+
+ def __connect(self):
try:
self.socket = socket.create_connection((self.address, self.port))
except socket.gaierror as e:
@@ -51,6 +56,7 @@ class LowLevel(object):
"failed to connect to host " + str(self.address) + ", port " + str(self.port) + ": " + str(e))
else:
self.logger.debug("connected to " + str(self.address) + ":" + str(self.port))
+ return True
def auth(self, password, name="*UserAgent*"):
@@ -62,15 +68,22 @@ class LowLevel(object):
'''
if not isinstance(password, Password):
raise AuthenticationError("password must by of type bareos.Password() not %s" % (type(password)))
- bashed_name = ProtocolMessages.hello(name)
+ self.password = password
+ self.name = name
+ return self.__auth()
+
+
+ def __auth(self):
+ bashed_name = ProtocolMessages.hello(self.name)
# send the bash to the director
self.send(bashed_name)
- (ssl, result_compatible, result) = self._cram_md5_respond(password=password.md5(), tls_remote_need=0)
+ (ssl, result_compatible, result) = self._cram_md5_respond(password=self.password.md5(), tls_remote_need=0)
if not result:
raise AuthenticationError("failed (in response)")
- if not self._cram_md5_challenge(clientname=name, password=password.md5(), tls_local_need=0, compatible=True):
+ if not self._cram_md5_challenge(clientname=self.name, password=self.password.md5(), tls_local_need=0, compatible=True):
raise AuthenticationError("failed (in challenge)")
+ self.auth_credentials_valid = True
return True
@@ -80,10 +93,20 @@ class LowLevel(object):
pass
+ def reconnect(self):
+ result = False
+ if self.auth_credentials_valid:
+ try:
+ if self.__connect() and self.__auth() and self._set_state_director_prompt():
+ result = True
+ except socket.error:
+ self.logger.warning("failed to reconnect")
+ return result
+
+
def send(self, msg=None):
'''use socket to send request to director'''
- if self.socket == None:
- raise RuntimeError("should connect to director first before send data")
+ self.__check_socket_connection()
msg_len = len(msg) # plus the msglen info
try:
@@ -96,8 +119,7 @@ class LowLevel(object):
def recv(self):
'''will receive data from director '''
- if self.socket == None:
- raise RuntimeError("should connect to director first before recv data")
+ self.__check_socket_connection()
# get the message header
header = self.__get_header()
if header <= 0:
@@ -110,8 +132,7 @@ class LowLevel(object):
def recv_msg(self):
'''will receive data from director '''
- if self.socket == None:
- raise RuntimeError("should connect to director first before recv data")
+ self.__check_socket_connection()
msg = ""
try:
timeouts = 0
@@ -139,6 +160,7 @@ class LowLevel(object):
self._handleSocketError(e)
return msg
+
def recv_submsg(self, length):
# get the message
msg = ""
@@ -154,6 +176,7 @@ class LowLevel(object):
def __get_header(self):
+ self.__check_socket_connection()
header = self.socket.recv(4)
if len(header) == 0:
self.logger.debug("received empty header, assuming connection is closed")
@@ -267,6 +290,18 @@ class LowLevel(object):
return True
+ def __check_socket_connection(self):
+ result = True
+ if self.socket == None:
+ result = False
+ if self.auth_credentials_valid:
+ # connection have worked before, but now it is gone
+ raise ConnectionLostError("currently no network connection")
+ else:
+ raise RuntimeError("should connect to director first before send data")
+ return result
+
+
def _handleSocketError(self, exception):
self.logger.error("socket error:" + str(exception))
self.socket = None
diff --git a/bareos/exceptions.py b/bareos/exceptions.py
index 1d79483..2602a00 100644
--- a/bareos/exceptions.py
+++ b/bareos/exceptions.py
@@ -14,6 +14,12 @@ class ConnectionError(Error):
"""
pass
+class ConnectionLostError(Error):
+ """
+ error with the Connection
+ """
+ pass
+
class SocketEmptyHeader(Error):
"""
socket connection received an empty header. Connection lost?