Skip to content

Commit

Permalink
Merge pull request #2010 from geektophe/enh_strict_object_coflict_policy
Browse files Browse the repository at this point in the history
Enh: added strict object name conflict policy
  • Loading branch information
geektophe committed May 10, 2021
2 parents 0e51d49 + d680640 commit fc4a0fe
Show file tree
Hide file tree
Showing 19 changed files with 337 additions and 24 deletions.
16 changes: 16 additions & 0 deletions doc/source/03_configuration/configmain.rst
Original file line number Diff line number Diff line change
Expand Up @@ -667,3 +667,19 @@ Default:


On some distributions, dealing with large configuration can result in memory leaks when the new configuration is sent, because of an inneficient memory cleanup in the python interpreter. This options enables a more aggressive memory routine that forces unused memory to be freed.

Object name conflict policy
---------------------------

::

conflict_policy=[loose/strict]

Default:

::

conflict_policy=loose


When more than one object are created with the same name and no definition order has been specified, the default behavior is to raise a warning message, and keep the last definition. When enabling strict conflict naming policy, this results in an error that prevents the configuration from being loaded. This is typically used to enforce more precise objects definition, and avoid silent collisions lading to unexpected behavior.
14 changes: 12 additions & 2 deletions shinken/objects/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,15 @@ class Config(Item):
'modules_dir':
StringProp(default='/var/lib/shinken/modules'),

'conflict_policy':
StringProp(default='loose'),

'use_local_log':
BoolProp(default=True),

'log_level':
LogLevelProp(default='WARNING'),


'local_log':
StringProp(default='/var/log/shinken/arbiterd.log'),

Expand Down Expand Up @@ -798,6 +800,9 @@ def __init__(self):
self.triggers = Triggers({})
self.packs_dirs = []
self.packs = Packs({})
# Initialize conflict_policy soon as it's required during object lists
# creation.
self.conflict_policy = self.properties["conflict_policy"].default

def get_name(self):
return 'global configuration file'
Expand Down Expand Up @@ -962,6 +967,11 @@ def read_config(self, files):
continue
# Ok it's a valid one, I keep it
self.triggers_dirs.append(trig_dir_name)
# Early read conflict_policy because it's necessary when
# parsing configuration files
elif re.search("^conflict_policy", line):
elts = line.split('=', 1)
self.conflict_policy = elts[1]

config = res.getvalue()
res.close()
Expand Down Expand Up @@ -1125,7 +1135,7 @@ def create_objects_for_type(self, raw_objects, type):
o.old_properties_names_to_new()
lst.append(o)
# we create the objects Class and we set it in prop
setattr(self, prop, clss(lst, initial_index))
setattr(self, prop, clss(lst, initial_index, self.conflict_policy))


# Here arbiter and modules objects should be prepare and link
Expand Down
24 changes: 18 additions & 6 deletions shinken/objects/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,8 @@ def _get_name(self):


class Items(object):
def __init__(self, items, index_items=True):
def __init__(self, items, index_items=True, conflict_policy="loose"):
self.conflict_policy = conflict_policy
self.items = {}
self.name_to_item = {}
self.templates = {}
Expand Down Expand Up @@ -803,11 +804,22 @@ def manage_conflict(self, item, name):
else:
# Don't know which one to keep, lastly defined has precedence
objcls = getattr(self.inner_class, "my_type", "[unknown]")
mesg = "duplicate %s name %s%s, using lastly defined. You may " \
"manually set the definition_order parameter to avoid " \
"this message." % \
(objcls, name, self.get_source(item))
item.configuration_warnings.append(mesg)
if objcls == "service":
objname = "%s/%s" % (item.host_name, item.service_description)
else:
objname = item.get_name()
if self.conflict_policy == "strict":
mesg = "duplicate %s name %s%s. "\
"You have to manually set the definition_order " \
"parameter to avoid this error." % \
(objcls, objname, self.get_source(item))
item.configuration_errors.append(mesg)
else:
mesg = "duplicate %s name %s%s, using lastly defined. "\
"You may manually set the definition_order " \
"parameter to avoid this message." % \
(objcls, objname, self.get_source(item))
item.configuration_warnings.append(mesg)
if item.is_tpl():
self.remove_template(existing)
else:
Expand Down
3 changes: 1 addition & 2 deletions test/docker-files/docker-file-DEV-debian9-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ RUN pip install Crypto
RUN pip install pygments
RUN pip install coveralls
RUN pip install nose-cov
RUN pip install unittest2
RUN apt-get install -y python-cherrypy3
RUN pip install rsa
# The internal yaml seems to not be used, thanks nose
Expand Down Expand Up @@ -45,4 +44,4 @@ ENTRYPOINT /bin/bash
#ENTRYPOINT cd test; python test_raft_multiprocess.py TestRaftMultiProcess.test_raft_large_leader_election
#ENTRYPOINT cd test; python test_raft.py
#ENTRYPOINT cd test;python test_yaml.py
#ENTRYPOINT opsbro agent start
#ENTRYPOINT opsbro agent start
3 changes: 1 addition & 2 deletions test/docker-files/docker-file-DEV-debian9-test-python.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ RUN pip install Crypto
RUN pip install pygments
RUN pip install coveralls
RUN pip install nose-cov
RUN pip install unittest2
RUN apt-get install -y python-cherrypy3
RUN pip install rsa
# The internal yaml seems to not be used, thanks nose
Expand All @@ -34,4 +33,4 @@ ENTRYPOINT nosetests -xv --processes=1 --process-timeout=300 --process-restar
#ENTRYPOINT cd test; python test_raft_multiprocess.py TestRaftMultiProcess.test_raft_large_leader_election
#ENTRYPOINT cd test; python test_raft.py
#ENTRYPOINT cd test;python test_yaml.py
#ENTRYPOINT opsbro agent start
#ENTRYPOINT opsbro agent start
3 changes: 1 addition & 2 deletions test/docker-files/docker-file-UNIT-TEST-python2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ RUN pip install Crypto
RUN pip install pygments
RUN pip install coveralls
RUN pip install nose-cov
RUN pip install unittest2
RUN apt-get install -y python-cherrypy3
RUN pip install rsa
# The internal yaml seems to not be used, thanks nose
Expand Down Expand Up @@ -48,4 +47,4 @@ ENTRYPOINT cd test;./quick_tests.sh
#ENTRYPOINT cd test; python test_raft_multiprocess.py TestRaftMultiProcess.test_raft_large_leader_election
#ENTRYPOINT cd test; python test_raft.py
#ENTRYPOINT cd test;python test_yaml.py
#ENTRYPOINT opsbro agent start
#ENTRYPOINT opsbro agent start
43 changes: 43 additions & 0 deletions test/etc/conflict_policy/commands.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
define command{
command_name check-host-alive
command_line $USER1$/test_hostcheck.pl --type=$ARG1$ --failchance=2% --previous-state=$HOSTSTATE$ --state-duration=$HOSTDURATIONSEC$ --hostname $HOSTNAME$
}
define command{
command_name check-host-alive-parent
command_line $USER1$/test_hostcheck.pl --type=$ARG1$ --failchance=2% --previous-state=$HOSTSTATE$ --state-duration=$HOSTDURATIONSEC$ --parent-state=$ARG2$ --hostname $HOSTNAME$
}
define command{
command_name notify-host
#command_line sleep 1 && /bin/true
command_line $USER1$/notifier.pl --hostname $HOSTNAME$ --notificationtype $NOTIFICATIONTYPE$ --hoststate $HOSTSTATE$ --hostoutput $HOSTOUTPUT$ --longdatetime $LONGDATETIME$ --hostattempt $HOSTATTEMPT$ --hoststatetype $HOSTSTATETYPE$
}
define command{
command_name notify-service
command_line $USER1$/notifier.pl --hostname $HOSTNAME$ --servicedesc $SERVICEDESC$ --notificationtype $NOTIFICATIONTYPE$ --servicestate $SERVICESTATE$ --serviceoutput $SERVICEOUTPUT$ --longdatetime $LONGDATETIME$ --serviceattempt $SERVICEATTEMPT$ --servicestatetype $SERVICESTATETYPE$
#command_line sleep 1 && /bin/true
}
define command{
command_name check_service
command_line $USER1$/test_servicecheck.pl --type=$ARG1$ --failchance=5% --previous-state=$SERVICESTATE$ --state-duration=$SERVICEDURATIONSEC$ --total-critical-on-host=$TOTALHOSTSERVICESCRITICAL$ --total-warning-on-host=$TOTALHOSTSERVICESWARNING$ --hostname $HOSTNAME$ --servicedesc $SERVICEDESC$ --custom $_SERVICECUSTNAME$
}
define command{
command_name eventhandler
command_line $USER1$/test_eventhandler.pl $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$
}
define command{
command_name special_macro
command_line $USER1$/nothing $ARG1$
}



define command{
command_name general
command_line $USER1$/general
}


define command{
command_name specific
command_line $USER1$/specific
}
71 changes: 71 additions & 0 deletions test/etc/conflict_policy/test_specific.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
define host{
host_name test_host_specific
use specific,generic,generic-host
}

define host{
host_name test_host_generic
use generic,generic-host
}

define host{
host_name test_host_conflict
use generic-host
}

define host{
host_name test_host_conflict
use generic-host
}

define host{
name generic
register 0
}

define host{
name specific
register 0
}

define host{
name template_conflict
register 0
}

define host{
name template_conflict
register 0
}

define service{
register 0
service_description ZE-SERVICE
host_name generic
check_command general
use generic-service
}

define service{
register 0
service_description ZE-SERVICE
host_name specific
check_command specific
use generic-service
}

define service{
register 0
service_description test_service_conflict
host_name generic
check_command general
use generic-service
}

define service{
register 0
service_description test_service_conflict
host_name specific
check_command specific
use generic-service
}
121 changes: 121 additions & 0 deletions test/etc/shinken_conflict_policy.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
accept_passive_host_checks=1
accept_passive_service_checks=1
additional_freshness_latency=15
admin_email=shinken@localhost
admin_pager=shinken@localhost
auto_reschedule_checks=0
auto_rescheduling_interval=30
auto_rescheduling_window=180
cached_host_check_horizon=15
cached_service_check_horizon=15
cfg_file=standard/hosts.cfg
cfg_file=standard/services.cfg
cfg_file=standard/contacts.cfg
cfg_file=conflict_policy/commands.cfg
cfg_file=conflict_policy/test_specific.cfg
cfg_file=standard/timeperiods.cfg
cfg_file=standard/hostgroups.cfg
cfg_file=standard/servicegroups.cfg
cfg_file=standard/shinken-specific.cfg
check_external_commands=1
check_for_orphaned_hosts=1
check_for_orphaned_services=1
check_host_freshness=0
check_result_path=var/spool/checkresults
check_result_reaper_frequency=10
check_service_freshness=1
command_check_interval=-1
command_file=var/shinken.cmd
conflict_policy=strict
daemon_dumps_core=0
date_format=iso8601
debug_file=var/shinken.debug
debug_level=112
debug_verbosity=1
enable_embedded_perl=0
enable_environment_macros=1
enable_event_handlers=1
enable_flap_detection=0
enable_notifications=1
enable_predictive_host_dependency_checks=1
enable_predictive_service_dependency_checks=1
event_broker_options=-1
event_handler_timeout=30
execute_host_checks=1
execute_service_checks=1
external_command_buffer_slots=4096
high_host_flap_threshold=20
high_service_flap_threshold=20
host_check_timeout=30
host_freshness_check_interval=60
host_inter_check_delay_method=s
illegal_macro_output_chars=`~\$&|'"<>
illegal_object_name_chars=`~!\$%^&*|'"<>?,()=
interval_length=60
lock_file=var/shinken.pid
log_archive_path=var/archives
log_event_handlers=1
log_external_commands=1
log_file=var/shinken.log
log_host_retries=1
log_initial_states=0
log_notifications=1
log_passive_checks=1
log_rotation_method=d
log_service_retries=1
low_host_flap_threshold=5
low_service_flap_threshold=5
max_check_result_file_age=3600
max_check_result_reaper_time=30
max_concurrent_checks=0
max_debug_file_size=1000000
max_host_check_spread=30
max_service_check_spread=30
shinken_group=shinken
shinken_user=shinken
notification_timeout=30
object_cache_file=var/objects.cache
obsess_over_hosts=0
obsess_over_services=0
ocsp_timeout=5
#p1_file=/tmp/test_shinken/plugins/p1.pl
p1_file=/usr/local/shinken/bin/p1.pl
passive_host_checks_are_soft=0
perfdata_timeout=5
precached_object_file=var/objects.precache
process_performance_data=1
resource_file=resource.cfg
retain_state_information=1
retained_contact_host_attribute_mask=0
retained_contact_service_attribute_mask=0
retained_host_attribute_mask=0
retained_process_host_attribute_mask=0
retained_process_service_attribute_mask=0
retained_service_attribute_mask=0
retention_update_interval=60
service_check_timeout=60
service_freshness_check_interval=60
service_inter_check_delay_method=s
service_interleave_factor=s
##shinken_group=shinken
##shinken_user=shinken
#shinken_group=shinken
#shinken_user=shinken
sleep_time=0.25
soft_state_dependencies=0
state_retention_file=var/retention.dat
status_file=var/status.dat
status_update_interval=5
temp_file=tmp/shinken.tmp
temp_path=var/tmp
translate_passive_host_checks=0
use_aggressive_host_checking=0
use_embedded_perl_implicitly=0
use_large_installation_tweaks=0
use_regexp_matching=0
use_retained_program_state=1
use_retained_scheduling_info=1
use_syslog=0
use_true_regexp_matching=0
enable_problem_impacts_states_change=1
no_event_handlers_during_downtimes=0
1 change: 0 additions & 1 deletion test/jenkins/requirements.tests.freeze
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ wsgiref==0.1.2
pycurl
importlib
mock
unittest2

0 comments on commit fc4a0fe

Please sign in to comment.