Files
Zabbix/config-mover/venv/lib/python3.12/site-packages/zabbix_utils/status.py

156 lines
5.5 KiB
Python

# zabbix_utils
#
# Copyright (C) 2001-2023 Zabbix SIA
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software
# is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
import json
import socket
import logging
from typing import Callable, Union
from .logger import EmptyHandler
from .common import ZabbixProtocol
from .exceptions import ProcessingError
log = logging.getLogger(__name__)
log.addHandler(EmptyHandler())
class ZabbixStatus():
"""Zabbix server status receiver.
Args:
server (str, optional): Zabbix server address. Defaults to `'127.0.0.1'`.
port (int, optional): Zabbix server port. Defaults to `10051`.
timeout (int, optional): Connection timeout value. Defaults to `10`.
use_ipv6 (bool, optional): Specifying IPv6 use instead of IPv4. Defaults to `False`.
source_ip (str, optional): IP from which to establish connection. Defaults to `None`.
socket_wrapper (Callable, optional): Func(`conn`) to wrap socket. Defaults to `None`.
"""
def __init__(self, server: str = '127.0.0.1', port: int = 10051, timeout: int = 10,
use_ipv6: bool = False, source_ip: Union[str, None] = None,
socket_wrapper: Union[Callable, None] = None):
self.server = server
self.port = port
self.timeout = timeout
self.use_ipv6 = use_ipv6
self.source_ip = source_ip
self.socket_wrapper = socket_wrapper
if self.socket_wrapper:
if not isinstance(self.socket_wrapper, Callable):
raise TypeError('Value "socket_wrapper" should be a function.')
def __get_response(self, conn: socket) -> Union[str, None]:
result = ZabbixProtocol.parse_sync_packet(conn, log, ProcessingError)
log.debug('Received data: %s', result)
return result
def __create_request(self, sid: str) -> dict:
return {
"request": "status.get",
"type": "full",
"sid": sid,
}
def status(self, sid: str) -> Union[str, None]:
"""Gets status metrics from Zabbix server.
Args:
sid (str): Zabbix API session id.
Returns:
str: Zabbix server statistics data in JSON.
"""
packet = ZabbixProtocol.create_packet(self.__create_request(sid), log)
try:
if self.use_ipv6:
connection = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
else:
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
raise ProcessingError(
f"Error creating socket for {self.server}:{self.port}") from None
connection.settimeout(self.timeout)
if self.source_ip:
connection.bind((self.source_ip, 0,))
try:
connection.connect((self.server, self.port))
if self.socket_wrapper is not None:
connection = self.socket_wrapper(connection)
connection.sendall(packet)
except (TimeoutError, socket.timeout) as err:
log.error(
'The connection to %s timed out after %d seconds',
f"{self.server}:{self.port}",
self.timeout
)
connection.close()
raise err
except (ConnectionRefusedError, socket.gaierror) as err:
log.error(
'An error occurred while trying to connect to %s: %s',
f"{self.server}:{self.port}",
getattr(err, 'msg', str(err))
)
connection.close()
raise err
except (OSError, socket.error) as err:
log.warning(
'An error occurred while trying to send to %s: %s',
f"{self.server}:{self.port}",
getattr(err, 'msg', str(err))
)
connection.close()
raise err
try:
response = json.loads(self.__get_response(connection))
except ConnectionResetError as err:
log.debug('Get value error: %s', err)
log.warning('Check access restrictions in Zabbix agent configuration.')
raise err
except json.decoder.JSONDecodeError as err:
log.debug('Parsing value error: %s', err)
raise err
log.debug('Response from [%s:%s]: %s', self.server, self.port, response)
try:
connection.close()
except socket.error:
pass
return response