# -*- coding: utf-8 -*- # # pynag - Python Nagios plug-in and configuration environment # Copyright (C) 2010 Drew Stinnet # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ The Control module includes classes to control the Nagios service and the Command submodule wraps Nagios commands. """ from __future__ import absolute_import import os import pynag.Utils from warnings import warn import pynag.errors from pynag.Utils import runCommand import six class ControlError(pynag.errors.PynagError): """ Base class for all errors in this module.""" class daemon(object): """ Control the nagios daemon through python >>> from pynag.Control import daemon >>> >>> d = daemon() # doctest: +SKIP >>> d.restart() # doctest: +SKIP """ SYSV_INIT_SCRIPT = 1 SYSV_INIT_SERVICE = 2 SYSTEMD = 3 systemd_service_path = "/lib/systemd/system" init_d_path = "/etc/init.d" def __init__(self, nagios_bin="/usr/bin/nagios", nagios_cfg="/etc/nagios/nagios.cfg", nagios_init=None, sudo=True, shell=None, service_name="nagios", nagios_config=None ): self.nagios_bin = nagios_bin self.nagios_cfg = nagios_cfg self.nagios_init = nagios_init self.service_name = service_name self.sudo = sudo self.stdout = "" self.stderr = "" self.nagios_config = nagios_config self._deprecate_sudo() self.method = self._guess_method() if shell: warn("shell is deprecated and not necessary anymore", FutureWarning) if nagios_init: warn("nagios_init is deprecated, use service_name instead", FutureWarning) def verify_config(self): """ Run nagios -v config_file to verify that the conf is working :returns: True -- if pynag.Utils.runCommand() returns 0, else None """ cmd = [self.nagios_bin, "-v", self.nagios_cfg] if self.sudo: cmd = ['sudo', '-n'] + cmd result, self.stdout, self.stderr = runCommand(cmd, shell=False) if result == 0: return True else: return None def running(self): """ Checks if the daemon is running :returns: Whether or not the daemon is running :rtype: bool """ if self.method == daemon.SYSV_INIT_SCRIPT or \ self.method == daemon.SYSV_INIT_SERVICE: if self.nagios_config is None: self.nagios_config = pynag.Parsers.config() if self.nagios_config._get_pid(): return True elif self.method == daemon.SYSTEMD: result = runCommand(["systemctl", "is-active", self.service_name], shell=False) if result[0] == 0: return True return False def restart(self): """ Restarts Nagios via it's init script. :returns: Return code of the restart command ran by pynag.Utils.runCommand() :rtype: int """ if self.method == daemon.SYSV_INIT_SCRIPT: cmd = [self.nagios_init, "restart"] else: cmd = ["service", self.service_name, "restart"] if self.sudo: cmd = ['sudo', '-n'] + cmd result, self.stdout, self.stderr = runCommand(cmd, shell=False) return result def status(self): """ Obtain the status of the Nagios service. :returns: Return code of the status command ran by pynag.Utils.runCommand() :rtype: int """ if self.method == daemon.SYSV_INIT_SCRIPT: cmd = [self.nagios_init, "status"] else: cmd = ["service", self.service_name, "status"] if self.sudo: cmd = ['sudo', '-n'] + cmd result, self.stdout, self.stderr = runCommand(cmd, shell=False) return result def start(self): """ Start the Nagios service. :returns: Return code of the start command ran by pynag.Utils.runCommand() :rtype: int """ if self.method == daemon.SYSV_INIT_SCRIPT: cmd = [self.nagios_init, "start"] else: cmd = ["service", self.service_name, "start"] if self.sudo: cmd = ['sudo', '-n'] + cmd result, self.stdout, self.stderr = runCommand(cmd, shell=False) return result def stop(self): """ Stop the Nagios service. :returns: Return code of the stop command ran by pynag.Utils.runCommand() :rtype: int """ if self.method == daemon.SYSV_INIT_SCRIPT: cmd = [self.nagios_init, "stop"] else: cmd = ["service", self.service_name, "stop"] if self.sudo: cmd = ['sudo', '-n'] + cmd result, self.stdout, self.stderr = runCommand(cmd, shell=False) return result def reload(self): """ Reloads Nagios. :returns: Return code of the reload command ran by pynag.Utils.runCommand() :rtype: int """ if self.method == daemon.SYSV_INIT_SCRIPT: cmd = [self.nagios_init, "reload"] else: cmd = ["service", self.service_name, "reload"] if self.sudo: cmd = ['sudo', '-n'] + cmd result, self.stdout, self.stderr = runCommand(cmd, shell=False) return result def _guess_method(self): """ Guesses whether to run via SYSV INIT script og via systemd. Will also modify nagios_init="service nagios" and set service_name=nagios and method to SYSV_INIT_SCRIPT :returns: ``deamon.SYSTEMD`` :rtype: int """ if self.nagios_init and os.path.exists(self.nagios_init): return daemon.SYSV_INIT_SCRIPT if self.nagios_init and self.nagios_init.split(None, 1)[0].endswith("service"): self.service_name = self.nagios_init.split(None, 1)[1] return daemon.SYSV_INIT_SERVICE if self.service_name and os.path.exists("%s/%s" % (daemon.init_d_path, self.service_name)): return daemon.SYSV_INIT_SERVICE if os.path.exists("%s/%s.service" % (daemon.systemd_service_path, self.service_name)): return daemon.SYSTEMD raise ControlError('Unable to detect daemon method, could not find init' 'script or systemd unit file') def _deprecate_sudo(self): """ Warns with a FutureWarning if sudo is being used in nagios_init or nagios_bin. It will also remove sudo from the command line and set sudo to True """ if self.nagios_init and \ self.nagios_init.split(None, 1)[0].endswith("sudo"): self.sudo = True self.nagios_init = self.nagios_init.split(None, 1)[1] warn("nagios_init command line with sudo is deprecated, please " "use sudo=True for daemon()", FutureWarning) if self.nagios_bin and \ self.nagios_bin.split(None, 1)[0].endswith("sudo"): self.sudo = True self.nagios_bin = self.nagios_bin.split(None, 1)[1] warn("nagios_bin command line with sudo is deprecated, please " "use sudo=True for daemon()", FutureWarning) def __setattr__(self, name, value): if not six.PY2 and \ name in [ "nagios_bin", "nagios_cfg", "nagios_init", "service_name", "stdout", "stderr", "nagios_config", ] and \ isinstance(value, six.binary_type): value = value.encode() self.__dict__[name] = value