Example #1
0
 def __init__(self, items):
     self.items = {}
     self.configuration_warnings = []
     self.configuration_errors = []
     for i in items:
         self.items[i.id] = i
     self.templates = {}
     # We should keep a graph of templates relations
     self.templates_graph = Graph()
Example #2
0
 def __init__(self, items):
     self.items = {}
     self.configuration_warnings = []
     self.configuration_errors = []
     for i in items:
         self.items[i.id] = i
     self.templates = {}
     # We should keep a graph of templates relations
     self.templates_graph = Graph()
Example #3
0
    def no_loop_in_parents(self):
        # Ok, we say "from now, no loop :) "
        r = True

        # Create parent graph
        parents = Graph()

        # With all hosts as nodes
        for h in self:
            if h is not None:
                parents.add_node(h)

        # And now fill edges
        for h in self:
            for p in h.parents:
                if p is not None:
                    parents.add_edge(p, h)

        # Now get the list of all hosts in a loop
        host_in_loops = parents.loop_check()

        # and raise errors about it
        for h in host_in_loops:
            logger.log("Error: The host '%s' is part of a circular parent/child chain!" % h.get_name())
            r = False

        return r
Example #4
0
class Items(object):
    def __init__(self, items):
        self.items = {}
        self.configuration_warnings = []
        self.configuration_errors = []
        for i in items:
            self.items[i.id] = i
        self.templates = {}
        # We should keep a graph of templates relations
        self.templates_graph = Graph()

    def __iter__(self):
        return self.items.itervalues()

    def __len__(self):
        return len(self.items)

    def __delitem__(self, key):
        try:
            del self.items[key]
        except KeyError:  # we don't want it, we do not have it. All is perfect
            pass

    def __setitem__(self, key, value):
        self.items[key] = value

    def __getitem__(self, key):
        return self.items[key]

    def __contains__(self, key):
        return key in self.items

    def compute_hash(self):
        for i in self:
            i.compute_hash()


    # We create the reversed list so search will be faster
    # We also create a twins list with id of twins (not the original
    # just the others, higher twins)
    def create_reversed_list(self):
        self.reversed_list = {}
        self.twins = []
        name_property = self.__class__.name_property
        for id in self.items:
            if hasattr(self.items[id], name_property):
                name = getattr(self.items[id], name_property)
                if name not in self.reversed_list:
                    self.reversed_list[name] = id
                else:
                    self.twins.append(id)


    def find_id_by_name(self, name):
        if hasattr(self, 'reversed_list'):
            if name in self.reversed_list:
                return self.reversed_list[name]
            else:
                return None
        else:  # ok, an early ask, with no reversed list from now...
            name_property = self.__class__.name_property
            for i in self:
                if hasattr(i, name_property):
                    i_name = getattr(i, name_property)
                    if i_name == name:
                        return i.id
            return None


    def find_by_name(self, name):
        id = self.find_id_by_name(name)
        if id is not None:
            return self.items[id]
        else:
            return None


    # Search items using a list of filter callbacks. Each callback is passed
    # the item instances and should return a boolean value indicating if it
    # matched the filter.
    # Returns a list of items matching all filters.
    def find_by_filter(self, filters):
        items = []
        for i in self:
            failed = False
            for f in filters:
                if not f(i):
                    failed = True
                    break
            if failed is False:
                items.append(i)
        return items


    # prepare_for_conf_sending to flatten some properties
    def prepare_for_sending(self):
        for i in self:
            i.prepare_for_conf_sending()

    
    # It's used to change old Nagios2 names to
    # Nagios3 ones
    def old_properties_names_to_new(self):
        for i in self:
            i.old_properties_names_to_new()

    def pythonize(self):
        for id in self.items:
            self.items[id].pythonize()

    def create_tpl_list(self):
        for id in self.items:
            i = self.items[id]
            if i.is_tpl():
                self.templates[id] = i

    def find_tpl_by_name(self, name):
        for i in self.templates.values():
            if hasattr(i, 'name') and i.name == name:
                return i
        return None

    # We will link all templates, and create the template
    # graph too
    def linkify_templates(self):
        # First we create a list of all templates
        self.create_tpl_list()
        for i in self:
            tpls = i.get_templates()
            new_tpls = []
            for tpl in tpls:
                tpl = tpl.strip()
                # We save this template in the 'tags' set
                i.tags.add(tpl)
                # Then we link it
                t = self.find_tpl_by_name(tpl)
                # If it's ok, add the template and update the
                # template graph too
                if t is not None:
                    # add the template object to us
                    new_tpls.append(t)
                else:  # not find? not good!
                    err = "the template '%s' defined for '%s' is unknown" % (tpl, i.get_name())
                    i.configuration_warnings.append(err)
            i.templates = new_tpls

        # Now we will create the template graph, so
        # we look only for templates here. First we should declare our nodes
        for tpl in self.templates.values():
            self.templates_graph.add_node(tpl)
        # And then really create our edge
        for tpl in self.templates.values():
            for father in tpl.templates:
                self.templates_graph.add_edge(father, tpl)

    def is_correct(self):
        # we are ok at the beginning. Hope we still ok at the end...
        r = True
        # Some class do not have twins, because they do not have names
        # like servicedependencies
        twins = getattr(self, 'twins', None)
        if twins is not None:
            # Ok, look at no twins (it's bad!)
            for id in twins:
                i = self.items[id]
                logger.warning("[items] %s.%s is duplicated from %s" %\
                    (i.__class__.my_type, i.get_name(), getattr(i, 'imported_from', "unknown source")))

        # Then look if we have some errors in the conf
        # Juts print warnings, but raise errors
        for err in self.configuration_warnings:
            logger.warning("[items] %s" % err)

        for err in self.configuration_errors:
            logger.error("[items] %s" % err)
            r = False

        # Then look for individual ok
        for i in self:
            # Alias and display_name hook hook
            prop_name = getattr(self.__class__, 'name_property', None)
            if prop_name and not hasattr(i, 'alias') and hasattr(i, prop_name):
                setattr(i, 'alias', getattr(i, prop_name))
            if prop_name and getattr(i, 'display_name', '') == '' and hasattr(i, prop_name):
                setattr(i, 'display_name', getattr(i, prop_name))

            # Now other checks
            if not i.is_correct():
                n = getattr(i, 'imported_from', "unknown source")
                logger.error("[items] In %s is incorrect ; from %s" % (i.get_name(), n))
                r = False

        return r

    def remove_templates(self):
        """ Remove useless templates (& properties) of our items ; otherwise we could get errors on config.is_correct() """
        tpls = [i for i in self if i.is_tpl()]
        for i in tpls:
            del self[i.id]
        del self.templates
        del self.templates_graph

    def clean(self):
        """ Request to remove the unnecessary attributes/others from our items """
        for i in self:
            i.clean()
        Item.clean(self)

    # If a prop is absent and is not required, put the default value
    def fill_default(self):
        for i in self:
            i.fill_default()

    def __str__(self):
        s = ''
        cls = self.__class__
        for id in self.items:
            s = s + str(cls) + ':' + str(id) + str(self.items[id]) + '\n'
        return s

    # Inheritance for just a property
    def apply_partial_inheritance(self, prop):
        for i in self:
            i.get_property_by_inheritance(self, prop)
            if not i.is_tpl():
                # If a "null" attribute was inherited, delete it
                try:
                    if getattr(i, prop) == 'null':
                        delattr(i, prop)
                except:
                    pass

    def apply_inheritance(self):
        # We check for all Class properties if the host has it
        # if not, it check all host templates for a value
        cls = self.inner_class
        for prop in cls.properties:
            self.apply_partial_inheritance(prop)
        for i in self:
            i.get_customs_properties_by_inheritance(self)

    # We remove twins
    # Remember: item id respect the order of conf. So if and item
    #  is defined multiple times,
    # we want to keep the first one.
    # Services are also managed here but they are specials:
    # We remove twins services with the same host_name/service_description
    # Remember: host service are take into account first before hostgroup service
    # Id of host service are lower than hostgroups one, so they are
    # in self.twins_services
    # and we can remove them.
    def remove_twins(self):
        for id in self.twins:
            i = self.items[id]
            type = i.__class__.my_type
            logger.warning("[items] %s.%s is already defined '%s'" % (type, i.get_name(), getattr(i, 'imported_from', "unknown source")))
            del self[id]  # bye bye
        # do not remove twins, we should look in it, but just void it
        self.twins = []
        #del self.twins #no more need



    # We've got a contacts property with , separated contacts names
    # and we want have a list of Contacts
    def linkify_with_contacts(self, contacts):
        for i in self:
            if hasattr(i, 'contacts'):
                contacts_tab = i.contacts.split(',')
                contacts_tab = strip_and_uniq(contacts_tab)
                new_contacts = []
                for c_name in contacts_tab:
                    if c_name != '':
                        c = contacts.find_by_name(c_name)
                        if c is not None:
                            new_contacts.append(c)
                        # Else: Add in the errors tab.
                        # will be raised at is_correct
                        else:
                            err = "the contact '%s' defined for '%s' is unknown" % (c_name, i.get_name())
                            i.configuration_errors.append(err)
                # Get the list, but first make elements uniq
                i.contacts = list(set(new_contacts))

    # Make link between an object and its escalations
    def linkify_with_escalations(self, escalations):
        for i in self:
            if hasattr(i, 'escalations'):
                escalations_tab = i.escalations.split(',')
                escalations_tab = strip_and_uniq(escalations_tab)
                new_escalations = []
                for es_name in [e for e in escalations_tab if e != '']:
                    es = escalations.find_by_name(es_name)
                    if es is not None:
                        new_escalations.append(es)
                    else:  # Escalation not find, not good!
                        err = "the escalation '%s' defined for '%s' is unknown" % (es_name, i.get_name())
                        i.configuration_errors.append(err)
                i.escalations = new_escalations

    # Make link between item and it's resultmodulations
    def linkify_with_resultmodulations(self, resultmodulations):
        for i in self:
            if hasattr(i, 'resultmodulations'):
                resultmodulations_tab = i.resultmodulations.split(',')
                resultmodulations_tab = strip_and_uniq(resultmodulations_tab)
                new_resultmodulations = []
                for rm_name in resultmodulations_tab:
                    rm = resultmodulations.find_by_name(rm_name)
                    if rm is not None:
                        new_resultmodulations.append(rm)
                    else:
                        err = "the result modulation '%s' defined on the %s '%s' do not exist" % (rm_name, i.__class__.my_type, i.get_name())
                        i.configuration_warnings.append(err)
                        continue
                i.resultmodulations = new_resultmodulations

    # Make link between item and it's business_impact_modulations
    def linkify_with_business_impact_modulations(self, business_impact_modulations):
        for i in self:
            if hasattr(i, 'business_impact_modulations'):
                business_impact_modulations_tab = i.business_impact_modulations.split(',')
                business_impact_modulations_tab = strip_and_uniq(business_impact_modulations_tab)
                new_business_impact_modulations = []
                for rm_name in business_impact_modulations_tab:
                    rm = business_impact_modulations.find_by_name(rm_name)
                    if rm is not None:
                        new_business_impact_modulations.append(rm)
                    else:
                        err = "the business impact modulation '%s' defined on the %s '%s' do not exist" % (rm_name, i.__class__.my_type, i.get_name())
                        i.configuration_errors.append(err)
                        continue
                i.business_impact_modulations = new_business_impact_modulations

    # If we've got a contact_groups properties, we search for all
    # theses groups and ask them their contacts, and then add them
    # all into our contacts property
    def explode_contact_groups_into_contacts(self, contactgroups):
        for i in self:
            if hasattr(i, 'contact_groups'):
                if isinstance(i.contact_groups, list):
                    cgnames = i.contact_groups
                else:
                    cgnames = i.contact_groups.split(',')
                cgnames = strip_and_uniq(cgnames)
                for cgname in cgnames:
                    cg = contactgroups.find_by_name(cgname)
                    if cg is None:
                        err = "The contact group '%s' defined on the %s '%s' do not exist" % (cgname, i.__class__.my_type, i.get_name())
                        i.configuration_errors.append(err)
                        continue
                    cnames = contactgroups.get_members_by_name(cgname)
                    # We add contacts into our contacts
                    if cnames != []:
                        if hasattr(i, 'contacts'):
                            i.contacts += ',' + cnames
                        else:
                            i.contacts = cnames

    # Link a timeperiod property (prop)
    def linkify_with_timeperiods(self, timeperiods, prop):
        for i in self:
            if hasattr(i, prop):
                tpname = getattr(i, prop).strip()
                # some default values are '', so set None
                if tpname == '':
                    setattr(i, prop, None)
                    continue

                # Ok, get a real name, search for it
                tp = timeperiods.find_by_name(tpname)
                # If not found, it's an error
                if tp is None:
                    err = "The %s of the %s '%s' named '%s' is unknown!" % (prop, i.__class__.my_type, i.get_name(), tpname)
                    i.configuration_errors.append(err)
                    continue
                # Got a real one, just set it :)
                setattr(i, prop, tp)

    def create_commandcall(self,prop, commands, command):
        comandcall = dict(commands=commands, call=command)
        if hasattr(prop, 'enable_environment_macros'):
            comandcall['enable_environment_macros'] = prop.enable_environment_macros

        if hasattr(prop, 'poller_tag'):
            comandcall['poller_tag']=prop.poller_tag
        elif hasattr(prop, 'reactionner_tag'):
            comandcall['reactionner_tag']=prop.reactionner_tag

        return CommandCall(**comandcall)

    # Link one command property
    def linkify_one_command_with_commands(self, commands, prop):
        for i in self:
            if hasattr(i, prop):
                command = getattr(i, prop).strip()
                if command != '':
                    cmdCall = self.create_commandcall(i, commands, command)

                    # TODO: catch None?
                    setattr(i, prop, cmdCall)
                else:

                    setattr(i, prop, None)

    # Link a command list (commands with , between) in real CommandCalls
    def linkify_command_list_with_commands(self, commands, prop):
        for i in self:
            if hasattr(i, prop):
                coms = getattr(i, prop).split(',')
                coms = strip_and_uniq(coms)
                com_list = []
                for com in coms:
                    if com != '':
                        cmdCall = self.create_commandcall(i, commands, com)
                        # TODO: catch None?
                        com_list.append(cmdCall)
                    else:  # TODO: catch?
                        pass
                setattr(i, prop, com_list)

    # Link with triggers. Can be with a "in source" trigger, or a file name
    def linkify_with_triggers(self, triggers):
        for i in self:
            i.linkify_with_triggers(triggers)


    # We've got a notificationways property with , separated contacts names
    # and we want have a list of NotificationWay
    def linkify_with_checkmodulations(self, checkmodulations):
        for i in self:
            if not hasattr(i, 'checkmodulations'):
                continue
            new_checkmodulations = []
            for cw_name in i.checkmodulations:
                cw = checkmodulations.find_by_name(cw_name)
                if cw is not None:
                    new_checkmodulations.append(cw)
                else:
                    err = "The checkmodulations of the %s '%s' named '%s' is unknown!" % (i.__class__.my_type, i.get_name(), cw_name)
                    i.configuration_errors.append(err)
            # Get the list, but first make elements uniq
            i.checkmodulations = new_checkmodulations


    # We've got list of macro modulations as list of names, and
    # we want real objects
    def linkify_with_macromodulations(self, macromodulations):
        for i in self:
            if not hasattr(i, 'macromodulations'):
                continue
            new_macromodulations = []
            for cw_name in i.macromodulations:
                cw = macromodulations.find_by_name(cw_name)
                if cw is not None:
                    new_macromodulations.append(cw)
                else:
                    err = "The macromodulations of the %s '%s' named '%s' is unknown!" % (i.__class__.my_type, i.get_name(), cw_name)
                    i.configuration_errors.append(err)
            # Get the list, but first make elements uniq
            i.macromodulations = new_macromodulations


    # Linkify with modules
    def linkify_s_by_plug(self, modules):
        for s in self:
            new_modules = []
            for plug_name in s.modules:
                plug_name = plug_name.strip()
                # don't tread void names
                if plug_name == '':
                    continue

                plug = modules.find_by_name(plug_name)
                print plug
                if plug is not None:
                    new_modules.append(plug)
                else:
                    err = "Error: the module %s is unknown for %s" % (plug_name, s.get_name())
                    s.configuration_errors.append(err)
            s.modules = new_modules


    def evaluate_hostgroup_expression(self, expr, hosts, hostgroups, look_in='hostgroups'):
        #print "\n"*10, "looking for expression", expr
        # Maybe exp is a list, like numerous hostgroups entries in a service, link them
        if isinstance(expr, list):
            expr = '|'.join(expr)
        #print "\n"*10, "looking for expression", expr        
        if look_in=='hostgroups':
            f = ComplexExpressionFactory(look_in, hostgroups, hosts)
        else: # templates
            f = ComplexExpressionFactory(look_in, hosts, hosts)
        expr_tree = f.eval_cor_pattern(expr)

        #print "RES of ComplexExpressionFactory"
        #print expr_tree

        #print "Try to resolve the Tree"
        set_res = expr_tree.resolve_elements()
        #print "R2d2 final is", set_res

        # HOOK DBG
        return list(set_res)



    # If we've got a hostgroup_name property, we search for all
    # theses groups and ask them their hosts, and then add them
    # all into our host_name property
    def explode_host_groups_into_hosts(self, hosts, hostgroups):
        for i in self:
            hnames_list = []
            if hasattr(i, 'hostgroup_name'):
                hnames_list.extend(self.evaluate_hostgroup_expression(i.hostgroup_name, hosts, hostgroups))

            # Maybe there is no host in the groups, and do not have any
            # host_name too, so tag is as template to do not look at
            if hnames_list == [] and not hasattr(i, 'host_name'):
                i.register = '0'

            if hasattr(i, 'host_name'):
                hst = i.host_name.split(',')
                for h in hst:
                    h = h.strip()
                    # If the host start with a !, it's to be removed from
                    # the hostgroup get list
                    if h.startswith('!'):
                        hst_to_remove = h[1:].strip()
                        try:
                            hnames_list.remove(hst_to_remove)
                        # was not in it
                        except ValueError:
                            pass
                    # Else it's an host to add, but maybe it's ALL
                    elif h == '*':
                        for newhost in  set(h.host_name for h in hosts.items.values() \
                                            if getattr(h, 'host_name', '') != '' and not h.is_tpl()):
                            hnames_list.append(newhost)
                            #print "DBG in item.explode_host_groups_into_hosts , added '%s' to group '%s'" % (newhost, i)
                    else:
                        hnames_list.append(h)

            i.host_name = ','.join(list(set(hnames_list)))

            # Ok, even with all of it, there is still no host, put it as a template
            if i.host_name == '':
                i.register = '0'


    # Take our trigger strings and create true objects with it
    def explode_trigger_string_into_triggers(self, triggers):
        for i in self:
            i.explode_trigger_string_into_triggers(triggers)

    # Parent graph: use to find quickly relations between all item, and loop
    # return True if there is a loop
    def no_loop_in_parents(self, attr1, attr2):
        """Find loop in dependencies.
        For now, used with the following attributes :
            (self, parents) => host dependencies from host object
            (host_name, dependent_host_name) => host dependencies from hostdependencies object
            (service_description, dependent_service_description) => service dependencies from servicedependencies object
        """

        # Ok, we say "from now, no loop :) "
        r = True

        # Create parent graph
        parents = Graph()

        # Start with all items as nodes
        for item in self:
            # Hack to get self here. Used when looping on host and host parent's
            if attr1 == "self":
                obj = item          # obj is a host/service [list]
            else:
                obj = getattr(item, attr1, None)
            if obj is not None:
                if isinstance(obj, list):
                    for sobj in obj:
                        parents.add_node(sobj)
                else:
                    parents.add_node(obj)

        # And now fill edges
        for item in self:
            if attr1 == "self":
                obj1 = item
            else:
                obj1 = getattr(item, attr1, None)
            obj2 = getattr(item, attr2, None)
            if obj2 is not None:
                if isinstance(obj2, list):
                    for sobj2 in obj2:
                        if isinstance(obj1, list):
                            for sobj1 in obj1:
                                parents.add_edge(sobj1, sobj2)
                        else:
                            parents.add_edge(obj1, sobj2)
                else:
                    if isinstance(obj1, list):
                        for sobj1 in obj1:
                            parents.add_edge(sobj1, obj2)
                    else:
                        parents.add_edge(obj1, obj2)

        # Now get the list of all item in a loop
        items_in_loops = parents.loop_check()

        # and raise errors about it
        for item in items_in_loops:
            logger.error("The %s object '%s'  is part of a circular parent/child chain!" % (item.my_type, item.get_name()))
            r = False

        return r
Example #5
0
    def no_loop_in_parents(self, attr1, attr2):
        """Find loop in dependencies.
        For now, used with the following attributes :
            (self, parents) => host dependencies from host object
            (host_name, dependent_host_name) => host dependencies from hostdependencies object
            (service_description, dependent_service_description) => service dependencies from servicedependencies object
        """

        # Ok, we say "from now, no loop :) "
        r = True

        # Create parent graph
        parents = Graph()

        # Start with all items as nodes
        for item in self:
            # Hack to get self here. Used when looping on host and host parent's
            if attr1 == "self":
                obj = item          # obj is a host/service [list]
            else:
                obj = getattr(item, attr1, None)
            if obj is not None:
                if isinstance(obj, list):
                    for sobj in obj:
                        parents.add_node(sobj)
                else:
                    parents.add_node(obj)

        # And now fill edges
        for item in self:
            if attr1 == "self":
                obj1 = item
            else:
                obj1 = getattr(item, attr1, None)
            obj2 = getattr(item, attr2, None)
            if obj2 is not None:
                if isinstance(obj2, list):
                    for sobj2 in obj2:
                        if isinstance(obj1, list):
                            for sobj1 in obj1:
                                parents.add_edge(sobj1, sobj2)
                        else:
                            parents.add_edge(obj1, sobj2)
                else:
                    if isinstance(obj1, list):
                        for sobj1 in obj1:
                            parents.add_edge(sobj1, obj2)
                    else:
                        parents.add_edge(obj1, obj2)

        # Now get the list of all item in a loop
        items_in_loops = parents.loop_check()

        # and raise errors about it
        for item in items_in_loops:
            logger.error("The %s object '%s'  is part of a circular parent/child chain!" % (item.my_type, item.get_name()))
            r = False

        return r
Example #6
0
class Items(object):
    def __init__(self, items):
        self.items = {}
        self.configuration_warnings = []
        self.configuration_errors = []
        for i in items:
            self.items[i.id] = i
        self.templates = {}
        # We should keep a graph of templates relations
        self.templates_graph = Graph()

    def __iter__(self):
        return self.items.itervalues()

    def __len__(self):
        return len(self.items)

    def __delitem__(self, key):
        try:
            del self.items[key]
        except KeyError:  # we don't want it, we do not have it. All is perfect
            pass

    def __setitem__(self, key, value):
        self.items[key] = value

    def __getitem__(self, key):
        return self.items[key]

    def __contains__(self, key):
        return key in self.items

    def compute_hash(self):
        for i in self:
            i.compute_hash()


    # We create the reversed list so search will be faster
    # We also create a twins list with id of twins (not the original
    # just the others, higher twins)
    def create_reversed_list(self):
        self.reversed_list = {}
        self.twins = []
        name_property = self.__class__.name_property
        for id in self.items:
            if hasattr(self.items[id], name_property):
                name = getattr(self.items[id], name_property)
                if name not in self.reversed_list:
                    self.reversed_list[name] = id
                else:
                    self.twins.append(id)


    def find_id_by_name(self, name):
        if hasattr(self, 'reversed_list'):
            if name in self.reversed_list:
                return self.reversed_list[name]
            else:
                return None
        else:  # ok, an early ask, with no reversed list from now...
            name_property = self.__class__.name_property
            for i in self:
                if hasattr(i, name_property):
                    i_name = getattr(i, name_property)
                    if i_name == name:
                        return i.id
            return None


    def find_by_name(self, name):
        id = self.find_id_by_name(name)
        if id is not None:
            return self.items[id]
        else:
            return None


    # Search items using a list of filter callbacks. Each callback is passed
    # the item instances and should return a boolean value indicating if it
    # matched the filter.
    # Returns a list of items matching all filters.
    def find_by_filter(self, filters):
        items = []
        for i in self:
            failed = False
            for f in filters:
                if not f(i):
                    failed = True
                    break
            if failed is False:
                items.append(i)
        return items


    # prepare_for_conf_sending to flatten some properties
    def prepare_for_sending(self):
        for i in self:
            i.prepare_for_conf_sending()

    
    # It's used to change old Nagios2 names to
    # Nagios3 ones
    def old_properties_names_to_new(self):
        for i in self:
            i.old_properties_names_to_new()

    def pythonize(self):
        for id in self.items:
            self.items[id].pythonize()

    def create_tpl_list(self):
        for id in self.items:
            i = self.items[id]
            if i.is_tpl():
                self.templates[id] = i

    def find_tpl_by_name(self, name):
        for i in self.templates.values():
            if hasattr(i, 'name') and i.name == name:
                return i
        return None

    # We will link all templates, and create the template
    # graph too
    def linkify_templates(self):
        # First we create a list of all templates
        self.create_tpl_list()
        for i in self:
            tpls = i.get_templates()
            new_tpls = []
            for tpl in tpls:
                tpl = tpl.strip()
                # We save this template in the 'tags' set
                i.tags.add(tpl)
                # Then we link it
                t = self.find_tpl_by_name(tpl)
                # If it's ok, add the template and update the
                # template graph too
                if t is not None:
                    # add the template object to us
                    new_tpls.append(t)
                else:  # not find? not good!
                    err = "the template '%s' defined for '%s' is unknown" % (tpl, i.get_name())
                    i.configuration_warnings.append(err)
            i.templates = new_tpls

        # Now we will create the template graph, so
        # we look only for templates here. First we should declare our nodes
        for tpl in self.templates.values():
            self.templates_graph.add_node(tpl)
        # And then really create our edge
        for tpl in self.templates.values():
            for father in tpl.templates:
                self.templates_graph.add_edge(father, tpl)

    def is_correct(self):
        # we are ok at the beginning. Hope we still ok at the end...
        r = True
        # Some class do not have twins, because they do not have names
        # like servicedependencies
        twins = getattr(self, 'twins', None)
        if twins is not None:
            # Ok, look at no twins (it's bad!)
            for id in twins:
                i = self.items[id]
                logger.warning("[items] %s.%s is duplicated from %s", \
                    i.__class__.my_type, i.get_name(), getattr(i, 'imported_from', "unknown source"))

        # Then look if we have some errors in the conf
        # Juts print warnings, but raise errors
        for err in self.configuration_warnings:
            logger.warning("[items] %s", err)

        for err in self.configuration_errors:
            logger.error("[items] %s", err)
            r = False

        # Then look for individual ok
        for i in self:
            # Alias and display_name hook hook
            prop_name = getattr(self.__class__, 'name_property', None)
            if prop_name and not hasattr(i, 'alias') and hasattr(i, prop_name):
                setattr(i, 'alias', getattr(i, prop_name))
            if prop_name and getattr(i, 'display_name', '') == '' and hasattr(i, prop_name):
                setattr(i, 'display_name', getattr(i, prop_name))

            # Now other checks
            if not i.is_correct():
                n = getattr(i, 'imported_from', "unknown source")
                logger.error("[items] In %s is incorrect ; from %s", i.get_name(), n)
                r = False

        return r

    def remove_templates(self):
        """ Remove useless templates (& properties) of our items ; otherwise we could get errors on config.is_correct() """
        tpls = [i for i in self if i.is_tpl()]
        for i in tpls:
            del self[i.id]
        del self.templates
        del self.templates_graph

    def clean(self):
        """ Request to remove the unnecessary attributes/others from our items """
        for i in self:
            i.clean()
        Item.clean(self)

    # If a prop is absent and is not required, put the default value
    def fill_default(self):
        for i in self:
            i.fill_default()

    def __str__(self):
        s = ''
        cls = self.__class__
        for id in self.items:
            s = s + str(cls) + ':' + str(id) + str(self.items[id]) + '\n'
        return s

    # Inheritance for just a property
    def apply_partial_inheritance(self, prop):
        for i in self:
            i.get_property_by_inheritance(self, prop)
            if not i.is_tpl():
                # If a "null" attribute was inherited, delete it
                try:
                    if getattr(i, prop) == 'null':
                        delattr(i, prop)
                except:
                    pass

    def apply_inheritance(self):
        # We check for all Class properties if the host has it
        # if not, it check all host templates for a value
        cls = self.inner_class
        for prop in cls.properties:
            self.apply_partial_inheritance(prop)
        for i in self:
            i.get_customs_properties_by_inheritance(self)

    # We remove twins
    # Remember: item id respect the order of conf. So if and item
    #  is defined multiple times,
    # we want to keep the first one.
    # Services are also managed here but they are specials:
    # We remove twins services with the same host_name/service_description
    # Remember: host service are take into account first before hostgroup service
    # Id of host service are lower than hostgroups one, so they are
    # in self.twins_services
    # and we can remove them.
    def remove_twins(self):
        for id in self.twins:
            i = self.items[id]
            type = i.__class__.my_type
            logger.warning("[items] %s.%s is already defined '%s'", type, i.get_name(), getattr(i, 'imported_from', "unknown source"))
            del self[id]  # bye bye
        # do not remove twins, we should look in it, but just void it
        self.twins = []
        #del self.twins #no more need



    # We've got a contacts property with , separated contacts names
    # and we want have a list of Contacts
    def linkify_with_contacts(self, contacts):
        for i in self:
            if hasattr(i, 'contacts'):
                contacts_tab = i.contacts.split(',')
                contacts_tab = strip_and_uniq(contacts_tab)
                new_contacts = []
                for c_name in contacts_tab:
                    if c_name != '':
                        c = contacts.find_by_name(c_name)
                        if c is not None:
                            new_contacts.append(c)
                        # Else: Add in the errors tab.
                        # will be raised at is_correct
                        else:
                            err = "the contact '%s' defined for '%s' is unknown" % (c_name, i.get_name())
                            i.configuration_errors.append(err)
                # Get the list, but first make elements uniq
                i.contacts = list(set(new_contacts))

    # Make link between an object and its escalations
    def linkify_with_escalations(self, escalations):
        for i in self:
            if hasattr(i, 'escalations'):
                escalations_tab = i.escalations.split(',')
                escalations_tab = strip_and_uniq(escalations_tab)
                new_escalations = []
                for es_name in [e for e in escalations_tab if e != '']:
                    es = escalations.find_by_name(es_name)
                    if es is not None:
                        new_escalations.append(es)
                    else:  # Escalation not find, not good!
                        err = "the escalation '%s' defined for '%s' is unknown" % (es_name, i.get_name())
                        i.configuration_errors.append(err)
                i.escalations = new_escalations

    # Make link between item and it's resultmodulations
    def linkify_with_resultmodulations(self, resultmodulations):
        for i in self:
            if hasattr(i, 'resultmodulations'):
                resultmodulations_tab = i.resultmodulations.split(',')
                resultmodulations_tab = strip_and_uniq(resultmodulations_tab)
                new_resultmodulations = []
                for rm_name in resultmodulations_tab:
                    rm = resultmodulations.find_by_name(rm_name)
                    if rm is not None:
                        new_resultmodulations.append(rm)
                    else:
                        err = "the result modulation '%s' defined on the %s '%s' do not exist" % (rm_name, i.__class__.my_type, i.get_name())
                        i.configuration_warnings.append(err)
                        continue
                i.resultmodulations = new_resultmodulations

    # Make link between item and it's business_impact_modulations
    def linkify_with_business_impact_modulations(self, business_impact_modulations):
        for i in self:
            if hasattr(i, 'business_impact_modulations'):
                business_impact_modulations_tab = i.business_impact_modulations.split(',')
                business_impact_modulations_tab = strip_and_uniq(business_impact_modulations_tab)
                new_business_impact_modulations = []
                for rm_name in business_impact_modulations_tab:
                    rm = business_impact_modulations.find_by_name(rm_name)
                    if rm is not None:
                        new_business_impact_modulations.append(rm)
                    else:
                        err = "the business impact modulation '%s' defined on the %s '%s' do not exist" % (rm_name, i.__class__.my_type, i.get_name())
                        i.configuration_errors.append(err)
                        continue
                i.business_impact_modulations = new_business_impact_modulations

    # If we've got a contact_groups properties, we search for all
    # theses groups and ask them their contacts, and then add them
    # all into our contacts property
    def explode_contact_groups_into_contacts(self, contactgroups):
        for i in self:
            if hasattr(i, 'contact_groups'):
                if isinstance(i.contact_groups, list):
                    cgnames = i.contact_groups
                else:
                    cgnames = i.contact_groups.split(',')
                cgnames = strip_and_uniq(cgnames)
                for cgname in cgnames:
                    cg = contactgroups.find_by_name(cgname)
                    if cg is None:
                        err = "The contact group '%s' defined on the %s '%s' do not exist" % (cgname, i.__class__.my_type, i.get_name())
                        i.configuration_errors.append(err)
                        continue
                    cnames = contactgroups.get_members_by_name(cgname)
                    # We add contacts into our contacts
                    if cnames != []:
                        if hasattr(i, 'contacts'):
                            i.contacts += ',' + cnames
                        else:
                            i.contacts = cnames

    # Link a timeperiod property (prop)
    def linkify_with_timeperiods(self, timeperiods, prop):
        for i in self:
            if hasattr(i, prop):
                tpname = getattr(i, prop).strip()
                # some default values are '', so set None
                if tpname == '':
                    setattr(i, prop, None)
                    continue

                # Ok, get a real name, search for it
                tp = timeperiods.find_by_name(tpname)
                # If not found, it's an error
                if tp is None:
                    err = "The %s of the %s '%s' named '%s' is unknown!" % (prop, i.__class__.my_type, i.get_name(), tpname)
                    i.configuration_errors.append(err)
                    continue
                # Got a real one, just set it :)
                setattr(i, prop, tp)

    def create_commandcall(self,prop, commands, command):
        comandcall = dict(commands=commands, call=command)
        if hasattr(prop, 'enable_environment_macros'):
            comandcall['enable_environment_macros'] = prop.enable_environment_macros

        if hasattr(prop, 'poller_tag'):
            comandcall['poller_tag']=prop.poller_tag
        elif hasattr(prop, 'reactionner_tag'):
            comandcall['reactionner_tag']=prop.reactionner_tag

        return CommandCall(**comandcall)

    # Link one command property
    def linkify_one_command_with_commands(self, commands, prop):
        for i in self:
            if hasattr(i, prop):
                command = getattr(i, prop).strip()
                if command != '':
                    cmdCall = self.create_commandcall(i, commands, command)

                    # TODO: catch None?
                    setattr(i, prop, cmdCall)
                else:

                    setattr(i, prop, None)

    # Link a command list (commands with , between) in real CommandCalls
    def linkify_command_list_with_commands(self, commands, prop):
        for i in self:
            if hasattr(i, prop):
                coms = getattr(i, prop).split(',')
                coms = strip_and_uniq(coms)
                com_list = []
                for com in coms:
                    if com != '':
                        cmdCall = self.create_commandcall(i, commands, com)
                        # TODO: catch None?
                        com_list.append(cmdCall)
                    else:  # TODO: catch?
                        pass
                setattr(i, prop, com_list)

    # Link with triggers. Can be with a "in source" trigger, or a file name
    def linkify_with_triggers(self, triggers):
        for i in self:
            i.linkify_with_triggers(triggers)


    # We've got a notificationways property with , separated contacts names
    # and we want have a list of NotificationWay
    def linkify_with_checkmodulations(self, checkmodulations):
        for i in self:
            if not hasattr(i, 'checkmodulations'):
                continue
            new_checkmodulations = []
            for cw_name in i.checkmodulations:
                cw = checkmodulations.find_by_name(cw_name)
                if cw is not None:
                    new_checkmodulations.append(cw)
                else:
                    err = "The checkmodulations of the %s '%s' named '%s' is unknown!" % (i.__class__.my_type, i.get_name(), cw_name)
                    i.configuration_errors.append(err)
            # Get the list, but first make elements uniq
            i.checkmodulations = new_checkmodulations


    # We've got list of macro modulations as list of names, and
    # we want real objects
    def linkify_with_macromodulations(self, macromodulations):
        for i in self:
            if not hasattr(i, 'macromodulations'):
                continue
            new_macromodulations = []
            for cw_name in i.macromodulations:
                cw = macromodulations.find_by_name(cw_name)
                if cw is not None:
                    new_macromodulations.append(cw)
                else:
                    err = "The macromodulations of the %s '%s' named '%s' is unknown!" % (i.__class__.my_type, i.get_name(), cw_name)
                    i.configuration_errors.append(err)
            # Get the list, but first make elements uniq
            i.macromodulations = new_macromodulations


    # Linkify with modules
    def linkify_s_by_plug(self, modules):
        for s in self:
            new_modules = []
            for plug_name in s.modules:
                plug_name = plug_name.strip()
                # don't tread void names
                if plug_name == '':
                    continue

                plug = modules.find_by_name(plug_name)
                print plug
                if plug is not None:
                    new_modules.append(plug)
                else:
                    err = "Error: the module %s is unknown for %s" % (plug_name, s.get_name())
                    s.configuration_errors.append(err)
            s.modules = new_modules


    def evaluate_hostgroup_expression(self, expr, hosts, hostgroups, look_in='hostgroups'):
        #print "\n"*10, "looking for expression", expr
        # Maybe exp is a list, like numerous hostgroups entries in a service, link them
        if isinstance(expr, list):
            expr = '|'.join(expr)
        #print "\n"*10, "looking for expression", expr        
        if look_in=='hostgroups':
            f = ComplexExpressionFactory(look_in, hostgroups, hosts)
        else: # templates
            f = ComplexExpressionFactory(look_in, hosts, hosts)
        expr_tree = f.eval_cor_pattern(expr)

        #print "RES of ComplexExpressionFactory"
        #print expr_tree

        #print "Try to resolve the Tree"
        set_res = expr_tree.resolve_elements()
        #print "R2d2 final is", set_res

        # HOOK DBG
        return list(set_res)



    # If we've got a hostgroup_name property, we search for all
    # theses groups and ask them their hosts, and then add them
    # all into our host_name property
    def explode_host_groups_into_hosts(self, hosts, hostgroups):
        for i in self:
            hnames_list = []
            if hasattr(i, 'hostgroup_name'):
                hnames_list.extend(self.evaluate_hostgroup_expression(i.hostgroup_name, hosts, hostgroups))

            # Maybe there is no host in the groups, and do not have any
            # host_name too, so tag is as template to do not look at
            if hnames_list == [] and not hasattr(i, 'host_name'):
                i.register = '0'

            if hasattr(i, 'host_name'):
                hst = i.host_name.split(',')
                for h in hst:
                    h = h.strip()
                    # If the host start with a !, it's to be removed from
                    # the hostgroup get list
                    if h.startswith('!'):
                        hst_to_remove = h[1:].strip()
                        try:
                            hnames_list.remove(hst_to_remove)
                        # was not in it
                        except ValueError:
                            pass
                    # Else it's an host to add, but maybe it's ALL
                    elif h == '*':
                        for newhost in  set(h.host_name for h in hosts.items.values() \
                                            if getattr(h, 'host_name', '') != '' and not h.is_tpl()):
                            hnames_list.append(newhost)
                            #print "DBG in item.explode_host_groups_into_hosts , added '%s' to group '%s'" % (newhost, i)
                    else:
                        hnames_list.append(h)

            i.host_name = ','.join(list(set(hnames_list)))

            # Ok, even with all of it, there is still no host, put it as a template
            if i.host_name == '':
                i.register = '0'


    # Take our trigger strings and create true objects with it
    def explode_trigger_string_into_triggers(self, triggers):
        for i in self:
            i.explode_trigger_string_into_triggers(triggers)

    # Parent graph: use to find quickly relations between all item, and loop
    # return True if there is a loop
    def no_loop_in_parents(self, attr1, attr2):
        """Find loop in dependencies.
        For now, used with the following attributes :
        :(self, parents):                                      host dependencies from host object
        :(host_name, dependent_host_name):                     host dependencies from hostdependencies object
        :(service_description, dependent_service_description): service dependencies from servicedependencies object
        """

        # Ok, we say "from now, no loop :) "
        r = True

        # Create parent graph
        parents = Graph()

        # Start with all items as nodes
        for item in self:
            # Hack to get self here. Used when looping on host and host parent's
            if attr1 == "self":
                obj = item          # obj is a host/service [list]
            else:
                obj = getattr(item, attr1, None)
            if obj is not None:
                if isinstance(obj, list):
                    for sobj in obj:
                        parents.add_node(sobj)
                else:
                    parents.add_node(obj)

        # And now fill edges
        for item in self:
            if attr1 == "self":
                obj1 = item
            else:
                obj1 = getattr(item, attr1, None)
            obj2 = getattr(item, attr2, None)
            if obj2 is not None:
                if isinstance(obj2, list):
                    for sobj2 in obj2:
                        if isinstance(obj1, list):
                            for sobj1 in obj1:
                                parents.add_edge(sobj1, sobj2)
                        else:
                            parents.add_edge(obj1, sobj2)
                else:
                    if isinstance(obj1, list):
                        for sobj1 in obj1:
                            parents.add_edge(sobj1, obj2)
                    else:
                        parents.add_edge(obj1, obj2)

        # Now get the list of all item in a loop
        items_in_loops = parents.loop_check()

        # and raise errors about it
        for item in items_in_loops:
            logger.error("The %s object '%s'  is part of a circular parent/child chain!", item.my_type, item.get_name())
            r = False

        return r
Example #7
0
    def no_loop_in_parents(self, attr1, attr2):
        """Find loop in dependencies.
        For now, used with the following attributes :
        :(self, parents):                                      host dependencies from host object
        :(host_name, dependent_host_name):                     host dependencies from hostdependencies object
        :(service_description, dependent_service_description): service dependencies from servicedependencies object
        """

        # Ok, we say "from now, no loop :) "
        r = True

        # Create parent graph
        parents = Graph()

        # Start with all items as nodes
        for item in self:
            # Hack to get self here. Used when looping on host and host parent's
            if attr1 == "self":
                obj = item          # obj is a host/service [list]
            else:
                obj = getattr(item, attr1, None)
            if obj is not None:
                if isinstance(obj, list):
                    for sobj in obj:
                        parents.add_node(sobj)
                else:
                    parents.add_node(obj)

        # And now fill edges
        for item in self:
            if attr1 == "self":
                obj1 = item
            else:
                obj1 = getattr(item, attr1, None)
            obj2 = getattr(item, attr2, None)
            if obj2 is not None:
                if isinstance(obj2, list):
                    for sobj2 in obj2:
                        if isinstance(obj1, list):
                            for sobj1 in obj1:
                                parents.add_edge(sobj1, sobj2)
                        else:
                            parents.add_edge(obj1, sobj2)
                else:
                    if isinstance(obj1, list):
                        for sobj1 in obj1:
                            parents.add_edge(sobj1, obj2)
                    else:
                        parents.add_edge(obj1, obj2)

        # Now get the list of all item in a loop
        items_in_loops = parents.loop_check()

        # and raise errors about it
        for item in items_in_loops:
            logger.error("The %s object '%s'  is part of a circular parent/child chain!", item.my_type, item.get_name())
            r = False

        return r