Source code for alignak.objects.servicegroup

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015-2015: Alignak team, see AUTHORS.txt file for contributors
#
# This file is part of Alignak.
#
# Alignak is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Alignak is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Alignak.  If not, see <http://www.gnu.org/licenses/>.
#
#
# This file incorporates work covered by the following copyright and
# permission notice:
#
#  Copyright (C) 2009-2014:
#     Hartmut Goebel, h.goebel@goebel-consult.de
#     Guillaume Bour, guillaume@bour.cc
#     Nicolas Dupeux, nicolas@dupeux.net
#     Grégory Starck, g.starck@gmail.com
#     Gerhard Lausser, gerhard.lausser@consol.de
#     Sebastien Coavoux, s.coavoux@free.fr
#     Christophe Simon, geektophe@gmail.com
#     Jean Gabes, naparuba@gmail.com
#     Romain Forlot, rforlot@yahoo.com

#  This file is part of Shinken.
#
#  Shinken is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Affero General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  Shinken is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Affero General Public License for more details.
#
#  You should have received a copy of the GNU Affero General Public License
#  along with Shinken.  If not, see <http://www.gnu.org/licenses/>.

"""
This module provide Servicegroup and Servicegroups classes used to group services
"""

from alignak.property import StringProp, IntegerProp
from alignak.log import logger

from .itemgroup import Itemgroup, Itemgroups


[docs]class Servicegroup(Itemgroup): """ Class to manage a servicegroup A servicegroup is used to group services """ _id = 1 # zero is always a little bit special... like in database my_type = 'servicegroup' properties = Itemgroup.properties.copy() properties.update({ '_id': IntegerProp(default=0, fill_brok=['full_status']), 'servicegroup_name': StringProp(fill_brok=['full_status']), 'alias': StringProp(fill_brok=['full_status']), 'notes': StringProp(default='', fill_brok=['full_status']), 'notes_url': StringProp(default='', fill_brok=['full_status']), 'action_url': StringProp(default='', fill_brok=['full_status']), }) macros = { 'SERVICEGROUPALIAS': 'alias', 'SERVICEGROUPMEMBERS': 'members', 'SERVICEGROUPNOTES': 'notes', 'SERVICEGROUPNOTESURL': 'notes_url', 'SERVICEGROUPACTIONURL': 'action_url' }
[docs] def get_services(self): """ Get services of this servicegroup :return: list of services (members) :rtype: list """ if getattr(self, 'members', None) is not None: return self.members else: return []
[docs] def get_name(self): """ Get the name of the servicegrop :return: the servicegroup name string :rtype: str """ return self.servicegroup_name
[docs] def get_servicegroup_members(self): """ Get list of members of this servicegroup :return: list of services (members) :rtype: list | str """ # TODO: a Servicegroup instance should always have its servicegroup_members defined. if hasattr(self, 'servicegroup_members'): return [m.strip() for m in self.servicegroup_members.split(',')] else: return []
[docs] def get_services_by_explosion(self, servicegroups): """ Get all services of this servicegroup and add it in members container :param servicegroups: servicegroups object :type servicegroups: object :return: return empty string or list of members :rtype: str or list """ # First we tag the hg so it will not be explode # if a son of it already call it self.already_explode = True # Now the recursive part # rec_tag is set to False every HG we explode # so if True here, it must be a loop in HG # calls... not GOOD! if self.rec_tag: logger.error("[servicegroup::%s] got a loop in servicegroup definition", self.get_name()) if hasattr(self, 'members'): return self.members else: return '' # Ok, not a loop, we tag it and continue self.rec_tag = True sg_mbrs = self.get_servicegroup_members() for sg_mbr in sg_mbrs: servicegroup = servicegroups.find_by_name(sg_mbr.strip()) if servicegroup is not None: value = servicegroup.get_services_by_explosion(servicegroups) if value is not None: self.add_string_member(value) if hasattr(self, 'members'): return self.members else: return ''
[docs]class Servicegroups(Itemgroups): """ Class to manage all servicegroups """ name_property = "servicegroup_name" # is used for finding servicegroup inner_class = Servicegroup
[docs] def linkify(self, hosts, services): """ Link services with host :param hosts: hosts object :type hosts: object :param services: services object :type services: object :return: None """ self.linkify_sg_by_srv(hosts, services)
[docs] def linkify_sg_by_srv(self, hosts, services): """ We just search for each host the id of the host and replace the name by the id TODO: very slow for hight services, so search with host list, not service one :param hosts: hosts object :type hosts: object :param services: services object :type services: object :return: None """ for servicegroup in self: mbrs = servicegroup.get_services() # The new member list, in id new_mbrs = [] seek = 0 host_name = '' if len(mbrs) == 1 and mbrs[0] != '': servicegroup.add_string_unknown_member('%s' % mbrs[0]) for mbr in mbrs: if seek % 2 == 0: host_name = mbr.strip() else: service_desc = mbr.strip() find = services.find_srv_by_name_and_hostname(host_name, service_desc) if find is not None: new_mbrs.append(find) else: host = hosts.find_by_name(host_name) if not (host and host.is_excluded_for_sdesc(service_desc)): servicegroup.add_string_unknown_member('%s,%s' % (host_name, service_desc)) elif host: self.configuration_warnings.append( 'servicegroup %r : %s is excluded from the services of the host %s' % (servicegroup, service_desc, host_name) ) seek += 1 # Make members uniq new_mbrs = list(set(new_mbrs)) # We find the id, we replace the names servicegroup.replace_members(new_mbrs) for serv in servicegroup.members: serv.servicegroups.append(servicegroup) # and make this uniq serv.servicegroups = list(set(serv.servicegroups))
[docs] def add_member(self, cname, sgname): """ Add a member (service) to this servicegroup :param cname: member (service) name :type cname: str :param sgname: servicegroup name :type sgname: str :return: None """ svcgp = self.find_by_name(sgname) # if the id do not exist, create the cg if svcgp is None: svcgp = Servicegroup({'servicegroup_name': sgname, 'alias': sgname, 'members': cname}) self.add(svcgp) else: svcgp.add_string_member(cname)
[docs] def explode(self): """ Get services and put them in members container :return: None """ # We do not want a same hg to be explode again and again # so we tag it for servicegroup in self: servicegroup.already_explode = False for servicegroup in self: if hasattr(servicegroup, 'servicegroup_members') and not \ servicegroup.already_explode: # get_services_by_explosion is a recursive # function, so we must tag hg so we do not loop for sg2 in self: sg2.rec_tag = False servicegroup.get_services_by_explosion(self) # We clean the tags for servicegroup in self: try: del servicegroup.rec_tag except AttributeError: pass del servicegroup.already_explode