Example #1
0
class Servicedependency(Item):
    id = 0
    my_type = "servicedependency"

    # F is dep of D
    # host_name                      Host B
    #       service_description             Service D
    #       dependent_host_name             Host C
    #       dependent_service_description   Service F
    #       execution_failure_criteria      o
    #       notification_failure_criteria   w,u
    #       inherits_parent         1
    #       dependency_period       24x7

    properties = Item.properties.copy()
    properties.update({
        'dependent_host_name':           StringProp(),
        'dependent_hostgroup_name':      StringProp(default=''),
        'dependent_service_description': StringProp(),
        'host_name':                     StringProp(),
        'hostgroup_name':                StringProp(default=''),
        'service_description':           StringProp(),
        'inherits_parent':               BoolProp(default='0'),
        'execution_failure_criteria':    ListProp(default='n'),
        'notification_failure_criteria': ListProp(default='n'),
        'dependency_period':             StringProp(default=''),
        'explode_hostgroup':             BoolProp(default='0')
    })

    # Give a nice name output, for debbuging purpose
    # (Yes, debbuging CAN happen...)
    def get_name(self):
        return getattr(self, 'dependent_host_name', '') + '/' + getattr(self, 'dependent_service_description', '') + '..' + getattr(self, 'host_name', '') + '/' + getattr(self, 'service_description', '')
Example #2
0
class Realm(Itemgroup):
    id = 1  # zero is always a little bit special... like in database
    my_type = 'realm'

    properties = Itemgroup.properties.copy()
    properties.update({
        'id':            IntegerProp(default=0, fill_brok=['full_status']),
        'realm_name':    StringProp(fill_brok=['full_status']),
        'realm_members': StringProp(default=''), # No status_broker_name because it put hosts, not host_name
        'higher_realms': StringProp(default=''),
        'default':       BoolProp(default='0'),
        'broker_complete_links':       BoolProp(default='0'),
        #'alias': {'required':  True, 'fill_brok': ['full_status']},
        #'notes': {'required': False, 'default':'', 'fill_brok': ['full_status']},
        #'notes_url': {'required': False, 'default':'', 'fill_brok': ['full_status']},
        #'action_url': {'required': False, 'default':'', 'fill_brok': ['full_status']},
    })

    running_properties = Item.running_properties.copy()
    running_properties.update({
            'serialized_confs': StringProp(default={}),
        })

    macros = {
        'REALMNAME': 'realm_name',
        'REALMMEMBERS': 'members',
    }


    def get_name(self):
        return self.realm_name


    def get_realms(self):
        return self.realm_members


    def add_string_member(self, member):
        self.realm_members += ',' + member


    def get_realm_members(self):
        if self.has('realm_members'):
            return [r.strip() for r in self.realm_members.split(',')]
        else:
            return []

    # Use to make python properties
    # TODO: change itemgroup function pythonize?
    def pythonize(self):
        cls = self.__class__
        for prop, tab in cls.properties.items():
            try:
                old_val = getattr(self, prop)
                new_val = tab.pythonize(old_val)
                #print "Changing ", old_val, "by", new_val
                setattr(self, prop, new_val)
            except AttributeError, exp:
                pass  # Will be catch at the is_correct moment
Example #3
0
class ReceiverLink(SatelliteLink):
    """Please Add a Docstring to describe the class here"""

    id = 0
    my_type = 'receiver'
    properties = SatelliteLink.properties.copy()
    properties.update({
        'receiver_name':
        StringProp(fill_brok=['full_status'], to_send=True),
        'port':
        IntegerProp(default=7772, fill_brok=['full_status']),
        'manage_sub_realms':
        BoolProp(default=True, fill_brok=['full_status']),
        'manage_arbiters':
        BoolProp(default=False, fill_brok=['full_status'], to_send=True),
        'direct_routing':
        BoolProp(default=False, fill_brok=['full_status'], to_send=True),
        'accept_passive_unknown_check_results':
        BoolProp(default=False, fill_brok=['full_status'], to_send=True),
        'harakiri_threshold':
        StringProp(default=None, fill_brok=['full_status'], to_send=True),
    })

    def get_name(self):
        return self.receiver_name

    def register_to_my_realm(self):
        self.realm.receivers.append(self)

    def push_host_names(self, sched_id, hnames):
        try:
            if self.con is None:
                self.create_connection()
            logger.info(" (%s)", self.uri)

            # If the connection failed to initialize, bail out
            if self.con is None:
                self.add_failed_check_attempt()
                return

            # r = self.con.push_host_names(sched_id, hnames)
            self.con.get('ping')
            self.con.post('push_host_names', {
                'sched_id': sched_id,
                'hnames': hnames
            },
                          wait='long')
        except HTTPExceptions, exp:
            self.add_failed_check_attempt(reason=str(exp))
Example #4
0
class Hostdependency(Item):
    id = 0

#F is dep of D
#host_name                      Host B
#       service_description             Service D
#       dependent_host_name             Host C
#       dependent_service_description   Service F
#       execution_failure_criteria      o
#       notification_failure_criteria   w,u
#       inherits_parent         1
#       dependency_period       24x7

    properties = {
        'dependent_host_name':           StringProp(),
        'dependent_hostgroup_name':      StringProp(default=''),
        'host_name':                     StringProp(),
        'hostgroup_name':                StringProp(default=''),
        'inherits_parent':               BoolProp(default='0'),
        'execution_failure_criteria':    ListProp(default='n'),
        'notification_failure_criteria': ListProp(default='n'),
        'dependency_period':             StringProp(default='')
    }
    
    running_properties = {
        'configuration_errors': ListProp(default=[]),
        }

    # Give a nice name output, for debbuging purpose
    # (debugging happens more often than expected...)
    def get_name(self):
        return self.dependent_host_name+'/'+self.host_name
Example #5
0
class ReactionnerLink(SatelliteLink):
    """Please Add a Docstring to describe the class here"""

    id = 0
    my_type = 'reactionner'
    properties = SatelliteLink.properties.copy()
    properties.update({
        'reactionner_name':
        StringProp(fill_brok=['full_status'], to_send=True),
        'port':
        IntegerProp(default='7769', fill_brok=['full_status']),
        'passive':
        BoolProp(default='0', fill_brok=['full_status'], to_send=True),
        'min_workers':
        IntegerProp(default='1', fill_brok=['full_status'], to_send=True),
        'max_workers':
        IntegerProp(default='30', fill_brok=['full_status'], to_send=True),
        'processes_by_worker':
        IntegerProp(default='256', fill_brok=['full_status'], to_send=True),
        'reactionner_tags':
        ListProp(default='None', to_send=True),
    })

    def get_name(self):
        return self.reactionner_name

    def register_to_my_realm(self):
        self.realm.reactionners.append(self)
Example #6
0
class PollerLink(SatelliteLink):
    """This class is the link between Arbiter and Poller. With it, arbiter
    can see if a poller is alive, and can send it new configuration

    """

    id = 0
    my_type = 'poller'
    # To_send: send or not to satellite conf
    properties = SatelliteLink.properties.copy()
    properties.update({
        'poller_name':
        StringProp(fill_brok=['full_status'], to_send=True),
        'port':
        IntegerProp(default=7771, fill_brok=['full_status']),
        'passive':
        BoolProp(default='0', fill_brok=['full_status'], to_send=True),
        'min_workers':
        IntegerProp(default='0', fill_brok=['full_status'], to_send=True),
        'max_workers':
        IntegerProp(default='30', fill_brok=['full_status'], to_send=True),
        'processes_by_worker':
        IntegerProp(default='256', fill_brok=['full_status'], to_send=True),
        'poller_tags':
        ListProp(default='None', to_send=True),
    })

    def get_name(self):
        return self.poller_name

    def register_to_my_realm(self):
        self.realm.pollers.append(self)
Example #7
0
class SchedulerLink(SatelliteLink):
    """Please Add a Docstring to describe the class here"""

    id = 0

    # Ok we lie a little here because we are a mere link in fact
    my_type = 'scheduler'

    properties = SatelliteLink.properties.copy()
    properties.update({
        'scheduler_name':
        StringProp(fill_brok=['full_status']),
        'port':
        IntegerProp(default=7768, fill_brok=['full_status']),
        'weight':
        IntegerProp(default=1, fill_brok=['full_status']),
        'skip_initial_broks':
        BoolProp(default=False, fill_brok=['full_status']),
        'accept_passive_unknown_check_results':
        BoolProp(default=False, fill_brok=['full_status']),
        'harakiri_threshold':
        StringProp(default=None, fill_brok=['full_status'], to_send=True),
    })

    running_properties = SatelliteLink.running_properties.copy()
    running_properties.update({
        'conf': StringProp(default=None),
        'need_conf': StringProp(default=True),
        'external_commands': StringProp(default=[]),
        'push_flavor': IntegerProp(default=0),
    })

    def get_name(self):
        return self.scheduler_name

    def run_external_commands(self, commands):
        if self.con is None:
            self.create_connection()
        if not self.alive:
            return None
        logger.debug("[SchedulerLink] Sending %d commands", len(commands))
        try:
            self.con.post('run_external_commands', {'cmds': commands})
        except HTTPExceptions, exp:
            self.con = None
            logger.debug(exp)
            return False
Example #8
0
class Trigger(Item):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'trigger'

    properties = Item.properties.copy()
    properties.update({
        'trigger_name':
        StringProp(fill_brok=['full_status']),
        'code_src':
        StringProp(default='', fill_brok=['full_status']),
    })

    running_properties = Item.running_properties.copy()
    running_properties.update({
        'code_bin':
        StringProp(default=None),
        'trigger_broker_raise_enabled':
        BoolProp(default=False)
    })

    # For debugging purpose only (nice name)
    def get_name(self):
        try:
            return self.trigger_name
        except AttributeError:
            return 'UnnamedTrigger'

    def compile(self):
        self.code_bin = compile(self.code_src, "<irc>", "exec")

    # ctx is the object we are evaluating the code. In the code
    # it will be "self".
    def eval(myself, ctx):
        self = ctx

        # Ok we can declare for this trigger call our functions
        for (n, f) in trigger_functions.iteritems():
            locals()[n] = f

        code = myself.code_bin  # Comment? => compile(myself.code_bin, "<irc>", "exec")
        try:
            exec code in dict(locals())
        except Exception as err:
            set_value(self, "UNKNOWN: Trigger error: %s" % err, "", 3)
            logger.error('%s Trigger %s failed: %s ; %s' %
                         (self.host_name, myself.trigger_name, err,
                          traceback.format_exc()))

    def __getstate__(self):
        return {
            'trigger_name': self.trigger_name,
            'code_src': self.code_src,
            'trigger_broker_raise_enabled': self.trigger_broker_raise_enabled
        }

    def __setstate__(self, d):
        self.trigger_name = d['trigger_name']
        self.code_src = d['code_src']
        self.trigger_broker_raise_enabled = d['trigger_broker_raise_enabled']
Example #9
0
class CommandCall(DummyCommandCall):
    # AutoSlots create the __slots__ with properties and
    # running_properties names
    __metaclass__ = AutoSlots

    #__slots__ = ('id', 'call', 'command', 'valid', 'args', 'poller_tag',
    #             'reactionner_tag', 'module_type', '__dict__')
    id = 0
    my_type = 'CommandCall'

    properties = {
        'call': StringProp(),
        'command': StringProp(),
        'poller_tag': StringProp(default='None'),
        'reactionner_tag': StringProp(default='None'),
        'module_type': StringProp(default=None),
        'valid': BoolProp(default=False),
        'args': StringProp(default=[]),
    }

    def __init__(self,
                 commands,
                 call,
                 poller_tag='None',
                 reactionner_tag='None'):
        self.id = self.__class__.id
        self.__class__.id += 1
        self.call = call
        tab = call.split('!')
        self.command = tab[0]
        self.args = tab[1:]
        self.command = commands.find_cmd_by_name(self.command.strip())
        if self.command is not None:
            self.valid = True
        else:
            self.valid = False
            self.command = tab[0]
        if self.valid:
            #If the host/service do not give an override poller_tag, take
            #the one of the command
            self.poller_tag = poller_tag  #from host/service
            self.reactionner_tag = reactionner_tag
            self.module_type = self.command.module_type
            if self.valid and poller_tag is 'None':
                self.poller_tag = self.command.poller_tag  #from command if not set
            # Same for reactionner tag
            if self.valid and reactionner_tag is 'None':
                self.reactionner_tag = self.command.reactionner_tag  #from command if not set

    def is_valid(self):
        return self.valid

    def __str__(self):
        return str(self.__dict__)

    def get_name(self):
        return self.call
Example #10
0
class ReceiverLink(SatelliteLink):
    id = 0
    my_type = 'receiver'
    properties = SatelliteLink.properties.copy()
    properties.update({
        'receiver_name':
        StringProp(fill_brok=['full_status'], to_send=True),
        'port':
        IntegerProp(default='7772', fill_brok=['full_status']),
        'manage_sub_realms':
        BoolProp(default='1', fill_brok=['full_status']),
        'manage_arbiters':
        BoolProp(default='0', fill_brok=['full_status'], to_send=True),
    })

    def get_name(self):
        return self.receiver_name

    def register_to_my_realm(self):
        self.realm.receivers.append(self)
Example #11
0
    def test_bool_property(self):
        p = BoolProp(default='1', class_inherit=[('Host', 'accept_passive_checks')])
        print p.__dict__
        s = "1"
        val = p.pythonize(s)
        print s, val
        self.assert_(val == True)
        s = "0"
        val = p.pythonize(s)
        print s, val
        self.assert_(val == False)

        #Now a service one
        p = BoolProp(default='0', fill_brok=['full_status'])
        print p.__dict__
        s = "1"
        val = p.pythonize(s)
        print s, val
        self.assert_(val == True)
        self.assert_('full_status' in p.fill_brok)
Example #12
0
class Contact(Item):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'contact'

    properties = Item.properties.copy()
    properties.update({
        'contact_name':     StringProp(fill_brok=['full_status']),
        'alias':            StringProp(default='none', fill_brok=['full_status']),
        'contactgroups':    StringProp(default='', fill_brok=['full_status']),
        'host_notifications_enabled': BoolProp(default='1', fill_brok=['full_status']),
        'service_notifications_enabled': BoolProp(default='1', fill_brok=['full_status']),
        'host_notification_period': StringProp(fill_brok=['full_status']),
        'service_notification_period': StringProp(fill_brok=['full_status']),
        'host_notification_options': StringProp(fill_brok=['full_status']),
        'service_notification_options': StringProp(fill_brok=['full_status']),
        'host_notification_commands': StringProp(fill_brok=['full_status']),
        'service_notification_commands': StringProp(fill_brok=['full_status']),
        'min_business_impact':    IntegerProp(default='0', fill_brok=['full_status']),
        'email':            StringProp(default='none', fill_brok=['full_status']),
        'pager':            StringProp(default='none', fill_brok=['full_status']),
        'address1':         StringProp(default='none', fill_brok=['full_status']),
        'address2':         StringProp(default='none', fill_brok=['full_status']),
        'address3':        StringProp(default='none', fill_brok=['full_status']),
        'address4':         StringProp(default='none', fill_brok=['full_status']),
        'address5':         StringProp(default='none', fill_brok=['full_status']),
        'address6':         StringProp(default='none', fill_brok=['full_status']),
        'can_submit_commands': BoolProp(default='0', fill_brok=['full_status']),
        'is_admin':         BoolProp(default='0', fill_brok=['full_status']),
        'retain_status_information': BoolProp(default='1', fill_brok=['full_status']),
        'notificationways': StringProp(default='', fill_brok=['full_status']),
        'password':        StringProp(default='NOPASSWORDSET', fill_brok=['full_status']),
    })

    running_properties = Item.running_properties.copy()
    running_properties.update({
        'modified_attributes': IntegerProp(default=0L, fill_brok=['full_status'], retention=True),
        'downtimes': StringProp(default=[], fill_brok=['full_status'], retention=True),
    })
Example #13
0
class Hostdependency(Item):
    id = 0
    my_type = 'hostdependency'

    # F is dep of D
    # host_name                      Host B
    #       service_description             Service D
    #       dependent_host_name             Host C
    #       dependent_service_description   Service F
    #       execution_failure_criteria      o
    #       notification_failure_criteria   w,u
    #       inherits_parent         1
    #       dependency_period       24x7

    properties = Item.properties.copy()
    properties.update({
        'dependent_host_name':
        StringProp(),
        'dependent_hostgroup_name':
        StringProp(default=''),
        'host_name':
        StringProp(),
        'hostgroup_name':
        StringProp(default=''),
        'inherits_parent':
        BoolProp(default=False),
        'execution_failure_criteria':
        ListProp(default=['n'], split_on_coma=True),
        'notification_failure_criteria':
        ListProp(default=['n'], split_on_coma=True),
        'dependency_period':
        StringProp(default='')
    })

    # Give a nice name output, for debugging purpose
    # (debugging happens more often than expected...)
    def get_name(self):
        dependent_host_name = 'unknown'
        if getattr(self, 'dependent_host_name', None):
            dependent_host_name = getattr(getattr(self, 'dependent_host_name'),
                                          'host_name', 'unknown')
        host_name = 'unknown'
        if getattr(self, 'host_name', None):
            host_name = getattr(getattr(self, 'host_name'), 'host_name',
                                'unknown')
        return dependent_host_name + '/' + host_name
Example #14
0
class SchedulerLink(SatelliteLink):
    """Please Add a Docstring to describe the class here"""

    id = 0

    # Ok we lie a little here because we are a mere link in fact
    my_type = 'scheduler'

    properties = SatelliteLink.properties.copy()
    properties.update({
        'scheduler_name':
        StringProp(fill_brok=['full_status']),
        'port':
        IntegerProp(default='7768', fill_brok=['full_status']),
        'weight':
        IntegerProp(default='1', fill_brok=['full_status']),
        'skip_initial_broks':
        BoolProp(default='0', fill_brok=['full_status']),
    })

    running_properties = SatelliteLink.running_properties.copy()
    running_properties.update({
        'conf': StringProp(default=None),
        'need_conf': StringProp(default=True),
        'external_commands': StringProp(default=[]),
        'push_flavor': IntegerProp(default=0),
    })

    def get_name(self):
        return self.scheduler_name

    def run_external_commands(self, commands):
        if self.con is None:
            self.create_connection()
        if not self.alive:
            return None
        logger.debug("[SchedulerLink] Sending %d commands" % len(commands))
        try:
            self.con.run_external_commands(commands)
        except Pyro.errors.URIError, exp:
            self.con = None
            return False
        except Pyro.errors.ProtocolError, exp:
            self.con = None
            return False
Example #15
0
class PollerLink(SatelliteLink):
    id = 0
    my_type = 'poller'
    #To_send : send or not to satellite conf
    properties = SatelliteLink.properties.copy()
    properties.update({
        'poller_name':  StringProp(fill_brok=['full_status'], to_send=True),
        'port':         IntegerProp(default=7771, fill_brok=['full_status']),
        'passive' :     BoolProp(default='0', fill_brok=['full_status'], to_send=True),
        'min_workers':  IntegerProp(default='1', fill_brok=['full_status'], to_send=True),
        'max_workers':  IntegerProp(default='30', fill_brok=['full_status'], to_send=True),
        'processes_by_worker': IntegerProp(default='256', fill_brok=['full_status'], to_send=True),
        'poller_tags':  ListProp(default='None', to_send=True),
    })

    def get_name(self):
        return self.poller_name


    def register_to_my_realm(self):
        self.realm.pollers.append(self)
        if self.poller_tags != []:
            print "I %s manage tags : %s " % (self.get_name(), self.poller_tags)
Example #16
0
class NotificationWay(Item):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'notificationway'

    properties = Item.properties.copy()
    properties.update({
        'notificationway_name':
        StringProp(fill_brok=['full_status']),
        'host_notifications_enabled':
        BoolProp(default=True, fill_brok=['full_status']),
        'service_notifications_enabled':
        BoolProp(default=True, fill_brok=['full_status']),
        'host_notification_period':
        StringProp(fill_brok=['full_status']),
        'service_notification_period':
        StringProp(fill_brok=['full_status']),
        'host_notification_options':
        ListProp(default=[''], fill_brok=['full_status'], split_on_coma=True),
        'service_notification_options':
        ListProp(default=[''], fill_brok=['full_status'], split_on_coma=True),
        'host_notification_commands':
        StringProp(fill_brok=['full_status']),
        'service_notification_commands':
        StringProp(fill_brok=['full_status']),
        'min_business_impact':
        IntegerProp(default=0, fill_brok=['full_status']),
    })

    running_properties = Item.running_properties.copy()

    # This tab is used to transform old parameters name into new ones
    # so from Nagios2 format, to Nagios3 ones.
    # Or Shinken deprecated names like criticity
    old_properties = {
        'min_criticity': 'min_business_impact',
    }

    macros = {}

    # For debugging purpose only (nice name)
    def get_name(self):
        return self.notificationway_name

    # Search for notification_options with state and if t is
    # in service_notification_period
    def want_service_notification(self,
                                  t,
                                  state,
                                  type,
                                  business_impact,
                                  cmd=None):
        if not self.service_notifications_enabled:
            return False

        # Maybe the command we ask for are not for us, but for another notification ways
        # on the same contact. If so, bail out
        if cmd and not cmd in self.service_notification_commands:
            return False

        # If the business_impact is not high enough, we bail out
        if business_impact < self.min_business_impact:
            return False

        b = self.service_notification_period.is_time_valid(t)
        if 'n' in self.service_notification_options:
            return False
        t = {
            'WARNING': 'w',
            'UNKNOWN': 'u',
            'CRITICAL': 'c',
            'RECOVERY': 'r',
            'FLAPPING': 'f',
            'DOWNTIME': 's'
        }
        if type == 'PROBLEM':
            if state in t:
                return b and t[state] in self.service_notification_options
        elif type == 'RECOVERY':
            if type in t:
                return b and t[type] in self.service_notification_options
        elif type == 'ACKNOWLEDGEMENT':
            return b
        elif type in ('FLAPPINGSTART', 'FLAPPINGSTOP', 'FLAPPINGDISABLED'):
            return b and 'f' in self.service_notification_options
        elif type in ('DOWNTIMESTART', 'DOWNTIMEEND', 'DOWNTIMECANCELLED'):
            # No notification when a downtime was cancelled. Is that true??
            # According to the documentation we need to look at _host_ options
            return b and 's' in self.host_notification_options

        return False

    # Search for notification_options with state and if t is in
    # host_notification_period
    def want_host_notification(self,
                               t,
                               state,
                               type,
                               business_impact,
                               cmd=None):
        if not self.host_notifications_enabled:
            return False

        # If the business_impact is not high enough, we bail out
        if business_impact < self.min_business_impact:
            return False

        # Maybe the command we ask for are not for us, but for another notification ways
        # on the same contact. If so, bail out
        if cmd and not cmd in self.host_notification_commands:
            return False

        b = self.host_notification_period.is_time_valid(t)
        if 'n' in self.host_notification_options:
            return False
        t = {
            'DOWN': 'd',
            'UNREACHABLE': 'u',
            'RECOVERY': 'r',
            'FLAPPING': 'f',
            'DOWNTIME': 's'
        }
        if type == 'PROBLEM':
            if state in t:
                return b and t[state] in self.host_notification_options
        elif type == 'RECOVERY':
            if type in t:
                return b and t[type] in self.host_notification_options
        elif type == 'ACKNOWLEDGEMENT':
            return b
        elif type in ('FLAPPINGSTART', 'FLAPPINGSTOP', 'FLAPPINGDISABLED'):
            return b and 'f' in self.host_notification_options
        elif type in ('DOWNTIMESTART', 'DOWNTIMEEND', 'DOWNTIMECANCELLED'):
            return b and 's' in self.host_notification_options

        return False

    # Call to get our commands to launch a Notification
    def get_notification_commands(self, type):
        # service_notification_commands for service
        notif_commands_prop = type + '_notification_commands'
        notif_commands = getattr(self, notif_commands_prop)
        return notif_commands

    # Check is required prop are set:
    # contacts OR contactgroups is need
    def is_correct(self):
        state = True
        cls = self.__class__

        # Raised all previously saw errors like unknown commands or timeperiods
        if self.configuration_errors != []:
            state = False
            for err in self.configuration_errors:
                logger.error("[item::%s] %s", self.get_name(), err)

        # A null notif way is a notif way that will do nothing (service = n, hot =n)
        is_null_notifway = False
        if hasattr(self, 'service_notification_options'
                   ) and self.service_notification_options == ['n']:
            if hasattr(self, 'host_notification_options'
                       ) and self.host_notification_options == ['n']:
                is_null_notifway = True
                return True

        for prop, entry in cls.properties.items():
            if prop not in _special_properties:
                if not hasattr(self, prop) and entry.required:
                    logger.warning("[notificationway::%s] %s property not set",
                                   self.get_name(), prop)
                    state = False  # Bad boy...

        # Ok now we manage special cases...
        # Service part
        if not hasattr(self, 'service_notification_commands'):
            logger.warning(
                "[notificationway::%s] do not have any service_notification_commands defined",
                self.get_name())
            state = False
        else:
            for cmd in self.service_notification_commands:
                if cmd is None:
                    logger.warning(
                        "[notificationway::%s] a service_notification_command is missing",
                        self.get_name())
                    state = False
                if not cmd.is_valid():
                    logger.warning(
                        "[notificationway::%s] a service_notification_command is invalid",
                        self.get_name())
                    state = False

        if getattr(self, 'service_notification_period', None) is None:
            logger.warning(
                "[notificationway::%s] the service_notification_period is invalid",
                self.get_name())
            state = False

        # Now host part
        if not hasattr(self, 'host_notification_commands'):
            logger.warning(
                "[notificationway::%s] do not have any host_notification_commands defined",
                self.get_name())
            state = False
        else:
            for cmd in self.host_notification_commands:
                if cmd is None:
                    logger.warning(
                        "[notificationway::%s] a host_notification_command is missing",
                        self.get_name())
                    state = False
                if not cmd.is_valid():
                    logger.warning(
                        "[notificationway::%s] a host_notification_command is invalid (%s)",
                        cmd.get_name(), str(cmd.__dict__))
                    state = False

        if getattr(self, 'host_notification_period', None) is None:
            logger.warning(
                "[notificationway::%s] the host_notification_period is invalid",
                self.get_name())
            state = False

        return state

    # In the scheduler we need to relink the commandCall with
    # the real commands
    def late_linkify_nw_by_commands(self, commands):
        props = ['service_notification_commands', 'host_notification_commands']
        for prop in props:
            for cc in getattr(self, prop, []):
                cc.late_linkify_with_command(commands)
Example #17
0
class Notification(Action):
    """Please Add a Docstring to describe the class here"""

    # AutoSlots create the __slots__ with properties and
    # running_properties names
    __metaclass__ = AutoSlots

    my_type = 'notification'

    properties = {
        'is_a': StringProp(default='notification'),
        'type': StringProp(default=''),
        'notification_type': IntegerProp(default=0, fill_brok=['full_status']),
        'start_time': StringProp(default=0, fill_brok=['full_status']),
        'end_time': StringProp(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': StringProp(default=0, fill_brok=['full_status']),
        'state': StringProp(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': StringProp(default=0, fill_brok=['full_status']),
        'env': StringProp(default={}),
        'exit_status': IntegerProp(default=3),
        'command_call': StringProp(default=None),
        'execution_time': FloatProp(default=0),
        'u_time': FloatProp(default=0.0),
        's_time': FloatProp(default=0.0),
        'contact': StringProp(default=None),
        '_in_timeout': BoolProp(default=False),
        'notif_nb': IntegerProp(default=0),
        'status': StringProp(default='scheduled'),
        't_to_go': IntegerProp(default=0),
        'command': StringProp(default=''),
        'sched_id': IntegerProp(default=0),
        'timeout': IntegerProp(default=10),
        'check_time': IntegerProp(default=0),
        'module_type': StringProp(default='fork', fill_brok=['full_status']),
        'worker': StringProp(default='none'),
        'reactionner_tag': StringProp(default='None'),
        'creation_time': IntegerProp(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,
                 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=0):

        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
        self.u_time = 0  # user executon time
        self.s_time = 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

    # return a copy of the check but just what is important for execution
    # So we remove the ref and all
    def copy_shell(self):
        # We create a dummy check with nothing in it, just defaults values
        return self.copy_shell__(
            Notification('', '', '', '', '', '', '', id=self.id))

    def is_launchable(self, t):
        return t >= self.t_to_go

    def is_administrative(self):
        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)))

    def get_id(self):
        return self.id

    def get_return_from(self, n):
        self.exit_status = n.exit_status
        self.execution_time = n.execution_time

    # Fill data with info of item by looking at brok_type
    # in props of properties or running_properties
    def fill_data_brok_from(self, data, brok_type):
        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)

    # Get a brok with initial status
    def get_initial_status_brok(self):
        data = {'id': self.id}

        self.fill_data_brok_from(data, 'full_status')
        b = Brok('notification_raise', data)
        return b

    # Call by pickle for dataify the comment
    # because we DO NOT WANT REF in this pickleisation!
    def __getstate__(self):
        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

    # Inverted function of getstate
    def __setstate__(self, state):
        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
            self.s_time = 0
Example #18
0
class SatelliteLink(Item):
    """SatelliteLink is a common Class for link to satellite for
    Arbiter with Conf Dispatcher.

    """
    # id = 0 each Class will have it's own id

    properties = Item.properties.copy()
    properties.update({
        'address':
        StringProp(fill_brok=['full_status']),
        'timeout':
        IntegerProp(default='3', fill_brok=['full_status']),
        'data_timeout':
        IntegerProp(default='120', fill_brok=['full_status']),
        'check_interval':
        IntegerProp(default='60', fill_brok=['full_status']),
        'max_check_attempts':
        IntegerProp(default='3', fill_brok=['full_status']),
        'spare':
        BoolProp(default='0', fill_brok=['full_status']),
        'manage_sub_realms':
        BoolProp(default='1', fill_brok=['full_status']),
        'manage_arbiters':
        BoolProp(default='0', fill_brok=['full_status'], to_send=True),
        'modules':
        ListProp(default='', to_send=True),
        'polling_interval':
        IntegerProp(default='1', fill_brok=['full_status'], to_send=True),
        'use_timezone':
        StringProp(default='NOTSET', to_send=True),
        'realm':
        StringProp(default='',
                   fill_brok=['full_status'],
                   brok_transformation=get_obj_name_two_args_and_void),
        'satellitemap':
        DictProp(default=None, elts_prop=AddrProp, to_send=True,
                 override=True),
        'use_ssl':
        BoolProp(default='0', fill_brok=['full_status']),
    })

    running_properties = Item.running_properties.copy()
    running_properties.update({
        'con':
        StringProp(default=None),
        'alive':
        StringProp(default=True, fill_brok=['full_status']),
        'broks':
        StringProp(default=[]),
        'attempt':
        StringProp(default=0,
                   fill_brok=['full_status']),  # the number of failed attempt
        'reachable':
        StringProp(default=False, fill_brok=[
            'full_status'
        ]),  # can be network ask or not (dead or check in timeout or error)
        'last_check':
        IntegerProp(default=0, fill_brok=['full_status']),
        'managed_confs':
        StringProp(default={}),
    })

    def __init__(self, *args, **kwargs):
        super(SatelliteLink, self).__init__(*args, **kwargs)

        self.arb_satmap = {'address': '0.0.0.0', 'port': 0}
        if hasattr(self, 'address'):
            self.arb_satmap['address'] = self.address
        if hasattr(self, 'port'):
            try:
                self.arb_satmap['port'] = int(self.port)
            except:
                pass

    def set_arbiter_satellitemap(self, satellitemap):
        """
            arb_satmap is the satellitemap in current context:
                - A SatelliteLink is owned by an Arbiter
                - satellitemap attribute of SatelliteLink is the map defined IN THE satellite configuration
                  but for creating connections, we need the have the satellitemap of the Arbiter
        """
        self.arb_satmap = {'address': self.address, 'port': self.port}
        self.arb_satmap.update(satellitemap)

    def create_connection(self):
        self.con = HTTPClient(address=self.arb_satmap['address'],
                              port=self.arb_satmap['port'],
                              timeout=self.timeout,
                              data_timeout=self.data_timeout,
                              use_ssl=self.use_ssl)
        self.uri = self.con.uri

    def put_conf(self, conf):
        if self.con is None:
            self.create_connection()

        # Maybe the connexion was not ok, bail out
        if not self.con:
            return False

        try:
            #pyro.set_timeout(self.con, self.data_timeout)
            self.con.post('put_conf', {'conf': conf}, wait='long')
            #pyro.set_timeout(self.con, self.timeout)
            print "PUT CONF SUCESS", self.get_name()
            return True
        except HTTPExceptions, exp:
            self.con = None
            logger.error("Failed sending configuration for %s: %s" %
                         (self.get_name(), str(exp)))
            return False
Example #19
0
class Escalation(Item):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'escalation'

    properties = Item.properties.copy()
    properties.update({
        'escalation_name':      StringProp(),
        'first_notification':   IntegerProp(),
        'last_notification':    IntegerProp(),
        'first_notification_time': IntegerProp(),
        'last_notification_time': IntegerProp(),
        # by default don't use the notification_interval defined in
        # the escalation, but the one defined by the object
        'notification_interval': IntegerProp(default='-1'),
        'escalation_period':    StringProp(default=''),
        'escalation_options':   ListProp(default='d,u,r,w,c'),
        'contacts':             StringProp(),
        'contact_groups':       StringProp(),
    })

    running_properties = Item.running_properties.copy()
    running_properties.update({
        'time_based': BoolProp(default=False),
    })

    # For debugging purpose only (nice name)
    def get_name(self):
        return self.escalation_name

    # Return True if:
    # *time in in escalation_period or we do not have escalation_period
    # *status is in escalation_options
    # *the notification number is in our interval [[first_notification .. last_notification]]
    # if we are a classic escalation.
    # *If we are time based, we check if the time that we were in notification
    # is in our time interval
    def is_eligible(self, t, status, notif_number, in_notif_time, interval):
        small_states = {
            'WARNING': 'w',    'UNKNOWN': 'u',     'CRITICAL': 'c',
            'RECOVERY': 'r',   'FLAPPING': 'f',    'DOWNTIME': 's',
            'DOWN': 'd',       'UNREACHABLE': 'u', 'OK': 'o', 'UP': 'o'
        }

        # If we are not time based, we check notification numbers:
        if not self.time_based:
            # Begin with the easy cases
            if notif_number < self.first_notification:
                return False

            #self.last_notification = 0 mean no end
            if self.last_notification != 0 and notif_number > self.last_notification:
                return False
        # Else we are time based, we must check for the good value
        else:
            # Begin with the easy cases
            if in_notif_time < self.first_notification_time * interval:
                return False

            # self.last_notification = 0 mean no end
            if self.last_notification_time != 0 and in_notif_time > self.last_notification_time * interval:
                return False

        # If our status is not good, we bail out too
        if status in small_states and small_states[status] not in self.escalation_options:
            return False

        # Maybe the time is not in our escalation_period
        if self.escalation_period is not None and not self.escalation_period.is_time_valid(t):
            return False

        # Ok, I do not see why not escalade. So it's True :)
        return True

    # t = the reference time
    def get_next_notif_time(self, t_wished, status, creation_time, interval):
        small_states = {'WARNING': 'w', 'UNKNOWN': 'u', 'CRITICAL': 'c',
             'RECOVERY': 'r', 'FLAPPING': 'f', 'DOWNTIME': 's',
             'DOWN': 'd', 'UNREACHABLE': 'u', 'OK': 'o', 'UP': 'o'}

        # If we are not time based, we bail out!
        if not self.time_based:
            return None

        # Check if we are valid
        if status in small_states and small_states[status] not in self.escalation_options:
            return None

        # Look for the min of our future validity
        start = self.first_notification_time * interval + creation_time

        # If we are after the classic next time, we are not asking for a smaller interval
        if start > t_wished:
            return None

        # Maybe the time we found is not a valid one....
        if self.escalation_period is not None and not self.escalation_period.is_time_valid(start):
            return None

        # Ok so I ask for my start as a possibility for the next notification time
        return start

    # Check is required prop are set:
    # template are always correct
    # contacts OR contactgroups is need
    def is_correct(self):
        state = True
        cls = self.__class__

        # If we got the _time parameters, we are time based. Unless, we are not :)
        if hasattr(self, 'first_notification_time') or hasattr(self, 'last_notification_time'):
            self.time_based = True
            special_properties = _special_properties_time_based
        else:  # classic ones
            special_properties = _special_properties

        for prop, entry in cls.properties.items():
            if prop not in special_properties:
                if not hasattr(self, prop) and entry.required:
                    logger.info('%s: I do not have %s', self.get_name(), prop)
                    state = False  # Bad boy...

        # Raised all previously saw errors like unknown contacts and co
        if self.configuration_errors != []:
            state = False
            for err in self.configuration_errors:
                logger.info(err)

        # Ok now we manage special cases...
        if not hasattr(self, 'contacts') and not hasattr(self, 'contact_groups'):
            logger.info('%s: I do not have contacts nor contact_groups', self.get_name())
            state = False

        # If time_based or not, we do not check all properties
        if self.time_based:
            if not hasattr(self, 'first_notification_time'):
                logger.info('%s: I do not have first_notification_time', self.get_name())
                state = False
            if not hasattr(self, 'last_notification_time'):
                logger.info('%s: I do not have last_notification_time', self.get_name())
                state = False
        else:  # we check classical properties
            if not hasattr(self, 'first_notification'):
                logger.info('%s: I do not have first_notification', self.get_name())
                state = False
            if not hasattr(self, 'last_notification'):
                logger.info('%s: I do not have last_notification', self.get_name())
                state = False

        return state
Example #20
0
class Realm(Itemgroup):
    id = 1  # zero is always a little bit special... like in database
    my_type = 'realm'

    properties = Itemgroup.properties.copy()
    properties.update({
        'id': IntegerProp(default=0, fill_brok=['full_status']),
        'realm_name': StringProp(fill_brok=['full_status']),
        'realm_members': ListProp(
            default=[], split_on_coma=True
        ),  # No status_broker_name because it put hosts, not host_name
        'higher_realms': ListProp(default=[], split_on_coma=True),
        'default': BoolProp(default=False),
        'broker_complete_links': BoolProp(default=False),
        #'alias': {'required':  True, 'fill_brok': ['full_status']},
        #'notes': {'required': False, 'default':'', 'fill_brok': ['full_status']},
        #'notes_url': {'required': False, 'default':'', 'fill_brok': ['full_status']},
        #'action_url': {'required': False, 'default':'', 'fill_brok': ['full_status']},
    })

    running_properties = Item.running_properties.copy()
    running_properties.update({
        'serialized_confs': DictProp(default={}),
    })

    macros = {
        'REALMNAME': 'realm_name',
        'REALMMEMBERS': 'members',
    }

    def get_name(self):
        return self.realm_name

    def get_realms(self):
        return self.realm_members

    def add_string_member(self, member):
        self.realm_members += ',' + member

    def get_realm_members(self):
        if self.has('realm_members'):
            return [r.strip() for r in self.realm_members]
        else:
            return []

    # We fillfull properties with template ones if need
    # Because hostgroup we call may not have it's members
    # we call get_hosts_by_explosion on it
    def get_realms_by_explosion(self, realms):
        # First we tag the hg so it will not be explode
        # if a son of it already call it
        self.already_explode = True

        # Now the recursive part
        # rec_tag is set to False every HG we explode
        # so if True here, it must be a loop in HG
        # calls... not GOOD!
        if self.rec_tag:
            err = "Error: we've got a loop in realm definition %s" % self.get_name(
            )
            self.configuration_errors.append(err)
            if self.has('members'):
                return self.members
            else:
                return ''

        # Ok, not a loop, we tag it and continue
        self.rec_tag = True

        p_mbrs = self.get_realm_members()
        for p_mbr in p_mbrs:
            p = realms.find_by_name(p_mbr.strip())
            if p is not None:
                value = p.get_realms_by_explosion(realms)
                if value is not None:
                    self.add_string_member(value)

        if self.has('members'):
            return self.members
        else:
            return ''

    def get_all_subs_satellites_by_type(self, sat_type):
        r = copy.copy(getattr(self, sat_type))
        for p in self.realm_members:
            tmps = p.get_all_subs_satellites_by_type(sat_type)
            for s in tmps:
                r.append(s)
        return r

    def count_reactionners(self):
        self.nb_reactionners = 0
        for reactionner in self.reactionners:
            if not reactionner.spare:
                self.nb_reactionners += 1
        for realm in self.higher_realms:
            for reactionner in realm.reactionners:
                if not reactionner.spare and reactionner.manage_sub_realms:
                    self.nb_reactionners += 1

    def count_pollers(self):
        self.nb_pollers = 0
        for poller in self.pollers:
            if not poller.spare:
                self.nb_pollers += 1
        for realm in self.higher_realms:
            for poller in realm.pollers:
                if not poller.spare and poller.manage_sub_realms:
                    self.nb_pollers += 1

    def count_brokers(self):
        self.nb_brokers = 0
        for broker in self.brokers:
            if not broker.spare:
                self.nb_brokers += 1
        for realm in self.higher_realms:
            for broker in realm.brokers:
                if not broker.spare and broker.manage_sub_realms:
                    self.nb_brokers += 1

    def count_receivers(self):
        self.nb_receivers = 0
        for receiver in self.receivers:
            if not receiver.spare:
                self.nb_receivers += 1
        for realm in self.higher_realms:
            for receiver in realm.receivers:
                if not receiver.spare and receiver.manage_sub_realms:
                    self.nb_receivers += 1

    # Return the list of satellites of a certain type
    # like reactionner -> self.reactionners
    def get_satellties_by_type(self, type):
        if hasattr(self, type + 's'):
            return getattr(self, type + 's')
        else:
            logger.debug("[realm] do not have this kind of satellites: %s",
                         type)
            return []

    def fill_potential_satellites_by_type(self, sat_type):
        setattr(self, 'potential_%s' % sat_type, [])
        for satellite in getattr(self, sat_type):
            getattr(self, 'potential_%s' % sat_type).append(satellite)
        for realm in self.higher_realms:
            for satellite in getattr(realm, sat_type):
                if satellite.manage_sub_realms:
                    getattr(self, 'potential_%s' % sat_type).append(satellite)

    # Return the list of potentials satellites of a certain type
    # like reactionner -> self.potential_reactionners
    def get_potential_satellites_by_type(self, type):
        if hasattr(self, 'potential_' + type + 's'):
            return getattr(self, 'potential_' + type + 's')
        else:
            logger.debug("[realm] do not have this kind of satellites: %s",
                         type)
            return []

    # Return the list of potentials satellites of a certain type
    # like reactionner -> self.nb_reactionners
    def get_nb_of_must_have_satellites(self, type):
        if hasattr(self, 'nb_' + type + 's'):
            return getattr(self, 'nb_' + type + 's')
        else:
            logger.debug("[realm] do not have this kind of satellites: %s",
                         type)
            return 0

    # Fill dict of realms for managing the satellites confs
    def prepare_for_satellites_conf(self):
        self.to_satellites = {}
        self.to_satellites['reactionner'] = {}
        self.to_satellites['poller'] = {}
        self.to_satellites['broker'] = {}
        self.to_satellites['receiver'] = {}

        self.to_satellites_need_dispatch = {}
        self.to_satellites_need_dispatch['reactionner'] = {}
        self.to_satellites_need_dispatch['poller'] = {}
        self.to_satellites_need_dispatch['broker'] = {}
        self.to_satellites_need_dispatch['receiver'] = {}

        self.to_satellites_managed_by = {}
        self.to_satellites_managed_by['reactionner'] = {}
        self.to_satellites_managed_by['poller'] = {}
        self.to_satellites_managed_by['broker'] = {}
        self.to_satellites_managed_by['receiver'] = {}

        self.count_reactionners()
        self.fill_potential_satellites_by_type('reactionners')
        self.count_pollers()
        self.fill_potential_satellites_by_type('pollers')
        self.count_brokers()
        self.fill_potential_satellites_by_type('brokers')
        self.count_receivers()
        self.fill_potential_satellites_by_type('receivers')

        s = "%s: (in/potential) (schedulers:%d) (pollers:%d/%d) (reactionners:%d/%d) (brokers:%d/%d) (receivers:%d/%d)" % \
            (self.get_name(),
             len(self.schedulers),
             self.nb_pollers, len(self.potential_pollers),
             self.nb_reactionners, len(self.potential_reactionners),
             self.nb_brokers, len(self.potential_brokers),
             self.nb_receivers, len(self.potential_receivers)
             )
        logger.info(s)

    # TODO: find a better name...
    # TODO: and if he goes active?
    def fill_broker_with_poller_reactionner_links(self, broker):
        # First we create/void theses links
        broker.cfg['pollers'] = {}
        broker.cfg['reactionners'] = {}
        broker.cfg['receivers'] = {}

        # First our own level
        for p in self.pollers:
            cfg = p.give_satellite_cfg()
            broker.cfg['pollers'][p.id] = cfg

        for r in self.reactionners:
            cfg = r.give_satellite_cfg()
            broker.cfg['reactionners'][r.id] = cfg

        for b in self.receivers:
            cfg = b.give_satellite_cfg()
            broker.cfg['receivers'][b.id] = cfg

        # Then sub if we must to it
        if broker.manage_sub_realms:
            # Now pollers
            for p in self.get_all_subs_satellites_by_type('pollers'):
                cfg = p.give_satellite_cfg()
                broker.cfg['pollers'][p.id] = cfg

            # Now reactionners
            for r in self.get_all_subs_satellites_by_type('reactionners'):
                cfg = r.give_satellite_cfg()
                broker.cfg['reactionners'][r.id] = cfg

            # Now receivers
            for r in self.get_all_subs_satellites_by_type('receivers'):
                cfg = r.give_satellite_cfg()
                broker.cfg['receivers'][r.id] = cfg

    # Get a conf package of satellites links that can be useful for
    # a scheduler
    def get_satellites_links_for_scheduler(self):
        cfg = {}

        # First we create/void theses links
        cfg['pollers'] = {}
        cfg['reactionners'] = {}

        # First our own level
        for p in self.pollers:
            c = p.give_satellite_cfg()
            cfg['pollers'][p.id] = c

        for r in self.reactionners:
            c = r.give_satellite_cfg()
            cfg['reactionners'][r.id] = c

        #print "***** Preparing a satellites conf for a scheduler", cfg
        return cfg
Example #21
0
class NotificationWay(Item):
    id = 1#0 is always special in database, so we do not take risk here
    my_type = 'notificationway'

    properties = {
        'notificationway_name':         StringProp (fill_brok=['full_status']),
        'host_notifications_enabled':   BoolProp   (default='1', fill_brok=['full_status']),
        'service_notifications_enabled':BoolProp   (default='1', fill_brok=['full_status']),
        'host_notification_period':     StringProp (fill_brok=['full_status']),
        'service_notification_period':  StringProp (fill_brok=['full_status']),
        'host_notification_options':    ListProp   (fill_brok=['full_status']),
        'service_notification_options': ListProp   (fill_brok=['full_status']),
        'host_notification_commands':   StringProp (fill_brok=['full_status']),
        'service_notification_commands':StringProp (fill_brok=['full_status']),
        'min_criticity':                IntegerProp(default = '0', fill_brok=['full_status']),
    }
    
    running_properties = {}

    macros = {}

    #For debugging purpose only (nice name)
    def get_name(self):
        return self.notificationway_name


    #Search for notification_options with state and if t is
    #in service_notification_period
    def want_service_notification(self, t, state, type, criticity):
        if not self.service_notifications_enabled:
            return False

        # If the criticity is not high enough, we bail out
        if criticity < self.min_criticity:
            return False

        b = self.service_notification_period.is_time_valid(t)
        if 'n' in self.service_notification_options:
            return False
        t = {'WARNING' : 'w', 'UNKNOWN' : 'u', 'CRITICAL' : 'c',
             'RECOVERY' : 'r', 'FLAPPING' : 'f', 'DOWNTIME' : 's'}
        if type == 'PROBLEM':
            if state in t:
                return b and t[state] in self.service_notification_options
        elif type == 'RECOVERY':
            if type in t:
                return b and t[type] in self.service_notification_options
        elif type == 'ACKNOWLEDGEMENT':
            return b
        elif type in ('FLAPPINGSTART', 'FLAPPINGSTOP', 'FLAPPINGDISABLED'):
            return b and 'f' in self.service_notification_options
        elif type in ('DOWNTIMESTART', 'DOWNTIMEEND', 'DOWNTIMECANCELLED'):
            #No notification when a downtime was cancelled. Is that true??
            # According to the documentation we need to look at _host_ options
            return b and 's' in self.host_notification_options

        return False


    #Search for notification_options with state and if t is in
    #host_notification_period
    def want_host_notification(self, t, state, type, criticity):
        if not self.host_notifications_enabled:
            return False

        # If the criticity is not high enough, we bail out
        if criticity < self.min_criticity:
            return False

        b = self.host_notification_period.is_time_valid(t)
        if 'n' in self.host_notification_options:
            return False
        t = {'DOWN' : 'd', 'UNREACHABLE' : 'u', 'RECOVERY' : 'r',
             'FLAPPING' : 'f', 'DOWNTIME' : 's'}
        if type == 'PROBLEM':
            if state in t:
                return b and t[state] in self.host_notification_options
        elif type == 'RECOVERY':
            if type in t:
                return b and t[type] in self.host_notification_options
        elif type == 'ACKNOWLEDGEMENT':
            return b
        elif type in ('FLAPPINGSTART', 'FLAPPINGSTOP', 'FLAPPINGDISABLED'):
            return b and 'f' in self.host_notification_options
        elif type in ('DOWNTIMESTART', 'DOWNTIMEEND', 'DOWNTIMECANCELLED'):
            return b and 's' in self.host_notification_options

        return False


    def clean(self):
        pass


    #Call to get our commands to launch a Notification
    def get_notification_commands(self, type):
        #service_notification_commands for service
        notif_commands_prop = type+'_notification_commands'
        notif_commands = getattr(self, notif_commands_prop)
        return notif_commands



    #Check is required prop are set:
    #contacts OR contactgroups is need
    def is_correct(self):
        state = True #guilty or not? :)
        cls = self.__class__

        #A null notif way is a notif way that will do nothing (service = n, hot =n)
        is_null_notifway = False
        if hasattr(self, 'service_notification_options') and self.service_notification_options==['n']:
            if hasattr(self, 'host_notification_options') and self.host_notification_options==['n']:
                is_null_notifway = True
                return True

        for prop, entry in cls.properties.items():
            if prop not in _special_properties:
                if not hasattr(self, prop) and entry.required:
                    print self.get_name(), " : I do not have", prop
                    state = False #Bad boy...

        #Ok now we manage special cases...
        #Service part
        if not hasattr(self, 'service_notification_commands') :
            print self.get_name()," : do not have any service_notification_commands defined"
            state = False
        else:
            for cmd in self.service_notification_commands:
                if cmd is None:
                    print self.get_name()," : a service_notification_command is missing"
                    state = False
                if not cmd.is_valid():
                    print self.get_name()," : a service_notification_command is invalid", cmd.get_name()
                    state = False
        
        if getattr(self, 'service_notification_period', None) is None:
            print self.get_name()," : the service_notification_period is invalid"
            state = False

        #Now host part
        if not hasattr(self, 'host_notification_commands') :
            print self.get_name()," : do not have any host_notification_commands defined"
            state = False
        else:
            for cmd in self.host_notification_commands:
                if cmd is None :
                    print self.get_name()," : a host_notification_command is missing"
                    state = False
                if not cmd.is_valid():
                    print self.get_name()," : a host_notification_command is invalid", cmd.get_name(), cmd.__dict__
                    state = False

        if getattr(self, 'host_notification_period', None) is None:
            print self.get_name()," : the host_notification_period is invalid"
            state = False

        return state
Example #22
0
class EventHandler(Action):
    # AutoSlots create the __slots__ with properties and
    # running_properties names
    __metaclass__ = AutoSlots

    my_type = 'eventhandler'

    properties = {
        'is_a': StringProp(default='eventhandler'),
        'type': StringProp(default=''),
        '_in_timeout': StringProp(default=False),
        'status': StringProp(default=''),
        'exit_status': StringProp(default=3),
        'output': StringProp(default=''),
        'long_output': StringProp(default=''),
        't_to_go': StringProp(default=0),
        'check_time': StringProp(default=0),
        'execution_time': FloatProp(default=0),
        'u_time': FloatProp(default=0.0),
        's_time': FloatProp(default=0.0),
        'env': StringProp(default={}),
        'perf_data': StringProp(default=''),
        'sched_id': IntegerProp(default=0),
        'timeout': IntegerProp(default=10),
        'check_time': IntegerProp(default=0),
        'command': StringProp(default=''),
        'module_type': StringProp(default='fork'),
        'worker': StringProp(default='none'),
        'reactionner_tag': StringProp(default='None'),
        'is_snapshot': BoolProp(default=False),
    }

    # id = 0  #Is common to Actions
    def __init__(self,
                 command,
                 id=None,
                 ref=None,
                 timeout=10,
                 env={},
                 module_type='fork',
                 reactionner_tag='None',
                 is_snapshot=False):
        self.is_a = 'eventhandler'
        self.type = ''
        self.status = 'scheduled'
        if id is None:  # id != None is for copy call only
            self.id = Action.id
            Action.id += 1
        self.ref = ref
        self._in_timeout = False
        self.timeout = timeout
        self.exit_status = 3
        self.command = command
        self.output = ''
        self.long_output = ''
        self.t_to_go = time.time()
        self.check_time = 0
        self.execution_time = 0
        self.u_time = 0
        self.s_time = 0
        self.perf_data = ''
        self.env = {}
        self.module_type = module_type
        self.worker = 'none'
        self.reactionner_tag = reactionner_tag
        self.is_snapshot = is_snapshot

    # return a copy of the check but just what is important for execution
    # So we remove the ref and all
    def copy_shell(self):
        # We create a dummy check with nothing in it, just defaults values
        return self.copy_shell__(
            EventHandler('', id=self.id, is_snapshot=self.is_snapshot))

    def get_return_from(self, e):
        self.exit_status = e.exit_status
        self.output = e.output
        self.long_output = getattr(e, 'long_output', '')
        self.check_time = e.check_time
        self.execution_time = getattr(e, 'execution_time', 0.0)
        self.perf_data = getattr(e, 'perf_data', '')

    def get_outputs(self, out, max_plugins_output_length):
        self.output = out

    def is_launchable(self, t):
        return t >= self.t_to_go

    def __str__(self):
        return "Check %d status:%s command:%s" % (self.id, self.status,
                                                  self.command)

    def get_id(self):
        return self.id

    # Call by pickle to dataify the comment
    # because we DO NOT WANT REF in this pickleisation!
    def __getstate__(self):
        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

    # Inverted function of getstate
    def __setstate__(self, state):
        cls = self.__class__
        self.id = state['id']
        for prop in cls.properties:
            if prop in state:
                setattr(self, prop, state[prop])
        if not hasattr(self, 'worker'):
            self.worker = 'none'
        if not getattr(self, 'module_type', None):
            self.module_type = 'fork'
        # s_time and u_time are added between 1.2 and 1.4
        if not hasattr(self, 'u_time'):
            self.u_time = 0
            self.s_time = 0
Example #23
0
class SatelliteLink(Item):
    """SatelliteLink is a common Class for link to satellite for
    Arbiter with Conf Dispatcher.

    """
    # id = 0 each Class will have it's own id

    properties = Item.properties.copy()
    properties.update({
        'address':
        StringProp(fill_brok=['full_status']),
        'timeout':
        IntegerProp(default='3', fill_brok=['full_status']),
        'data_timeout':
        IntegerProp(default='120', fill_brok=['full_status']),
        'check_interval':
        IntegerProp(default='60', fill_brok=['full_status']),
        'max_check_attempts':
        IntegerProp(default='3', fill_brok=['full_status']),
        'spare':
        BoolProp(default='0', fill_brok=['full_status']),
        'manage_sub_realms':
        BoolProp(default='1', fill_brok=['full_status']),
        'manage_arbiters':
        BoolProp(default='0', fill_brok=['full_status'], to_send=True),
        'modules':
        ListProp(default='', to_send=True),
        'polling_interval':
        IntegerProp(default='1', fill_brok=['full_status'], to_send=True),
        'use_timezone':
        StringProp(default='NOTSET', to_send=True),
        'realm':
        StringProp(default='',
                   fill_brok=['full_status'],
                   brok_transformation=get_obj_name_two_args_and_void),
        'satellitemap':
        DictProp(default=None, elts_prop=AddrProp, to_send=True,
                 override=True),
    })

    running_properties = Item.running_properties.copy()
    running_properties.update({
        'con':
        StringProp(default=None),
        'alive':
        StringProp(default=True, fill_brok=['full_status']),
        'broks':
        StringProp(default=[]),
        'attempt':
        StringProp(default=0,
                   fill_brok=['full_status']),  # the number of failed attempt
        'reachable':
        StringProp(default=False, fill_brok=[
            'full_status'
        ]),  # can be network ask or not (dead or check in timeout or error)
        'last_check':
        IntegerProp(default=0, fill_brok=['full_status']),
        'managed_confs':
        StringProp(default={}),
    })

    def __init__(self, *args, **kwargs):
        super(SatelliteLink, self).__init__(*args, **kwargs)

        self.arb_satmap = {'address': '0.0.0.0', 'port': 0}
        if hasattr(self, 'address'):
            self.arb_satmap['address'] = self.address
        if hasattr(self, 'port'):
            try:
                self.arb_satmap['port'] = int(self.port)
            except:
                pass

    def set_arbiter_satellitemap(self, satellitemap):
        """
            arb_satmap is the satellitemap in current context:
                - A SatelliteLink is owned by an Arbiter
                - satellitemap attribute of SatelliteLink is the map defined IN THE satellite configuration
                  but for creating connections, we need the have the satellitemap of the Arbiter
        """
        self.arb_satmap = {'address': self.address, 'port': self.port}
        self.arb_satmap.update(satellitemap)

    def create_connection(self):
        try:
            self.uri = pyro.create_uri(self.arb_satmap['address'],
                                       self.arb_satmap['port'], "ForArbiter",
                                       self.__class__.use_ssl)
            # By default Pyro got problem in connect() function that can take
            # long seconds to raise a timeout. And even with the _setTimeout()
            # call. So we change the whole default connect() timeout
            socket.setdefaulttimeout(self.timeout)
            self.con = pyro.getProxy(self.uri)
            # But the multiprocessing module is not copatible with it!
            # so we must disable it imadiatly after
            socket.setdefaulttimeout(None)
            pyro.set_timeout(self.con, self.timeout)
        except Pyro_exp_pack, exp:
            # But the multiprocessing module is not compatible with it!
            # so we must disable it imadiatly after
            socket.setdefaulttimeout(None)
            self.con = None
            logger.error("Creating connection for %s: %s" %
                         (self.get_name(), str(exp)))
Example #24
0
class Check(Action):
    # AutoSlots create the __slots__ with properties and
    # running_properties names
    __metaclass__ = AutoSlots

    properties = {
        'is_a': StringProp(default='check'),
        'type': StringProp(default=''),
        '_in_timeout': BoolProp(default=False),
        'status': StringProp(default=''),
        'exit_status': IntegerProp(default=3),
        'state': IntegerProp(default=0),
        'output': StringProp(default=''),
        'long_output': StringProp(default=''),
        'ref': IntegerProp(default=-1),
        't_to_go': IntegerProp(default=0),
        'depend_on': StringProp(default=[]),
        'dep_check': StringProp(default=[]),
        'check_time': IntegerProp(default=0),
        'execution_time': IntegerProp(default=0),
        'perf_data': StringProp(default=''),
        'poller_tag': StringProp(default='None'),
        'reactionner_tag': StringProp(default='None'),
        'env': StringProp(default={}),
        'internal': BoolProp(default=False),
        'module_type': StringProp(default='fork'),
        'worker': StringProp(default='none'),
    }

    #id = 0 #Is common to Actions
    def __init__(self, status, command, ref, t_to_go, dep_check=None, id=None, timeout=10,\
                     poller_tag='None', reactionner_tag='None', env={}, module_type='fork'):

        self.is_a = 'check'
        self.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.output = ''
        self.long_output = ''
        self.ref = ref
        #self.ref_type = ref_type
        self.t_to_go = t_to_go
        self.depend_on = []
        if dep_check is None:
            self.depend_on_me = []
        else:
            self.depend_on_me = [dep_check]
        self.check_time = 0
        self.execution_time = 0
        self.perf_data = ''
        self.poller_tag = poller_tag
        self.reactionner_tag = reactionner_tag
        self.module_type = module_type
        self.env = env
        # we keep the reference of the poller that will take us
        self.worker = 'none'
        # If it's a business rule, manage it as a special check
        if ref and ref.got_business_rule or command.startswith('_internal'):
            self.internal = True
        else:
            self.internal = False

    #return a copy of the check but just what is important for execution
    #So we remove the ref and all
    def copy_shell(self):
        #We create a dummy check with nothing in it, jsut defaults values
        return self.copy_shell__(Check('', '', '', '', '', id=self.id))

    def get_return_from(self, c):
        self.exit_status = c.exit_status
        self.output = c.output
        self.long_output = c.long_output
        self.check_time = c.check_time
        self.execution_time = c.execution_time
        self.perf_data = c.perf_data

    def is_launchable(self, t):
        return t > self.t_to_go

    def __str__(self):
        return "Check %d status:%s command:%s ref:%s" % (
            self.id, self.status, self.command, self.ref)

    def get_id(self):
        return self.id
Example #25
0
class Timeperiod(Item):
    id = 1
    my_type = 'timeperiod'

    properties = Item.properties.copy()
    properties.update({
        'timeperiod_name':
        StringProp(fill_brok=['full_status']),
        'alias':
        StringProp(default='', fill_brok=['full_status']),
        'use':
        StringProp(default=''),
        'register':
        IntegerProp(default='1'),

        # These are needed if a broker module calls methods on timeperiod objects
        'dateranges':
        ListProp(fill_brok=['full_status'], default=[]),
        'exclude':
        ListProp(fill_brok=['full_status'], default=[]),
        'is_active':
        BoolProp(default='0')
    })
    running_properties = Item.running_properties.copy()

    def __init__(self, params={}):
        self.id = Timeperiod.id
        Timeperiod.id = Timeperiod.id + 1
        self.unresolved = []
        self.dateranges = []
        self.exclude = ''
        self.customs = {}
        self.plus = {}
        self.invalid_entries = []
        for key in params:
            if key in [
                    'name', 'alias', 'timeperiod_name', 'exclude', 'use',
                    'register', 'imported_from', 'is_active', 'dateranges'
            ]:
                setattr(self, key, params[key])
            else:
                self.unresolved.append(key + ' ' + params[key])

        self.cache = {}  # For tunning purpose only
        self.invalid_cache = {}  # same but for invalid search
        self.configuration_errors = []
        self.configuration_warnings = []
        # By default the tp is None so we know we just start
        self.is_active = None
        self.tags = set()

    def get_name(self):
        return getattr(self, 'timeperiod_name', 'unknown_timeperiod')

    # We fillfull properties with template ones if need
    # for the unresolved values (like sunday ETCETC)
    def get_unresolved_properties_by_inheritance(self, items):
        # Ok, I do not have prop, Maybe my templates do?
        # Same story for plus
        for i in self.templates:
            self.unresolved.extend(i.unresolved)

    # Ok timeperiods are a bit different from classic items, because we do not have a real list
    # of our raw properties, like if we got february 1 - 15 / 3 for example
    def get_raw_import_values(self):
        properties = ['timeperiod_name', 'alias', 'use', 'register']
        r = {}
        for prop in properties:
            if hasattr(self, prop):
                v = getattr(self, prop)
                print prop, ":", v
                r[prop] = v
        # Now the unresolved one. The only way to get ride of same key things is to put
        # directly the full value as the key
        for other in self.unresolved:
            r[other] = ''
        return r

    def is_time_valid(self, t):
        if self.has('exclude'):
            for dr in self.exclude:
                if dr.is_time_valid(t):
                    return False
        for dr in self.dateranges:
            if dr.is_time_valid(t):
                return True
        return False

    # will give the first time > t which is valid
    def get_min_from_t(self, t):
        mins_incl = []
        for dr in self.dateranges:
            mins_incl.append(dr.get_min_from_t(t))
        return min(mins_incl)

    # will give the first time > t which is not valid
    def get_not_in_min_from_t(self, f):
        pass

    def find_next_valid_time_from_cache(self, t):
        try:
            return self.cache[t]
        except KeyError:
            return None

    def find_next_invalid_time_from_cache(self, t):
        try:
            return self.invalid_cache[t]
        except KeyError:
            return None

    # will look for active/un-active change. And log it
    # [1327392000] TIMEPERIOD TRANSITION: <name>;<from>;<to>
    # from is -1 on startup.  to is 1 if the timeperiod starts
    # and 0 if it ends.
    def check_and_log_activation_change(self):
        now = int(time.time())

        was_active = self.is_active
        self.is_active = self.is_time_valid(now)

        # If we got a change, log it!
        if self.is_active != was_active:
            _from = 0
            _to = 0
            # If it's the start, get a special value for was
            if was_active is None:
                _from = -1
            if was_active:
                _from = 1
            if self.is_active:
                _to = 1

            # Now raise the log
            console_logger.info('TIMEPERIOD TRANSITION: %s;%d;%d' %
                                (self.get_name(), _from, _to))

    # clean the get_next_valid_time_from_t cache
    # The entries are a dict on t. t < now are useless
    # Because we do not care about past anymore.
    # If not, it's not important, it's just a cache after all :)
    def clean_cache(self):
        now = int(time.time())
        t_to_del = []
        for t in self.cache:
            if t < now:
                t_to_del.append(t)
        for t in t_to_del:
            del self.cache[t]

        # same for the invalid cache
        t_to_del = []
        for t in self.invalid_cache:
            if t < now:
                t_to_del.append(t)
        for t in t_to_del:
            del self.invalid_cache[t]

    def get_next_valid_time_from_t(self, t):
        # first find from cache
        t = int(t)
        original_t = t

        #logger.debug("[%s] Check valid time for %s" % ( self.get_name(), time.asctime(time.localtime(t)))

        res_from_cache = self.find_next_valid_time_from_cache(t)
        if res_from_cache is not None:
            return res_from_cache

        still_loop = True

        # Loop for all minutes...
        while still_loop:
            local_min = None

            # Ok, not in cache...
            dr_mins = []
            s_dr_mins = []

            for dr in self.dateranges:
                dr_mins.append(dr.get_next_valid_time_from_t(t))

            s_dr_mins = sorted([d for d in dr_mins if d is not None])

            for t1 in s_dr_mins:
                if not self.exclude and still_loop is True:
                    # No Exclude so we are good
                    local_min = t1
                    still_loop = False
                else:
                    for tp in self.exclude:
                        if not tp.is_time_valid(t1) and still_loop is True:
                            # OK we found a date that is not valid in any exclude timeperiod
                            local_min = t1
                            still_loop = False

            if local_min is None:
                # print "Looking for next valid date"
                exc_mins = []
                if s_dr_mins != []:
                    for tp in self.exclude:
                        exc_mins.append(
                            tp.get_next_invalid_time_from_t(s_dr_mins[0]))

                s_exc_mins = sorted([d for d in exc_mins if d is not None])

                if s_exc_mins != []:
                    local_min = s_exc_mins[0]

            if local_min is None:
                still_loop = False
            else:
                t = local_min
                # No loop more than one year
                if t > original_t + 3600 * 24 * 366 + 1:
                    still_loop = False
                    local_min = None

        # Ok, we update the cache...
        self.cache[original_t] = local_min
        return local_min

    def get_next_invalid_time_from_t(self, t):
        #print '\n\n', self.get_name(), 'Search for next invalid from', time.asctime(time.localtime(t)), t
        t = int(t)
        original_t = t
        still_loop = True

        # First try to find in cache
        res_from_cache = self.find_next_invalid_time_from_cache(t)
        if res_from_cache is not None:
            return res_from_cache

        # Then look, maybe t is already invalid
        if not self.is_time_valid(t):
            return t

        local_min = t
        res = None
        # Loop for all minutes...
        while still_loop:
            #print "Invalid loop with", time.asctime(time.localtime(local_min))

            dr_mins = []
            #val_valids = []
            #val_inval = []
            # But maybe we can find a better solution with next invalid of standard dateranges
            #print self.get_name(), "After valid of exclude, local_min =", time.asctime(time.localtime(local_min))
            for dr in self.dateranges:
                #print self.get_name(), "Search a next invalid from DR", time.asctime(time.localtime(local_min))
                #print dr.__dict__
                m = dr.get_next_invalid_time_from_t(local_min)

                #print self.get_name(), "Dr", dr.__dict__,  "give me next invalid", time.asctime(time.localtime(m))
                if m is not None:
                    # But maybe it's invalid for this dr, but valid for other ones.
                    #if not self.is_time_valid(m):
                    #     print "Final: Got a next invalid at", time.asctime(time.localtime(m))
                    dr_mins.append(m)
                    #if not self.is_time_valid(m):
                    #    val_inval.append(m)
                    #else:
                    #    val_valids.append(m)
                    #    print "Add a m", time.asctime(time.localtime(m))
                    #else:
                    #     print dr.__dict__
                    #     print "F**K bad result\n\n\n"
            #print "Inval"
            #for v in val_inval:
            #    print "\t", time.asctime(time.localtime(v))
            #print "Valid"
            #for v in val_valids:
            #    print "\t", time.asctime(time.localtime(v))

            if dr_mins != []:
                local_min = min(dr_mins)
                # Take the minimum valid as lower for next search
                #local_min_valid = 0
                #if val_valids != []:
                #    local_min_valid = min(val_valids)
                #if local_min_valid != 0:
                #    local_min = local_min_valid
                #else:
                #    local_min = min(dr_mins)
                #print "UPDATE After dr: found invalid local min:", time.asctime(time.localtime(local_min)), "is valid", self.is_time_valid(local_min)

            #print self.get_name(), 'Invalid: local min', local_min #time.asctime(time.localtime(local_min))
            # We do not loop unless the local_min is not valid
            if not self.is_time_valid(local_min):
                still_loop = False
            else:  # continue until we reach too far..., in one minute
                # After one month, go quicker...
                if local_min > original_t + 3600 * 24 * 30:
                    local_min += 3600
                else:  # else search for 1min precision
                    local_min += 60
                # after one year, stop.
                if local_min > original_t + 3600 * 24 * 366 + 1:  # 60*24*366 + 1:
                    still_loop = False
            #print "Loop?", still_loop
            # if we've got a real value, we check it with the exclude
            if local_min is not None:
                # Now check if local_min is not valid
                for tp in self.exclude:
                    #print self.get_name(),"we check for invalid", time.asctime(time.localtime(local_min)), 'with tp', tp.name
                    if tp.is_time_valid(local_min):
                        still_loop = True
                        # local_min + 60
                        local_min = tp.get_next_invalid_time_from_t(local_min +
                                                                    60)
                        # No loop more than one year
                        if local_min > original_t + 60 * 24 * 366 + 1:
                            still_loop = False
                            res = None

            if not still_loop:  # We find a possible value
                # We take the result the minimal possible
                if res is None or local_min < res:
                    res = local_min

        #print "Finished Return the next invalid", time.asctime(time.localtime(local_min))
        # Ok, we update the cache...
        self.invalid_cache[original_t] = local_min
        return local_min

    def has(self, prop):
        return hasattr(self, prop)

    # We are correct only if our daterange are
    # and if we have no unmatch entries
    def is_correct(self):
        b = True
        for dr in self.dateranges:
            b &= dr.is_correct()

        # Even one invalid is non correct
        for e in self.invalid_entries:
            b = False
            logger.error("[timeperiod::%s] invalid entry '%s'" %
                         (self.get_name(), e))
        return b

    def __str__(self):
        s = ''
        s += str(self.__dict__) + '\n'
        for elt in self.dateranges:
            s += str(elt)
            (start, end) = elt.get_start_and_end_time()
            start = time.asctime(time.localtime(start))
            end = time.asctime(time.localtime(end))
            s += "\nStart and end:" + str((start, end))
        s += '\nExclude'
        for elt in self.exclude:
            s += str(elt)

        return s

    def resolve_daterange(self, dateranges, entry):
        #print "Trying to resolve ", entry

        res = re.search(
            '(\d{4})-(\d{2})-(\d{2}) - (\d{4})-(\d{2})-(\d{2}) / (\d+)[\s\t]*([0-9:, -]+)',
            entry)
        if res is not None:
            #print "Good catch 1"
            (syear, smon, smday, eyear, emon, emday, skip_interval,
             other) = res.groups()
            dateranges.append(
                CalendarDaterange(syear, smon, smday, 0, 0, eyear, emon, emday,
                                  0, 0, skip_interval, other))
            return

        res = re.search('(\d{4})-(\d{2})-(\d{2}) / (\d+)[\s\t]*([0-9:, -]+)',
                        entry)
        if res is not None:
            #print "Good catch 2"
            (syear, smon, smday, skip_interval, other) = res.groups()
            eyear = syear
            emon = smon
            emday = smday
            dateranges.append(
                CalendarDaterange(syear, smon, smday, 0, 0, eyear, emon, emday,
                                  0, 0, skip_interval, other))
            return

        res = re.search(
            '(\d{4})-(\d{2})-(\d{2}) - (\d{4})-(\d{2})-(\d{2})[\s\t]*([0-9:, -]+)',
            entry)
        if res is not None:
            #print "Good catch 3"
            (syear, smon, smday, eyear, emon, emday, other) = res.groups()
            dateranges.append(
                CalendarDaterange(syear, smon, smday, 0, 0, eyear, emon, emday,
                                  0, 0, 0, other))
            return

        res = re.search('(\d{4})-(\d{2})-(\d{2})[\s\t]*([0-9:, -]+)', entry)
        if res is not None:
            #print "Good catch 4"
            (syear, smon, smday, other) = res.groups()
            eyear = syear
            emon = smon
            emday = smday
            dateranges.append(
                CalendarDaterange(syear, smon, smday, 0, 0, eyear, emon, emday,
                                  0, 0, 0, other))
            return

        res = re.search(
            '([a-z]*) ([\d-]+) ([a-z]*) - ([a-z]*) ([\d-]+) ([a-z]*) / (\d+)[\s\t]*([0-9:, -]+)',
            entry)
        if res is not None:
            #print "Good catch 5"
            (swday, swday_offset, smon, ewday, ewday_offset, emon,
             skip_interval, other) = res.groups()
            dateranges.append(
                MonthWeekDayDaterange(0, smon, 0, swday, swday_offset, 0, emon,
                                      0, ewday, ewday_offset, skip_interval,
                                      other))
            return

        res = re.search(
            '([a-z]*) ([\d-]+) - ([a-z]*) ([\d-]+) / (\d+)[\s\t]*([0-9:, -]+)',
            entry)
        if res is not None:
            #print "Good catch 6"
            (t0, smday, t1, emday, skip_interval, other) = res.groups()
            if t0 in Daterange.weekdays and t1 in Daterange.weekdays:
                swday = t0
                ewday = t1
                swday_offset = smday
                ewday_offset = emday
                dateranges.append(
                    WeekDayDaterange(0, 0, 0, swday, swday_offset, 0, 0, 0,
                                     ewday, ewday_offset, skip_interval,
                                     other))
                return
            elif t0 in Daterange.months and t1 in Daterange.months:
                smon = t0
                emon = t1
                dateranges.append(
                    MonthDateDaterange(0, smon, smday, 0, 0, 0, emon, emday, 0,
                                       0, skip_interval, other))
                return
            elif t0 == 'day' and t1 == 'day':
                dateranges.append(
                    MonthDayDaterange(0, 0, smday, 0, 0, 0, 0, emday, 0, 0,
                                      skip_interval, other))
                return

        res = re.search(
            '([a-z]*) ([\d-]+) - ([\d-]+) / (\d+)[\s\t]*([0-9:, -]+)', entry)
        if res is not None:
            #print "Good catch 7"
            (t0, smday, emday, skip_interval, other) = res.groups()
            if t0 in Daterange.weekdays:
                swday = t0
                swday_offset = smday
                ewday = swday
                ewday_offset = emday
                dateranges.append(
                    WeekDayDaterange(0, 0, 0, swday, swday_offset, 0, 0, 0,
                                     ewday, ewday_offset, skip_interval,
                                     other))
                return
            elif t0 in Daterange.months:
                smon = t0
                emon = smon
                dateranges.append(
                    MonthDateDaterange(0, smon, smday, 0, 0, 0, emon, emday, 0,
                                       0, skip_interval, other))
                return
            elif t0 == 'day':
                dateranges.append(
                    MonthDayDaterange(0, 0, smday, 0, 0, 0, 0, emday, 0, 0,
                                      skip_interval, other))
                return

        res = re.search(
            '([a-z]*) ([\d-]+) ([a-z]*) - ([a-z]*) ([\d-]+) ([a-z]*) [\s\t]*([0-9:, -]+)',
            entry)
        if res is not None:
            #print "Good catch 8"
            (swday, swday_offset, smon, ewday, ewday_offset, emon,
             other) = res.groups()
            #print "Debug:", (swday, swday_offset, smon, ewday, ewday_offset, emon, other)
            dateranges.append(
                MonthWeekDayDaterange(0, smon, 0, swday, swday_offset, 0, emon,
                                      0, ewday, ewday_offset, 0, other))
            return

        res = re.search('([a-z]*) ([\d-]+) - ([\d-]+)[\s\t]*([0-9:, -]+)',
                        entry)
        if res is not None:
            #print "Good catch 9"
            (t0, smday, emday, other) = res.groups()
            if t0 in Daterange.weekdays:
                swday = t0
                swday_offset = smday
                ewday = swday
                ewday_offset = emday
                dateranges.append(
                    WeekDayDaterange(0, 0, 0, swday, swday_offset, 0, 0, 0,
                                     ewday, ewday_offset, 0, other))
                return
            elif t0 in Daterange.months:
                smon = t0
                emon = smon
                dateranges.append(
                    MonthDateDaterange(0, smon, smday, 0, 0, 0, emon, emday, 0,
                                       0, 0, other))
                return
            elif t0 == 'day':
                dateranges.append(
                    MonthDayDaterange(0, 0, smday, 0, 0, 0, 0, emday, 0, 0, 0,
                                      other))
                return

        res = re.search(
            '([a-z]*) ([\d-]+) - ([a-z]*) ([\d-]+)[\s\t]*([0-9:, -]+)', entry)
        if res is not None:
            #print "Good catch 10"
            (t0, smday, t1, emday, other) = res.groups()
            if t0 in Daterange.weekdays and t1 in Daterange.weekdays:
                swday = t0
                ewday = t1
                swday_offset = smday
                ewday_offset = emday
                dateranges.append(
                    WeekDayDaterange(0, 0, 0, swday, swday_offset, 0, 0, 0,
                                     ewday, ewday_offset, 0, other))
                return
            elif t0 in Daterange.months and t1 in Daterange.months:
                smon = t0
                emon = t1
                dateranges.append(
                    MonthDateDaterange(0, smon, smday, 0, 0, 0, emon, emday, 0,
                                       0, 0, other))
                return
            elif t0 == 'day' and t1 == 'day':
                dateranges.append(
                    MonthDayDaterange(0, 0, smday, 0, 0, 0, 0, emday, 0, 0, 0,
                                      other))
                return

        res = re.search('([a-z]*) ([\d-]+) ([a-z]*)[\s\t]*([0-9:, -]+)', entry)
        if res is not None:
            #print "Good catch 11"
            (t0, swday_offset, t1, other) = res.groups()
            if t0 in Daterange.weekdays and t1 in Daterange.months:
                swday = t0
                smon = t1
                emon = smon
                ewday = swday
                ewday_offset = swday_offset
                dateranges.append(
                    MonthWeekDayDaterange(0, smon, 0, swday, swday_offset, 0,
                                          emon, 0, ewday, ewday_offset, 0,
                                          other))
                return

        res = re.search('([a-z]*) ([\d-]+)[\s\t]+([0-9:, -]+)', entry)
        if res is not None:
            #print "Good catch 12"
            (t0, smday, other) = res.groups()
            if t0 in Daterange.weekdays:
                swday = t0
                swday_offset = smday
                ewday = swday
                ewday_offset = swday_offset
                dateranges.append(
                    WeekDayDaterange(0, 0, 0, swday, swday_offset, 0, 0, 0,
                                     ewday, ewday_offset, 0, other))
                return
            if t0 in Daterange.months:
                smon = t0
                emon = smon
                emday = smday
                dateranges.append(
                    MonthDateDaterange(0, smon, smday, 0, 0, 0, emon, emday, 0,
                                       0, 0, other))
                return
            if t0 == 'day':
                emday = smday
                dateranges.append(
                    MonthDayDaterange(0, 0, smday, 0, 0, 0, 0, emday, 0, 0, 0,
                                      other))
                return

        res = re.search('([a-z]*)[\s\t]+([0-9:, -]+)', entry)
        if res is not None:
            #print "Good catch 13"
            (t0, other) = res.groups()
            if t0 in Daterange.weekdays:
                day = t0
                dateranges.append(StandardDaterange(day, other))
                return
        logger.info("[timeentry::%s] no match for %s" %
                    (self.get_name(), entry))
        self.invalid_entries.append(entry)

    def apply_inheritance(self):
        pass

    # create daterange from unresolved param
    def explode(self, timeperiods):
        for entry in self.unresolved:
            #print "Revolving entry", entry
            self.resolve_daterange(self.dateranges, entry)
        self.unresolved = []

    # Will make tp in exclude with id of the timeperiods
    def linkify(self, timeperiods):
        new_exclude = []
        if self.has('exclude') and self.exclude != '':
            logger.debug("[timeentry::%s] have excluded %s" %
                         (self.get_name(), self.exclude))
            excluded_tps = self.exclude.split(',')
            #print "I will exclude from:", excluded_tps
            for tp_name in excluded_tps:
                tp = timeperiods.find_by_name(tp_name.strip())
                if tp is not None:
                    new_exclude.append(tp)
                else:
                    logger.error("[timeentry::%s] unknown %s timeperiod" %
                                 (self.get_name(), tp_name))
        self.exclude = new_exclude

    def check_exclude_rec(self):
        if self.rec_tag:
            logger.error("[timeentry::%s] is in a loop in exclude parameter" %
                         self.get_name())
            return False
        self.rec_tag = True
        for tp in self.exclude:
            tp.check_exclude_rec()
        return True

    def fill_data_brok_from(self, data, brok_type):
        cls = self.__class__
        # Now config properties
        for prop, entry in cls.properties.items():
            # Is this property intended for broking?
            #if 'fill_brok' in entry:
            if brok_type in entry.fill_brok:
                if hasattr(self, prop):
                    data[prop] = getattr(self, prop)
                elif entry.has_default:
                    data[prop] = entry.default

    # Get a brok with initial status
    def get_initial_status_brok(self):
        cls = self.__class__
        my_type = cls.my_type
        data = {'id': self.id}

        self.fill_data_brok_from(data, 'full_status')
        b = Brok('initial_' + my_type + '_status', data)
        return b
Example #26
0
class Check(Action):
    """ ODO: Add some comment about this class for the doc"""
    # AutoSlots create the __slots__ with properties and
    # running_properties names

    ###FIXME : reenable AutoSlots if possible
    #__metaclass__ = AutoSlots

    my_type = 'check'

    properties = {
        'is_a':         StringProp(default='check'),
        'type':         StringProp(default=''),
        '_in_timeout':  BoolProp(default=False),
        'status':       StringProp(default=''),
        'exit_status':  IntegerProp(default=3),
        'state':        IntegerProp(default=0),
        'output':       StringProp(default=''),
        'long_output':  StringProp(default=''),
        'ref':          IntegerProp(default=-1),
        't_to_go':      IntegerProp(default=0),
        'depend_on':    StringProp(default=[]),
        'dep_check':    StringProp(default=[]),
        'check_time':   IntegerProp(default=0),
        'execution_time': FloatProp(default=0.0),
        'u_time':       FloatProp(default=0.0),
        's_time':       FloatProp(default=0.0),
        'perf_data':    StringProp(default=''),
        'check_type':   IntegerProp(default=0),
        'poller_tag':   StringProp(default='None'),
        'reactionner_tag':   StringProp(default='None'),
        'env':          StringProp(default={}),
        'internal':     BoolProp(default=False),
        'module_type':  StringProp(default='fork'),
        'worker':       StringProp(default='none'),
        'from_trigger': BoolProp(default=False),
    }

    def __init__(self, status, command, ref, t_to_go, dep_check=None, id=None,
                 timeout=10, poller_tag='None', reactionner_tag='None',
                 env={}, module_type='fork', from_trigger=False, dependency_check=False):

        self.is_a = 'check'
        self.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.output = ''
        self.long_output = ''
        self.ref = ref
        #self.ref_type = ref_type
        self.t_to_go = t_to_go
        self.depend_on = []
        if dep_check is None:
            self.depend_on_me = []
        else:
            self.depend_on_me = [dep_check]
        self.check_time = 0
        self.execution_time = 0
        self.u_time = 0  # user executon time
        self.s_time = 0  # system execution time
        self.perf_data = ''
        self.check_type = 0  # which kind of check result? 0=active 1=passive
        self.poller_tag = poller_tag
        self.reactionner_tag = reactionner_tag
        self.module_type = module_type
        self.env = env
        # we keep the reference of the poller that will take us
        self.worker = 'none'
        # If it's a business rule, manage it as a special check
        if ref and ref.got_business_rule or command.startswith('_internal'):
            self.internal = True
        else:
            self.internal = False
        self.from_trigger = from_trigger
        self.dependency_check = dependency_check


    def copy_shell(self):
        """return a copy of the check but just what is important for execution
        So we remove the ref and all
        """

        # We create a dummy check with nothing in it, just defaults values
        return self.copy_shell__(Check('', '', '', '', '', id=self.id))

    def get_return_from(self, c):
        self.exit_status = c.exit_status
        self.output = c.output
        self.long_output = c.long_output
        self.check_time = c.check_time
        self.execution_time = c.execution_time
        self.perf_data = c.perf_data
        self.u_time = c.u_time
        self.s_time = c.s_time


    def is_launchable(self, t):
        return t > self.t_to_go

    def __str__(self):
        return "Check %d status:%s command:%s ref:%s" % \
               (self.id, self.status, self.command, self.ref)

    def get_id(self):
        return self.id

    def set_type_active(self):
        self.check_type = 0

    def set_type_passive(self):
        self.check_type = 1

    def is_dependent(self):
        return self.dependency_check
Example #27
0
class CommandCall(DummyCommandCall):
    """This class is use when a service, contact or host define
    a command with args.
    """
    # AutoSlots create the __slots__ with properties and
    # running_properties names
    __metaclass__ = AutoSlots

    #__slots__ = ('id', 'call', 'command', 'valid', 'args', 'poller_tag',
    #             'reactionner_tag', 'module_type', '__dict__')
    id = 0
    my_type = 'CommandCall'

    properties = {
        'call':            StringProp(),
        'command':         StringProp(),
        'poller_tag':      StringProp(default='None'),
        'reactionner_tag': StringProp(default='None'),
        'module_type':     StringProp(default='fork'),
        'valid':           BoolProp(default=False),
        'args':            StringProp(default=[]),
        'timeout':         IntegerProp(default='-1'),
        'late_relink_done':BoolProp(default=False),
    }

    def __init__(self, commands, call, poller_tag='None',
                 reactionner_tag='None'):
        self.id = self.__class__.id
        self.__class__.id += 1
        self.call = call
        self.timeout = -1
        # Now split by ! and get command and args
        self.get_command_and_args()
        self.command = commands.find_by_name(self.command.strip())
        self.late_relink_done = False  # To do not relink again and again the same commandcall
        if self.command is not None:
            self.valid = True
        else:
            self.valid = False
        if self.valid:
            # If the host/service do not give an override poller_tag, take
            # the one of the command
            self.poller_tag = poller_tag  # from host/service
            self.reactionner_tag = reactionner_tag
            self.module_type = self.command.module_type
            self.timeout = int(self.command.timeout)
            if self.valid and poller_tag is 'None':
                # from command if not set
                self.poller_tag = self.command.poller_tag
            # Same for reactionner tag
            if self.valid and reactionner_tag is 'None':
                # from command if not set
                self.reactionner_tag = self.command.reactionner_tag

    def get_command_and_args(self):
        """We want to get the command and the args with ! splitting.
        but don't forget to protect against the \! to do not split them
        """

        # First protect
        p_call = self.call.replace('\!', '___PROTECT_EXCLAMATION___')
        tab = p_call.split('!')
        self.command = tab[0]
        # Reverse the protection
        self.args = [s.replace('___PROTECT_EXCLAMATION___', '!')
                     for s in tab[1:]]

    # If we didn't already lately relink us, do it
    def late_linkify_with_command(self, commands):
        if self.late_relink_done:
            return
        self.late_relink_done = True
        c = commands.find_by_name(self.command)
        self.command = c

    def is_valid(self):
        return self.valid

    def __str__(self):
        return str(self.__dict__)

    def get_name(self):
        return self.call

    def __getstate__(self):
        """Call by pickle to dataify the comment
        because we DO NOT WANT REF in this pickleisation!
        """
        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)

        # The command is a bit special, we just put it's name
        # or a '' if need
        if self.command and not isinstance(self.command, basestring):
            res['command'] = self.command.get_name()
        # Maybe it's a repickle of a unpickle thing... (like with deepcopy). If so
        # only take the value
        elif self.command and isinstance(self.command, basestring):
            res['command'] = self.command
        else:
            res['command'] = ''

        return res

    def __setstate__(self, state):
        """Inverted function of getstate"""
        cls = self.__class__
        # We move during 1.0 to a dict state
        # but retention file from 0.8 was tuple
        if isinstance(state, tuple):
            self.__setstate_pre_1_0__(state)
            return

        self.id = state['id']
        for prop in cls.properties:
            if prop in state:
                setattr(self, prop, state[prop])

    def __setstate_pre_1_0__(self, state):
        """In 1.0 we move to a dict save. Before, it was
        a tuple save, like
        ({'id': 11}, {'poller_tag': 'None', 'reactionner_tag': 'None',
        'command_line': u'/usr/local/nagios/bin/rss-multiuser',
        'module_type': 'fork', 'command_name': u'notify-by-rss'})
        """
        for d in state:
            for k, v in d.items():
                setattr(self, k, v)
Example #28
0
class Command(Item):
    # AutoSlots create the __slots__ with properties and
    # running_properties names
    __metaclass__ = AutoSlots

    id = 0
    my_type = "command"

    properties = Item.properties.copy()
    properties.update({
        'command_name': StringProp(fill_brok=['full_status']),
        'command_line': StringProp(fill_brok=['full_status']),
        'poller_tag': StringProp(default='None'),
        'reactionner_tag': StringProp(default='None'),
        'module_type': StringProp(default=None),
        'timeout': IntegerProp(default=-1),
        'enable_environment_macros': BoolProp(default=False),
    })

    def __init__(self, params={}):
        setattr(self, 'id', self.__class__.id)
        #self.id = self.__class__.id
        self.__class__.id += 1

        self.init_running_properties()

        self.customs = {}

        for key in params:
            # delistify attributes if there is only one value
            params[key] = self.compact_unique_attr_value(params[key])
            # Manage customs values
            if key.startswith('_'):
                self.customs[key.upper()] = params[key]
            else:
                setattr(self, key, params[key])

        if not hasattr(self, 'timeout'):
            self.timeout = '-1'

        if not hasattr(self, 'poller_tag'):
            self.poller_tag = 'None'
        if not hasattr(self, 'enable_environment_macros'):
            self.enable_environment_macros = 0
        if not hasattr(self, 'reactionner_tag'):
            self.reactionner_tag = 'None'
        if not hasattr(self, 'module_type'):
            # If the command start with a _, set the module_type
            # as the name of the command, without the _
            if getattr(self, 'command_line', '').startswith('_'):
                module_type = getattr(self, 'command_line', '').split(' ')[0]
                # and we remove the first _
                self.module_type = module_type[1:]
            # If no command starting with _, be fork :)
            else:
                self.module_type = 'fork'

    def get_name(self):
        return self.command_name

    def __str__(self):
        return str(self.__dict__)

    # Get a brok with initial status
    def get_initial_status_brok(self):
        cls = self.__class__
        my_type = cls.my_type
        data = {'id': self.id}

        self.fill_data_brok_from(data, 'full_status')
        b = Brok('initial_' + my_type + '_status', data)
        return b

    def fill_data_brok_from(self, data, brok_type):
        cls = self.__class__
        # Now config properties
        for prop, entry in cls.properties.items():
            # Is this property intended for broking?
            #if 'fill_brok' in entry[prop]:
            if brok_type in entry.fill_brok:
                if hasattr(self, prop):
                    data[prop] = getattr(self, prop)
                #elif 'default' in entry[prop]:
                #    data[prop] = entry.default

    # Call by pickle to dataify the comment
    # because we DO NOT WANT REF in this pickleisation!
    def __getstate__(self):
        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

    # Inversed function of getstate
    def __setstate__(self, state):
        cls = self.__class__
        # We move during 1.0 to a dict state
        # but retention file from 0.8 was tuple
        if isinstance(state, tuple):
            self.__setstate_pre_1_0__(state)
            return
        self.id = state['id']
        for prop in cls.properties:
            if prop in state:
                setattr(self, prop, state[prop])

    # In 1.0 we move to a dict save. Before, it was
    # a tuple save, like
    # ({'id': 11}, {'poller_tag': 'None', 'reactionner_tag': 'None',
    # 'command_line': u'/usr/local/nagios/bin/rss-multiuser',
    # 'module_type': 'fork', 'command_name': u'notify-by-rss'})
    def __setstate_pre_1_0__(self, state):
        for d in state:
            for k, v in d.items():
                setattr(self, k, v)
Example #29
0
class Downtime:
    id = 1

    # Just to list the properties we will send as pickle
    # so to others daemons, so all but NOT REF
    properties = {
        'activate_me':        StringProp(default=[]),
        'entry_time':         IntegerProp(default=0, fill_brok=['full_status']),
        'fixed':              BoolProp(default=True, fill_brok=['full_status']),
        'start_time':         IntegerProp(default=0, fill_brok=['full_status']),
        'duration':           IntegerProp(default=0, fill_brok=['full_status']),
        'trigger_id':         IntegerProp(default=0),
        'end_time':           IntegerProp(default=0, fill_brok=['full_status']),
        'real_end_time':      IntegerProp(default=0),
        'author':             StringProp(default='', fill_brok=['full_status']),
        'comment':            StringProp(default=''),
        'is_in_effect':       BoolProp(default=False),
        'has_been_triggered': BoolProp(default=False),
        'can_be_deleted':     BoolProp(default=False),

        # TODO: find a very good way to handle the downtime "ref".
        # ref must effectively not be in properties because it points
        # onto a real object.
        # 'ref': None
    }


    def __init__(self, ref, start_time, end_time, fixed, trigger_id, duration, author, comment):
        now = datetime.datetime.now()
        self.id = int(time.mktime(now.timetuple()) * 1e6 + now.microsecond)
        self.__class__.id = self.id + 1
        self.ref = ref  # pointer to srv or host we are apply
        self.activate_me = []  # The other downtimes i need to activate
        self.entry_time = int(time.time())
        self.fixed = fixed
        self.start_time = start_time
        self.duration = duration
        self.trigger_id = trigger_id
        if self.trigger_id != 0:  # triggered plus fixed makes no sense
            self.fixed = False
        self.end_time = end_time
        if fixed:
            self.duration = end_time - start_time
        # This is important for flexible downtimes. Here start_time and
        # end_time mean: in this time interval it is possible to trigger
        # the beginning of the downtime which lasts for duration.
        # Later, when a non-ok event happens, real_end_time will be
        # recalculated from now+duration
        # end_time will be displayed in the web interface, but real_end_time
        # is used internally
        self.real_end_time = end_time
        self.author = author
        self.comment = comment
        self.is_in_effect = False
        # fixed: start_time has been reached,
        # flexible: non-ok checkresult

        self.has_been_triggered = False  # another downtime has triggered me
        self.can_be_deleted = False
        self.add_automatic_comment()


    def __str__(self):
        if self.is_in_effect is True:
            active = "active"
        else:
            active = "inactive"
        if self.fixed is True:
            type = "fixed"
        else:
            type = "flexible"
        return "%s %s Downtime id=%d %s - %s" % (
            active, type, self.id, time.ctime(self.start_time), time.ctime(self.end_time))


    def trigger_me(self, other_downtime):
        self.activate_me.append(other_downtime)


    def in_scheduled_downtime(self):
        return self.is_in_effect


    # The referenced host/service object enters now a (or another) scheduled
    # downtime. Write a log message only if it was not already in a downtime
    def enter(self):
        res = []
        self.is_in_effect = True
        if self.fixed is False:
            now = time.time()
            self.real_end_time = now + self.duration
        if self.ref.scheduled_downtime_depth == 0:
            self.ref.raise_enter_downtime_log_entry()
            self.ref.create_notifications('DOWNTIMESTART')
        self.ref.scheduled_downtime_depth += 1
        self.ref.in_scheduled_downtime = True
        for dt in self.activate_me:
            res.extend(dt.enter())
        return res


    # The end of the downtime was reached.
    def exit(self):
        res = []
        if self.is_in_effect is True:
            # This was a fixed or a flexible+triggered downtime
            self.is_in_effect = False
            self.ref.scheduled_downtime_depth -= 1
            if self.ref.scheduled_downtime_depth <= 0:
                self.ref.raise_exit_downtime_log_entry()
                self.ref.create_notifications('DOWNTIMEEND')
                self.ref.in_scheduled_downtime = False
        else:
            # This was probably a flexible downtime which was not triggered
            # In this case it silently disappears
            pass
        self.del_automatic_comment()
        self.can_be_deleted = True
        # when a downtime ends and the service was critical
        # a notification is sent with the next critical check
        # So we should set a flag here which signals consume_result
        # to send a notification
        self.ref.in_scheduled_downtime_during_last_check = True
        return res


    # A scheduled downtime was prematurely canceled
    def cancel(self):
        res = []
        self.is_in_effect = False
        self.ref.scheduled_downtime_depth -= 1
        if self.ref.scheduled_downtime_depth == 0:
            self.ref.raise_cancel_downtime_log_entry()
            self.ref.in_scheduled_downtime = False
        self.del_automatic_comment()
        self.can_be_deleted = True
        self.ref.in_scheduled_downtime_during_last_check = True
        # Nagios does not notify on canceled downtimes, but we does
        self.ref.create_notifications('DOWNTIMECANCELLED')
        # Also cancel other downtimes triggered by me
        for dt in self.activate_me:
            res.extend(dt.cancel())
        return res


    # Scheduling a downtime creates a comment automatically
    def add_automatic_comment(self):
        if self.fixed is True:
            text = (
                "This %s has been scheduled for fixed downtime from %s to %s. "
                "Notifications for the %s will not be sent out during that time period." % (
                    self.ref.my_type,
                    time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.start_time)),
                    time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.end_time)),
                    self.ref.my_type)
            )
        else:
            hours, remainder = divmod(self.duration, 3600)
            minutes, seconds = divmod(remainder, 60)
            text = ("This %s has been scheduled for flexible downtime starting between %s and %s "
                    "and lasting for a period of %d hours and %d minutes. "
                    "Notifications for the %s will not be sent out during that time period." % (
                        self.ref.my_type,
                        time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.start_time)),
                        time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.end_time)),
                        hours, minutes, self.ref.my_type)
                    )
        if self.ref.my_type == 'host':
            comment_type = 1
        else:
            comment_type = 2
        c = Comment(self.ref, False, "(Nagios Process)", text, comment_type, 2, 0, False, 0)
        self.comment_id = c.id
        self.extra_comment = c
        self.ref.add_comment(c)


    def del_automatic_comment(self):
        # Extra comment can be None if we load it from a old version of Shinken
        # TODO: remove it in a future version when every one got upgrade
        if self.extra_comment is not None:
            self.extra_comment.can_be_deleted = True
            # self.ref.del_comment(self.comment_id)


    # Fill data with info of item by looking at brok_type
    # in props of properties or running_properties
    def fill_data_brok_from(self, data, brok_type):
        cls = self.__class__
        # Now config properties
        for prop, entry in cls.properties.items():
            if hasattr(prop, 'fill_brok'):
                if brok_type in entry['fill_brok']:
                    data[prop] = getattr(self, prop)


    # Get a brok with initial status
    def get_initial_status_brok(self):
        data = {'id': self.id}

        self.fill_data_brok_from(data, 'full_status')
        b = Brok('downtime_raise', data)
        return b


    # Call by pickle for dataify the downtime
    # because we DO NOT WANT REF in this pickleisation!
    def __getstate__(self):
        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


    # Inverted function of getstate
    def __setstate__(self, state):
        cls = self.__class__

        self.id = state['id']
        for prop in cls.properties:
            if prop in state:
                setattr(self, prop, state[prop])

        if self.id >= cls.id:
            cls.id = self.id + 1
Example #30
0
class SatelliteLink(Item):
    #id = 0 each Class will have it's own id

    properties = {
        'address':
        StringProp(fill_brok=['full_status']),
        'timeout':
        IntegerProp(default='3', fill_brok=['full_status']),
        'data_timeout':
        IntegerProp(default='120', fill_brok=['full_status']),
        'check_interval':
        IntegerProp(default='60', fill_brok=['full_status']),
        'max_check_attempts':
        IntegerProp(default='3', fill_brok=['full_status']),
        'spare':
        BoolProp(default='0', fill_brok=['full_status']),
        'manage_sub_realms':
        BoolProp(default='1', fill_brok=['full_status']),
        'manage_arbiters':
        BoolProp(default='0', fill_brok=['full_status'], to_send=True),
        'modules':
        ListProp(default='', to_send=True),
        'polling_interval':
        IntegerProp(default='1', fill_brok=['full_status'], to_send=True),
        'use_timezone':
        StringProp(default='NOTSET', to_send=True),
        'realm':
        StringProp(default=''),
    }

    running_properties = {
        'con': StringProp(default=None),
        'alive': StringProp(default=True, fill_brok=['full_status']),
        'broks': StringProp(default=[]),
        'attempt':
        StringProp(default=0,
                   fill_brok=['full_status']),  # the number of failed attempt
        'reachable': StringProp(default=False, fill_brok=[
            'full_status'
        ]),  # can be network ask or not (dead or check in timeout or error)
        'configuration_errors': StringProp(default=[]),
        'last_check': IntegerProp(default=0, fill_brok=['full_status']),
    }

    macros = {}

    #Clean? Really?
    def clean(self):
        pass

    #Check is required prop are set:
    #contacts OR contactgroups is need
    def is_correct(self):
        state = True  #guilty or not? :)
        cls = self.__class__

        special_properties = ['realm']
        for prop, entry in cls.properties.items():
            if prop not in special_properties:
                if not hasattr(self, prop) and entry['required']:
                    print self.get_name(), " : I do not have", prop
                    state = False  #Bad boy...
        # Ok now we manage special cases...
        if getattr(self, 'realm', None) is None:
            print self.get_name(), " : I do not have a valid realm"
            state = False
        return state

    def create_connexion(self):
        self.uri = pyro.create_uri(self.address, self.port, "ForArbiter",
                                   self.__class__.use_ssl)
        self.con = pyro.getProxy(self.uri)
        pyro.set_timeout(self.con, self.timeout)

    def put_conf(self, conf):

        if self.con is None:
            self.create_connexion()
        #print "Connexion is OK, now we put conf", conf
        #print "Try to put conf:", conf

        try:
            pyro.set_timeout(self.con, self.data_timeout)
            print "DBG: put conf to", self.con.__dict__
            self.con.put_conf(conf)
            pyro.set_timeout(self.con, self.timeout)
            return True
        except Pyro_exp_pack, exp:
            self.con = None
            #print ''.join(Pyro.util.getPyroTraceback(exp))
            return False