From dae5ac8939d328698c8e48927ab6b3d5877d56b3 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 25 Jun 2013 15:39:02 +0200 Subject: [PATCH] configconvert: serviceescalations with servicegroup_name requires a new functionality to grab all service names by a given servicegroup name. this only works after reprocessing all services with their updated "servicegroups" attribute as array in the 2.x objects hive. after fetching the service names and their logical objects, it's quite the same procedure as for the hostgroups and single host_names/service_descriptions - for better reading, code remains duplicated for now. furthermore, escalation notification template objects are only added based on the old contact->notification_command, and only a reference template added when using within the service linking. refs #4009 --- tools/configconvert/Icinga2/Convert.pm | 200 ++++++++++++++++++++++++- 1 file changed, 192 insertions(+), 8 deletions(-) diff --git a/tools/configconvert/Icinga2/Convert.pm b/tools/configconvert/Icinga2/Convert.pm index 40994d95f..febed0226 100644 --- a/tools/configconvert/Icinga2/Convert.pm +++ b/tools/configconvert/Icinga2/Convert.pm @@ -313,6 +313,66 @@ sub obj_get_usernames_arr_by_usergroup_name { return @user_names; } +# used after relinking all services with servicegroups +sub obj_2x_get_service_arr_by_servicegroup_name { + my $objs_2x = shift; + my $objs = $objs_2x; + my $obj_type = 'service'; + my $obj_attr = 'servicegroups'; + my $obj_val = shift; + my @service_names = (); + + #debug("My objects hive: ".Dumper($objs)); + + #debug("Checking for type=$obj_type attr=$obj_attr val=$obj_val "); + foreach my $obj_key (keys %{@$objs{$obj_type}}) { + my $obj = @$objs{$obj_type}->{$obj_key}; + # this there's no attr, try template tree + my @servicegroups = (); + my $host_name = $obj->{'__I2CONVERT_SERVICE_HOSTNAME'}; + + # skip invalid resolved objects + if (!defined($host_name)) { + #say Dumper("missing host name..."); + next; + } + + if (defined($obj->{$obj_attr}) && scalar(@{$obj->{$obj_attr}} > 0)) { + push @servicegroups, @{$obj->{$obj_attr}}; + #say Dumper("$obj_attr ========== found in object $obj->{'__I2CONVERT_SERVICE_HOSTNAME'}:$obj->{'__I2CONVERT_SERVICEDESCRIPTION'}"); + #say Dumper(@servicegroups); + } else { + #say Dumper("START ------------------------"); + #say Dumper($obj); + my @service_sgs = obj_2x_get_service_servicegroups($objs_2x,$obj,$host_name,$obj_attr); + #say Dumper(@service_sgs); + if (scalar @service_sgs > 0) { + push @servicegroups, @service_sgs; + #say Dumper("$obj_attr ========== found in template tree $obj->{'__I2CONVERT_SERVICE_HOSTNAME'}:$obj->{'__I2CONVERT_SERVICEDESCRIPTION'}"); + #say Dumper(@servicegroups); + #say Dumper($obj); + } + #say Dumper("END ------------------------"); + } + #debug("Getting attr $obj_attr and val $obj_val"); + + # check if servicegroup_name is in the array of servicegroups for this processed service + foreach my $servicegroup (@servicegroups) { + # skip templates + next if ($obj->{'__I2CONVERT_SERVICE_IS_TEMPLATE'} == 1); + if ($servicegroup eq $obj_val) { + #debug("Found object: ".Dumper($obj)); + my $service_name; + $service_name->{'__I2CONVERT_SERVICE_HOSTNAME'} = $obj->{'__I2CONVERT_SERVICE_HOSTNAME'}; + $service_name->{'__I2CONVERT_SERVICEDESCRIPTION'} = $obj->{'__I2CONVERT_SERVICEDESCRIPTION'}; + push @service_names, $service_name; + } + } + } + + return @service_names; +} + sub obj_1x_get_all_hostnames_arr { my $objs = shift; my $obj_type = 'host'; @@ -518,7 +578,8 @@ sub obj_1x_get_service_attr { # if this object got what we want, return (it can be recursion and a template!) if(defined($obj_1x->{$search_attr})) { $obj_1x->{'__I2CONVERT_SEARCH_ATTR'} = $obj_1x->{$search_attr}; - return $obj_1x->{'__I2CONVERT_SEARCH_ATTR'}; + return $obj_1x->{$search_attr}; + #return $obj_1x->{'__I2CONVERT_SEARCH_ATTR'}; } # we don't have the attribute, should we look into a template? @@ -532,12 +593,14 @@ sub obj_1x_get_service_attr { # now recurse into ourselves and look for a possible service_description $service_attr = obj_1x_get_service_attr($objs_1x,$obj_1x_tmpl,$host_name,$search_attr); # we must pass the host_name and search_attr + #say Dumper($service_attr); # bail here if search did not unveil anything next if(!defined($service_attr)); # get the service attr and return - first template wins $obj_1x->{'__I2CONVERT_SEARCH_ATTR'} = $service_attr; - return $obj_1x->{'__I2CONVERT_SEARCH_ATTR'}; + return $service_attr; + #return $obj_1x->{'__I2CONVERT_SEARCH_ATTR'}; } } # no template used, and not service description - broken object, ignore it @@ -597,6 +660,56 @@ sub obj_1x_get_contact_attr { return undef; } +# get servicegroups from object (already 2x and _array_ XXX) +sub obj_2x_get_service_servicegroups { + my $objs_2x = shift; + my $obj_2x = shift; + my $host_name = shift; + my $search_attr = shift; + my @service_groups; + + #say Dumper("in obj_2x_get_service_attr"); + # if this object is invalid, bail early + return undef if !defined($obj_2x); + + # if this object got what we want, return (it can be recursion and a template!) + if(defined($obj_2x->{$search_attr}) && scalar(@{$obj_2x->{$search_attr}}) > 0) { + #say Dumper("in obj_2x_get_service_attr. found "); + #say Dumper($obj_2x->{$search_attr}); + return @{$obj_2x->{$search_attr}}; + } + + # we don't have the attribute, should we look into a template? + # make sure _not_ to use + if (defined($obj_2x->{'__I2CONVERT_USES_TEMPLATE'}) && $obj_2x->{'__I2CONVERT_USES_TEMPLATE'} == 1) { + # get the object referenced as template - this is an array of templates, loop (funny recursion here) + foreach my $obj_2x_template (@{$obj_2x->{'__I2CONVERT_TEMPLATE_NAMES'}}) { + + #say Dumper("in obj_2x_get_service_attr template"); + #say Dumper($obj_2x_template); + # get the template object associated with by its unique 'name' attr + my $obj_2x_tmpl = obj_get_tmpl_obj_by_tmpl_name($objs_2x, 'service', $obj_2x_template); + #say Dumper($obj_2x_tmpl); + + # now recurse into ourselves and look for a possible service_description + push @service_groups, obj_2x_get_service_servicegroups($objs_2x,$obj_2x_tmpl,$host_name,$search_attr); # we must pass the host_name and search_attr + #say Dumper($service_attr); + # bail here if search did not unveil anything + next if(scalar(@service_groups) == 0); + + # get the service attr and return - first template wins + return @service_groups; + } + } + # no template used, and not service description - broken object, ignore it + else { + return undef; + } + + # we should never hit here + return undef; +} + ################################################################################ # Conversion @@ -899,8 +1012,9 @@ sub convert_2x { # servicegroups ########################################## delete($cfg_obj_2x->{'service'}->{$service_cnt}->{'servicegroups'}); - # debug # @{$cfg_obj_2x->{'service'}->{$service_cnt}->{'servicegroups'}} = (); - + # debug # + @{$cfg_obj_2x->{'service'}->{$service_cnt}->{'servicegroups'}} = (); + if(defined($obj_1x_service->{'servicegroups'})) { # check if there's additive inheritance required, and save a flag if ($obj_1x_service->{'servicegroups'} =~ /^\+/) { @@ -911,6 +1025,8 @@ sub convert_2x { push @{$cfg_obj_2x->{'service'}->{$service_cnt}->{'servicegroups'}}, Icinga2::Utils::str2arr_by_delim_without_excludes($obj_1x_service->{'servicegroups'}, ',', 1); #print "DEBUG: servicegroups " . join (" ", @{$cfg_obj_2x->{'service'}->{$service_cnt}->{'servicegroups'}}); } + #say Dumper($cfg_obj_2x->{'service'}->{$service_cnt}->{__I2CONVERT_SERVICE_HOSTNAME}); + #say Dumper($cfg_obj_2x->{'service'}->{$service_cnt}->{'servicegroups'}); ########################################## # check_interval @@ -1817,8 +1933,8 @@ sub convert_2x { $user_notification->{$notification_name_2x}->{'type'} = $notification_command_type; # XXX do not add duplicate notifications, they must remain unique by their notification_command origin! - say Dumper("checking existing $notification_command_name_2x"); - say Dumper($user_notification); + #say Dumper("checking existing $notification_command_name_2x"); + #say Dumper($user_notification); if (obj_2x_notification_exists($cfg_obj_2x, $notification_command_name_2x) == 1) { #say Dumper("already existing $notification_command_name_2x"); next; @@ -2088,6 +2204,7 @@ sub convert_2x { if (defined($obj_1x_serviceescalation->{'service_description'})) { my $serviceescalation_service_obj = obj_get_service_obj_by_host_name_service_description($cfg_obj_2x, "__I2CONVERT_SERVICE_HOSTNAME", "__I2CONVERT_SERVICEDESCRIPTION", $obj_1x_serviceescalation->{'host_name'}, $obj_1x_serviceescalation->{'service_description'}); + push @{$serviceescalation_service_obj->{'__I2CONVERT_NOTIFICATIONS'}}, $user_notification; # we need to calculate begin/end based on service->notification_interval @@ -2135,7 +2252,7 @@ sub convert_2x { $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_NOTIFICATION_COMMAND'} = $notification_command_name; $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_IS_TEMPLATE'} = 1; # this is a template, used in hosts/services then - # more reference + # more references (this is why code duplication happens $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'users'} = $user_notification->{$notification_name_2x}->{'users'}; # add dependency to ITL template to objects @@ -2158,9 +2275,76 @@ sub convert_2x { ###################################### # XXX FIXME if (defined($obj_1x_serviceescalation->{'servicegroup_name'})) { + say Dumper($obj_1x_serviceescalation); + my @service_names = obj_2x_get_service_arr_by_servicegroup_name($cfg_obj_2x, $obj_1x_serviceescalation->{'servicegroup_name'}); + foreach my $serviceescalation_service_name (@service_names) { + my $serviceescalation_service_obj = obj_get_service_obj_by_host_name_service_description($cfg_obj_2x, "__I2CONVERT_SERVICE_HOSTNAME", "__I2CONVERT_SERVICEDESCRIPTION", $serviceescalation_service_name->{'__I2CONVERT_SERVICE_HOSTNAME'}, $serviceescalation_service_name->{'__I2CONVERT_SERVICEDESCRIPTION'}); + + #say Dumper($serviceescalation_service_obj); + # skip any templates which would create duplicates + next if ($serviceescalation_service_obj->{'__I2CONVERT_IS_TEMPLATE'} == 1); + say Dumper($serviceescalation_service_name); + + push @{$serviceescalation_service_obj->{'__I2CONVERT_NOTIFICATIONS'}}, $user_notification; + + # we need to calculate begin/end based on service->notification_interval + # if notification_interval is not defined, we need to look it up in the template tree! + if (defined($serviceescalation_service_obj->{'notification_interval'})) { + $notification_interval = $serviceescalation_service_obj->{'notification_interval'}; + } else { + $notification_interval = obj_1x_get_service_attr($cfg_obj_1x, $serviceescalation_service_obj, $serviceescalation_service_obj->{'__I2CONVERT_SERVICE_HOSTNAME'}, 'notification_interval'); + } + $user_notification->{$notification_name_2x}->{'__I2CONVERT_NOTIFICATION_TIMES'}->{'begin'} = $obj_1x_serviceescalation->{'first_notification'} * $notification_interval; + $user_notification->{$notification_name_2x}->{'__I2CONVERT_NOTIFICATION_TIMES'}->{'end'} = $obj_1x_serviceescalation->{'last_notification'} * $notification_interval; + # save a reference to more infos + $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_NOTIFICATION_TIMES'} = $user_notification->{$notification_name_2x}->{'__I2CONVERT_NOTIFICATION_TIMES'}; + + ###################################### + # now ADD the new escalation notification + ###################################### + + # XXX do not add duplicate notifications, they must remain unique by their notification_command origin! + next if (obj_2x_notification_exists($cfg_obj_2x, $notification_command_name_2x) == 1); + + next if (!defined($notification_command_name_2x)); + + # create a new NotificationCommand 2x object with the original name + $cfg_obj_2x->{'command'}->{$command_obj_cnt}->{'__I2CONVERT_COMMAND_TYPE'} = 'Notification'; + $cfg_obj_2x->{'command'}->{$command_obj_cnt}->{'__I2CONVERT_COMMAND_NAME'} = $notification_command_name; + $cfg_obj_2x->{'command'}->{$command_obj_cnt}->{'__I2CONVERT_COMMAND_LINE'} = $notification_command_line; + + # use the ITL plugin notification command template + if(defined($icinga2_cfg->{'itl'}->{'notificationcommand-template'}) && $icinga2_cfg->{'itl'}->{'notificationcommand-template'} ne "") { + push @{$cfg_obj_2x->{'command'}->{$command_obj_cnt}->{'__I2CONVERT_TEMPLATE_NAMES'}}, $icinga2_cfg->{'itl'}->{'notificationcommand-template'}; + $cfg_obj_2x->{'command'}->{$command_obj_cnt}->{'__I2CONVERT_USES_TEMPLATE'} = 1; + } + + # the check command name of 1.x is still the unique command object name, so we just keep it + # in __I2CONVERT_NOTIFICATION_COMMAND + + # our global PK + $command_obj_cnt++; + + # create a new notification template object + $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_NOTIFICATION_TEMPLATE_NAME'} = $notification_command_name_2x; + $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_NOTIFICATION_NAME'} = $notification_command_name_2x; + $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_NOTIFICATION_COMMAND'} = $notification_command_name; + $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_IS_TEMPLATE'} = 1; # this is a template, used in hosts/services then + + # more references (this is why code duplication happens + $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'users'} = $user_notification->{$notification_name_2x}->{'users'}; + + # add dependency to ITL template to objects + if(defined($icinga2_cfg->{'itl'}->{'notification-template'}) && $icinga2_cfg->{'itl'}->{'notification-template'} ne "") { + @{$cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_TEMPLATE_NAMES'}} = (); + push @{$cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_TEMPLATE_NAMES'}}, $icinga2_cfg->{'itl'}->{'notification-template'}; + $cfg_obj_2x->{'notification'}->{$notification_obj_cnt}->{'__I2CONVERT_USES_TEMPLATE'} = 1; # we now use a template, otherwise it won't be dumped + } + # our PK + $notification_obj_cnt++; + } } - } }