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

github.com/bareos/bareos.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Steffens <joerg.steffens@bareos.com>2019-10-31 12:25:53 +0300
committerJoerg Steffens <joerg.steffens@bareos.com>2019-12-06 11:42:00 +0300
commit92d17dbabc5d5e2b5ef3d89c8a7c2ed526c77849 (patch)
tree1831b1758285697ba534947f686e9f058eaf3270 /python-bareos
parent1e0a32c9c58bcb8ccc402be8b3169882d26d1eed (diff)
python-bareos: implement protocol >= 18.2
Also: * Implement PAM authentication. * Reduce warnings by closing socket, when they are no longer required. * Prepare python-bareos version number. Fallback to 18.2.5, as this is the first version that uses the new protocol. * Handle end of data in interactive mode. * Adapted for connections to the Filedaemon.
Diffstat (limited to 'python-bareos')
-rw-r--r--python-bareos/README.rst51
-rw-r--r--python-bareos/TODO.txt6
-rw-r--r--python-bareos/bareos/__init__.py17
-rw-r--r--python-bareos/bareos/bsock/__init__.py1
-rw-r--r--python-bareos/bareos/bsock/constants.py10
-rw-r--r--python-bareos/bareos/bsock/directorconsole.py65
-rw-r--r--python-bareos/bareos/bsock/filedaemon.py21
-rw-r--r--python-bareos/bareos/bsock/lowlevel.py177
-rw-r--r--python-bareos/bareos/bsock/protocolmessageids.py19
-rw-r--r--python-bareos/bareos/bsock/protocolmessages.py29
-rw-r--r--python-bareos/bareos/bsock/protocolversions.py5
-rwxr-xr-xpython-bareos/bin/bareos-fd-connect.py2
-rwxr-xr-xpython-bareos/bin/bconsole-json.py11
-rwxr-xr-xpython-bareos/bin/bconsole.py7
-rw-r--r--python-bareos/setup.py30
15 files changed, 345 insertions, 106 deletions
diff --git a/python-bareos/README.rst b/python-bareos/README.rst
index 53c50afb7..cbe75cbe9 100644
--- a/python-bareos/README.rst
+++ b/python-bareos/README.rst
@@ -3,7 +3,7 @@ python-bareos
Python module to access a http://www.bareos.org backup system.
-`python-bareos` packages are included in the Bareos core distribution since bareos >= 17.2.
+`python-bareos` packages are included in the Bareos core distribution since Bareos >= 17.2.
TLS-PSK
-------
@@ -13,59 +13,62 @@ Since Bareos >= 18.2.4 can secure its connections via TLS-PSK (Transport-Layer-S
This subset of TLS is currently not supported by the Python SSL module.
To enable this feature in `python-bareos` the Python module 'sslpsk` must be installed:
- * `pip install sslpsk`
+.. code::
+ pip install sslpsk
-calling bareos-director user agent commands
+
+Calling bareos-director user agent commands
-------------------------------------------
.. code:: python
- import bareos.bsock
+ import bareos.bsock
- password=bareos.bsock.Password('secret')
- directorconsole=bareos.bsock.DirectorConsole(address='localhost', port=9101, password=password)
- print directorconsole.call('help')
- ...
+ password=bareos.bsock.Password('secret')
+ directorconsole=bareos.bsock.DirectorConsole(address='localhost', port=9101, password=password)
+ print directorconsole.call('help')
+ ...
To connected to a named console instead, use the `name` parameter:
.. code:: python
- directorconsole=bareos.bsock.DirectorConsole(address='localhost', port=9101, name='user1', password=password)
+ password=bareos.bsock.Password('secret')
+ directorconsole=bareos.bsock.DirectorConsole(address='localhost', port=9101, name='user1', password=password)
-simple version of the bconsole in Python
---------------------------------------------
+Simple version of the bconsole in Python
+----------------------------------------
.. code:: python
- import bareos.bsock
- password=bareos.bsock.Password('secret')
- directorconsole=bareos.bsock.DirectorConsole(address='localhost', port=9101, password=password)
- directorconsole.interactive()
- ...
+ import bareos.bsock
+ password=bareos.bsock.Password('secret')
+ directorconsole=bareos.bsock.DirectorConsole(address='localhost', port=9101, password=password)
+ directorconsole.interactive()
+ ...
or use the included bconsole.py script:
..
- bconsole.py --debug --name=user1 --password=secret --port 9101 localhost
+ bconsole.py --debug --name=user1 --password=secret --port 9101 localhost
-use JSON objects of API mode 2
+Use JSON objects of API mode 2
----------------------------------
-Requires: bareos >= 15.2
+Requires: Bareos >= 15.2
.. code:: python
- import bareos.bsock
- password=bareos.bsock.Password('secret')
- directorconsole=bareos.bsock.DirectorConsoleJson(address='localhost', port=9101, password=password)
- directorconsole.call('list pools')
- ...
+ import bareos.bsock
+ password=bareos.bsock.Password('secret')
+ directorconsole=bareos.bsock.DirectorConsoleJson(address='localhost', port=9101, password=password)
+ directorconsole.call('list pools')
+ ...
diff --git a/python-bareos/TODO.txt b/python-bareos/TODO.txt
deleted file mode 100644
index f7bc3b3b1..000000000
--- a/python-bareos/TODO.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-TODO:
-
- * pyunit
-
-To test the Bareos Python module without installing, set PYTHONPATH accordingly, eg.
-export PYTHONPATH=.
diff --git a/python-bareos/bareos/__init__.py b/python-bareos/bareos/__init__.py
index 6e6f32faf..d8c6a73ec 100644
--- a/python-bareos/bareos/__init__.py
+++ b/python-bareos/bareos/__init__.py
@@ -1,4 +1,21 @@
#__all__ = [ "bconsole" ]
+
+import os.path
+
+try:
+ base_dir = os.path.dirname(os.path.abspath(__file__))
+except NameError:
+ base_dir = None
+else:
+ try:
+ with open(os.path.join(base_dir, 'VERSION.txt')) as version_file:
+ __version__ = version_file.read().strip()
+ except IOError:
+ # Fallback version.
+ # First protocol implemented
+ # has been introduced with this version.
+ __version__ = '18.2.5'
+
from bareos.exceptions import *
from bareos.util.password import Password
import bareos.util
diff --git a/python-bareos/bareos/bsock/__init__.py b/python-bareos/bareos/bsock/__init__.py
index 8984d21d3..111faf0de 100644
--- a/python-bareos/bareos/bsock/__init__.py
+++ b/python-bareos/bareos/bsock/__init__.py
@@ -1,4 +1,5 @@
#__all__ = [ "bconsole" ]
+
from bareos.exceptions import *
from bareos.util.password import Password
from bareos.bsock.connectiontype import ConnectionType
diff --git a/python-bareos/bareos/bsock/constants.py b/python-bareos/bareos/bsock/constants.py
index b4c0ba468..684942f5d 100644
--- a/python-bareos/bareos/bsock/constants.py
+++ b/python-bareos/bareos/bsock/constants.py
@@ -3,8 +3,14 @@ Constants used by Bareos.
"""
class Constants:
+
+ unit_separator = chr(0x1f);
+ record_separator = chr(0x1e);
+ record_separator_compat_regex = r'[ {}]'.format(chr(0x1e));
+ group_separator = chr(0x1d);
+
"""
- translated enum from https://github.com/bareos/bareos/blob/master/src/lib/bsock.h
+ translated enum from https://github.com/bareos/bareos/blob/master/core/src/lib/bsock.h
"""
BNET_EOD = -1 #, /* End of data stream, new data may follow */
BNET_EOD_POLL = -2 #, /* End of data and poll all in one */
@@ -67,7 +73,7 @@ class Constants:
}
@staticmethod
- def get_description( code ):
+ def get_description(code):
try:
description = Constants.description[code]
except KeyError:
diff --git a/python-bareos/bareos/bsock/directorconsole.py b/python-bareos/bareos/bsock/directorconsole.py
index 3545fed56..1752b000c 100644
--- a/python-bareos/bareos/bsock/directorconsole.py
+++ b/python-bareos/bareos/bsock/directorconsole.py
@@ -2,8 +2,13 @@
Communicates with the bareos-dir console
"""
-from bareos.bsock.connectiontype import ConnectionType
+from bareos.bsock.connectiontype import ConnectionType
+from bareos.bsock.constants import Constants
from bareos.bsock.lowlevel import LowLevel
+from bareos.bsock.protocolmessageids import ProtocolMessageIds
+from bareos.bsock.protocolmessages import ProtocolMessages
+from bareos.bsock.protocolversions import ProtocolVersions
+import bareos.exceptions
class DirectorConsole(LowLevel):
'''use to send and receive the response to Bareos File Daemon'''
@@ -14,18 +19,74 @@ class DirectorConsole(LowLevel):
dirname=None,
name="*UserAgent*",
password=None,
+ protocolversion=ProtocolVersions.last,
+ pam_username=None,
+ pam_password=None,
tls_psk_enable=True,
tls_psk_require=False
):
super(DirectorConsole, self).__init__()
+ self.pam_username=pam_username
+ self.pam_password=pam_password
self.tls_psk_enable=tls_psk_enable
self.tls_psk_require=tls_psk_require
self.identity_prefix = u'R_CONSOLE'
+ self.protocolversion = protocolversion
+ if self.protocolversion:
+ self.protocol_messages.set_version(self.protocolversion)
self.connect(address, port, dirname, ConnectionType.DIRECTOR, name, password)
- self.auth(name=name, password=password, auth_success_regex=b'^1000 OK.*$')
+ self.auth(name=name, password=password)
self._init_connection()
+ def get_and_evaluate_auth_responses(self):
+ code, text = self.receive_and_evaluate_response_message()
+
+ self.logger.debug(u'code: {}'.format(code))
+
+ #
+ # Test if PAM is requested.
+ # If yes, handle PAM messages.
+ #
+ # Is is only available, with protocolversion >= ProtocolVersions.bareos_18_2,
+ # however as it is optional,
+ # it will be evaluated with all protocol versions.
+ #
+ if code == ProtocolMessageIds.PamRequired:
+ self.logger.debug(u'PAM request: {}'.format(text))
+ if (not self.pam_username) or (not self.pam_password):
+ raise bareos.exceptions.AuthenticationError("PAM authentication is requested, but no PAM credentials given. Giving up.\n");
+ self.send(ProtocolMessages.pam_user_credentials(self.pam_username, self.pam_password))
+ try:
+ code, text = self.receive_and_evaluate_response_message()
+ except bareos.exceptions.ConnectionLostError as e:
+ raise bareos.exceptions.AuthenticationError(u'PAM authentication failed.')
+ else:
+ if (self.pam_username) or (self.pam_password):
+ raise bareos.exceptions.AuthenticationError("PAM credentials provided, but this Director console does not offer PAM login. Giving up.\n");
+
+
+ #
+ # Test if authentication has been accepted.
+ #
+ if code == ProtocolMessageIds.Ok:
+ self.logger.info(u'Authentication: {}'.format(text))
+ self.auth_credentials_valid = True
+ else:
+ raise bareos.exceptions.AuthenticationError("Received unexcepted message: {} {} (expecting auth ok)".format(code, text))
+
+
+ if self.protocolversion >= ProtocolVersions.bareos_18_2:
+ #
+ # Handle info message.
+ #
+ code, text = self.receive_and_evaluate_response_message()
+ if code == ProtocolMessageIds.InfoMessage:
+ self.logger.debug(u'Info: {}'.format(text))
+ else:
+ raise bareos.exceptions.AuthenticationError("Received unexcepted message: {} {} (expecting info message)".format(code, text))
+
+
def _init_connection(self):
self.call("autodisplay off")
diff --git a/python-bareos/bareos/bsock/filedaemon.py b/python-bareos/bareos/bsock/filedaemon.py
index 9f89d6de9..893419254 100644
--- a/python-bareos/bareos/bsock/filedaemon.py
+++ b/python-bareos/bareos/bsock/filedaemon.py
@@ -4,6 +4,8 @@ Communicates with the bareos-fd
from bareos.bsock.connectiontype import ConnectionType
from bareos.bsock.lowlevel import LowLevel
+from bareos.bsock.protocolmessageids import ProtocolMessageIds
+import bareos.exceptions
import shlex
@@ -26,9 +28,26 @@ class FileDaemon(LowLevel):
# but using the interface provided for Directors.
self.identity_prefix = u'R_DIRECTOR'
self.connect(address, port, dirname, ConnectionType.FILEDAEMON, name, password)
- self.auth(name=name, password=password, auth_success_regex=b'^2000 OK Hello.*$')
+ self.auth(name=name, password=password)
self._init_connection()
+
+ def get_and_evaluate_auth_responses(self):
+ code, text = self.receive_and_evaluate_response_message()
+
+ self.logger.debug(u'code: {}'.format(code))
+
+
+ #
+ # Test if authentication has been accepted.
+ #
+ if code == ProtocolMessageIds.FdOk:
+ self.logger.info(u'Authentication: {}'.format(text))
+ self.auth_credentials_valid = True
+ else:
+ raise bareos.exceptions.AuthenticationError("Received unexcepted message: {} {} (expecting auth ok)".format(code, text))
+
+
def call(self, command):
'''
Replace spaces by char(1) in quoted arguments
diff --git a/python-bareos/bareos/bsock/lowlevel.py b/python-bareos/bareos/bsock/lowlevel.py
index 522073300..b981022c4 100644
--- a/python-bareos/bareos/bsock/lowlevel.py
+++ b/python-bareos/bareos/bsock/lowlevel.py
@@ -20,7 +20,9 @@ import warnings
from bareos.bsock.constants import Constants
from bareos.bsock.connectiontype import ConnectionType
+from bareos.bsock.protocolmessageids import ProtocolMessageIds
from bareos.bsock.protocolmessages import ProtocolMessages
+from bareos.bsock.protocolversions import ProtocolVersions
from bareos.util.bareosbase64 import BareosBase64
from bareos.util.password import Password
import bareos.exceptions
@@ -46,6 +48,8 @@ class LowLevel(object):
self.status = None
self.address = None
self.password = None
+ self.pam_username = None
+ self.pam_password = None
self.port = None
self.dirname = None
self.socket = None
@@ -53,10 +57,14 @@ class LowLevel(object):
self.tls_psk_enable = True
self.tls_psk_require = False
self.connection_type = None
+ self.protocolversion = ProtocolVersions.last
+ self.protocol_messages = ProtocolMessages()
# identity_prefix have to be set in each class
self.identity_prefix = u'R_NONE'
self.receive_buffer = b''
+ def __del__(self):
+ self.close()
def connect(self, address, port, dirname, type, name = None, password = None):
self.address = address
@@ -101,14 +109,13 @@ class LowLevel(object):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# initialize
try:
- #self.socket = socket.create_connection((self.address, self.port))
self.socket.connect((self.address, self.port))
except (socket.error, socket.gaierror) as e:
self._handleSocketError(e)
raise bareos.exceptions.ConnectionError(
"Failed to connect to host {}, port {}: {}".format(self.address, self.port, str(e)))
- else:
- self.logger.debug("connected to {}:{}".format(self.address, self.port))
+
+ self.logger.debug("connected to {}:{}".format(self.address, self.port))
return True
@@ -124,14 +131,13 @@ class LowLevel(object):
if isinstance(self.password, Password):
password = self.password.md5()
else:
- raise bareos.exceptions.ConnectionError(u'No password provides.')
+ raise bareos.exceptions.ConnectionError(u'No password provided.')
self.logger.debug("identity = {}, password = {}".format(identity, password))
try:
self.socket = sslpsk.wrap_socket(
client_socket,
psk=(password, identity),
ciphers='ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH',
- #ssl_version=ssl.PROTOCOL_TLSv1_2,
server_side=False)
except ssl.SSLError as e:
# raise ConnectionError(
@@ -143,29 +149,41 @@ class LowLevel(object):
def get_tls_psk_identity(self):
'''Bareos TLS-PSK excepts the identiy is a specific format.'''
- return u'{}{}{}'.format(self.identity_prefix, chr(0x1e), str(self.name))
+ return u'{}{}{}'.format(self.identity_prefix, Constants.record_separator, str(self.name))
+
- def is_tls_psk_available(self):
+ @staticmethod
+ def is_tls_psk_available():
'''Checks if we have all required modules for TLS-PSK.'''
return 'sslpsk' in sys.modules
- def auth(self, name, password, auth_success_regex):
+
+ def auth(self, name, password):
'''
- Login to the Bareos Director.
- If the authenticate succeeds return True else False.
- dir: the director name
- name: own name.
+ Login to a Bareos Daemon.
+
+ @param name: Own name.
+ @type name: str
+
+ @param password: Password.
+ @type password: bareos.bsock.Password
+
+ @return: True, if the authentication succeeds.
+ In earlier versions, authentication failures returned False.
+ However, now an authentication failure raises an exception.
+ @rtype: bool
+
+ @raise bareos.exceptions.AuthenticationError: if authentication fails.
'''
if not isinstance(password, Password):
raise bareos.exceptions.AuthenticationError("password must by of type bareos.Password() not %s" % (type(password)))
self.password = password
self.name = name
- self.auth_success_regex = auth_success_regex
return self.__auth()
def __auth(self):
- bashed_name = ProtocolMessages.hello(self.name, type=self.connection_type)
+ bashed_name = self.protocol_messages.hello(self.name, type=self.connection_type)
# send the bash to the director
self.send(bashed_name)
@@ -177,19 +195,32 @@ class LowLevel(object):
raise bareos.exceptions.AuthenticationError("failed (in response)")
if not self._cram_md5_challenge(clientname=self.name, password=self.password.md5(), tls_local_need=0, compatible=True):
raise bareos.exceptions.AuthenticationError("failed (in challenge)")
- self.recv_msg(self.auth_success_regex)
- self.auth_credentials_valid = True
- return True
+
+ self.get_and_evaluate_auth_responses()
+
+ return self.auth_credentials_valid
+
+
+ def receive_and_evaluate_response_message(self):
+ regex_str = r'^(\d\d\d\d){}(.*)$'.format(Constants.record_separator_compat_regex)
+ regex = bytes(bytearray(regex_str, 'utf8'))
+ incoming_message = self.recv_msg(regex)
+ match = re.search(regex, incoming_message, re.DOTALL)
+ code = int(match.group(1))
+ text = match.group(2)
+
+ return (code, text)
def _init_connection(self):
pass
- def disconnect(self):
+ def close(self):
'''disconnect'''
- # TODO
- pass
+ if self.socket:
+ self.socket.close()
+ self.socket = None
def reconnect(self):
@@ -221,7 +252,7 @@ class LowLevel(object):
try:
self.send(bytearray(command, 'utf-8'))
result = self.recv_msg()
- except (SocketEmptyHeader, bareos.exceptions.ConnectionLostError) as e:
+ except (bareos.exceptions.SocketEmptyHeader, bareos.exceptions.ConnectionLostError) as e:
self.logger.error("connection problem (%s): %s" % (type(e).__name__, str(e)))
if count == 0:
if self.reconnect():
@@ -246,8 +277,43 @@ class LowLevel(object):
self._handleSocketError(e)
+ def recv_bytes(self, length, timeout=10):
+ '''
+ Receive a number of bytes.
+
+ @raise bareos.exceptions.ConnectionLostError:
+ is raised, if the socket connection gets lost.
+ @raise socket.timeout:
+ is raised, if a timeout occurs on the socket connection,
+ meaning no data received.
+ '''
+ self.socket.settimeout(timeout)
+ msg = b''
+ # get the message
+ while length > 0:
+ self.logger.debug(" submsg len: " + str(length))
+ submsg = self.socket.recv(length)
+ if len(submsg) == 0:
+ errormsg = u'Failed to retrieve data. Assuming the connection is lost.'
+ self._handleSocketError(errormsg)
+ raise bareos.exceptions.ConnectionLostError(errormsg)
+ length -= len(submsg)
+ msg += submsg
+ return msg
+
+
def recv(self):
- '''will receive data from director '''
+ '''
+ Receive a single Director message.
+ This is,
+ header (4 bytes): if
+ > 0: length of the following message
+ < 0: Bareos signal
+ msg: of the length descriped in the header.
+
+ @raise bareos.exceptions.SignalReceivedException:
+ is raised, if a Bareos signal is received.
+ '''
self.__check_socket_connection()
# get the message header
header = self.__get_header()
@@ -260,8 +326,18 @@ class LowLevel(object):
return msg
- def recv_msg(self, regex = b'^\d\d\d\d OK.*$', timeout = None):
- '''will receive data from director '''
+ def recv_msg(self, regex=b'^\d\d\d\d OK.*$', timeout=None):
+ '''
+ Receive a full Director message.
+
+ It retrieves Director messages (header + message text),
+ until
+ 1. the message matches the specified regex or
+ 2. the header indicates a signal.
+
+ @raise bareos.exceptions.SignalReceivedException:
+ is raised, if a Bareos signal is received.
+ '''
self.__check_socket_connection()
try:
timeouts = 0
@@ -292,35 +368,25 @@ class LowLevel(object):
# which might have been incomplete without new submsg.
lastlineindex = self.receive_buffer.rfind(b'\n') + 1
self.receive_buffer += submsg
- match = re.search(regex, self.receive_buffer[lastlineindex:], re.MULTILINE)
+ match = re.search(regex, self.receive_buffer[lastlineindex:], re.DOTALL)
# Bareos indicates end of command result by line starting with 4 digits
if match:
self.logger.debug("msg \"{0}\" matches regex \"{1}\"".format(self.receive_buffer.strip(), regex))
result = self.receive_buffer[0:lastlineindex+match.end()]
self.receive_buffer = self.receive_buffer[lastlineindex+match.end()+1:]
return result
- #elif re.search("^\d\d\d\d .*$", msg, re.MULTILINE):
- #return msg
except socket.error as e:
self._handleSocketError(e)
def recv_submsg(self, length):
# get the message
- msg = b''
- while length > 0:
- self.logger.debug(" submsg len: " + str(length))
- # TODO
- self.socket.settimeout(10)
- submsg = self.socket.recv(length)
- length -= len(submsg)
- #self.logger.debug(submsg)
- msg += submsg
+ msg = self.recv_bytes(length)
if (type(msg) is str):
msg = bytearray(msg.decode('utf-8'), 'utf-8')
if (type(msg) is bytes):
msg = bytearray(msg)
- #self.logger.debug(str(msg))
+ self.logger.debug(str(msg))
return msg
@@ -331,9 +397,17 @@ class LowLevel(object):
"""
command = ""
while command != "exit" and command != "quit" and self.is_connected():
- command = self._get_input()
- resultmsg = self.call(command)
- self._show_result(resultmsg)
+ try:
+ command = self._get_input()
+ except EOFError:
+ return False
+ try:
+ resultmsg = self.call(command)
+ self._show_result(resultmsg)
+ except bareos.exceptions.JsonRpcErrorReceivedException as exp:
+ print(str(exp))
+ #print(str(exp.jsondata))
+
return True
@@ -357,21 +431,8 @@ class LowLevel(object):
def __get_header(self):
- header = b''
- header_length = 4
- while header_length > 0:
- self.logger.debug(" remaining header len: {0}".format(header_length))
- self.__check_socket_connection()
- # TODO
- self.socket.settimeout(10)
- submsg = self.socket.recv(header_length)
- header_length -= len(submsg)
- header += submsg
- if len(header) == 0:
- self.logger.debug("received empty header, assuming connection is closed")
- raise bareos.exceptions.SocketEmptyHeader()
- else:
- return self.__get_header_data(header)
+ header = self.recv_bytes(4)
+ return self.__get_header_data(header)
def __get_header_data(self, header):
@@ -505,7 +566,7 @@ class LowLevel(object):
def __check_socket_connection(self):
result = True
- if self.socket == None:
+ if self.socket is None:
result = False
if self.auth_credentials_valid:
# connection have worked before, but now it is gone
@@ -516,5 +577,5 @@ class LowLevel(object):
def _handleSocketError(self, exception):
- self.logger.warn("socket error: {}".format(str(exception)))
- self.socket = None
+ self.logger.warning("socket error: {}".format(str(exception)))
+ self.close()
diff --git a/python-bareos/bareos/bsock/protocolmessageids.py b/python-bareos/bareos/bsock/protocolmessageids.py
new file mode 100644
index 000000000..48cb3fe47
--- /dev/null
+++ b/python-bareos/bareos/bsock/protocolmessageids.py
@@ -0,0 +1,19 @@
+class ProtocolMessageIds(object):
+ '''
+ From https://github.com/bareos/bareos/blob/master/core//src/lib/bnet.h
+ '''
+
+ #
+ # Director
+ #
+ Unknown = 0
+ ProtokollError = 1
+ ReceiveError = 2
+ Ok = 1000
+ PamRequired = 1001
+ InfoMessage = 1002
+ PamInteractive = 4001
+ PamUserCredentials = 4002
+
+ # Filedaemon
+ FdOk = 2000
diff --git a/python-bareos/bareos/bsock/protocolmessages.py b/python-bareos/bareos/bsock/protocolmessages.py
index 0db3642df..8c9a3d95b 100644
--- a/python-bareos/bareos/bsock/protocolmessages.py
+++ b/python-bareos/bareos/bsock/protocolmessages.py
@@ -2,18 +2,31 @@
Protocol messages between bareos-director and user-agent.
"""
+from bareos import __version__
from bareos.bsock.connectiontype import ConnectionType
+from bareos.bsock.constants import Constants
+from bareos.bsock.protocolmessageids import ProtocolMessageIds
+from bareos.bsock.protocolversions import ProtocolVersions
class ProtocolMessages():
"""
strings defined by the protocol to talk to the Bareos Director.
"""
- @staticmethod
- def hello(name, type=ConnectionType.DIRECTOR):
+
+ def __init__(self, protocolversion = ProtocolVersions.last):
+ self.set_version(protocolversion)
+
+ def set_version(self, protocolversion):
+ self.protocolversion = protocolversion
+
+ def hello(self, name, type=ConnectionType.DIRECTOR):
if type == ConnectionType.FILEDAEMON:
return bytearray("Hello Director %s calling\n" % (name), 'utf-8')
else:
- return bytearray("Hello %s calling\n" % (name), 'utf-8')
+ if self.protocolversion < ProtocolVersions.bareos_18_2:
+ return bytearray("Hello %s calling\n" % (name), 'utf-8')
+ else:
+ return bytearray("Hello %s calling version %s\n" % (name, __version__), 'utf-8')
#@staticmethod
#def ok():
@@ -37,4 +50,12 @@ class ProtocolMessages():
@staticmethod
def is_not_authorized(msg):
- return msg == ProtocolMessages.not_authorized() \ No newline at end of file
+ return msg == ProtocolMessages.not_authorized()
+
+ @staticmethod
+ def pam_user_credentials(pam_username, pam_password):
+ '''
+ Returns a string similar to:
+ 4002 USERNAME PASSWORD
+ '''
+ return b'{id}{s}{username}{s}{password}'.format(id=ProtocolMessageIds.PamUserCredentials, username=pam_username, password=pam_password, s=Constants.record_separator)
diff --git a/python-bareos/bareos/bsock/protocolversions.py b/python-bareos/bareos/bsock/protocolversions.py
new file mode 100644
index 000000000..cf819159e
--- /dev/null
+++ b/python-bareos/bareos/bsock/protocolversions.py
@@ -0,0 +1,5 @@
+class ProtocolVersions(object):
+
+ bareos_12_4 = 1
+ bareos_18_2 = 2
+ last = 2
diff --git a/python-bareos/bin/bareos-fd-connect.py b/python-bareos/bin/bareos-fd-connect.py
index 00a7fbb8a..bd505531f 100755
--- a/python-bareos/bin/bareos-fd-connect.py
+++ b/python-bareos/bin/bareos-fd-connect.py
@@ -7,7 +7,7 @@ import logging
import sys
def getArguments():
- parser = argparse.ArgumentParser(description='Connect to Bareos File Daemon.' )
+ parser = argparse.ArgumentParser(description='Connect to Bareos File Daemon.')
parser.add_argument('-d', '--debug', action='store_true', help="enable debugging output")
parser.add_argument('--name', help="Name of the Director resource in the File Daemon", required=True)
parser.add_argument('-p', '--password', help="password to authenticate to a Bareos File Daemon", required=True)
diff --git a/python-bareos/bin/bconsole-json.py b/python-bareos/bin/bconsole-json.py
index d04c7ab4c..fb242081b 100755
--- a/python-bareos/bin/bconsole-json.py
+++ b/python-bareos/bin/bconsole-json.py
@@ -3,6 +3,8 @@
from __future__ import print_function
import argparse
import bareos.bsock
+import bareos.exceptions
+from bareos.bsock.protocolversions import ProtocolVersions
import logging
import sys
@@ -13,6 +15,9 @@ def getArguments():
parser.add_argument('-p', '--password', help="password to authenticate to a Bareos Director console", required=True)
parser.add_argument('--port', default=9101, help="Bareos Director network port")
parser.add_argument('--dirname', help="Bareos Director name")
+ parser.add_argument('--protocolversion',
+ default=ProtocolVersions.last,
+ help=u'Specify the protocol version to use. Default: {} (current)'.format(ProtocolVersions.last))
parser.add_argument('address', nargs='?', default="localhost", help="Bareos Director network address")
args = parser.parse_args()
return args
@@ -37,7 +42,11 @@ if __name__ == '__main__':
logger.debug('options: %s' % (parameter))
password = bareos.bsock.Password(args.password)
parameter['password']=password
- director = bareos.bsock.DirectorConsoleJson(**parameter)
+ try:
+ director = bareos.bsock.DirectorConsoleJson(**parameter)
+ except (bareos.exceptions.ConnectionError) as e:
+ print(str(e))
+ sys.exit(1)
except RuntimeError as e:
print(str(e))
sys.exit(1)
diff --git a/python-bareos/bin/bconsole.py b/python-bareos/bin/bconsole.py
index 9e5dd9854..2dfe8f81b 100755
--- a/python-bareos/bin/bconsole.py
+++ b/python-bareos/bin/bconsole.py
@@ -2,9 +2,9 @@
from __future__ import print_function
import argparse
-#import bareos
import bareos.bsock
import bareos.exceptions
+from bareos.bsock.protocolversions import ProtocolVersions
import logging
import sys
@@ -15,6 +15,9 @@ def getArguments():
parser.add_argument('-p', '--password', help="password to authenticate to a Bareos Director console", required=True)
parser.add_argument('--port', default=9101, help="Bareos Director network port")
parser.add_argument('--dirname', help="Bareos Director name")
+ parser.add_argument('--protocolversion',
+ default=ProtocolVersions.last,
+ help=u'Specify the protocol version to use. Default: {} (current)'.format(ProtocolVersions.last))
parser.add_argument('address', nargs='?', default="localhost", help="Bareos Director network address")
args = parser.parse_args()
return args
@@ -32,7 +35,7 @@ if __name__ == '__main__':
parameter = {}
for i in options:
if hasattr(args, i) and getattr(args,i) != None:
- logger.debug( "%s: %s" %(i, getattr(args,i)))
+ logger.debug("%s: %s" %(i, getattr(args,i)))
parameter[i] = getattr(args,i)
else:
logger.debug( '%s: ""' %(i))
diff --git a/python-bareos/setup.py b/python-bareos/setup.py
index 0eb78830d..06c950e8c 100644
--- a/python-bareos/setup.py
+++ b/python-bareos/setup.py
@@ -1,14 +1,32 @@
#!/usr/bin/python
+import os
from setuptools import find_packages, setup
+
+def get_version():
+ base_dir = os.path.abspath(os.path.dirname(__file__))
+
+ try:
+ with open(os.path.join(base_dir, 'python-bareos', 'VERSION.txt')) as version_file:
+ __version__ = version_file.read().strip()
+ except IOError:
+ # Fallback version.
+ # First protocol implemented
+ # has been introduced with this version.
+ __version__ = '18.2.5'
+
+ return __version__
+
+
setup(
name='python-bareos',
- version='0.3',
- author='Joerg Steffens',
- author_email='joerg.steffens@bareos.com',
+ version=get_version(),
+ author='Bareos Team',
+ author_email='packager@bareos.com',
packages=find_packages(),
scripts=['bin/bconsole.py', 'bin/bconsole-json.py', 'bin/bareos-fd-connect.py'],
+ package_data={'bareos': ['VERSION.txt']},
url='https://github.com/bareos/python-bareos/',
# What does your project relate to?
keywords='bareos',
@@ -18,6 +36,8 @@ setup(
#'hmac',
#'socket',
'python-dateutil',
- ]
+ ],
+ extras_require={
+ 'TLS-PSK': ["sslpsk"],
+ }
)
-