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