PageRenderTime 80ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/bin/lib/NConf/ExportNagios.pm

https://github.com/jvogt-swp/development
Perl | 1722 lines | 1181 code | 257 blank | 284 comment | 262 complexity | 10f55a01fab3224c8fa68c89d26a381c MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. ##############################################################################
  2. # "NConf::ExportNagios" library
  3. # A collection of shared functions for the NConf Perl scripts.
  4. # Functions needed to generate and export Nagios configuration files from NConf.
  5. #
  6. # Version 0.3
  7. # Written by Angelo Gargiulo
  8. #
  9. # Revision history:
  10. # 2009-10-08 v0.1 A. Gargiulo First release
  11. # 2010-01-21 v0.2 A. Gargiulo Removed hostextinfo/serviceextinfo items
  12. # 2010-04-19 v0.3 A. Gargiulo Changed the way global/server-specific files are generated
  13. #
  14. # To-Do:
  15. # This module was migrated from the former generate_config.pl script.
  16. # Functions which access the database need to be consolidated with
  17. # NConf::DB::Read, if possible.
  18. #
  19. ##############################################################################
  20. package NConf::ExportNagios;
  21. use strict;
  22. use Exporter;
  23. use NConf;
  24. use NConf::DB;
  25. use NConf::DB::Read;
  26. use NConf::Helpers;
  27. use NConf::Logger;
  28. use Tie::IxHash; # preserve hash order
  29. ##############################################################################
  30. ### I N I T ##################################################################
  31. ##############################################################################
  32. BEGIN {
  33. use vars qw(@ISA @EXPORT @EXPORT_OK);
  34. @ISA = qw(NConf);
  35. @EXPORT = qw(@NConf::EXPORT create_monitor_config create_collector_config create_global_config);
  36. @EXPORT_OK = qw(@NConf::EXPORT_OK);
  37. }
  38. # set loglevel
  39. my $loglevel = &readNConfConfig(NC_CONFDIR."/nconf.php","DEBUG_GENERATE","scalar",1);
  40. unless($loglevel =~ /^[1245]$/){$loglevel=3}
  41. &setLoglevel($loglevel);
  42. # global vars
  43. use vars qw($fattr $fval); # Superglobals
  44. my ($root_path, $output_path, $global_path, $test_path, $monitor_path, $collector_path, $check_static_cfg);
  45. my (@superadmins, @oncall_groups, @global_cfg_files, @server_cfg_files, @static_cfg);
  46. my (%class_info, %checkcommand_info, %files_written);
  47. # fetch options from main NConf config
  48. $root_path = &readNConfConfig(NC_CONFDIR."/nconf.php","NCONFDIR","scalar");
  49. @superadmins = &readNConfConfig(NC_CONFDIR."/nconf.php","SUPERADMIN_GROUPS","array");
  50. @oncall_groups = &readNConfConfig(NC_CONFDIR."/nconf.php","ONCALL_GROUPS","array");
  51. @static_cfg = &readNConfConfig(NC_CONFDIR."/nconf.php","STATIC_CONFIG","array");
  52. $check_static_cfg = &readNConfConfig(NC_CONFDIR."/nconf.php","CHECK_STATIC_SYNTAX","scalar",1);
  53. if($check_static_cfg ne 0){$check_static_cfg=1}
  54. # fetch and cache all classes in ConfigClasses table
  55. %class_info = &getConfigClasses();
  56. # fetch and cache all checkcommands and their attributes/values
  57. %checkcommand_info = &fetch_cmd_info();
  58. # define output structure
  59. $output_path = "$root_path/temp";
  60. $test_path = "$root_path/temp/test";
  61. $global_path = "$output_path/global";
  62. my $timestamp = time();
  63. my $mon_count = 0;
  64. my $progress_step = 0;
  65. my $progress_status = 0;
  66. # calculate amount of "steps" for progress bar
  67. &define_progress_steps;
  68. ##############################################################################
  69. ### S U B S ##################################################################
  70. ##############################################################################
  71. # SUB create_monitor_config
  72. # Generate Nagios configuration files for monitor server(s)
  73. sub create_monitor_config {
  74. &logger(5,"Entered create_monitor_config()");
  75. # fetch all monitor servers
  76. my @monitors = &getItems("nagios-monitor",1);
  77. foreach my $row (@monitors){
  78. &logger(3,"Generating config for Nagios-monitor '$row->[1]'");
  79. # store monitor name separately
  80. $NC_macro_values{'NAGIOS_SERVER_NAME'} = $row->[1];
  81. # create output directory
  82. $row->[1] =~ s/-|\s/_/g;
  83. $monitor_path = "$output_path/$row->[1]";
  84. if(-e $monitor_path){rename($monitor_path,$monitor_path."_".time) or &logger(1,"Could not rename $monitor_path")}
  85. &logger(4,"Creating output directory '$monitor_path'");
  86. mkdir($monitor_path,0755) or &logger(1,"Could not create $monitor_path");
  87. # create configuration files for monitor server(s)
  88. &create_monitor_specific_files($row->[0]);
  89. # create nagios.cfg file for monitor server to test generated config
  90. &create_test_cfg($row->[1]);
  91. @server_cfg_files = undef;
  92. $mon_count++;
  93. # increase progress status for web GUI
  94. &set_progress();
  95. }
  96. }
  97. ########################################################################################
  98. # SUB create_collector_config
  99. # Generate Nagios configuration files for collector servers
  100. sub create_collector_config {
  101. &logger(5,"Entered create_collector_config()");
  102. # fetch all collector servers
  103. my @collectors = &getItems("nagios-collector",1);
  104. my $col_count = 0;
  105. foreach my $row (@collectors){
  106. &logger(3,"Generating config for Nagios-collector '$row->[1]'");
  107. # store collector name separately
  108. $NC_macro_values{'NAGIOS_SERVER_NAME'} = $row->[1];
  109. # create output directory
  110. $row->[1] =~ s/-|\s/_/g;
  111. $row->[1] =~ s/Nagios|Icinga/collector/i;
  112. $collector_path = "$output_path/$row->[1]";
  113. if(-e $collector_path){rename($collector_path,$collector_path."_".time) or &logger(1,"[ERROR] Could not rename $collector_path")}
  114. &logger(4,"Creating output directory '$collector_path'");
  115. mkdir($collector_path,0755) or &logger(1,"Could not create $collector_path");
  116. # create configuration files for collector server(s)
  117. &create_collector_specific_files($row->[0]);
  118. # create nagios.cfg file for each collector server to test generated config
  119. &create_test_cfg($row->[1]);
  120. @server_cfg_files = undef;
  121. $col_count++;
  122. # increase progress status for web GUI
  123. &set_progress();
  124. }
  125. unless($col_count > 0){&logger(2,"No collector servers defined. Specify at least one.")}
  126. }
  127. ########################################################################################
  128. # SUB create_global_config
  129. # Process global config files. These only need to be created once.
  130. sub create_global_config {
  131. &logger(5,"Entered create_global_config()");
  132. &logger(3,"Generating global config files");
  133. # create "global" folder
  134. if(-e $global_path){rename($global_path,$global_path."_".$timestamp)}
  135. &logger(4,"Creating output directory '$global_path'");
  136. mkdir($global_path,0755) or &logger(1,"Could not create $global_path");
  137. # iterate through all available ConfigClasses in database
  138. foreach my $class (keys(%class_info)){
  139. # skip collector/monitor specific classes or classes with no 'out_file'
  140. if($class_info{$class}->{'class_type'} ne "global"){next}
  141. # warn if certain Nagios specific items were not exported
  142. unless($class_info{$class}->{'out_file'}){
  143. if($class eq "contact" || $class eq "contactgroup" || $class eq "checkcommand" || $class eq "misccommand" || $class eq "timeperiod"){
  144. &logger(2,"No ".$class."s were exported. Make sure 'out_file' is set properly for the correspondig class.");
  145. }
  146. next;
  147. }
  148. # fetch all object ID's for current class
  149. my @class_items = &getItems("$class");
  150. # write an output file for each class in ConfigClasses table
  151. push(@global_cfg_files, "$global_path/$class_info{$class}->{'out_file'}");
  152. &write_file("$global_path/$class_info{$class}->{'out_file'}","$class","$class_info{$class}->{'nagios_object'}",\@class_items);
  153. # also generate a .htpasswd file, if there are contacts with a password attr
  154. if($class eq "contact"){
  155. &write_htpasswd_file("$global_path/nagios.htpasswd",\@class_items);
  156. }
  157. }
  158. # increase progress status for web GUI
  159. &set_progress();
  160. }
  161. ########################################################################################
  162. # SUB create_monitor_specific_files
  163. # Fetch all monitor-specific data and write configuration files for monitor server(s)
  164. sub create_monitor_specific_files {
  165. &logger(5,"Entered create_monitor_specific_files()");
  166. my $sql = undef;
  167. my @monitor_host_tpl;
  168. my @monitor_srv_tpl_params;
  169. # fetch all host ID's that have a collector assigned (hosts which are monitored)
  170. $sql = "SELECT id_item AS item_id
  171. FROM ConfigItems,ConfigClasses
  172. WHERE id_class=fk_id_class
  173. AND config_class = 'host'
  174. HAVING (SELECT fk_item_linked2 FROM ConfigItems,ItemLinks,ConfigClasses
  175. WHERE fk_item_linked2=id_item
  176. AND id_class=fk_id_class
  177. AND config_class = 'nagios-collector'
  178. AND fk_id_item=item_id) <> ''";
  179. my @hosts1 = &queryExecRead($sql, "Fetching all host ID's that have a collector assigned", "all");
  180. # fetch monitor-specific host-templates, these will be added to each host
  181. $sql = "SELECT attr_name,attr_value,write_to_conf
  182. FROM ConfigValues,ItemLinks,ConfigAttrs
  183. WHERE fk_item_linked2=ConfigValues.fk_id_item
  184. AND id_attr=ItemLinks.fk_id_attr
  185. AND (SELECT naming_attr FROM ConfigAttrs WHERE id_attr=ConfigValues.fk_id_attr)='yes'
  186. AND attr_name = 'host_template'
  187. AND ItemLinks.fk_id_item=$_[0]
  188. ORDER BY cust_order,ordering";
  189. my @host_tpl = &queryExecRead($sql, "Fetching monitor-specific host-templates", "all");
  190. foreach (@host_tpl){push(@monitor_host_tpl,$_)}
  191. # fetch all host ID's that have a collector assigned (hosts which are monitored) and if a host is a collector itself
  192. $sql = "SELECT id_item AS item_id,
  193. (SELECT attr_value FROM ConfigValues,ConfigAttrs
  194. WHERE id_attr=fk_id_attr
  195. AND attr_name='host_is_collector'
  196. AND fk_id_item=item_id) AS host_is_collector
  197. FROM ConfigItems,ConfigClasses
  198. WHERE id_class=fk_id_class
  199. AND config_class = 'host'
  200. HAVING (SELECT fk_item_linked2 FROM ConfigItems,ItemLinks,ConfigClasses
  201. WHERE fk_item_linked2=id_item
  202. AND id_class=fk_id_class
  203. AND config_class = 'nagios-collector'
  204. AND fk_id_item=item_id) <> ''";
  205. my @hosts2 = &queryExecRead($sql, "Fetching all host ID's that have a collector assigned and if a host is a collector itself", "all");
  206. # fetch special monitor-specific options
  207. $sql = "SELECT attr_name,attr_value,write_to_conf FROM ConfigValues,ConfigAttrs
  208. WHERE id_attr=fk_id_attr
  209. AND naming_attr='no'
  210. AND (attr_name='collector_check_freshness'
  211. OR attr_name='collector_freshness_threshold')
  212. AND fk_id_item=$_[0]
  213. ORDER BY ordering";
  214. my @srv_attrs1 = &queryExecRead($sql, "Fetching special monitor-specific options for services", "all");
  215. foreach (@srv_attrs1){push(@monitor_srv_tpl_params,$_)}
  216. # fetch monitor-specific service-templates, these will be added to each service
  217. $sql = "SELECT attr_name,attr_value,write_to_conf
  218. FROM ConfigValues,ItemLinks,ConfigAttrs
  219. WHERE fk_item_linked2=ConfigValues.fk_id_item
  220. AND id_attr=ItemLinks.fk_id_attr
  221. AND (SELECT naming_attr FROM ConfigAttrs WHERE id_attr=ConfigValues.fk_id_attr)='yes'
  222. AND attr_name = 'service_template'
  223. AND ItemLinks.fk_id_item=$_[0]
  224. ORDER BY cust_order,ordering";
  225. my @srv_tpl = &queryExecRead($sql, "Fetching monitor-specific service-templates", "all");
  226. foreach (@srv_tpl){push(@monitor_srv_tpl_params,$_)}
  227. # fetch 'stale_service_command' attr for nagios-monitor
  228. $sql = "SELECT attr_name,attr_value,write_to_conf
  229. FROM ConfigValues,ItemLinks,ConfigAttrs
  230. WHERE fk_item_linked2=ConfigValues.fk_id_item
  231. AND id_attr=ItemLinks.fk_id_attr
  232. AND (SELECT naming_attr FROM ConfigAttrs WHERE id_attr=ConfigValues.fk_id_attr)='yes'
  233. AND attr_name = 'stale_service_command'
  234. AND ItemLinks.fk_id_item=$_[0]
  235. LIMIT 1";
  236. # expect exactly one row to be returned
  237. push(@monitor_srv_tpl_params,&queryExecRead($sql, "Fetching 'stale_service_command' attr", "all"));
  238. # fetch all service ID's of hosts that have a collector assigned and which are not disabled, also pass if a host is a collector itself
  239. my @services = undef;
  240. foreach my $host (@hosts2){
  241. $sql = "SELECT ItemLinks.fk_id_item AS item_id,'','$host->[0]','$host->[1]' FROM ConfigValues,ItemLinks,ConfigAttrs,ConfigClasses
  242. WHERE ItemLinks.fk_id_item=ConfigValues.fk_id_item
  243. AND id_attr=ItemLinks.fk_id_attr
  244. AND fk_id_class=id_class
  245. AND config_class = 'service'
  246. AND (SELECT naming_attr FROM ConfigAttrs WHERE id_attr=ConfigValues.fk_id_attr)='yes'
  247. AND ItemLinks.fk_item_linked2='$host->[0]'
  248. HAVING ((SELECT attr_value FROM ConfigValues, ConfigAttrs
  249. WHERE id_attr=fk_id_attr AND attr_name='service_enabled' AND fk_id_item=item_id) <> 'no'
  250. OR (SELECT attr_value FROM ConfigValues, ConfigAttrs
  251. WHERE id_attr=fk_id_attr AND attr_name='service_enabled' AND fk_id_item=item_id) IS NULL)
  252. ORDER BY attr_value";
  253. my @queryref = &queryExecRead($sql, "Fetching service ID's for host '$host->[0]', assigning collector to service", "all");
  254. foreach my $service (@queryref){push(@services, $service)}
  255. }
  256. # remove first array element if it's empty
  257. unless($services[0]){shift(@services)}
  258. # write monitor-specific classes to cfg file
  259. foreach my $config_class (keys(%class_info)){
  260. if($class_info{$config_class}->{'class_type'} eq "monitor" || $class_info{$config_class}->{'class_type'} eq "collector"){
  261. # skip classes with no 'out_file'
  262. unless($class_info{$config_class}->{'out_file'}){
  263. if($config_class eq 'host' || $config_class eq 'hostgroup' || $config_class eq 'service' || $config_class eq 'servicegroup'){
  264. &logger(2,"No ".$config_class."s were exported. Make sure 'out_file' is set properly for the correspondig class.");
  265. }
  266. next;
  267. }
  268. push(@server_cfg_files, "$monitor_path/$class_info{$config_class}->{'out_file'}");
  269. if($config_class eq 'host'){
  270. # write hosts to cfg file
  271. &write_file("$monitor_path/$class_info{'host'}->{'out_file'}","host","$class_info{'host'}->{'nagios_object'}",
  272. \@hosts1,\@monitor_host_tpl);
  273. }
  274. elsif($config_class eq 'service'){
  275. # write services to cfg file
  276. &write_file("$monitor_path/$class_info{'service'}->{'out_file'}","service","$class_info{'service'}->{'nagios_object'}",
  277. \@services,\@monitor_srv_tpl_params);
  278. }
  279. else{
  280. # write remaining classes to cfg file (attach @monitor_srv_tpl_params array, which is needed for advanced-services)
  281. my @class_items = &getItems("$config_class");
  282. &write_file("$monitor_path/$class_info{$config_class}->{'out_file'}","$config_class","$class_info{$config_class}->{'nagios_object'}",
  283. \@class_items,\@monitor_srv_tpl_params);
  284. }
  285. }
  286. }
  287. }
  288. ########################################################################################
  289. # SUB create_collector_specific_files
  290. # Fetch all collector-specific data and write configuration files for collector server(s)
  291. sub create_collector_specific_files {
  292. &logger(5,"Entered create_collector_specific_files()");
  293. my $sql = undef;
  294. my @collector_host_tpl;
  295. my @collector_srv_tpl;
  296. # fetch all host ID's that are assigned to the collector (hosts which are monitored)
  297. $sql = "SELECT id_item AS item_id FROM ConfigItems,ConfigClasses
  298. WHERE id_class=fk_id_class
  299. AND config_class = 'host'
  300. HAVING (SELECT fk_item_linked2 FROM ConfigItems,ItemLinks,ConfigClasses
  301. WHERE fk_item_linked2=id_item
  302. AND id_class=fk_id_class
  303. AND config_class = 'nagios-collector'
  304. AND fk_id_item=item_id) = $_[0]";
  305. my @hosts = &queryExecRead($sql, "Fetching all host ID's that are assigned to the current collector", "all");
  306. # fetch collector-specific host-templates, these will be added to each host
  307. $sql = "SELECT attr_name,attr_value,write_to_conf
  308. FROM ConfigValues,ItemLinks,ConfigAttrs
  309. WHERE fk_item_linked2=ConfigValues.fk_id_item
  310. AND id_attr=ItemLinks.fk_id_attr
  311. AND (SELECT naming_attr FROM ConfigAttrs WHERE id_attr=ConfigValues.fk_id_attr)='yes'
  312. AND attr_name = 'host_template'
  313. AND ItemLinks.fk_id_item=$_[0]
  314. ORDER BY cust_order,ordering";
  315. my @host_tpl = &queryExecRead($sql, "Fetching collector-specific host-templates", "all");
  316. foreach (@host_tpl){push(@collector_host_tpl,$_)}
  317. # fetch collector-specific service-templates, these will be added to each service
  318. $sql = "SELECT attr_name,attr_value,write_to_conf
  319. FROM ConfigValues,ItemLinks,ConfigAttrs
  320. WHERE fk_item_linked2=ConfigValues.fk_id_item
  321. AND id_attr=ItemLinks.fk_id_attr
  322. AND (SELECT naming_attr FROM ConfigAttrs WHERE id_attr=ConfigValues.fk_id_attr)='yes'
  323. AND attr_name = 'service_template'
  324. AND ItemLinks.fk_id_item=$_[0]
  325. ORDER BY cust_order,ordering";
  326. my @srv_tpl = &queryExecRead($sql, "Fetching collector-specific service-templates", "all");
  327. foreach (@srv_tpl){push(@collector_srv_tpl,$_)}
  328. # fetch all service ID's of hosts assigned to the collector and which are not disabled
  329. my @services = undef;
  330. foreach my $host (@hosts){
  331. $sql = "SELECT ItemLinks.fk_id_item AS item_id,'','$host->[0]' FROM ConfigValues,ItemLinks,ConfigAttrs,ConfigClasses
  332. WHERE ItemLinks.fk_id_item=ConfigValues.fk_id_item
  333. AND id_attr=ItemLinks.fk_id_attr
  334. AND fk_id_class=id_class
  335. AND config_class = 'service'
  336. AND (SELECT naming_attr FROM ConfigAttrs WHERE id_attr=ConfigValues.fk_id_attr)='yes'
  337. AND ItemLinks.fk_item_linked2='$host->[0]'
  338. HAVING ((SELECT attr_value FROM ConfigValues, ConfigAttrs
  339. WHERE id_attr=fk_id_attr AND attr_name='service_enabled' AND fk_id_item=item_id) <> 'no'
  340. OR (SELECT attr_value FROM ConfigValues, ConfigAttrs
  341. WHERE id_attr=fk_id_attr AND attr_name='service_enabled' AND fk_id_item=item_id) IS NULL)
  342. ORDER BY attr_value";
  343. my @queryref = &queryExecRead($sql, "Fetching service ID's for host '$host->[0]'", "all");
  344. foreach my $service (@queryref){push(@services, $service)}
  345. }
  346. # remove first array element if it's empty
  347. unless($services[0]){shift(@services)}
  348. # write collector-specific classes to cfg file
  349. foreach my $config_class (keys(%class_info)){
  350. if(($class_info{$config_class}->{'class_type'} eq "collector" && $mon_count > 0)
  351. || (($class_info{$config_class}->{'class_type'} eq "monitor" || $class_info{$config_class}->{'class_type'} eq "collector") && $mon_count eq "0")){
  352. # skip classes with no 'out_file'
  353. unless($class_info{$config_class}->{'out_file'}){
  354. if($config_class eq 'host' || $config_class eq 'hostgroup' || $config_class eq 'service' || $config_class eq 'servicegroup'){
  355. &logger(2,"No ".$config_class."s were exported. Make sure 'out_file' is set properly for the correspondig class.");
  356. }
  357. next;
  358. }
  359. push(@server_cfg_files, "$collector_path/$class_info{$config_class}->{'out_file'}");
  360. if($config_class eq 'host'){
  361. # add the collector's ID to the list of host ID's
  362. foreach my $entry (@hosts){
  363. $entry->[1] = $_[0];
  364. }
  365. # write hosts to cfg file
  366. &write_file("$collector_path/$class_info{'host'}->{'out_file'}","host","$class_info{'host'}->{'nagios_object'}",
  367. \@hosts,\@collector_host_tpl);
  368. }
  369. elsif($config_class eq 'service'){
  370. # add the collector's ID to the list of service ID's
  371. foreach my $entry (@services){
  372. $entry->[1] = $_[0];
  373. }
  374. # write services to cfg file
  375. &write_file("$collector_path/$class_info{'service'}->{'out_file'}","service","$class_info{'service'}->{'nagios_object'}",
  376. \@services,\@collector_srv_tpl);
  377. }
  378. else{
  379. my @class_items = &getItems("$config_class");
  380. # add the collector's ID to the list of item ID's
  381. foreach my $entry (@class_items){
  382. $entry->[1] = $_[0];
  383. }
  384. # write remaining classes to cfg file (attach @collector_srv_tpl array, which is needed for advanced-services)
  385. &write_file("$collector_path/$class_info{$config_class}->{'out_file'}","$config_class","$class_info{$config_class}->{'nagios_object'}",
  386. \@class_items,\@collector_srv_tpl);
  387. }
  388. }
  389. }
  390. }
  391. ########################################################################################
  392. # SUB write_file
  393. # Write actual config files.
  394. sub write_file {
  395. &logger(5,"Entered write_file()");
  396. # define output format
  397. format FILE =
  398. @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @*
  399. $fattr,$fval
  400. .
  401. # read params passed
  402. my $path = $_[0];
  403. my $class = $_[1];
  404. my $item = $_[2];
  405. my $list = $_[3];
  406. my $params = $_[4];
  407. my @items = @$list;
  408. # use class name if no Nagios object definition was specified
  409. unless($item){$item=$class};
  410. # read and parse additional monitor/collector params
  411. my @mon_col_params;
  412. my $stale_service_command = undef;
  413. if($params){
  414. @mon_col_params = @$params;
  415. # determine if a 'stale_service_command' attr is set for the services of the current nagios-monitor
  416. if($class eq "service" || $class eq "advanced-service"){
  417. foreach my $extattr (@mon_col_params){
  418. if($extattr->[0] eq "stale_service_command"){
  419. $stale_service_command = $extattr->[1];
  420. }
  421. }
  422. }
  423. }
  424. # vars needed for several checks
  425. my $has_proc_sshd = 0;
  426. my @curr_host = undef;
  427. my @prev_host = undef;
  428. my %host_srv_cmd; # used for default service dependencies within checkcommands
  429. my $default_srv_deps_exist = 0;
  430. if($files_written{$path} && $files_written{$path} ne ""){open(FILE,">>$path") or &logger(1,"Could not open $path for writing (appending)")}
  431. else{open(FILE,">$path") or &logger(1,"Could not open $path for writing")}
  432. &logger(4,"Writing file '$path'");
  433. foreach my $id_item (@items){
  434. # INFO: "$id_item" is a reference to an array with the following structure:
  435. # in "global" context:
  436. # [0] id_item
  437. # [1] <unused>
  438. # [2] <unused>
  439. # [3] <unused>
  440. # in "collector" server context:
  441. # [0] id_item
  442. # [1] the collector's id
  443. # [2] the host's id (only for services)
  444. # [3] <unused>
  445. # in "monitor" server context:
  446. # [0] id_item
  447. # [1] <unused>
  448. # [2] the service's host id (only for services)
  449. # [3] if a service belongs to a host that is a collector itself ("yes"/"no", only for services)
  450. ########################
  451. # CASE1: process hosts #
  452. ########################
  453. if($class eq "host"){
  454. my (@host_templates1, @host_templates2, @host_templates3);
  455. print FILE "define $item {\n";
  456. # fetch all ordinary attributes (text, select etc.)
  457. my @item_attrs = &getItemData($id_item->[0]);
  458. my $hostname = undef;
  459. foreach my $attr (@item_attrs){
  460. if($attr->[0] ne "" && $attr->[1] ne "" && $attr->[2] ne "no"){ $fattr=$attr->[0];$fval=$attr->[1];write FILE}
  461. if($attr->[0] eq "host_name"){$hostname=$attr->[1]}
  462. }
  463. # fetch OS information for hosts (icons etc.)
  464. my @item_attrs = &fetch_host_os_info($id_item->[0]);
  465. foreach my $attr (@item_attrs){
  466. if($attr->[0] ne "" && $attr->[1] ne "" && $attr->[2] ne "no"){ $fattr=$attr->[0];$fval=$attr->[1];write FILE}
  467. }
  468. # fetch host-alive check and templates inherited from timeperiod
  469. my @aux_data = &fetch_inherited_host_templates($id_item->[0]);
  470. foreach my $attr (@aux_data){
  471. # don't write templates to config yet, store them separately to be processed later on
  472. if($attr->[0] eq "host_template"){push(@host_templates2, $attr->[1]);next}
  473. if($attr->[0] ne "" && $attr->[1] ne ""){ $fattr=$attr->[0];$fval=$attr->[1];write FILE}
  474. }
  475. # process monitor-/collector-specific templates
  476. foreach my $attr (@mon_col_params){
  477. # don't write templates to config yet, store them separately to be processed later on
  478. if($attr->[0] eq "host_template"){push(@host_templates3, $attr->[1]);next}
  479. }
  480. # fetch all linked items (assign_one, assign_many etc.)
  481. my @item_links = &getItemsLinked($id_item->[0]);
  482. @item_links = &makeValuesDistinct(@item_links);
  483. my $has_contactgroup = 0;
  484. my $has_oncall_group = 0;
  485. foreach my $attr (@item_links){
  486. # check for all parent hosts if they exist on the current collector / if they are monitored
  487. if($attr->[0] eq "parents"){
  488. my @parents = split(/,/, $attr->[1]);
  489. my $checked_parents = undef;
  490. foreach my $host (@parents){
  491. unless($host){next}
  492. # the id_item contained within $attr->[3] is unusable, because makeValuesDistinct() breaks it for assign_many links
  493. # so, let's fetch each host ID individually based on the hostname
  494. my $host_id = getItemId($host, "host");
  495. # check if parent host exists on the current collector
  496. if(&checkItemExistsOnServer($host_id, $id_item->[1]) eq "true"){
  497. $checked_parents = $checked_parents.",".$host;
  498. }
  499. }
  500. # only write parents to config, which exist on the current collector
  501. $checked_parents =~ s/^,//;
  502. if($checked_parents ne ""){$attr->[1]=$checked_parents}
  503. else{next} # don't write "parents" attribute, if empty
  504. }
  505. # don't write templates to config yet, store them separately to be processed later on
  506. if($attr->[0] eq "use"){push(@host_templates1, $attr->[1]);next}
  507. # check for contactgroups
  508. if($attr->[0] eq "contact_groups"){
  509. $has_contactgroup = 1;
  510. # check for oncall groups
  511. my @cg_parts = split(/,/, $attr->[1]);
  512. foreach my $cgroup (@cg_parts){
  513. foreach (@oncall_groups){
  514. if($cgroup eq $_){$has_oncall_group=1}
  515. }
  516. }
  517. # add superadmin groups to all hosts by default
  518. if(defined($superadmins[0])){
  519. foreach(@superadmins){
  520. my $user_wo_plus = $_;
  521. $user_wo_plus =~ s/\+//g;
  522. if($attr->[1] =~ /\b$user_wo_plus\b/){$attr->[1] =~ s/$user_wo_plus\,{0,1}//}
  523. }
  524. if($attr->[1]){$attr->[1] = join(",", @superadmins).",".$attr->[1]}
  525. else{$attr->[1] = join(",", @superadmins)}
  526. }
  527. }
  528. if($attr->[0] ne "" && $attr->[1] ne "" && $attr->[2] ne "no"){$fattr=$attr->[0];$fval=$attr->[1];write FILE}
  529. }
  530. # process host-templates
  531. # templates will be applied to hosts in the following order:
  532. # 1. host specific template(s)
  533. # 2. notification_period template(s)
  534. # 3. check_period template(s)
  535. # 4. collector/monitor template(s)
  536. my @host_templates;
  537. push(@host_templates, @host_templates1);
  538. push(@host_templates, @host_templates2);
  539. push(@host_templates, @host_templates3);
  540. # make sure templates are only applied once, keeping original order (first occurence wins)
  541. tie my %tpl_hash, 'Tie::IxHash';
  542. foreach my $tpl (@host_templates){
  543. if($tpl_hash{$tpl}){next}
  544. if($tpl =~ /,/){
  545. my @temp = split(/,/,$tpl);
  546. foreach(@temp){$tpl_hash{$_}=$_}
  547. }else{
  548. $tpl_hash{$tpl} = $tpl;
  549. }
  550. }
  551. $fattr = "use";
  552. $fval = join(",",keys(%tpl_hash));
  553. if($fval){write FILE}
  554. # warn if no oncall groups were assigned to host
  555. if($has_oncall_group == 0 && $oncall_groups[0] ne ""){
  556. &logger(2,"No oncall group is assigned to host $hostname");
  557. }
  558. # add superadmin groups, even if no contactgroups were specified at all
  559. if($has_contactgroup == 0 && defined($superadmins[0])){
  560. $fattr = "contact_groups";
  561. $fval = join(",",@superadmins);
  562. write FILE;
  563. }
  564. print FILE "}\n\n";
  565. ###########################
  566. # CASE2: process services #
  567. ###########################
  568. }elsif($class eq "service"){
  569. my $is_proc_sshd = 0;
  570. my $is_trap_service = 0;
  571. my (@service_templates1, @service_templates2, @service_templates3);
  572. # fetch hostname of the host which the service belongs to
  573. my $hostname = &getItemName($id_item->[2]);
  574. # fetch service_description and all ordinary attributes (text, select etc.)
  575. my @item_attrs = &getItemData($id_item->[0]);
  576. my $srvname = undef;
  577. foreach my $attr (@item_attrs){
  578. if($attr->[0] eq "service_description"){$srvname=$attr->[1]}
  579. if($attr->[0] eq "service_description" && $attr->[0] ne "" && $attr->[1] ne "" && $attr->[2] ne "no"){
  580. if($attr->[1] =~ /trap/i && $path =~ /\Q$collector_path\E/ && $mon_count > 0){
  581. # don't write "TRAP" services to collector config, if a monitor server is present
  582. $is_trap_service = 1;
  583. }else{
  584. # write all ordinary attributes to config (text, select etc.)
  585. print FILE "define $item {\n";
  586. $fattr=$attr->[0];
  587. $fval=$attr->[1];
  588. write FILE;
  589. }
  590. }
  591. }
  592. if($is_trap_service == 1){next}
  593. # fetch all linked items (assign_one, assign_many etc.)
  594. my @item_links = &getItemsLinked($id_item->[0]);
  595. @item_links = &makeValuesDistinct(@item_links);
  596. my $has_contactgroup = 0;
  597. my $has_oncall_group = 0;
  598. foreach my $attr (@item_links){
  599. if($attr->[0] eq "check_command"){
  600. # proccess default service dependencies
  601. if($class eq "service" &&
  602. (($class_info{'service-dependency'}->{'class_type'} eq "monitor"
  603. && (($monitor_path && $path =~ /\Q$monitor_path\E/) || $mon_count eq "0"))
  604. ||($class_info{'service-dependency'}->{'class_type'} eq "collector"
  605. && (($collector_path && $path =~ /\Q$collector_path\E/) || ($monitor_path && $path =~ /\Q$monitor_path\E/))))){
  606. # check for default_service_dependency attributes on a command level
  607. my @srv_cmd_deps;
  608. my %def_srv_deps_params;
  609. my $def_srv_deps = $checkcommand_info{$attr->[1]}->{"default_service_dependency"};
  610. if($def_srv_deps ne ""){
  611. $default_srv_deps_exist = 1;
  612. my @parts = split(/,/,$def_srv_deps);
  613. foreach(@parts){
  614. unless($_){next};
  615. push(@srv_cmd_deps,$_);
  616. }
  617. # fetch additional parameters for default service dependency
  618. $def_srv_deps_params{"execution_failure_criteria"} =
  619. $checkcommand_info{$attr->[1]}->{"dependency_execution_failure_criteria"};
  620. $def_srv_deps_params{"notification_failure_criteria"} =
  621. $checkcommand_info{$attr->[1]}->{"dependency_notification_failure_criteria"};
  622. }
  623. # store hosts, services, their checkcommand and the command's default service dependencies to a hash structure
  624. my @srv_info;
  625. push(@srv_info, $srvname);
  626. push(@srv_info, \@srv_cmd_deps);
  627. push(@srv_info, \%def_srv_deps_params);
  628. if($host_srv_cmd{$hostname}){
  629. if($host_srv_cmd{$hostname}->{$attr->[1]}){
  630. push (@{$host_srv_cmd{$hostname}->{$attr->[1]}}, \@srv_info);
  631. }else{
  632. my @cmd_srv;
  633. push(@cmd_srv, \@srv_info);
  634. $host_srv_cmd{$hostname}->{$attr->[1]} = \@cmd_srv;
  635. }
  636. }else{
  637. my %host_cmd;
  638. my @cmd_srv;
  639. push(@cmd_srv, \@srv_info);
  640. $host_cmd{$attr->[1]} = \@cmd_srv;
  641. $host_srv_cmd{$hostname} = \%host_cmd;
  642. }
  643. }
  644. # execute this at the very end of "check_command" processing!
  645. # add a dummy check_command to all services of a monitor server, if stale_service_command attr is set
  646. if($monitor_path && $path =~ /\Q$monitor_path\E/ && $stale_service_command){
  647. $attr->[1] = $stale_service_command;
  648. }
  649. else{
  650. # add check_params to check_command attr
  651. my $cmd_params = &fetch_cmd_params($id_item->[0]);
  652. $cmd_params = &replaceMacros($cmd_params);
  653. $attr->[1] = $attr->[1].$cmd_params;
  654. }
  655. }
  656. # don't write templates to config yet, store them separately to be processed later on
  657. if($attr->[0] eq "use"){push(@service_templates1, $attr->[1]);next}
  658. # check for contactgroups
  659. if($attr->[0] eq "contact_groups"){
  660. $has_contactgroup = 1;
  661. # check for oncall groups
  662. my @cg_parts = split(/,/, $attr->[1]);
  663. foreach my $cgroup (@cg_parts){
  664. foreach (@oncall_groups){
  665. if($cgroup eq $_){$has_oncall_group=1}
  666. }
  667. }
  668. # add superadmin groups to all services by default
  669. if(defined($superadmins[0])){
  670. foreach(@superadmins){
  671. my $user_wo_plus = $_;
  672. $user_wo_plus =~ s/\+//g;
  673. if($attr->[1] =~ /\b$user_wo_plus\b/){$attr->[1] =~ s/$user_wo_plus\,{0,1}//}
  674. }
  675. if($attr->[1]){$attr->[1] = join(",", @superadmins).",".$attr->[1]}
  676. else{$attr->[1] = join(",", @superadmins)}
  677. }
  678. }
  679. if($attr->[0] ne "" && $attr->[1] ne "" && $attr->[2] ne "no"){ $fattr=$attr->[0];$fval=$attr->[1];write FILE}
  680. # TO CHANGE
  681. # read and store the host we're currently working on
  682. $curr_host[0] = $hostname;
  683. $curr_host[1] = $id_item->[3];
  684. if($prev_host[0] eq ""){$prev_host[0] = $hostname;$prev_host[1] = $id_item->[3]}
  685. } # end of loop through a service's links
  686. # TO CHANGE
  687. # check if the host whose services we're working on has changed
  688. if($curr_host[0] ne $prev_host[0]){
  689. # if previous host was a collector, warn if no sshd service was found
  690. if($prev_host[1] eq "yes" && $monitor_path && $path =~ /\Q$monitor_path\E/ && $has_proc_sshd != 1){
  691. &logger(2,"No SSH check was found for $prev_host[0]");
  692. }
  693. $has_proc_sshd = 0;
  694. }
  695. foreach my $attr (@item_attrs){
  696. if($attr->[0] eq "service_description" && $attr->[1] =~ /ssh/i){$is_proc_sshd=1;$has_proc_sshd=1}
  697. if($attr->[0] ne "" && $attr->[1] ne "" && $attr->[2] ne "no" && $attr->[0] ne "service_description"){
  698. $fattr=$attr->[0];
  699. $fval=$attr->[1];
  700. write FILE;
  701. }
  702. }
  703. # fetch templates inherited from checkcommand / timeperiod
  704. my @aux_data = &fetch_inherited_service_templates($id_item->[0]);
  705. foreach my $attr (@aux_data){
  706. # don't write templates to config yet, store them separately to be processed later on
  707. if($attr->[0] eq "service_template"){push(@service_templates2, $attr->[1]);next}
  708. if($attr->[0] ne "" && $attr->[1] ne ""){ $fattr=$attr->[0];$fval=$attr->[1];write FILE}
  709. }
  710. # TO CHANGE
  711. # determine if this service belongs to a collector host ("host is collector" flag is set to "yes")
  712. my $checkfreshness = undef;
  713. my $freshthresh = undef;
  714. if($id_item->[3] eq "yes"){
  715. # look for collector-specific check_freshness and freshness_threshhold
  716. foreach my $extattr (@mon_col_params){
  717. if($extattr->[0] eq "collector_check_freshness"){$checkfreshness = $extattr->[1]}
  718. if($extattr->[0] eq "collector_freshness_threshold"){$freshthresh = $extattr->[1]}
  719. }
  720. }
  721. # process monitor-/collector-specific templates
  722. foreach my $attr (@mon_col_params){
  723. # don't write templates to config yet, store them separately to be processed later on
  724. if($attr->[0] eq "service_template"){push(@service_templates3, $attr->[1]);next}
  725. }
  726. # TO CHANGE
  727. # apply the collector_check_freshness value to .*ssh.* service(s) on "host is collector" flagged hosts (only in monitor config)
  728. if($id_item->[3] eq "yes" && $is_proc_sshd == 1 && $monitor_path && $path =~ /\Q$monitor_path\E/ && $checkfreshness){
  729. $fattr = "check_freshness";
  730. $fval = $checkfreshness;
  731. write FILE;
  732. }
  733. # apply the collector_freshness_threshhold value to .*ssh.* service(s) on "host is collector" flagged hosts (only in monitor config)
  734. if($id_item->[3] eq "yes" && $is_proc_sshd == 1 && $monitor_path && $path =~ /\Q$monitor_path\E/ && $freshthresh){
  735. $fattr = "freshness_threshold";
  736. $fval = $freshthresh;
  737. write FILE;
  738. }
  739. # process service-templates
  740. # templates will be applied to services in the following order:
  741. # 1. template(s) directly linked to advanced-service
  742. # 2. default service template(s) linked to checkcommand
  743. # 3. notification_period template(s)
  744. # 4. check_period template(s)
  745. # 5. collector/monitor template(s)
  746. my @service_templates;
  747. push(@service_templates, @service_templates1);
  748. push(@service_templates, @service_templates2);
  749. push(@service_templates, @service_templates3);
  750. # make sure templates are only applied once, keeping original order (first occurence wins)
  751. tie my %tpl_hash, 'Tie::IxHash';
  752. foreach my $tpl (@service_templates){
  753. if($tpl_hash{$tpl}){next}
  754. if($tpl =~ /,/){
  755. my @temp = split(/,/,$tpl);
  756. foreach(@temp){$tpl_hash{$_}=$_}
  757. }else{
  758. $tpl_hash{$tpl} = $tpl;
  759. }
  760. }
  761. $fattr = "use";
  762. $fval = join(",",keys(%tpl_hash));
  763. if($fval){write FILE}
  764. # warn if no oncall groups were assigned to service
  765. if($has_oncall_group == 0 && $oncall_groups[0] ne ""){
  766. &logger(2,"No oncall group is assigned to service \"$srvname\" on host $hostname");
  767. }
  768. # add superadmin groups, even if no contactgroups were specified at all
  769. if($has_contactgroup == 0 && defined($superadmins[0])){
  770. $fattr = "contact_groups";
  771. $fval = join(",",@superadmins);
  772. write FILE;
  773. }
  774. @prev_host = @curr_host;
  775. print FILE "}\n\n";
  776. ##################################
  777. # CASE3: process all other items #
  778. ##################################
  779. # this section processes all items that are neither "hosts" nor "services"
  780. }else{
  781. ##### (0) special processing for advanced-services
  782. my $has_contactgroup = 0;
  783. my $has_oncall_group = 0;
  784. my (@service_templates1, @service_templates2, @service_templates3);
  785. if($class eq "advanced-service"){
  786. # don't write adv. services that contain the string "TRAP" in "advanced service name" to collector config, if a monitor server is present
  787. my $srvname = &getItemName($id_item->[0]);
  788. if($srvname =~ /trap/i && defined($id_item->[1]) && $mon_count > 0){next}
  789. }
  790. ##### (1) fetch all linked items (assign_one, assign_many etc.)
  791. my @item_links = &getItemsLinked($id_item->[0]);
  792. my $has_empty_linking_attrs = 0;
  793. ##### (1A) collector/monitor-specific processing for linked items (assign_* attrs)
  794. if(defined($id_item->[1]) || ($monitor_path && $path =~ /\Q$monitor_path\E/)){
  795. # look for linked items, that are server-specific (hosts, services, hostgroups, servicegroups),
  796. # check if they exist on the current Nagios server, remove them if not;
  797. # this routine makes sense both for collectors and monitors, since hosts/services can also be disabled (not monitored) on a monitor,
  798. # and must therefore be removed from any items they might be linked to;
  799. foreach my $attr (@item_links){
  800. # in "collector" context, $id_item->[1] contains the collector's ID
  801. # in "monitor" context, $id_item->[1] is undefined
  802. unless(&checkItemExistsOnServer($attr->[3],$id_item->[1]) eq "true"){
  803. # if the linked item doesn't exist on current server, empty the linking attribute
  804. # (careful, there may be multiple instances of the same linking attribute per item)
  805. # the empty linking attributes will be processed later (after class_dependent_processing() & makeValuesDistinct() )
  806. if($id_item->[1]){
  807. &logger(4,"Removing item '$attr->[3]' from $class '$id_item->[0]' because the item doesn't exist on collector '$id_item->[1]'");
  808. }else{
  809. &logger(4,"Removing item '$attr->[3]' from $class '$id_item->[0]' because the item is not monitored");
  810. }
  811. undef $attr->[1];
  812. }
  813. }
  814. # apply certain class specific exceptions
  815. # caution: this function must always be called before makeValuesDistinct() AND after checking for collector specific items
  816. @item_links = &class_dependent_processing($class, @item_links);
  817. # consolidate multi-line attributes into one line
  818. @item_links = &makeValuesDistinct(@item_links);
  819. # after a first cleanup round, look for linking attributes that are now empty; hostgroups and servicegroups are handled separately
  820. # IMPORTANT: this logic only concerns items with linking attrs that were cleared above, not items that weren't linked to start with!
  821. my $group_has_members = 0;
  822. my $has_members = 0;
  823. my $has_hg_members = 0;
  824. my $has_sg_members = 0;
  825. foreach my $attr (@item_links){
  826. # if we find any empty linking attributes (there may be multiple empty attributes per item)
  827. if(defined($attr->[0]) && $attr->[1] eq "" && $class ne "hostgroup" && $class ne "servicegroup"){
  828. # remove the whole item from the configuration, unless it's an advanced-service (special rule applies there)
  829. unless($class eq "advanced-service" && ($attr->[0] eq "host_name" || $attr->[0] eq "hostgroup_name" || $attr->[0] eq "servicegroups")){
  830. &logger(4,"Removing $class '$id_item->[0]' from config because the attribute '$attr->[0]' was empty");
  831. $has_empty_linking_attrs = 1;
  832. }
  833. # additional rules might be necessary for dependencies & escalations
  834. }
  835. # handle hostgroups and servicegroups separately
  836. if($class eq "hostgroup" || $class eq "servicegroup"){
  837. if($attr->[0] eq "members" && $attr->[1] ne ""){$has_members=1}
  838. if($attr->[0] eq "hostgroup_members" && $attr->[1] ne ""){$has_hg_members=1}
  839. if($attr->[0] eq "servicegroup_members" && $attr->[1] ne ""){$has_sg_members=1}
  840. }
  841. # special processing for advanced-services
  842. if($class eq "advanced-service"){
  843. if($attr->[0] eq "check_command"){
  844. # add a dummy check_command to all services of a monitor server, if stale_service_command attr is set
  845. if($monitor_path && $path =~ /\Q$monitor_path\E/ && $stale_service_command){
  846. $attr->[1] = $stale_service_command;
  847. }
  848. else{
  849. # add check_params to check_command attr
  850. my $cmd_params = &fetch_cmd_params($id_item->[0]);
  851. $cmd_params = &replaceMacros($cmd_params);
  852. $attr->[1] = $attr->[1].$cmd_params;
  853. }
  854. }
  855. # check for contactgroups
  856. if($attr->[0] eq "contact_groups"){
  857. $has_contactgroup = 1;
  858. # check for oncall groups
  859. my @cg_parts = split(/,/, $attr->[1]);
  860. foreach my $cgroup (@cg_parts){
  861. foreach (@oncall_groups){
  862. if($cgroup eq $_){$has_oncall_group=1}
  863. }
  864. }
  865. # add superadmin groups to all services by default
  866. if(defined($superadmins[0])){
  867. foreach(@superadmins){
  868. my $user_wo_plus = $_;
  869. $user_wo_plus =~ s/\+//g;
  870. if($attr->[1] =~ /\b$user_wo_plus\b/){$attr->[1] =~ s/$user_wo_plus\,{0,1}//}
  871. }
  872. if($attr-

Large files files are truncated, but you can click here to view the full file