Source code for alignak.notification

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015-2015: Alignak team, see AUTHORS.txt file for contributors
#
# This file is part of Alignak.
#
# Alignak is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Alignak 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Alignak.  If not, see <http://www.gnu.org/licenses/>.
#
#
# This file incorporates work covered by the following copyright and
# permission notice:
#
#  Copyright (C) 2009-2014:
#     Hartmut Goebel, h.goebel@goebel-consult.de
#     Frédéric Vachon, fredvac@gmail.com
#     Nicolas Dupeux, nicolas@dupeux.net
#     Jan Ulferts, jan.ulferts@xing.com
#     Grégory Starck, g.starck@gmail.com
#     Sebastien Coavoux, s.coavoux@free.fr
#     Olivier Hanesse, olivier.hanesse@gmail.com
#     Jean Gabes, naparuba@gmail.com
#     Zoran Zaric, zz@zoranzaric.de
#     Gerhard Lausser, gerhard.lausser@consol.de

#  This file is part of Shinken.
#
#  Shinken is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Affero General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  Shinken 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 Affero General Public License for more details.
#
#  You should have received a copy of the GNU Affero General Public License
#  along with Shinken.  If not, see <http://www.gnu.org/licenses/>.
"""This module provides Notification class.
Used to define monitoring notifications (email, contacts..)

"""
import time

from alignak.action import Action
from alignak.brok import Brok
from alignak.property import BoolProp, IntegerProp, StringProp, FloatProp
from alignak.autoslots import AutoSlots


[docs]class Notification(Action): """Notification class, inherits from action class. Used to notify contacts and execute notification command defined in configuration """ # AutoSlots create the __slots__ with properties and # running_properties names __metaclass__ = AutoSlots my_type = 'notification' properties = Action.properties.copy() properties.update({ 'is_a': StringProp(default='notification'), 'notification_type': IntegerProp(default=0, fill_brok=['full_status']), 'start_time': IntegerProp(default=0, fill_brok=['full_status']), 'end_time': IntegerProp(default=0, fill_brok=['full_status']), 'contact_name': StringProp(default='', fill_brok=['full_status']), 'host_name': StringProp(default='', fill_brok=['full_status']), 'service_description': StringProp(default='', fill_brok=['full_status']), 'reason_type': IntegerProp(default=0, fill_brok=['full_status']), 'state': IntegerProp(default=0, fill_brok=['full_status']), 'output': StringProp(default='', fill_brok=['full_status']), 'ack_author': StringProp(default='', fill_brok=['full_status']), 'ack_data': StringProp(default='', fill_brok=['full_status']), 'escalated': BoolProp(default=False, fill_brok=['full_status']), 'contacts_notified': IntegerProp(default=0, fill_brok=['full_status']), 'command_call': StringProp(default=None), 'contact': StringProp(default=None), 'notif_nb': IntegerProp(default=0), 'status': StringProp(default='scheduled'), 'command': StringProp(default=''), 'sched_id': IntegerProp(default=0), 'timeout': IntegerProp(default=10), 'module_type': StringProp(default='fork', fill_brok=['full_status']), 'creation_time': FloatProp(default=0), 'enable_environment_macros': BoolProp(default=False), # Keep a list of currently active escalations 'already_start_escalations': StringProp(default=set()), }) macros = { 'NOTIFICATIONTYPE': 'type', 'NOTIFICATIONRECIPIENTS': 'recipients', 'NOTIFICATIONISESCALATED': 'escalated', 'NOTIFICATIONAUTHOR': 'author', 'NOTIFICATIONAUTHORNAME': 'author_name', 'NOTIFICATIONAUTHORALIAS': 'author_alias', 'NOTIFICATIONCOMMENT': 'comment', 'HOSTNOTIFICATIONNUMBER': 'notif_nb', 'HOSTNOTIFICATIONID': '_id', 'SERVICENOTIFICATIONNUMBER': 'notif_nb', 'SERVICENOTIFICATIONID': '_id' } def __init__(self, _type='PROBLEM', status='scheduled', command='UNSET', command_call=None, ref=None, contact=None, t_to_go=0.0, contact_name='', host_name='', service_description='', reason_type=1, state=0, ack_author='', ack_data='', escalated=False, contacts_notified=0, start_time=0, end_time=0, notification_type=0, _id=None, notif_nb=1, timeout=10, env={}, module_type='fork', reactionner_tag='None', enable_environment_macros=False): self.is_a = 'notification' self.type = _type if _id is None: # _id != None is for copy call only self._id = Action._id Action._id += 1 self._in_timeout = False self.timeout = timeout self.status = status self.exit_status = 3 self.command = command self.command_call = command_call self.output = None self.execution_time = 0.0 self.u_time = 0.0 # user executon time self.s_time = 0.0 # system execution time self.ref = ref # Set host_name and description from the ref try: self.host_name = self.ref.host_name except Exception: self.host_name = host_name try: self.service_description = self.ref.service_description except Exception: self.service_description = service_description self.env = env self.module_type = module_type self.t_to_go = t_to_go self.notif_nb = notif_nb self.contact = contact # For brok part self.contact_name = contact_name self.reason_type = reason_type self.state = state self.ack_author = ack_author self.ack_data = ack_data self.escalated = escalated self.contacts_notified = contacts_notified self.start_time = start_time self.end_time = end_time self.notification_type = notification_type self.creation_time = time.time() self.worker = 'none' self.reactionner_tag = reactionner_tag self.already_start_escalations = set() self.enable_environment_macros = enable_environment_macros
[docs] def copy_shell(self): """Get a copy o this notification with minimal values (default + id) :return: new notification :rtype: alignak.notification.Notification """ # We create a dummy check with nothing in it, just defaults values return self.copy_shell__(Notification('', '', '', '', '', '', '', _id=self._id))
[docs] def is_launchable(self, timestamp): """Check if this notification can be launched base on time :param timestamp: time to compare :type timestamp: int :return: True if timestamp >= self.t_to_go, False otherwise :rtype: bool """ return timestamp >= self.t_to_go
[docs] def is_administrative(self): """Check if this notification is "administrative" :return: True in type not in ('PROBLEM', 'RECOVERY'), False otherwise :rtype: bool """ if self.type in ('PROBLEM', 'RECOVERY'): return False else: return True
def __str__(self): return "Notification %d status:%s command:%s ref:%s t_to_go:%s" % \ (self._id, self.status, self.command, getattr(self, 'ref', 'unknown'), time.asctime(time.localtime(self.t_to_go)))
[docs] def get_id(self): """Getter to id attribute :return: notification id :rtype: int """ return self._id
[docs] def get_return_from(self, notif): """Setter of exit_status and execution_time attributes :param notif: notification to get data from :type notif: alignak.notification.Notification :return: None """ self.exit_status = notif.exit_status self.execution_time = notif.execution_time
[docs] def fill_data_brok_from(self, data, brok_type): """Fill data with info of item by looking at brok_type in props of properties or running_properties :param data: data to fill :type data: :param brok_type: type of brok :type brok_type: :return: brok with wanted data :rtype: alignak.brok.Brok """ cls = self.__class__ # Now config properties for prop, entry in cls.properties.items(): if brok_type in entry.fill_brok: data[prop] = getattr(self, prop)
[docs] def get_initial_status_brok(self): """Get a initial status brok :return: brok with wanted data :rtype: alignak.brok.Brok """ data = {'_id': self._id} self.fill_data_brok_from(data, 'full_status') brok = Brok('notification_raise', data) return brok
def __getstate__(self): """Call by pickle for dataify the comment because we DO NOT WANT REF in this pickleisation! :return: dict containing notification data :rtype: dict """ cls = self.__class__ # id is not in *_properties res = {'_id': self._id} for prop in cls.properties: if hasattr(self, prop): res[prop] = getattr(self, prop) return res def __setstate__(self, state): """Inverted function of getstate :param state: state to restore :type state: dict :return: None """ cls = self.__class__ self._id = state['_id'] for prop in cls.properties: if prop in state: setattr(self, prop, state[prop]) # Hook for load of 0.4 notification: there were no # creation time, must put one if not hasattr(self, 'creation_time'): self.creation_time = time.time() if not hasattr(self, 'reactionner_tag'): self.reactionner_tag = 'None' if not hasattr(self, 'worker'): self.worker = 'none' if not getattr(self, 'module_type', None): self.module_type = 'fork' if not hasattr(self, 'already_start_escalations'): self.already_start_escalations = set() if not hasattr(self, 'execution_time'): self.execution_time = 0 # s_time and u_time are added between 1.2 and 1.4 if not hasattr(self, 'u_time'): self.u_time = 0.0 self.s_time = 0.0