File Coverage

blib/lib/Ym/ymcommon.pl
Criterion Covered Total %
statement 9 193 4.6
branch 0 110 0.0
condition 0 39 0.0
subroutine 3 19 15.7
pod 0 16 0.0
total 12 377 3.1


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package Ym;
4              
5 1     1   6 use warnings;
  1         2  
  1         42  
6 1     1   5 use strict;
  1         3  
  1         36  
7              
8 1     1   6 use Ym;
  1         2  
  1         3116  
9              
10             sub TouchTree {
11 0     0 0   my ($tree) = @_;
12 0 0         die "TouchTree: tree reference is missing in args.\n" unless $tree;
13              
14 0           $tree->{'meta'}->{'tree_mod_time'} = time();
15             }
16              
17             sub TouchConfigs {
18 0     0 0   my ($tree) = @_;
19 0           my $sub_name = 'TouchConfigs';
20              
21 0 0         defined($tree)
22             or die "$sub_name: tree reference is missing in args.\n";
23              
24 0           $tree->{'meta'}->{'configs_gen_time'} = time();
25             }
26              
27             sub SetMeta {
28 0     0 0   my ($tree, $opts) = @_;
29 0           my $sub_name = 'SetMeta';
30              
31 0 0         defined($tree)
32             or die "$sub_name: tree reference is missing in args.\n";
33              
34 0 0         $opts = {} unless $opts;
35              
36 0           foreach my $k (keys %$opts) {
37 0           $tree->{'meta'}->{$k} = $opts->{$k};
38             }
39             }
40              
41             sub GetMeta {
42 0     0 0   my ($tree, $opt) = @_;
43 0           my $sub_name = 'GetMeta';
44              
45 0 0         defined($tree)
46             or die "$sub_name: tree reference is missing in args.\n";
47              
48 0 0         defined($opt)
49             or die "$sub_name: option name is missing in args.\n";
50              
51 0 0         if (defined($tree->{'meta'}->{$opt})) {
52 0           return $tree->{'meta'}->{$opt};
53             }
54             else {
55 0           return undef;
56             }
57             }
58              
59             sub Ask_For_Change {
60              
61             # Check if it is safe to auto generate configs for Nagios.
62              
63 0     0 0   my ($tree) = @_;
64 0           my $sub_name = 'Ask_For_Change';
65              
66 0 0         defined($tree)
67             or die "$sub_name: tree reference is missing in args.\n";
68              
69 0           my $tree_mod_time = GetMeta($tree, 'tree_mod_time');
70 0           my $configs_gen_time = GetMeta($tree, 'configs_gen_time');
71              
72 0           $tree_mod_time |= 0;
73 0           $configs_gen_time |= 0;
74              
75 0           for my $c (@Ym::NAGIOS_CONFIGS) {
76 0           my $file = "$Ym::NAGIOS_CFG_DIR/$c";
77              
78 0 0         next unless (-e $file);
79              
80 0           my $mtime = (stat("$Ym::NAGIOS_CFG_DIR/$c"))[9];
81              
82 0 0 0       if ($mtime < $tree_mod_time
      0        
83             || ($configs_gen_time > 0 && $mtime > $configs_gen_time))
84             {
85 0           return 0;
86             }
87             }
88              
89 0           return 1;
90             }
91              
92             sub GetMembers {
93 0     0 0   my ($group, $grp_branch) = @_;
94              
95 0           my @members = ();
96              
97 0 0 0       if(!defined($grp_branch)
98             || !defined($grp_branch->{$group}))
99             {
100 0           return \@members;
101             }
102              
103 0           foreach my $m (split (/[,:;\s]+/o,
104             $grp_branch->{$group}->{'members'}))
105             {
106 0           push(@members, $m);
107             }
108              
109 0           return \@members;
110              
111             # Note thar there may be hostgroup_members or contactgroup_members attribute
112             # If so, we should recursively look into other groups.
113             # I'll add this feature if someone need it.
114             }
115              
116             sub read_file_macros {
117 0     0 0   my ($f) = @_;
118 0           my $sub_name = 'read_file_macros';
119 0           my $file_contents = '';
120              
121 0 0         if ($f !~ /^READ_FILE=(.*)/o) {
122              
123 0           die "$sub_name: Error in argument: [$f]. ".
124             "File name is missing.\n";
125             }
126            
127 0           my $fname = $1;
128              
129 0 0         open(LIST, "<$fname") or die "Can't open [$fname]: $!\n";
130 0           $/ = undef;
131              
132 0           $file_contents = ;
133              
134 0           close(LIST);
135              
136 0           return \$file_contents;
137             }
138              
139             sub GetObjectList {
140 0     0 0   my ($obj_ref, $grp_ref, $opts) = @_;
141 0           my $sub_name = 'GetObjectList';
142              
143 0 0         $opts = {} unless $opts;
144              
145 0           my $res;
146 0           @$res = [];
147              
148             # Check for empty input
149 0 0 0       if(!defined($obj_ref) && !defined($grp_ref)) {
150 0           return $res;
151             }
152              
153             # Check args type
154 0 0 0       if(defined($obj_ref)
      0        
155             && (!ref($obj_ref) || ref($obj_ref) ne 'ARRAY'))
156             {
157 0           die "$sub_name: first argument must be an array reference\n";
158             }
159              
160 0 0 0       if(defined($grp_ref)
      0        
161             && (!ref($grp_ref) || ref($grp_ref) ne 'ARRAY'))
162             {
163 0           die "$sub_name: second argument must be an array reference\n";
164             }
165              
166             # Check for mandatory options
167 0 0         if(defined($obj_ref)) {
168 0 0 0       if(defined($opts->{'allow_regexp_in_obj'})
169             && !defined($opts->{'obj_branch'}))
170             {
171 0           die "$sub_name: Programmer error - 'obj_branch' option is not set.\n";
172             }
173             }
174              
175 0 0 0       if(defined($grp_ref)
176             && !defined($opts->{'grp_branch'}))
177             {
178 0           die "$sub_name: Programmer error - 'grp_branch' option is not set.\n";
179             }
180              
181 0           my $split_pattern = '[,:;\n\s]+';
182 0           my %tmp = ();
183 0           my $verbose = $Ym::VERBOSE;
184              
185 0 0         if(defined($obj_ref)) { # Extract objects
186              
187 0           my $obj_raw = '';
188              
189 0           foreach my $item (@$obj_ref) {
190 0 0         if ($item =~ /^\/(.*)\//o) { # If item contains REGEXP
191 0           my $regex = $1;
192            
193 0 0         ($verbose) && print "Found REGEXP $1\n";
194              
195 0 0         unless($opts->{'allow_regex_in_obj'}) {
196 0           die "$sub_name: invalid argument [$item]. ".
197             "No regex allowed in this command.\n";
198             }
199              
200 0           foreach my $obj (keys %{$opts->{'obj_branch'}}) {
  0            
201 0 0         if ($obj =~ /$regex/) {
202 0           $tmp{$obj} = 1;
203             }
204             }
205             }
206             else {
207 0 0         if($item =~ /^READ_FILE/o) { # READ_FILE macros found
208            
209 0 0         ($verbose) && print "Found MACROS $item\n";
210            
211 0           $obj_raw = ${read_file_macros($item)};
  0            
212             }
213             else {
214 0           $obj_raw = $item;
215             }
216              
217             # Split obj_raw and add objects to %tmp
218 0           foreach my $obj (split($split_pattern, $obj_raw)) {
219 0           $tmp{$obj} = 1;
220             }
221             }
222             }
223             } # End extract objects
224              
225 0 0         if(defined($grp_ref)) { # Extract group members
226            
227 0           my $grp_raw = '';
228              
229 0           foreach my $item (@$grp_ref) {
230              
231 0 0         if ($item =~ /^\/(.*)\//o) { # If item contains REGEXP
232 0           die "$sub_name: invalid argument [$item]. ".
233             "No regexp allowed in group definition.\n";
234             }
235              
236 0 0         if($item =~ /^READ_FILE/o) { # READ_FILE macros found
237            
238 0 0         ($verbose) && print "Found MACROS $item\n";
239              
240 0           $grp_raw = ${read_file_macros($item)};
  0            
241             }
242             else {
243 0           $grp_raw = $item;
244             }
245             }
246              
247             # Split grp_raw, find members for each group and add them to %tmp
248 0           foreach my $grp (split($split_pattern, $grp_raw)) {
249              
250 0           my $grp_members = GetMembers($grp, $opts->{'grp_branch'});
251              
252 0           foreach my $m (@$grp_members) {
253 0           $tmp{$m} = 1;
254             }
255             }
256             } # End extract group members
257              
258 0           @$res = keys %tmp;
259              
260 0           return $res;
261             }
262              
263             sub VerifyDataStructure {
264 0     0 0   my ($tree) = @_;
265              
266 0           foreach my $class (sort keys %$tree) {
267 0 0 0       next if ($class eq "config" || $class eq "meta");
268              
269 0           foreach my $object (keys %{$tree->{$class}}) {
  0            
270 0           my $count = scalar(keys %{$tree->{$class}->{$object}});
  0            
271              
272 0 0         if ($count eq 0) {
273 0           print "Object: $class -> $object has too few elements $count\n";
274             }
275              
276 0 0         if ($class =~ /hosts|service_dependencies/o) {
277              
278 0 0         my $k = ($class eq "hosts") ? "services" : "service_dependencies";
279              
280 0           my $count = scalar(keys %{$tree->{$class}->{$object}->{$k}});
  0            
281              
282 0 0         if ($count eq 0) {
283 0           print "Object: $class -> $object -> $k has too few elements $count\n";
284             }
285             }
286             }
287             }
288             }
289              
290             sub ShowDiff {
291             # Shows difference between two (previous and current) versions of data structure
292              
293 0     0 0   my ($old, $new) = @_;
294              
295             sub Compare($$) {
296 0     0 0   my ($one, $two) = @_;
297 0           my @res;
298              
299 0           foreach my $class (keys %{$one}) {
  0            
300              
301 0           foreach my $object (keys %{$one->{$class}}) {
  0            
302 0 0         if (!defined($two->{$class}->{$object})) {
303              
304 0           push @res, "{$class}->{$object}";
305 0           next;
306             }
307 0 0         if ($class eq "hosts") {
308              
309 0           foreach my $srv (keys %{$one->{$class}->{$object}->{'services'}}) {
  0            
310              
311 0 0         if (!defined($two->{$class}->{$object}->{'services'}->{$srv})) {
312 0           push @res, "{$class}->{$object}->{services}->{$srv}";
313             }
314             }
315             }
316             }
317             }
318 0           return \@res;
319             }
320              
321             sub PrintDiff {
322 0     0 0   my ($ref, $prefix) = @_;
323 0           my $sub_name = 'PrintDiff';
324              
325 0 0         if (ref($ref) ne "ARRAY") {
326 0           warn("$sub_name: first argument must be an ARRAY reference\n");
327 0           return 0;
328             }
329              
330 0 0         if (scalar(@$ref) > 0) {
331 0           foreach my $l (@$ref) {
332 0           print "$prefix $l\n";
333             }
334             }
335             }
336              
337 0           my $deleted = Compare($old, $new);
338 0           my $added = Compare($new, $old);
339              
340 0           PrintDiff($deleted, "Deleted");
341 0           PrintDiff($added, "Added");
342              
343 0           return 1;
344             }
345              
346             sub GetStruct {
347 0     0 0   my ($file, $cfg) = @_;
348 0           my $ref;
349              
350 0 0         if (-e $file) {
351 0 0         ($Ym::VERBOSE) && print "Reading structure from file\n\n";
352 0 0         $ref = Storable::retrieve($file)
353             or die "GetStruct: Can't load structure file $file : $!\n";
354             }
355             else {
356 0 0         ($Ym::VERBOSE) && print "Ym::MakeTree\n";
357 0           $ref = Ym::MakeTree($cfg);
358             }
359 0           return $ref;
360             }
361              
362             sub CloneStruct {
363 0     0 0   my ($tree) = @_;
364 0 0         my $clone = Storable::dclone($tree)
365             or die "CloneStruct: Can't clone structure : $!\n";
366              
367 0           return $clone;
368             }
369              
370             sub SaveStruct {
371 0     0 0   my ($tree, $file) = @_;
372 0           my $tmp_file = "$file.tmp";
373 0           my $sub_name = 'SaveStruct';
374              
375 0 0         Storable::store($tree, $tmp_file)
376             or warn "$sub_name: Store fo $tmp_file failed\n";
377              
378 0 0         rename($tmp_file, $file)
379             or warn "$sub_name: Failed to rename $tmp_file to $file\n";
380             }
381              
382             sub Backup {
383 0     0 0   my ($opts) = @_;
384 0           my $sub_name = 'Backup';
385            
386 0 0         $opts = {} unless $opts;
387              
388 0           my $stamp=`date +%Y-%m-%d_%H-%M-%S`;
389 0           chomp($stamp);
390              
391 0 0         if(!defined($Ym::BACKUP_PATH)) {
392 0           die "$sub_name: [BACKUP_PATH] variable is not defined in config.\n";
393             }
394              
395 0 0 0       unless( -d $Ym::BACKUP_PATH && -w $Ym::BACKUP_PATH ) {
396 0           die "$sub_name: [$Ym::BACKUP_PATH] is not a writable dir.\n";
397             }
398              
399 0           my $bckp_dir = "$Ym::BACKUP_PATH/$stamp";
400              
401 0 0         opendir(DIR, $Ym::NAGIOS_CFG_DIR)
402             or die "$sub_name: Can not open [$Ym::NAGIOS_CFG_DIR]: $!\n";
403              
404 0 0 0       my @contents = grep { /^[^.]/o && /\.cfg$/o && -f "$Ym::NAGIOS_CFG_DIR/$_" } readdir(DIR);
  0            
405              
406 0           closedir(DIR);
407              
408 0 0         mkdir($bckp_dir)
409             or die "$sub_name: Can not create [$bckp_dir]: $!\n";
410              
411 0           foreach my $f (@contents) {
412 0 0         File::Copy::copy("$Ym::NAGIOS_CFG_DIR/$f", "$bckp_dir/$f")
413             or die "$sub_name: Can not copy [$Ym::NAGIOS_CFG_DIR/$f] to [$bckp_dir/$f]: $!\n";
414             }
415              
416 0           return $bckp_dir;
417             }
418              
419             1;