# -*- 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