Skip to content

Commit 4f2bbe2

Browse files
author
Quentin Bouget
committed
Enh: auto-computing of hosts for servicedependencies when none defined
What: Create dependencies between services host by host without the need to write long and dull configuration files. Why: Because servicedependencies are rather useful but really complicated to correctly setup right now, especially on large clusters. Currently the host_name, dependent_host_name, hostgroup_name and dependent_hostgroup_name properties do not allow users to define host by host servicedependencies or service to service dependencies at once. How: Users will just need to define the service and the dependent_service descriptions in the servicedependency configuration. The function Servicedependency.explode will then compute the hosts having both the dependent_service and the service depended on, and for these hosts a servicedependency will be created. Example: With this configuration: define host{ ... host_name h0 } define host{ ... host_name h1 } define service{ ... service_description svc0 host_name h0, h1 } define service{ ... service_description svc1 host_name h0, h1 } define servicedependency{ service_description svc0 dependent_service_description svc1 } We will create these servicedependencies: define servicedependency{ service_description svc0 dependent_service_description svc1 host_name h0 } define servicedependency{ service_description svc0 dependent_service_description svc1 host_name h1 } And: - Each couple of service/dependent_service will be processed separately - Tests for the new feature are also in this commit
1 parent 57b3068 commit 4f2bbe2

File tree

8 files changed

+328
-3
lines changed

8 files changed

+328
-3
lines changed

shinken/objects/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1469,7 +1469,7 @@ def explode(self):
14691469
self.hostdependencies.explode(self.hostgroups)
14701470

14711471
# print "Servicedependency"
1472-
self.servicedependencies.explode(self.hostgroups)
1472+
self.servicedependencies.explode(self.hostgroups, self.services)
14731473

14741474
# Serviceescalations hostescalations will create new escalations
14751475
self.serviceescalations.explode(self.escalations)

shinken/objects/servicedependency.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def explode_hostgroup(self, sd, hostgroups):
122122
self.add_item(new_sd)
123123

124124
# We create new servicedep if necessary (host groups and co)
125-
def explode(self, hostgroups):
125+
def explode(self, hostgroups, services):
126126
# The "old" services will be removed. All services with
127127
# more than one host or a host group will be in it
128128
srvdep_to_remove = []
@@ -203,9 +203,41 @@ def explode(self, hostgroups):
203203
self.add_item(new_sd)
204204
# Ok so we can remove the old one, once
205205
if not removed_once:
206-
removed_once = true
206+
removed_once = True
207207
srvdep_to_remove.append(id)
208208

209+
if dep_couples == []:
210+
special_singles = {}
211+
for sname in snames:
212+
special_singles[sname] = set()
213+
for service in services:
214+
sname = service.service_description
215+
if sname in snames:
216+
special_singles[sname].add(service.host_name)
217+
218+
special_dep_singles = {}
219+
for sname in dep_snames:
220+
special_dep_singles[sname] = set()
221+
for service in services:
222+
sname = service.service_description
223+
if sname in dep_snames:
224+
special_dep_singles[sname].add(service.host_name)
225+
226+
for dep_sname in special_dep_singles:
227+
for sname in special_singles:
228+
hnames_in_both = special_singles[sname]
229+
hnames_in_both &= special_dep_singles[dep_sname]
230+
for hname in hnames_in_both:
231+
new_sd = sd.copy()
232+
new_sd.host_name = hname
233+
new_sd.service_description = sname
234+
new_sd.dependent_host_name = hname
235+
new_sd.dependent_service_description = dep_sname
236+
self.add_item(new_sd)
237+
if not removed_once:
238+
removed_once = True
239+
srvdep_to_remove.append(id)
240+
209241
self.delete_servicesdep_by_id(srvdep_to_remove)
210242

211243
def linkify(self, hosts, services, timeperiods):
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
define command{
2+
command_name nothing
3+
command_line /bin/true
4+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
define host {
2+
use generic-host
3+
host_name h0
4+
address 127.0.0.1
5+
}
6+
7+
define host {
8+
use generic-host
9+
host_name h1
10+
address 127.0.0.2
11+
}
12+
13+
define host {
14+
use generic-host
15+
host_name h2
16+
address 127.0.0.3
17+
}
18+
19+
define host {
20+
use generic-host
21+
host_name h3
22+
address 127.0.0.4
23+
}
24+
25+
define host {
26+
use generic-host
27+
host_name h4
28+
address 127.0.0.5
29+
}
30+
31+
define host {
32+
use generic-host
33+
host_name h5
34+
address 127.0.0.6
35+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
define servicedependency{
2+
service_description svc0
3+
dependent_service_description svc2
4+
}
5+
6+
define servicedependency{
7+
service_description svc1
8+
dependent_service_description svc2, svc3
9+
}
10+
11+
define servicedependency{
12+
service_description svc0
13+
dependent_service_description svc3
14+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
define service{
2+
active_checks_enabled 1
3+
check_freshness 0
4+
check_interval 1
5+
check_period 24x7
6+
contact_groups test_contact
7+
event_handler_enabled 1
8+
failure_prediction_enabled 1
9+
flap_detection_enabled 1
10+
is_volatile 0
11+
max_check_attempts 2
12+
name generic-service
13+
notification_interval 1
14+
notification_options w,u,c,r,f,s
15+
notification_period 24x7
16+
notifications_enabled 1
17+
obsess_over_service 1
18+
parallelize_check 1
19+
passive_checks_enabled 1
20+
process_perf_data 1
21+
register 0
22+
retain_nonstatus_information 1
23+
retain_status_information 1
24+
retry_interval 1
25+
}
26+
27+
define service {
28+
use generic-service
29+
service_description svc0
30+
check_command nothing
31+
host_name h0, h1, h2
32+
}
33+
34+
define service {
35+
use generic-service
36+
service_description svc1
37+
check_command nothing
38+
host_name h1, h2, h3, h4
39+
}
40+
41+
define service {
42+
use generic-service
43+
service_description svc2
44+
check_command nothing
45+
host_name h0, h1, h2, h3, h4, h5
46+
}
47+
48+
define service {
49+
use generic-service
50+
service_description svc3
51+
check_command nothing
52+
host_name h3, h4, h5
53+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
accept_passive_host_checks=1
2+
accept_passive_service_checks=1
3+
additional_freshness_latency=15
4+
admin_email=shinken@localhost
5+
admin_pager=shinken@localhost
6+
auto_reschedule_checks=0
7+
auto_rescheduling_interval=30
8+
auto_rescheduling_window=180
9+
cached_host_check_horizon=15
10+
cached_service_check_horizon=15
11+
cfg_file=servicedependency_auto_computing/hosts.cfg
12+
cfg_file=servicedependency_auto_computing/services.cfg
13+
cfg_file=servicedependency_auto_computing/servicedependencies.cfg
14+
cfg_file=servicedependency_auto_computing/commands.cfg
15+
cfg_file=standard/commands.cfg
16+
cfg_file=standard/contacts.cfg
17+
cfg_file=standard/timeperiods.cfg
18+
check_external_commands=1
19+
check_for_orphaned_hosts=1
20+
check_for_orphaned_services=1
21+
check_host_freshness=0
22+
check_result_path=var/spool/checkresults
23+
check_result_reaper_frequency=10
24+
check_service_freshness=1
25+
command_check_interval=-1
26+
command_file=var/shinken.cmd
27+
daemon_dumps_core=0
28+
date_format=iso8601
29+
debug_file=var/shinken.debug
30+
debug_level=112
31+
debug_verbosity=1
32+
enable_embedded_perl=0
33+
enable_environment_macros=1
34+
enable_event_handlers=1
35+
enable_flap_detection=0
36+
enable_notifications=1
37+
enable_predictive_host_dependency_checks=1
38+
enable_predictive_service_dependency_checks=1
39+
event_broker_options=-1
40+
event_handler_timeout=30
41+
execute_host_checks=1
42+
execute_service_checks=1
43+
external_command_buffer_slots=4096
44+
high_host_flap_threshold=20
45+
high_service_flap_threshold=20
46+
host_check_timeout=30
47+
host_freshness_check_interval=60
48+
host_inter_check_delay_method=s
49+
illegal_macro_output_chars=`~\$&|'"<>
50+
illegal_object_name_chars=`~!\$%^&*|'"<>?,()=
51+
interval_length=60
52+
lock_file=var/shinken.pid
53+
log_archive_path=var/archives
54+
log_event_handlers=1
55+
log_external_commands=1
56+
log_file=var/shinken.log
57+
log_host_retries=1
58+
log_initial_states=1
59+
log_notifications=1
60+
log_passive_checks=1
61+
log_rotation_method=d
62+
log_service_retries=1
63+
low_host_flap_threshold=5
64+
low_service_flap_threshold=5
65+
max_check_result_file_age=3600
66+
max_check_result_reaper_time=30
67+
max_concurrent_checks=0
68+
max_debug_file_size=1000000
69+
max_host_check_spread=30
70+
max_service_check_spread=30
71+
shinken_group=shinken
72+
shinken_user=shinken
73+
notification_timeout=30
74+
object_cache_file=var/objects.cache
75+
obsess_over_hosts=0
76+
obsess_over_services=0
77+
ocsp_timeout=5
78+
p1_file=/usr/local/shinken/bin/p1.pl
79+
passive_host_checks_are_soft=0
80+
perfdata_timeout=5
81+
precached_object_file=var/objects.precache
82+
process_performance_data=1
83+
resource_file=resource.cfg
84+
retain_state_information=1
85+
retained_contact_host_attribute_mask=0
86+
retained_contact_service_attribute_mask=0
87+
retained_host_attribute_mask=0
88+
retained_process_host_attribute_mask=0
89+
retained_process_service_attribute_mask=0
90+
retained_service_attribute_mask=0
91+
retention_update_interval=60
92+
service_check_timeout=60
93+
service_freshness_check_interval=60
94+
service_inter_check_delay_method=s
95+
service_interleave_factor=s
96+
sleep_time=0.25
97+
soft_state_dependencies=0
98+
state_retention_file=var/retention.dat
99+
status_file=var/status.dat
100+
status_update_interval=5
101+
temp_file=tmp/shinken.tmp
102+
temp_path=var/tmp
103+
translate_passive_host_checks=0
104+
use_aggressive_host_checking=0
105+
use_embedded_perl_implicitly=0
106+
use_large_installation_tweaks=0
107+
use_regexp_matching=0
108+
use_retained_program_state=1
109+
use_retained_scheduling_info=1
110+
use_syslog=0
111+
use_true_regexp_matching=0
112+
enable_problem_impacts_states_change=1
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env python
2+
# Copyright (C) 2009-2014:
3+
# Gabes Jean, naparuba@gmail.com
4+
# Gerhard Lausser, Gerhard.Lausser@consol.de
5+
#
6+
# This file is part of Shinken.
7+
#
8+
# Shinken is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU Affero General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# Shinken is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU Affero General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU Affero General Public License
19+
# along with Shinken. If not, see <http://www.gnu.org/licenses/>.
20+
21+
#
22+
# This file is used to test reading and processing of config files
23+
#
24+
25+
from shinken_test import ShinkenTest, unittest
26+
27+
28+
class TestServiceDependencyAutoComputing(ShinkenTest):
29+
30+
def setUp(self):
31+
self.setup_with_file('etc/shinken_servicedependency_auto_computing.cfg')
32+
if hasattr(self, 'sched'):
33+
# There are no common host between svc0 and svc3 therefore
34+
# no servicedependency can be created and shinken should
35+
# print the error msg :
36+
# "[Shinken] [items] Service svc3 not found for host
37+
# [Shinken] [items] Service svc0 not found for host
38+
# [Shinken] servicedependencies conf incorrect!!"
39+
self.fail("The configuration should not be correct")
40+
41+
def test_matching_svc(self):
42+
services = self.conf.services
43+
svcs = []
44+
svcs.append(services.find_srv_by_name_and_hostname('h0', 'svc0'))
45+
svcs.append(services.find_srv_by_name_and_hostname('h1', 'svc0'))
46+
svcs.append(services.find_srv_by_name_and_hostname('h2', 'svc0'))
47+
for svc in svcs:
48+
self.assertIsNotNone(svc)
49+
dep_svcs = [info_dep[0] for info_dep in svc.act_depend_of_me]
50+
self.assertNotEqual(dep_svcs, [])
51+
for dep_svc in dep_svcs:
52+
self.assertEqual(dep_svc.host_name, svc.host_name)
53+
self.assertEqual(dep_svc.service_description, 'svc2')
54+
55+
def test_multiple_srv_description(self):
56+
services = self.conf.services
57+
expected_dep_svc = {'h1': ['svc2'], 'h2': ['svc2'],\
58+
'h3': ['svc2', 'svc3'], 'h4': ['svc2', 'svc3']}
59+
svcs = []
60+
svcs.append(services.find_srv_by_name_and_hostname('h1', 'svc1'))
61+
svcs.append(services.find_srv_by_name_and_hostname('h2', 'svc1'))
62+
svcs.append(services.find_srv_by_name_and_hostname('h3', 'svc1'))
63+
svcs.append(services.find_srv_by_name_and_hostname('h4', 'svc1'))
64+
for svc in svcs:
65+
self.assertIsNotNone(svc)
66+
dep_svcs = [info_dep[0] for info_dep in svc.act_depend_of_me]
67+
description = expected_dep_svc[svc.host_name]
68+
for dep_svc in dep_svcs:
69+
self.assertTrue(dep_svc.service_description in description)
70+
description.remove(dep_svc.service_description)
71+
self.assertEqual(description, [])
72+
73+
74+
if __name__ == '__main__':
75+
unittest.main()

0 commit comments

Comments
 (0)