예제 #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', '')
예제 #2
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
예제 #3
0
class Resultmodulation(Item):
    id = 1#0 is always special in database, so we do not take risk here
    my_type = 'resultmodulation'

    properties = {
        'resultmodulation_name': StringProp(),
        'exit_codes_match':      ListProp  (default=''),
        'exit_code_modulation':  StringProp(default=None),
        'modulation_period':     StringProp(default=None),
    }
    
    running_properties = {
        'configuration_errors': ListProp(default=[]),
        }
    macros = {}


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


    def clean(self):
        pass


    #Make the return code modulation if need
    def module_return(self, return_code):
        #Only if in modulation_period of modulation_period == None
        if self.modulation_period is None or self.modulation_period.is_time_valid(time.time()):
            #Try to change the exit code only if a new one is defined
            if self.exit_code_modulation is not None:
                #First with the exit_code_match
                if return_code in self.exit_codes_match:
                    return_code = self.exit_code_modulation

        return return_code


    #We override the pythonize because we have special cases that we do not want
    #to be do at running
    def pythonize(self):
        #First apply Item pythonize
        super(self.__class__, self).pythonize()

        #Then very special cases
        # Intify the exit_codes_match, and make list
        self.exit_codes_match = [ int(ec) for ec in getattr(self, 'exit_codes_match', []) ]

        if hasattr(self, 'exit_code_modulation'):
            self.exit_code_modulation = int(self.exit_code_modulation)
        else:
            self.exit_code_modulation = None
예제 #4
0
파일: pollerlink.py 프로젝트: zxahu/shinken
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)
예제 #5
0
class ReactionnerLink(SatelliteLink):
    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)
예제 #6
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']),
        '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)
예제 #7
0
class Serviceescalation(Item):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'serviceescalation'

    properties = Item.properties.copy()
    properties.update({
        'host_name':
        StringProp(),
        'hostgroup_name':
        StringProp(),
        'service_description':
        StringProp(),
        'first_notification':
        IntegerProp(),
        'last_notification':
        IntegerProp(),
        'notification_interval':
        IntegerProp(default=30),  # like Nagios value
        'escalation_period':
        StringProp(default=''),
        'escalation_options':
        ListProp(default=['d', 'u', 'r', 'w', 'c'], split_on_coma=True),
        'contacts':
        StringProp(),
        'contact_groups':
        StringProp(),
        'first_notification_time':
        IntegerProp(),
        'last_notification_time':
        IntegerProp(),
    })

    # For debugging purpose only (nice name)
    def get_name(self):
        return ''
예제 #8
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
예제 #9
0
class Module(Item):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'module'

    properties = Item.properties.copy()
    properties.update({
        'module_name': StringProp(),
        'module_type': StringProp(),
        'modules': ListProp(default=''),
    })

    macros = {}

    # For debugging purpose only (nice name)
    def get_name(self):
        return self.module_name
예제 #10
0
class Discoveryrun(Item):
    id = 1  #0 is always special in database, so we do not take risk here
    my_type = 'discoveryrun'

    properties = {
        'discoveryrun_name': StringProp(),
        'discoveryrun_command': StringProp(),
    }

    running_properties = {
        'current_launch': StringProp(default=None),
        'configuration_errors': ListProp(default=[]),
    }

    macros = {}

    # Output name
    def get_name(self):
        return self.discoveryrun_name

    # Get an eventhandler object and launch it
    def launch(self):
        m = MacroResolver()
        data = []
        cmd = m.resolve_command(self.discoveryrun_command, data)
        self.current_launch = EventHandler(cmd, timeout=300)
        self.current_launch.execute()

    def check_finished(self):
        max_output = 10**9
        #print "Max output", max_output
        self.current_launch.check_finished(max_output)

    # Look if the current launch is done or not
    def is_finished(self):
        if self.current_launch == None:
            return True
        if self.current_launch.status in ('done', 'timeout'):
            return True
        return False

    # we use an EventHandler object, so we have output with a single line
    # and longoutput with the rest. We just need to return all
    def get_output(self):
        return '\n'.join(
            [self.current_launch.output, self.current_launch.long_output])
예제 #11
0
파일: module.py 프로젝트: bdunbar/shinken
class Module(Item):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'module'

    properties = Item.properties.copy()
    properties.update({
        'module_name': StringProp(),
        'module_type': StringProp(),
        'modules': ListProp(default=[''], split_on_coma=True),
    })

    macros = {}

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

    def __repr__(self):
        return '<module name=%s />' % self.get_name()
예제 #12
0
class Hostescalation(Item):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'hostescalation'

    properties = Item.properties.copy()
    properties.update({
        'host_name':             StringProp(),
        'hostgroup_name':        StringProp(),
        'first_notification':    IntegerProp(),
        'last_notification':     IntegerProp(),
        'notification_interval': IntegerProp(default='30'), # like Nagios value
        'escalation_period':     StringProp(default=''),
        'escalation_options':    ListProp(default='d,u,r,w,c'),
        'contacts':              StringProp(),
        'contact_groups':        StringProp(),
    })

    # For debugging purpose only (nice name)
    def get_name(self):
        return ''
예제 #13
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']),
        '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),
        'max_q_size':
        IntegerProp(default=0, fill_brok=['full_status'], to_send=True),
        'q_factor':
        IntegerProp(default=0, fill_brok=['full_status'], to_send=True),
        'results_batch':
        IntegerProp(default=0, fill_brok=['full_status'], to_send=True),
        'poller_tags':
        ListProp(default=['None'], to_send=True),
        'harakiri_threshold':
        StringProp(default=None, fill_brok=['full_status'], to_send=True),
    })

    def get_name(self):
        return getattr(self, 'poller_name', 'UNNAMED-POLLER')

    def register_to_my_realm(self):
        self.realm.pollers.append(self)
예제 #14
0
class Hostescalation(Item):
    id = 1  #0 is always special in database, so we do not take risk here
    my_type = 'hostescalation'

    properties = {
        'host_name': StringProp(),
        'hostgroup_name': StringProp(),
        'first_notification': IntegerProp(),
        'last_notification': IntegerProp(),
        'notification_interval': IntegerProp(),
        'escalation_period': StringProp(default=''),
        'escalation_options': ListProp(default='d,u,r,w,c'),
        'contacts': StringProp(),
        'contact_groups': StringProp(),
    }

    running_properties = {}

    macros = {}

    #For debugging purpose only (nice name)
    def get_name(self):
        return ''
예제 #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)
예제 #16
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':    ListProp(default=[], 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),
        # To be consistent with notificationway object attributes
        'host_notification_commands': ListProp(fill_brok=['full_status']),
        'service_notification_commands': ListProp(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=False, fill_brok=['full_status']),
        'is_admin':         BoolProp(default=False, fill_brok=['full_status']),
        'expert':           BoolProp(default=False, fill_brok=['full_status']),
        'retain_status_information': BoolProp(default=True, fill_brok=['full_status']),
        'notificationways': ListProp(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),
    })
예제 #17
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
예제 #18
0
class Discoveryrule(MatchingItem):
    id = 1  # zero is always special in database, so we do not take risk here
    my_type = 'discoveryrule'

    properties = Item.properties.copy()
    properties.update({
        'discoveryrule_name': StringProp(),
        'creation_type': StringProp(default='service'),
        'discoveryrule_order': IntegerProp(default='0'),
        ## 'check_command':         StringProp (),
        ## 'service_description':   StringProp (),
        ## 'use':                   StringProp(),
    })

    running_properties = {
        'configuration_errors': ListProp(default=[]),
    }

    macros = {}

    # The init of a discovery will set the property of
    # Discoveryrule.properties as in setattr, but all others
    # will be in a list because we need to have all names
    # and not lost all in __dict__
    def __init__(self, params={}):
        cls = self.__class__

        # We have our own id of My Class type :)
        # use set attr for going into the slots
        # instead of __dict__ :)
        setattr(self, 'id', cls.id)
        cls.id += 1

        self.matches = {}  # for matching rules
        self.not_matches = {}  # for rules that should NOT match
        self.writing_properties = {}

        for key in params:
            # delistify attributes if there is only one value
            params[key] = self.compact_unique_attr_value(params[key])

        # Get the properties of the Class we want
        if not 'creation_type' in params:
            params['creation_type'] = 'service'

        map = {'service': Service, 'host': Host}
        t = params['creation_type']
        if not t in map:
            return
        tcls = map[t]

        # In my own property:
        #  -> in __dict__
        # In the properties of the 'creation_type' Class:
        #  -> in self.writing_properties
        # if not, in matches or not match (if key starts
        # with a !, it's a not rule)
        # -> in self.matches or self.not_matches
        # in writing properties if start with + (means 'add this')
        # in writing properties if start with - (means 'del this')
        for key in params:
            # Some key are quite special
            if key in cls.properties:
                setattr(self, key, params[key])
            elif key in ['use'] or key.startswith('+') or key.startswith(
                    '-') or key in tcls.properties or key.startswith('_'):
                self.writing_properties[key] = params[key]
            else:
                if key.startswith('!'):
                    key = key.split('!')[1]
                    self.not_matches[key] = params['!' + key]
                else:
                    self.matches[key] = params[key]

        # Then running prop :)
        cls = self.__class__
        # adding running properties like latency, dependency list, etc
        for prop, entry in cls.running_properties.items():
            # Copy is slow, so we check type
            # Type with __iter__ are list or dict, or tuple.
            # Item need it's own list, so qe copy
            val = entry.default
            if hasattr(val, '__iter__'):
                setattr(self, prop, copy(val))
            else:
                setattr(self, prop, val)

            # each instance to have his own running prop!

    # Output name
    def get_name(self):
        try:
            return self.discoveryrule_name
        except AttributeError:
            return "UnnamedDiscoveryRule"
예제 #19
0
class Itemgroup(Item):

    id = 0

    properties = Item.properties.copy()
    properties.update({
        'members':
        ListProp(fill_brok=['full_status'], default=None, split_on_coma=True),
        # Shinken specific
        'unknown_members':
        ListProp(default=None),
    })

    def __init__(self, params={}):
        self.id = self.__class__.id
        self.__class__.id += 1
        cls = self.__class__
        self.init_running_properties()

        for key in params:

            if key in self.properties:
                val = self.properties[key].pythonize(params[key])
            elif key in self.running_properties:
                warning = "using a the running property %s in a config file" % key
                self.configuration_warnings.append(warning)
                val = self.running_properties[key].pythonize(params[key])
            else:
                warning = "Guessing the property %s type because it is not in %s object properties" % \
                          (key, cls.__name__)
                self.configuration_warnings.append(warning)
                val = ToGuessProp.pythonize(params[key])

            setattr(self, key, val)

    # Copy the groups properties EXCEPT the members
    # members need to be fill after manually
    def copy_shell(self):
        cls = self.__class__
        old_id = cls.id
        new_i = cls()  # create a new group
        new_i.id = self.id  # with the same id
        cls.id = old_id  # Reset the Class counter

        # Copy all properties
        for prop in cls.properties:
            if prop is not 'members':
                if self.has(prop):
                    val = getattr(self, prop)
                    setattr(new_i, prop, val)
        # but no members
        new_i.members = []
        return new_i

    def replace_members(self, members):
        self.members = members

    # If a prop is absent and is not required, put the default value
    def fill_default(self):
        cls = self.__class__
        for prop, entry in cls.properties.items():
            if not hasattr(self, prop) and not entry.required:
                value = entry.default
                setattr(self, prop, value)

    def add_string_member(self, member):
        add_fun = list.extend if isinstance(member, list) else list.append
        if not hasattr(self, "members"):
            self.members = []
        add_fun(self.members, member)

    def add_string_unknown_member(self, member):
        add_fun = list.extend if isinstance(member, list) else list.append
        if not self.unknown_members:
            self.unknown_members = []
        add_fun(self.unknown_members, member)

    def __str__(self):
        return str(self.__dict__) + '\n'

    def __iter__(self):
        return self.members.__iter__()

    def __delitem__(self, i):
        try:
            self.members.remove(i)
        except ValueError:
            pass

    # a item group is correct if all members actually exists,
    # so if unknown_members is still []
    def is_correct(self):
        res = True

        if self.unknown_members:
            for m in self.unknown_members:
                logger.error("[itemgroup::%s] as %s, got unknown member %s",
                             self.get_name(), self.__class__.my_type, m)
            res = False

        if self.configuration_errors != []:
            for err in self.configuration_errors:
                logger.error("[itemgroup] %s", err)
            res = False

        return res

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

    # Get a brok with hostgroup info (like id, name)
    # members is special: list of (id, host_name) for database info
    def get_initial_status_brok(self):
        cls = self.__class__
        data = {}
        # Now config properties
        for prop, entry in cls.properties.items():
            if entry.fill_brok != []:
                if self.has(prop):
                    data[prop] = getattr(self, prop)
        # Here members is just a bunch of host, I need name in place
        data['members'] = []
        for i in self.members:
            # it look like lisp! ((( ..))), sorry....
            data['members'].append((i.id, i.get_name()))
        b = Brok('initial_' + cls.my_type + '_status', data)
        return b
예제 #20
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)
예제 #21
0
class Item(object):

    properties = {
        'imported_from':            StringProp(default='unknown'),
        'use':                      ListProp(default=''),
        'name':                     StringProp(default=''),
        'definition_order':         IntegerProp(default='100'),
        # TODO: find why we can't uncomment this line below.
        #'register':                 BoolProp(default='1'),
    }

    running_properties = {
        # All errors and warning raised during the configuration parsing
        # and that will raised real warning/errors during the is_correct
        'configuration_warnings':   ListProp(default=[]),
        'configuration_errors':     ListProp(default=[]),
        'hash':   StringProp(default=''),
        # We save all template we asked us to load from
        'tags': ListProp(default=set(), fill_brok=['full_status']),
    }

    macros = {
    }

    def __init__(self, params={}):
        # We have our own id of My Class type :)
        # use set attr for going into the slots
        # instead of __dict__ :)
        cls = self.__class__
        self.id = cls.id
        cls.id += 1

        self.customs = {}  # for custom variables
        self.plus = {}  # for value with a +

        self.init_running_properties()

        # [0] = +  -> new key-plus
        # [0] = _  -> new custom entry in UPPER case
        for key in params:
            # delistify attributes if there is only one value
            params[key] = self.compact_unique_attr_value(params[key])
            # checks for attribute value special syntax (+ or _)
            if not isinstance(params[key], list) and \
               len(params[key]) >= 1 and params[key][0] == '+':
                # Special case: a _MACRO can be a plus. so add to plus
                # but upper the key for the macro name
                if key[0] == "_":
                    self.plus[key.upper()] = params[key][1:]  # we remove the +
                else:
                    self.plus[key] = params[key][1:]  # we remove the +
            elif key[0] == "_":
                if isinstance(params[key], list):
                    err = "no support for _ syntax in multiple valued attributes"
                    self.configuration_errors.append(err)
                    continue
                custom_name = key.upper()
                self.customs[custom_name] = params[key]
            else:
                setattr(self, key, params[key])


    # When values to set on attributes are unique (single element list),
    # return the value directly rather than setting list element.
    def compact_unique_attr_value(self, val):
        if isinstance(val, list):
            if len(val) > 1:
                return val
            elif len(val) == 0:
                return ''
            else:
                return val[0]
        else:
            return val

    def init_running_properties(self):
        for prop, entry in self.__class__.running_properties.items():
            # Copy is slow, so we check type
            # Type with __iter__ are list or dict, or tuple.
            # Item need it's own list, so we copy
            val = entry.default
            if hasattr(val, '__iter__'):
                setattr(self, prop, copy(val))
            else:
                setattr(self, prop, val)
            # each instance to have his own running prop!

    def copy(self):
        """ Return a copy of the item, but give him a new id """
        cls = self.__class__
        i = cls({})  # Dummy item but with it's own running properties
        for prop in cls.properties:
            if hasattr(self, prop):
                val = getattr(self, prop)
                setattr(i, prop, val)
        # Also copy the customs tab
        i.customs = copy(self.customs)
        return i

    def clean(self):
        """ Clean useless things not requested once item has been fully initialized&configured.
Like temporary attributes such as "imported_from", etc.. """
        for name in ('imported_from', 'use', 'plus', 'templates',):
            try:
                delattr(self, name)
            except AttributeError:
                pass

    def __str__(self):
        return str(self.__dict__) + '\n'

    def is_tpl(self):
        """ Return if the elements is a template """
        try:
            return self.register == '0'
        except Exception, exp:
            return False
예제 #22
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
예제 #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),
        '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
예제 #24
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
예제 #25
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
예제 #26
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
예제 #27
0
class Timeperiod(Item):
    id = 1
    my_type = 'timeperiod'

    properties = {
        'timeperiod_name':  StringProp (fill_brok=['full_status']),
        'alias':            StringProp (default='',fill_brok=['full_status']),
        'use':              StringProp (default=''),
        'exclude':          StringProp (default=''),
        'register':         IntegerProp(default='1'),
        #All errors and warning raised during the configuration parsing
        #and taht will raised real warning/errors during the is_correct
        'configuration_warnings': ListProp(default=[]),
        'configuration_errors': ListProp(default=[]),
        # 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=[]),
    }


    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']:
                setattr(self, key, params[key])
            else:
                self.unresolved.append(key+' '+params[key])

        self.cache = {} #For tunning purpose only
        self.configuration_errors = []
        self.configuration_warnings = []


    def get_name(self):
        return self.timeperiod_name


    def clean(self):
        pass


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



    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


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


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

        #print self.get_name(), "Check valid time for", 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

        local_min = None
        #Loop for all minutes...
        while still_loop:
            #print self.get_name(), '\nLoop'
            #Ok, not in cache...
            dr_mins = []
            for dr in self.dateranges:
                dr_mins.append(dr.get_next_valid_time_from_t(t))

            #print "TOTO", self.get_name(), 'Mins:', dr_mins
            #for o in dr_mins:
            #    print "F**K",time.asctime(time.localtime(o)), "\n"

            #Min but not the None valus...
            try:
                local_min = min([d for d in dr_mins if d is not None])
            except ValueError: #dr_mins if full of None, not good
                local_min = None

            #if local_min != None:
            #    print "Poposed?", local_min
            #    print "Proposed local min", time.asctime(time.localtime(local_min))


            #We do not loop unless the local_min is not valid
            still_loop = False

            #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(), "Check in TP"
                    if tp.is_time_valid(local_min):
                        still_loop = True
                        #t = local_min + 60
                        #print self.get_name(), "TP pas content:", tp.get_name(), time.asctime(time.localtime(local_min))
                        local_min = tp.get_next_invalid_time_from_t(local_min+60)
                        #if local_min != None:
                        #    print "Exclude TP proposed new local min", time.asctime(time.localtime(local_min))
                        #    print local_min
                            #print "Is it really a invalid date?", tp.is_time_valid(local_min), "if true F**K"
                        #print self.get_name(), "Apres content:", tp.get_name(), time.asctime(time.localtime(local_min))
                    #else:
                    #    print self.get_name(), "Tp ca lui va", tp.get_name()

            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

        #print "We got it!"
        #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 = int(t)
        original_t = t
        still_loop = True

        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))

#            #Ok, not in cache...
#            #print self.get_name(), "Begin loop with", time.asctime(time.localtime(local_min))
#            next_exclude = None
#            for dr in self.exclude:
#                m = dr.get_next_valid_time_from_t(local_min)
#                if m != None:
#                    #print time.asctime(time.localtime(m))
#                    if next_exclude == None or m <= next_exclude:
#                        next_exclude = m

#            #Maybe the min of exclude is not valid, it is the min we can find.
#            if next_exclude != None and not self.is_time_valid(next_exclude):
#                #print self.get_name(), "find a possible early exit for invalid ! with", time.asctime(time.localtime(next_exclude))
#                res = next_exclude
#                still_loop = False

            dr_mins = []
            #But maybe we can find a better solution with next invalid of standart 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 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)
                        #print "Add a m", time.asctime(time.localtime(m))
#                    else:
#                        print dr.__dict__
#                        print "F**K bad result\n\n\n"

            if dr_mins != []:
                local_min = min(dr_mins)
                #print "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', time.asctime(time.localtime(local_min))
            #We do not loop unless the local_min is not valid
            still_loop = False

            #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))
        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
            print "Error : The timeperiod %s got an 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 "Googd 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 "Googd 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 "Googd 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 "Googd 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 "Googd 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 "Googd 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 "Googd 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 "Googd 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 "Googd 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
        print "No match for", 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 != '':
            print "I have excluded"
            print 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:
                    print "Error : the timeperiod", tp_name, "is unknown!"
        self.exclude = new_exclude


    def check_exclude_rec(self):
        if self.rec_tag:
            print "Error :", self.get_name(), "is in a loop in exclude parameter"
            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 brokking?
#            if 'fill_brok' in entry:
            if brok_type in entry.fill_brok:
                if hasattr(self, prop):
                    data[prop] = getattr(self, prop)
                elif 'default' in entry:
                    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
예제 #28
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)))
예제 #29
0
class HostExtInfo(Item):
    # AutoSlots create the __slots__ with properties and
    # running_properties names
    __metaclass__ = AutoSlots

    id = 1  # zero is reserved for host (primary node for parents)
    my_type = 'hostextinfo'

    # properties defined by configuration
    # *required: is required in conf
    # *default: default value if no set in conf
    # *pythonize: function to call when transfort string to python object
    # *fill_brok: if set, send to broker. there are two categories: full_status for initial and update status, check_result for check results
    # *no_slots: do not take this property for __slots__
    #  Only for the inital call
    # conf_send_preparation: if set, will pass the property to this function. It's used to "flatten"
    #  some dangerous properties like realms that are too 'linked' to be send like that.
    # brok_transformation: if set, will call the function with the value of the property
    #  the major times it will be to flatten the data (like realm_name instead of the realm object).
    properties = Item.properties.copy()
    properties.update({
        'host_name':
        ListProp(brok_transformation=to_hostnames_list),
        'notes':
        StringProp(default=''),
        'notes_url':
        StringProp(default=''),
        'icon_image':
        StringProp(default=''),
        'icon_image_alt':
        StringProp(default=''),
        'vrml_image':
        StringProp(default=''),
        'statusmap_image':
        StringProp(default=''),

        # No slots for this 2 because begin property by a number seems bad
        # it's stupid!
        '2d_coords':
        StringProp(default='', no_slots=True),
        '3d_coords':
        StringProp(default='', no_slots=True),
    })

    # Hosts macros and prop that give the information
    # the prop can be callable or not
    macros = {
        'HOSTNAME': 'host_name',
        'HOSTNOTESURL': 'notes_url',
        'HOSTNOTES': 'notes',
    }

    #######
    #                   __ _                       _   _
    #                  / _(_)                     | | (_)
    #   ___ ___  _ __ | |_ _  __ _ _   _ _ __ __ _| |_ _  ___  _ __
    #  / __/ _ \| '_ \|  _| |/ _` | | | | '__/ _` | __| |/ _ \| '_ \
    # | (_| (_) | | | | | | | (_| | |_| | | | (_| | |_| | (_) | | | |
    #  \___\___/|_| |_|_| |_|\__, |\__,_|_|  \__,_|\__|_|\___/|_| |_|
    #                         __/ |
    #                        |___/
    ######

    # Check is required prop are set:
    # host_name is needed
    def is_correct(self):
        state = True
        cls = self.__class__

        return state

    # For get a nice name
    def get_name(self):
        if not self.is_tpl():
            try:
                return self.host_name
            except AttributeError:  # outch, no hostname
                return 'UNNAMEDHOST'
        else:
            try:
                return self.name
            except AttributeError:  # outch, no name for this template
                return 'UNNAMEDHOSTTEMPLATE'

    # For debugin purpose only
    def get_dbg_name(self):
        return self.host_name

    # Same but for clean call, no debug
    def get_full_name(self):
        return self.host_name
예제 #30
0
class Discoveryrule(Item):
    id = 1  #0 is always special in database, so we do not take risk here
    my_type = 'discoveryrule'

    properties = {
        'discoveryrule_name': StringProp(),
        'creation_type': StringProp(default='service'),
        #        'check_command':         StringProp (),
        #        'service_description':   StringProp (),
        #        'use':                   StringProp(),
    }

    running_properties = {
        'configuration_errors': ListProp(default=[]),
    }

    macros = {}

    # The init of a discovery will set the property of
    # Discoveryrule.properties as in setattr, but all others
    # will be in a list because we need to have all names
    # and not lost all in __dict__
    def __init__(self, params={}):
        cls = self.__class__

        # We have our own id of My Class type :)
        # use set attr for going into the slots
        # instead of __dict__ :)
        setattr(self, 'id', cls.id)
        cls.id += 1

        self.matches = {}  # for matching rules
        self.not_matches = {}  # for rules that should NOT match
        self.writing_properties = {}

        # Get teh properties of the Class we want
        if not 'creation_type' in params:
            params['creation_type'] = 'service'

        map = {'service': Service, 'host': Host}
        t = params['creation_type']
        if not t in map:
            return
        tcls = map[t]

        # In my own property :
        #  -> in __dict__
        # In the properties of the 'creation_type' Class:
        #  -> in self.writing_properties
        # if not, in matches or not match (if key starts
        # with a !, it's a not rule)
        # -> in self.matches or self.not_matches
        for key in params:
            # Some key are quite special
            if key in ['use']:
                self.writing_properties[key] = params[key]
            elif key in cls.properties:
                setattr(self, key, params[key])
            elif key in tcls.properties:
                self.writing_properties[key] = params[key]
            else:
                if key.startswith('!'):
                    key = key.split('!')[1]
                    self.not_matches[key] = params['!' + key]
                else:
                    self.matches[key] = params[key]

        # Then running prop :)
        cls = self.__class__
        # adding running properties like latency, dependency list, etc
        for prop, entry in cls.running_properties.items():
            # Copy is slow, so we check type
            # Type with __iter__ are list or dict, or tuple.
            # Item need it's own list, so qe copy
            val = entry.default
            if hasattr(val, '__iter__'):
                setattr(self, prop, copy(val))
            else:
                setattr(self, prop, val)
            #eatch istance to have his own running prop!

    # Output name
    def get_name(self):
        try:
            return self.discoveryrule_name
        except AttributeError:
            return "UnnamedDiscoveryRule"

    # Try to see if the key,value is matching one or
    # our rule. If value got ',' we must look for each value
    # If one match, we quit
    # We can find in matches or not_matches
    def is_matching(self, key, value, look_in='matches'):
        if look_in == 'matches':
            d = self.matches
        else:
            d = self.not_matches
        # If we do not even have the key, we bailout
        if not key.strip() in d:
            return False

        # Get my matching patern
        m = d[key]
        if ',' in m:
            matchings = [mt.strip() for mt in m.split(',')]
        else:
            matchings = [m]

        # Split the alue by , too
        values = value.split(',')
        for m in matchings:
            for v in values:
                #print "Try to match", m, v
                if re.search(m, v):
                    return True
        return False

    # Look if we match all discovery data or not
    # a disco data look as a list of (key, values)
    def is_matching_disco_datas(self, datas):
        # If we got not data, no way we can match
        if len(datas) == 0:
            return False

        # First we look if it's possible to match
        # we must match All self.matches things
        for m in self.matches:
            #print "Compare to", m
            match_one = False
            for (k, v) in datas:
                # We found at least one of our match key
                if m == k:
                    if self.is_matching(k, v):
                        #print "Got matching with", m, k, v
                        match_one = True
                        continue
            if not match_one:
                # It match none
                #print "Match none, FAlse"
                return False
        #print "It's possible to be OK"

        # And now look if ANY of not_matches is reach. If so
        # it's False
        for m in self.not_matches:
            #print "Compare to NOT", m
            match_one = False
            for (k, v) in datas:
                #print "K,V", k,v
                # We found at least one of our match key
                if m == k:
                    #print "Go loop"
                    if self.is_matching(k, v, look_in='not_matches'):
                        #print "Got matching with", m, k, v
                        match_one = True
                        continue
            if match_one:
                #print "I match one, I quit"
                return False

        # Ok we match ALL rules in self.matches
        # and NONE of self.not_matches, we can go :)
        return True