Skip to content

Commit

Permalink
Merge pull request #92 from adubkov/release
Browse files Browse the repository at this point in the history
Release 1.1.4
  • Loading branch information
adubkov authored Oct 1, 2018
2 parents 7d32af3 + 4880b50 commit 4b34dec
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 18 deletions.
9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@ before_install:
- popd

install:
- pip install coveralls pep8
- pip install coveralls pycodestyle

script:
- while ! nc -z 127.0.0.1 10051; do sleep 1; done
- sleep 60
- pep8 pyzabbix/
- pep8 tests/*.py
- pycodestyle --ignore=E501,W504 pyzabbix/
- pycodestyle tests/*.py
- coverage run setup.py test

after_success:
coveralls

notifications:
email:
- [email protected]
- [email protected]
- [email protected]
2 changes: 1 addition & 1 deletion docs/source/quickstart_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Get list of not monitored hosts from zabbix
zapi = ZabbixAPI(url='https://localhost/zabbix/', user='admin', password='zabbix')

# Get all disabled hosts
result = zapi.host.get(status=1)
result1 = zapi.host.get(status=1)
hostnames = [host['host'] for host in result1]

# Other way to get all disabled hosts
Expand Down
2 changes: 1 addition & 1 deletion pyzabbix/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .api import ZabbixAPI, ZabbixAPIException, ssl_context_compat
from .sender import ZabbixMetric, ZabbixSender, ZabbixResponse

__version__ = '1.1.3'
__version__ = '1.1.4'
13 changes: 9 additions & 4 deletions pyzabbix/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,14 @@ class ZabbixAPIException(Exception):
:32602: Invalid params (eg already exists)
:32500: No permissions
"""
pass
def __init__(self, *args):
super(Exception, self).__init__(*args)
if len(args) == 1 and isinstance(args[0], dict):
self.error = args[0]
self.message = self.error['message']
self.code = self.error['code']
self.data = self.error['data']
self.json = self.error['json']


class ZabbixAPIObjectClass(object):
Expand Down Expand Up @@ -253,9 +260,7 @@ def do_request(self, method, params=None):
if 'error' in res_json:
err = res_json['error'].copy()
err.update({'json': str(request_json)})
msg_str = "Error {code}: {message}, {data} while sending {json}"
msg = msg_str.format(**err)
raise ZabbixAPIException(msg, err['code'])
raise ZabbixAPIException(err)

return res_json

Expand Down
63 changes: 55 additions & 8 deletions pyzabbix/sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# along with py-zabbix. If not, see <http://www.gnu.org/licenses/>.

from decimal import Decimal
import inspect
import json
import logging
import socket
Expand Down Expand Up @@ -49,7 +50,7 @@ def __init__(self):
self._time = 0
self._chunk = 0
pattern = (r'[Pp]rocessed:? (\d*);? [Ff]ailed:? (\d*);? '
'[Tt]otal:? (\d*);? [Ss]econds spent:? (\d*\.\d*)')
r'[Tt]otal:? (\d*);? [Ss]econds spent:? (\d*\.\d*)')
self._regex = re.compile(pattern)

def __repr__(self):
Expand Down Expand Up @@ -125,7 +126,7 @@ def __init__(self, host, key, value, clock=None):
def __repr__(self):
"""Represent detailed ZabbixMetric view."""

result = json.dumps(self.__dict__)
result = json.dumps(self.__dict__, ensure_ascii=False)
logger.debug('%s: %s', self.__class__.__name__, result)

return result
Expand All @@ -151,6 +152,22 @@ class ZabbixSender(object):
:type chunk_size: int
:param chunk_size: Number of metrics send to the server at one time
:type socket_wrapper: function
:param socket_wrapper: to provide a socket wrapper function to be used to
wrap the socket connection to zabbix.
Example:
from pyzabbix import ZabbixSender
import ssl
secure_connection_option = dict(..)
zs = ZabbixSender(
zabbix_server=zabbix_server,
zabbix_port=zabbix_port,
socket_wrapper=lambda sock:ssl.wrap_socket(sock,**secure_connection_option)
)
:type timeout: int
:param timeout: Number of seconds before call to Zabbix server times out
Default: 10
>>> from pyzabbix import ZabbixMetric, ZabbixSender
>>> metrics = []
>>> m = ZabbixMetric('localhost', 'cpu[usage]', 20)
Expand All @@ -163,10 +180,14 @@ def __init__(self,
zabbix_server='127.0.0.1',
zabbix_port=10051,
use_config=None,
chunk_size=250):
chunk_size=250,
socket_wrapper=None,
timeout=10):

self.chunk_size = chunk_size
self.timeout = timeout

self.socket_wrapper = socket_wrapper
if use_config:
self.zabbix_uri = self._load_from_config(use_config)
else:
Expand All @@ -181,7 +202,8 @@ def __repr__(self):
return result

def _load_from_config(self, config_file):
"""Load zabbix server IP address and port from zabbix agent config file.
"""Load zabbix server IP address and port from zabbix agent config
file.
If ServerActive variable is not found in the file, it will
use the default: 127.0.0.1:10051
Expand All @@ -205,8 +227,22 @@ def _load_from_config(self, config_file):
'ServerActive': '127.0.0.1:10051',
}

params = dict(defaults=default_params)

try:
# python2
args = inspect.getargspec(
configparser.RawConfigParser.__init__).args
except ValueError:
# python3
args = inspect.getfullargspec(
configparser.RawConfigParser.__init__).kwonlyargs

if 'strict' in args:
params['strict'] = True

config_file_fp = StringIO(config_file_data)
config = configparser.RawConfigParser(default_params)
config = configparser.RawConfigParser(**params)
config.readfp(config_file_fp)
zabbix_serveractives = config.get('root', 'ServerActive')
result = []
Expand Down Expand Up @@ -349,16 +385,27 @@ def _chunk_send(self, metrics):
logger.debug('Sending data to %s', host_addr)

# create socket object
connection = socket.socket()
connection_ = socket.socket()
if self.socket_wrapper:
connection = self.socket_wrapper(connection_)
else:
connection = connection_

# server and port must be tuple
connection.connect(host_addr)
connection.settimeout(self.timeout)

try:
# server and port must be tuple
connection.connect(host_addr)
connection.sendall(packet)
except socket.timeout:
logger.error('Sending failed: Connection to %s timed out after'
'%d seconds', host_addr, self.timeout)
connection.close()
raise socket.timeout
except Exception as err:
# In case of error we should close connection, otherwise
# we will close it afret data will be received.
logger.warn('Sending failed: %s', err.msg)
connection.close()
raise Exception(err)

Expand Down

0 comments on commit 4b34dec

Please sign in to comment.