# MonArch - Groundwork Monitor Architect # MonarchProfileImport.pm # ############################################################################ # Release 4.0 # November 2011 ############################################################################ # # Original author: Scott Parris # # Copyright 2007-2011 GroundWork Open Source, Inc. (GroundWork) # All rights reserved. This program is free software; you can redistribute # it and/or modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # use strict; use MonarchStorProc; use MonarchForms; use XML::LibXML; package ProfileImporter; my $debug = 0; my %objects = (); my @host_externals = (); my %db_values = (); my %ov = ( 1 => 'Yes', 2 => 'No' ); my ( $file, $overwrite, $parser, $tree, $root, $monarch_ver ) = 0; my $objects_read = 0; my @messages = (); my $empty_data = qq( ); sub data_prep(@) { my $obj = $_[0]; my %values = %{ $_[1] }; my %data_vals = (); my %property_list = StorProc->property_list(); my @props = split( /,/, $property_list{$obj} ); my @db_vals = split( /,/, $db_values{$obj} ); foreach my $name ( keys %values ) { foreach my $p (@props) { if ( $p eq $name or $p eq 'custom_object_variables' && $name =~ /^_/ ) { my $match = undef; foreach my $val (@db_vals) { if ( $val eq $name ) { $data_vals{$val} = $values{$name}; $match = 1; last; } } unless ($match) { if ( $values{$p} || defined( $values{$p} ) && $values{$p} eq '0' || $p eq 'custom_object_variables' ) { $data_vals{'data'} .= "\n \n "; } } } } } if ( $data_vals{'data'} ) { $data_vals{'data'} = qq( $data_vals{'data'} ); } return %data_vals; } # ############################################################################ # Commands # sub commands() { my @errors = (); my @objs = $root->findnodes("//command"); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; foreach my $obj (@objs) { my %name_vals = (); $cnt++; my $command_name = $obj->findnodes('prop[@name="name"]') || '-- unknown --'; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $name_vals{$property} = $value; if ( $property eq 'command_line' ) { if ( $name_vals{'command_line'} =~ /\$(USER\d+)\$\/(\S+)\s/ ) { my ( $res, $file ) = ( $1, $2 ); $res = lc($res); unless ( $objects{'resources'}{$res} ) { push @errors, "Resource value \"$res\" for plugin does not exist, for command definition \"$command_name\"."; } unless ( -e "$objects{'resources'}{$res}/$file" ) { push @errors, "Plugin \"$objects{'resources'}{$res}/$2\" does not exist, for command definition \"$command_name\"."; } } } } } # unless ($errors[0]) { my %values = data_prep( 'commands', \%name_vals ); ($values{'comment'} = $name_vals{'comment'}) =~ s/^\s+|\s+$//g if defined $name_vals{'comment'}; foreach my $val ( keys %{ $objects{'commands'} } ) { ## FIX THIS: case insensitivity in matching command names is probably a bad idea, leading to confusion if ( $val =~ /^$values{'name'}$/i ) { $objects{'commands'}{ $values{'name'} } = $objects{'commands'}{$val}; } } if ( $objects{'commands'}{ $values{'name'} } ) { if ( $overwrite == 1 ) { my $result = StorProc->update_obj( 'commands', 'name', $values{'name'}, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } else { $update_cnt++; } } } else { my @db_vals = split( /,/, $db_values{'commands'} ); my @values = (\undef); foreach my $val (@db_vals) { push @values, $values{$val} } my $id = StorProc->insert_obj_id( 'commands', \@values, 'command_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ...;"; } else { $objects{'commands'}{ $values{'name'} } = $id; $add_cnt++; } } # } } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Commands: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Time periods # sub timeperiods() { my @errors = (); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; my $result = undef; eval { my $parser = XML::LibXML->new(); my $tree = $parser->parse_file("$file"); my $root = $tree->getDocumentElement; my @objs = $root->findnodes("//time_period"); my %tp_exclude = (); my %overwrite = (); foreach my $obj (@objs) { my %name_vals = (); $cnt++; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $name_vals{$property} = $value; } } my %values = data_prep( 'time_periods', \%name_vals ); ($values{'comment'} = $name_vals{'comment'}) =~ s/^\s+|\s+$//g if defined $name_vals{'comment'}; my $tp_name = $values{'name'}; # FIX THIS: case insensitivity here and for other objects is likely to lead to massive confusion, # partly because it is not handled correctly in subsequent code below and will result in either # database corruption or update errors foreach my $val ( keys %{ $objects{'time_periods'} } ) { ## FIX THIS: case insensitivity in matching time period names is probably a bad idea, leading to confusion if ( $val =~ /^$tp_name$/i ) { $objects{'time_periods'}{$tp_name} = $objects{'time_periods'}{$val}; } } if ( $objects{'time_periods'}{$tp_name} ) { if ( $overwrite == 1 ) { $result = StorProc->update_obj( 'time_periods', 'name', $tp_name, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result (time period \"$tp_name\"); continuing ..."; } else { $overwrite{$tp_name} = 1; $update_cnt++; } } } else { my @db_vals = split( /,/, $db_values{'time_periods'} ); my @values = (\undef); foreach my $val (@db_vals) { push @values, $values{$val}; } my $id = StorProc->insert_obj_id( 'time_periods', \@values, 'timeperiod_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id (time period \"$tp_name\"); continuing ..."; } else { $objects{'time_periods'}{$tp_name} = $id; $overwrite{$tp_name} = 1; $add_cnt++; } } if ( $objects{'time_periods'}{$tp_name} && $overwrite{$tp_name} ) { $result = StorProc->delete_all( 'time_period_property', 'timeperiod_id', $objects{'time_periods'}{$tp_name} ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result (time period \"$tp_name\"); continuing ..."; } $result = StorProc->delete_all( 'time_period_exclude', 'timeperiod_id', $objects{'time_periods'}{$tp_name} ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result (time period \"$tp_name\"); continuing ..."; } $tp_exclude{$tp_name} = $name_vals{'exclude'}; my @db_vals = split( /,/, $db_values{'time_periods'} ); foreach my $val (@db_vals) { delete $name_vals{$val}; } # Note: In the future, we might also want to add code here to # also process "use" and "require" directives for time periods. delete $name_vals{'exclude'}; delete $name_vals{'use'}; delete $name_vals{'require'}; foreach my $dayrule ( keys %name_vals ) { my @values = (); $values[0] = $objects{'time_periods'}{$tp_name}; $values[1] = $dayrule; $values[2] = 'exception'; $values[2] = 'weekday' if $dayrule =~ /^\S+day$/; if ( $name_vals{$dayrule} =~ /(.*?)[;#](.*)/ ) { $values[3] = $1; $values[4] = $2; } else { $values[3] = $name_vals{$dayrule}; $values[4] = ''; } my $result = StorProc->insert_obj( 'time_period_property', \@values ); if ( $result =~ /error/i ) { push @errors, "Error: $result (time period \"$tp_name\"); continuing ..."; } } } } # We have to wait until now to populate all time_period_exclude rows, so we # know we should have timeperiod_id values for all referenced time periods. foreach my $tp_name ( keys %tp_exclude ) { my @elist = defined( $tp_exclude{$tp_name} ) ? split( /,/, $tp_exclude{$tp_name} ) : (); foreach my $excluded_tp_name (@elist) { if ( $objects{'time_periods'}{$excluded_tp_name} ) { my @values = ( $objects{'time_periods'}{$tp_name}, $objects{'time_periods'}{$excluded_tp_name} ); $result = StorProc->insert_obj( 'time_period_exclude', \@values ); if ( $result =~ /error/i ) { push @errors, "Error: $result (time period \"$tp_name\"); continuing ..."; } } else { push @errors, "Error: time period \"$tp_name\" exclusion of time period \"$excluded_tp_name\" has not been saved; continuing ..."; } } } }; # end eval if ($@) { push @errors, $@ } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Time periods: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Host templates # sub host_templates() { my @errors = (); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; eval { my $parser = XML::LibXML->new(); my $tree = $parser->parse_file("$file"); my $root = $tree->getDocumentElement; my @objs = $root->findnodes("//host_template"); foreach my $obj (@objs) { my %name_vals = (); $cnt++; my $db_update = 1; my $host_template_name = $obj->findnodes('prop[@name="name"]') || '-- unknown --'; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; if ( $value eq '0' ) { $value = "-zero-" } $name_vals{$property} = $value; if ($value) { if ( $property =~ /^check_command$|^event_handler$/ ) { if ( $objects{'commands'}{$value} ) { $name_vals{$property} = $objects{'commands'}{$value}; } else { $db_update = 0; push @errors, "Command definition \"$value\" for \"$property\" does not exist for host template \"$host_template_name\"."; } } if ( $property =~ /period/ ) { if ( $objects{'time_periods'}{$value} ) { $name_vals{$property} = $objects{'time_periods'}{$value}; } else { $db_update = 0; push @errors, "Time period definition \"$value\" for \"$property\" does not exist for host template \"$host_template_name\"."; } } } } } unless ( $errors[0] ) { my %values = data_prep( 'host_templates', \%name_vals ); ($values{'comment'} = $name_vals{'comment'}) =~ s/^\s+|\s+$//g if defined $name_vals{'comment'}; foreach my $val ( keys %{ $objects{'host_templates'} } ) { ## FIX THIS: case insensitivity in matching host template names is probably a bad idea, leading to confusion if ( $val =~ /^$values{'name'}$/i ) { $objects{'host_templates'}{ $values{'name'} } = $objects{'host_templates'}{$val}; } } if ( $objects{'host_templates'}{ $values{'name'} } ) { if ( $overwrite == 1 ) { my $result = StorProc->update_obj( 'host_templates', 'name', $values{'name'}, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } else { $update_cnt++; } } } else { my @db_vals = split( /,/, $db_values{'host_templates'} ); my @values = (\undef); foreach my $val (@db_vals) { push @values, $values{$val} } my $id = StorProc->insert_obj_id( 'host_templates', \@values, 'hosttemplate_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ..."; } else { $objects{'host_templates'}{ $values{'name'} } = $id; $add_cnt++; } } } } }; # end eval if ($@) { push @errors, $@ } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Host templates: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Extended Host Info # sub hostextinfo_templates() { my @errors = (); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; my @objs = $root->findnodes("//extended_host_info_template"); foreach my $obj (@objs) { my %name_vals = (); $cnt++; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $name_vals{$property} = $value; } } my %values = data_prep( 'extended_host_info_templates', \%name_vals ); ($values{'comment'} = $name_vals{'comment'}) =~ s/^\s+|\s+$//g if defined $name_vals{'comment'}; foreach my $val ( keys %{ $objects{'extended_host_info_templates'} } ) { ## FIX THIS: case insensitivity in matching host extended info template names is probably a bad idea, leading to confusion if ( $val =~ /^$values{'name'}$/i ) { $objects{'extended_host_info_templates'}{ $values{'name'} } = $objects{'extended_host_info_templates'}{$val}; } } if ( $objects{'extended_host_info_templates'}{ $values{'name'} } ) { if ( $overwrite == 1 ) { my $result = StorProc->update_obj( 'extended_host_info_templates', 'name', $values{'name'}, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } else { $update_cnt++; } } } else { my @db_vals = split( /,/, $db_values{'extended_host_info_templates'} ); my @values = (\undef); foreach my $val (@db_vals) { push @values, $values{$val} } my $id = StorProc->insert_obj_id( 'extended_host_info_templates', \@values, 'hostextinfo_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ..."; } else { $objects{'extended_host_info_templates'}{ $values{'name'} } = $id; $add_cnt++; } } } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Extended host info templates: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Service Templates # sub service_templates() { my %parent = (); my @errors = (); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; my @objs = $root->findnodes("//service_template"); foreach my $obj (@objs) { my %name_vals = (); $cnt++; my $db_update = 1; # We must get the service template name early so we have it ready for use no matter where it appears in sequence. my $service_template_name = $obj->findnodes('prop[@name="name"]') || '-- unknown --'; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; if ( $value eq '0' ) { $value = "-zero-" } $name_vals{$property} = $value; if ($value) { if ( $property =~ /^check_command$|^event_handler$/ ) { if ( $objects{'commands'}{$value} ) { $name_vals{$property} = $objects{'commands'}{$value}; } else { $db_update = 0; delete $parent{$service_template_name}; push @errors, "Command definition \"$value\" for \"$property\" does not exist for service template \"$service_template_name\"."; } } if ( $property =~ /period/ ) { if ( $objects{'time_periods'}{$value} ) { $name_vals{$property} = $objects{'time_periods'}{$value}; } else { $db_update = 0; delete $parent{$service_template_name}; push @errors, "Time period definition \"$value\" for \"$property\" does not exist for service template \"$service_template_name\"."; } } } if ( $property eq 'template' && $db_update == 1 ) { $parent{$service_template_name} = $value; $name_vals{'parent_id'} = ''; delete $name_vals{'template'}; } } } if ( !scalar(%name_vals) ) { # FIX THIS: Some of our current distributed profiles contain empty service templates. # Until we fix that, we will simply ignore this condition. Even afterward, we need to # decide whether this should be considered an error or whether we should simply ignore # it as being unimportant. # push @errors, "Found an empty service template."; } unless ( $errors[0] || !scalar(%name_vals) ) { my %values = data_prep( 'service_templates', \%name_vals ); ($values{'comment'} = $name_vals{'comment'}) =~ s/^\s+|\s+$//g if defined $name_vals{'comment'}; foreach my $val ( keys %{ $objects{'service_templates'} } ) { ## FIX THIS: case insensitivity in matching service template names is probably a bad idea, leading to confusion if ( $val =~ /^$values{'name'}$/i ) { $objects{'service_templates'}{ $values{'name'} } = $objects{'service_templates'}{$val}; } } if ( $objects{'service_templates'}{ $values{'name'} } ) { if ( $overwrite == 1 ) { my $result = StorProc->update_obj( 'service_templates', 'name', $values{'name'}, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } else { $update_cnt++; } } else { # If we're not overwriting, it would be inappropriate to update the parent_id link below. delete $parent{ $values{'name'} }; } } else { my @db_vals = split( /,/, $db_values{'service_templates'} ); my @values = (\undef); foreach my $val (@db_vals) { push @values, $values{$val} } my $id = StorProc->insert_obj_id( 'service_templates', \@values, 'servicetemplate_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ..."; } else { $objects{'service_templates'}{ $values{'name'} } = $id; $add_cnt++; } } } } foreach my $child ( keys %parent ) { my %values = ( 'parent_id' => $objects{'service_templates'}{ $parent{$child} } ); my $result = StorProc->update_obj( 'service_templates', 'name', $child, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Service templates: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Extended Service Info # sub serviceextinfo_templates() { my @errors = (); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; my @objs = $root->findnodes("//extended_service_info_template"); foreach my $obj (@objs) { my %name_vals = (); $cnt++; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $name_vals{$property} = $value; } } my %values = data_prep( 'extended_service_info_templates', \%name_vals ); ($values{'comment'} = $name_vals{'comment'}) =~ s/^\s+|\s+$//g if defined $name_vals{'comment'}; foreach my $val ( keys %{ $objects{'extended_service_info_templates'} } ) { ## FIX THIS: case insensitivity in matching service extended info template names is probably a bad idea, leading to confusion if ( $val =~ /^$values{'name'}$/i ) { $objects{'extended_service_info_templates'}{ $values{'name'} } = $objects{'extended_service_info_templates'}{$val}; } } if ( $objects{'extended_service_info_templates'}{ $values{'name'} } ) { if ( $overwrite == 1 ) { my $result = StorProc->update_obj( 'extended_service_info_templates', 'name', $values{'name'}, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } else { $update_cnt++; } } } else { my @db_vals = split( /,/, $db_values{'extended_service_info_templates'} ); my @values = (\undef); foreach my $val (@db_vals) { push @values, $values{$val} } my $id = StorProc->insert_obj_id( 'extended_service_info_templates', \@values, 'serviceextinfo_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ..."; } else { $objects{'extended_service_info_templates'}{ $values{'name'} } = $id; $add_cnt++; } } } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Extended service info templates: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Services # sub services() { my @errors = (); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; my @objs = $root->findnodes("//service_name"); foreach my $obj (@objs) { my @externals = (); my %name_vals = (); $cnt++; # Who can explain why this magical incantation works? my $service_name = $obj->findnodes('prop[@name="name"]') || '-- unknown --'; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; if ( $value eq '0' ) { $value = "-zero-" } $name_vals{$property} = $value; # This old attempt to get the service name would only be good if the name were guaranteed # to pop up early in the list of sibling nodes. Otherwise, it would still be undefined # when we need it in an error message. That's why we now find the $service_name from the # XML stream (actually, from the corresponding DOM, above) instead. # if ( $property eq 'name' ) { $service_name = $value } if ($value) { if ( $property =~ /^(?:check_command|event_handler)$/ ) { if ( $objects{'commands'}{$value} ) { $name_vals{$property} = $objects{'commands'}{$value}; } else { push @errors, "Command definition \"$value\" for $property does not exist for the \"$service_name\" service."; } } elsif ( $property eq 'template' ) { if ( $objects{'service_templates'}{$value} ) { $name_vals{$property} = $objects{'service_templates'}{$value}; } else { push @errors, "Service template \"$value\" does not exist for the \"$service_name\" service."; } } elsif ( $property =~ /check_period|notification_period/ ) { if ( $objects{'time_periods'}{$value} ) { $name_vals{$property} = $objects{'time_periods'}{$value}; } else { push @errors, "Time periods definition \"$value\" for $property does not exist for the \"$service_name\" service."; } } elsif ( $property eq 'extinfo' ) { if ( $objects{'extended_service_info_templates'}{$value} ) { $name_vals{$property} = $objects{'extended_service_info_templates'}{$value}; } else { push @errors, "Extended info definition \"$value\" does not exist for the \"$service_name\" service."; } } elsif ( $property eq 'service_external' ) { if ( $objects{'externals'}{$value} ) { push @externals, $objects{'externals'}{$value}; } else { push @errors, "External definition \"$value\" does not exist for the \"$service_name\" service."; } } } } } unless ( $name_vals{'command_line'} ) { $name_vals{'command_line'} = 'NULL'; } unless ( $errors[0] ) { my %values = data_prep( 'service_names', \%name_vals ); my %override_values = data_prep( 'servicename_overrides', \%name_vals ); foreach my $val ( keys %{ $objects{'service_names'} } ) { ## FIX THIS: case insensitivity in matching service names is probably a bad idea, leading to confusion if ( $val =~ /^$values{'name'}$/i ) { $objects{'service_names'}{ $values{'name'} } = $objects{'service_names'}{$val}; } } if ( $objects{'service_names'}{ $values{'name'} } ) { if ( $overwrite == 1 ) { $update_cnt++; my $result = StorProc->update_obj( 'service_names', 'name', $values{'name'}, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } elsif (%override_values) { my %service = StorProc->fetch_one( 'service_names', 'name', $values{'name'} ); my %service_override = StorProc->fetch_one( 'servicename_overrides', 'servicename_id', $service{'servicename_id'} ); if ( $service_override{'servicename_id'} ) { $result = StorProc->update_obj( 'servicename_overrides', 'servicename_id', $service{'servicename_id'}, \%override_values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } else { my @db_vals = split( /,/, $db_values{'servicename_overrides'} ); my @values = ( $service{'servicename_id'} ); foreach my $val (@db_vals) { push @values, $override_values{$val}; } my $result = StorProc->insert_obj( 'servicename_overrides', \@values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } } $result = StorProc->delete_all( 'external_service_names', 'servicename_id', $objects{'service_names'}{ $values{'name'} } ); if ( $result =~ /^Error/ ) { push @errors, $result } foreach my $eid (@externals) { my @values = ( $eid, $objects{'service_names'}{ $values{'name'} } ); my $result = StorProc->insert_obj( 'external_service_names', \@values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } } } else { my @db_vals = split( /,/, $db_values{'service_names'} ); my @values = (\undef); foreach my $val (@db_vals) { push @values, $values{$val} } unless ( $monarch_ver eq '0.97a' ) { pop @values; push @values, $empty_data; } my $id = StorProc->insert_obj_id( 'service_names', \@values, 'servicename_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ... $db_values{'service_names'}"; } else { if (%override_values) { my @db_vals = split( /,/, $db_values{'servicename_overrides'} ); @values = ($id); foreach my $val (@db_vals) { push @values, $override_values{$val}; } my $result = StorProc->insert_obj( 'servicename_overrides', \@values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } $objects{'service_names'}{ $values{'name'} } = $id; $add_cnt++; foreach my $eid (@externals) { my @values = ( $eid, $id ); my $result = StorProc->insert_obj( 'external_service_names', \@values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } } } } } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Services: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Service Profiles # sub service_profiles() { my @errors = (); my @services = (); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; my @objs = $root->findnodes("//service_profile"); foreach my $obj (@objs) { my %name_vals = (); $cnt++; my %services = (); my $spid = undef; my $service_profile_name = $obj->findnodes('prop[@name="name"]') || '-- unknown --'; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $name_vals{$property} = $value; if ( $property eq 'name' ) { $service_profile_name = $value } if ( $property eq 'service' ) { if ( $objects{'service_names'}{$value} ) { $services{ $objects{'service_names'}{$value} } = 1; } else { push @messages, "Service definition \"$value\" does not exist for service profile \"$service_profile_name\"."; } } } } foreach my $val ( keys %{ $objects{'profiles_service'} } ) { ## FIX THIS: case insensitivity in matching service profile names is probably a bad idea, leading to confusion if ( $val =~ /^$name_vals{'name'}$/i ) { $objects{'profiles_service'}{ $name_vals{'name'} } = $objects{'profiles_service'}{$val}; } } if ( $objects{'profiles_service'}{ $name_vals{'name'} } ) { push @messages, "Service profile \"$service_profile_name\" already exists."; if ( $overwrite == 1 ) { my %vals = ( 'description' => $name_vals{'description'} ); my $result = StorProc->update_obj( 'profiles_service', 'name', $name_vals{'name'}, \%vals ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } else { $update_cnt++; } } } else { my @values = ( \undef, $name_vals{'name'}, $name_vals{'description'} ); unless ( $monarch_ver eq '0.97a' ) { push @values, $empty_data } my $id = StorProc->insert_obj_id( 'profiles_service', \@values, 'serviceprofile_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ..."; } else { $add_cnt++; $objects{'profiles_service'}{ $name_vals{'name'} } = $id; } } my %where = ( 'serviceprofile_id' => $objects{'profiles_service'}{ $name_vals{'name'} } ); my @snids = StorProc->fetch_list_where( 'serviceprofile', 'servicename_id', \%where ); foreach my $service ( keys %services ) { my $exists = 0; foreach (@snids) { if ( $_ eq $service ) { $exists = 1 } } unless ($exists) { my @vals = ( $service, $objects{'profiles_service'}{ $name_vals{'name'} } ); my $result = StorProc->insert_obj( 'serviceprofile', \@vals ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } } } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Service profiles: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Import Externals - used for both host or service externals # sub import_externals($) { my $obj_type = shift; my @objs = (); my @errors = (); my $read_cnt = 0; my $added_cnt = 0; my $updated_cnt = 0; if ( $obj_type =~ /^(?:host|service)$/ ) { my $node_str = '//' . $obj_type . '_external'; @objs = $root->findnodes($node_str); $read_cnt = scalar @objs; } else { push @errors, "Error: invalid object type [$obj_type] passed to import_externals(); continuing ..."; } foreach my $obj (@objs) { my %name_vals = (); my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $name_vals{$property} = $value; } } my %values = ( 'type' => $name_vals{'type'}, 'display' => $name_vals{'data'} ); if ( $objects{'externals'}{ $name_vals{'name'} } ) { if ( $overwrite == 1 ) { my $result = StorProc->update_obj( 'externals', 'name', $name_vals{'name'}, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } else { $updated_cnt++; } } push( @host_externals, $objects{'externals'}{ $name_vals{'name'} } ) if ( $obj_type eq 'host' ); } else { my @values = ( \undef, $name_vals{'name'}, '', $name_vals{'type'}, $name_vals{'data'}, '' ); my $id = StorProc->insert_obj_id( 'externals', \@values, 'external_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ..."; } else { $objects{'externals'}{ $name_vals{'name'} } = $id; $added_cnt++; push( @host_externals, $id ) if ( $obj_type eq 'host' ); } } } my $error_cnt = scalar(@errors); $objects_read += $read_cnt; push @messages, "\u$obj_type externals: $read_cnt read, $added_cnt added, $updated_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # ############################################################################ # Host Profiles # sub host_profiles() { my @errors = (); my $cnt = 0; my $add_cnt = 0; my $update_cnt = 0; my @objs = $root->findnodes("//host_profile"); foreach my $obj (@objs) { my %name_vals = (); $cnt++; my %service_profiles = (); my $host_profile_name = $obj->findnodes('prop[@name="name"]') || '-- unknown --'; my @siblings = $obj->getChildnodes(); foreach my $node (@siblings) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $name_vals{$property} = $value; if ( $property eq 'name' ) { $host_profile_name = $value } if ( $property eq 'host_template' ) { if ( $objects{'host_templates'}{$value} ) { $name_vals{'host_template_id'} = $objects{'host_templates'}{$value}; } else { push @errors, "Host template definition \"$value\" does not exist for host profile \"$host_profile_name\"."; } delete $name_vals{$property}; } unless ( $errors[0] ) { if ( $property eq 'extended_host_info_templates' ) { if ( $objects{'extended_host_info_templates'}{$value} ) { $name_vals{$property} = $objects{'extended_host_info_templates'}{$value}; } else { push @messages, "Extended info definition \"$value\" does not exist for host profile \"$host_profile_name\"."; push @messages, "Action: \"$value\" ignored."; } delete $name_vals{$property}; } if ( $property eq 'service_profile' ) { if ( $objects{'profiles_service'}{$value} ) { if ( $monarch_ver eq '0.97a' ) { $name_vals{'serviceprofile_id'} = $objects{'profiles_service'}{$value}; } else { $service_profiles{ $objects{'profiles_service'}{$value} } = 1; } } else { push @messages, "Service profile definition \"$value\" does not exist for host profile \"$host_profile_name\"."; push @messages, "Action: \"$value\" ignored."; } delete $name_vals{$property}; } } } } unless ( $errors[0] ) { my %values = data_prep( 'profiles_host', \%name_vals ); foreach my $val ( keys %{ $objects{'profiles_host'} } ) { ## FIX THIS: case insensitivity in matching host profile names is probably a bad idea, leading to confusion if ( $val =~ /^$values{'name'}$/i ) { $objects{'profiles_host'}{ $values{'name'} } = $objects{'profiles_host'}{$val}; } } if ( $objects{'profiles_host'}{ $values{'name'} } ) { if ( $overwrite == 1 ) { my $result = StorProc->update_obj( 'profiles_host', 'name', $values{'name'}, \%values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } else { $update_cnt++; my $result = StorProc->delete_all( 'external_host_profile', 'hostprofile_id', $objects{'profiles_host'}{ $values{'name'} } ); if ( $result =~ /^Error/ ) { push @errors, $result } ## FIX LATER: This loop should depend not on the presence of ## sections in the imported file, but instead on the presence of ## ## properties within the section. foreach my $eid (@host_externals) { my @values = ( $eid, $objects{'profiles_host'}{ $values{'name'} } ); my $result = StorProc->insert_obj( 'external_host_profile', \@values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } } } } else { my @db_vals = split( /,/, $db_values{'profiles_host'} ); my @values = (\undef); foreach my $val (@db_vals) { push @values, $values{$val} } unless ( $monarch_ver eq '0.97a' ) { push @values, $empty_data } my $id = StorProc->insert_obj_id( 'profiles_host', \@values, 'hostprofile_id' ); if ( $id =~ /^Error/ ) { push @errors, "Error: $id; continuing ..."; } else { $objects{'profiles_host'}{ $values{'name'} } = $id; $add_cnt++; ## FIX LATER: See above about the @host_externals loop. foreach my $eid (@host_externals) { my @values = ( $eid, $id ); my $result = StorProc->insert_obj( 'external_host_profile', \@values ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } } } unless ( $monarch_ver eq '0.97a' ) { my %where = ( 'hostprofile_id' => $objects{'profiles_host'}{ $values{'name'} } ); my @snids = StorProc->fetch_list_where( 'profile_host_profile_service', 'serviceprofile_id', \%where ); foreach my $service ( keys %service_profiles ) { my $exists = 0; foreach (@snids) { if ( $_ eq $service ) { $exists = 1 } } unless ($exists) { my @vals = ( $objects{'profiles_host'}{ $name_vals{'name'} }, $service ); my $result = StorProc->insert_obj( 'profile_host_profile_service', \@vals ); if ( $result =~ /^Error/ ) { push @errors, "Error: $result; continuing ..."; } } } } } } my $error_cnt = scalar(@errors); $objects_read += $cnt; push @messages, "Host profile: $cnt read, $add_cnt added, $update_cnt updated" . ( $error_cnt == 0 ? '' : ", $error_cnt error" . ( $error_cnt == 1 ? '' : 's' ) ) . " (overwrite existing = $ov{$overwrite})."; return @errors; } # # Performance configuration # sub parse_perfconfig_xml(@) { my $xmlfile = $_[0]; my $overwrite = $_[1]; my @errors = (); my $data = undef; my $end_config = undef; if ( !open( XMLFILE, '<', $xmlfile ) ) { push @errors, "ERROR: Can't open XML file $xmlfile ($!)"; } else { while ( my $line = ) { chomp $line; $data .= $line; } close(XMLFILE); } my ( $host, $service, $type, $enable, $parseregx_first, $service_regx, $label, $rrdname, $rrdcreatestring, $rrdupdatestring, $graphcgi, $perfidstring, $parseregx ) = (); if ($data) { push @messages, "Performance configuration $xmlfile found."; eval { my $parser = XML::LibXML->new(); my $doc = $parser->parse_string($data); my @nodes = $doc->findnodes("groundwork_performance_configuration"); foreach my $node (@nodes) { foreach my $servprof ( $node->getChildnodes ) { foreach my $childnode ( $servprof->findnodes("graph") ) { foreach my $key ( $childnode->findnodes("host") ) { $host = $key->textContent; } foreach my $key ( $childnode->findnodes("service") ) { $service = $key->textContent; if ( $key->hasAttributes() ) { $service_regx = $key->getAttribute('regx'); } } foreach my $key ( $childnode->findnodes("type") ) { $type = $key->textContent; } foreach my $key ( $childnode->findnodes("enable") ) { $enable = $key->textContent; } foreach my $key ( $childnode->findnodes("label") ) { $label = $key->textContent; } foreach my $key ( $childnode->findnodes("rrdname") ) { $rrdname = $key->textContent; } foreach my $key ( $childnode->findnodes("rrdcreatestring") ) { $rrdcreatestring = $key->textContent; } foreach my $key ( $childnode->findnodes("rrdupdatestring") ) { $rrdupdatestring = $key->textContent; } foreach my $key ( $childnode->findnodes("graphcgi") ) { $graphcgi = $key->textContent; } foreach my $key ( $childnode->findnodes("perfidstring") ) { $perfidstring = $key->textContent; } foreach my $key ( $childnode->findnodes("parseregx") ) { $parseregx = $key->textContent; if ( $key->hasAttributes() ) { $parseregx_first = $key->getAttribute('first'); } } my %where = ( 'host' => $host, 'service' => $service ); my %perf_config = StorProc->fetch_one_where( 'performanceconfig', \%where ); unless ($perfidstring) { $perfidstring = ' ' } unless ($parseregx) { $parseregx = ' ' } if ( $perf_config{'performanceconfig_id'} ) { if ( $overwrite == 1 ) { my %values = ( 'host' => $host, 'service' => $service, 'type' => $type, 'enable' => $enable, 'parseregx_first' => $parseregx_first, 'service_regx' => $service_regx, 'label' => $label, 'rrdname' => $rrdname, 'rrdcreatestring' => $rrdcreatestring, 'rrdupdatestring' => $rrdupdatestring, 'graphcgi' => $graphcgi, 'perfidstring' => $perfidstring, 'parseregx' => $parseregx ); my $result = StorProc->update_obj_where( 'performanceconfig', \%values, \%where ); if ( $result =~ /error/i ) { push @errors, $result; } else { push @messages, "Performance configuration for host \"$host\", service \"$service\" updated (overwrite existing = $ov{$overwrite})."; } } else { push @messages, "Performance configuration for host \"$host\", service \"$service\" already exists (overwrite existing = $ov{$overwrite})."; } } else { unless ($graphcgi) { $graphcgi = '/' } my @values = ( \undef, $host, $service, $type, $enable, $parseregx_first, $service_regx, $label, $rrdname, $rrdcreatestring, $rrdupdatestring, $graphcgi, $perfidstring, $parseregx ); my $result = StorProc->insert_obj( 'performanceconfig', \@values ); if ( $result =~ /error/i ) { push @errors, $result; } else { push @messages, "Performance configuration created for host \"$host\", service \"$service\"."; } } } } } }; # end eval if ($@) { push @errors, $@ } } return @errors; } sub apply_discovery_template(@) { my $id = $_[1]; my $template = $_[2]; my $source = $_[3]; my @errors = (); my $data = undef; if ( !open( FILE, '<', "$source/discover-template-$template.xml" ) ) { push @errors, "$source/discover-template-$template.xml ($!)"; } else { while ( my $line = ) { $line =~ s/\r\n/\n/; $data .= $line; } close(FILE); } my %schemas = StorProc->get_table_objects('import_schema'); if ($data) { my %values = (); my $parser = XML::LibXML->new(); my $doc = undef; eval { $doc = $parser->parse_string($data); }; if ($@) { print STDERR $@; # FIX LATER: HTMLifying here is something of a hack, as it presumes a context not in evidence. $@ = HTML::Entities::encode($@); $@ =~ s/\n/
/g; push @errors, "Bad XML string (apply_discovery_template):
$@"; } else { my @nodes = $doc->findnodes("//prop"); foreach my $node (@nodes) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $values{$property} = $value; } } my %group_methods = (); my @methods = $doc->findnodes("//method"); foreach my $method (@methods) { my $name = undef; my %props = (); if ( $method->hasChildNodes() ) { my @nodes = $method->getChildnodes(); foreach my $node (@nodes) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; if ( $property eq 'name' ) { $name = $value; } else { $props{$property} = $value; } } } } %{ $group_methods{$name} } = %props; # foreach my $prop (keys %props) { # next statement was commented out, so commenting out entire loop # $group_methods{$name}{$prop} = $props{$prop}; # } } if ( $schemas{ $values{'schema'} } ) { $values{'schema_id'} = $schemas{ $values{'schema'} }; } else { my $data = qq( ); my @vals = ( \undef, $values{'schema'}, '', '', $data, '', '', '', '' ); my $schema_id = StorProc->insert_obj_id( 'import_schema', \@vals, 'schema_id' ); if ( $schema_id =~ /error/i ) { push @errors, $schema_id; } else { my $template = "$values{'schema'}"; $values{'schema_id'} = $schema_id; $template =~ s/\s|\\|\/|\'|\"|\%|\^|\#|\@|\!|\$/-/g; if ( -e "$source/schema-template-$template.xml" ) { my @errs = apply_automation_template( '', $schema_id, $template, $source ); if (@errs) { push( @errors, @errs ) } } } } delete $values{'name'}; delete $values{'auto'}; delete $values{'schema'}; my $result = StorProc->update_obj( 'discover_group', 'group_id', $id, \%values ); my %discover_methods = StorProc->get_table_objects('discover_method'); foreach my $method ( keys %group_methods ) { unless ( $discover_methods{$method} ) { my ( $description, $type ) = undef; my $config = "\n"; foreach my $prop ( keys %{ $group_methods{$method} } ) { if ( $prop eq 'description' ) { $description = $group_methods{$method}{$prop}; } elsif ( $prop eq 'type' ) { $type = $group_methods{$method}{$prop}; } else { $config .= "\n"; } } $config .= "\n"; my @vals = ( \undef, $method, $description, $config, $type ); $discover_methods{$method} = StorProc->insert_obj_id( 'discover_method', \@vals, 'method_id' ); if ( $discover_methods{$method} =~ /error/i ) { push @errors, $discover_methods{$method}; } } unless (@errors) { my @vals = ( $id, $discover_methods{$method} ); my $result = StorProc->insert_obj( 'discover_group_method', \@vals ); if ( $result =~ /error/i ) { push @errors, $result } } } } } return @errors; } sub apply_automation_template(@) { my $id = $_[1]; my $template = $_[2]; my $source = $_[3]; my @errors = (); my $data = undef; if ( !open( FILE, '<', "$source/schema-template-$template.xml" ) ) { push @errors, "$source/schema-template-$template.xml ($!)"; } else { while ( my $line = ) { $line =~ s/\r\n/\n/; $data .= $line; } close(FILE); } my %serviceprofile_name = StorProc->get_table_objects('profiles_service'); my %hostprofile_name = StorProc->get_table_objects('profiles_host'); my %group_name = StorProc->get_table_objects('monarch_groups'); my %host_name = StorProc->get_table_objects('hosts'); my %contactgroup_name = StorProc->get_table_objects('contactgroups'); my %hostgroup_name = StorProc->get_table_objects('hostgroups'); my %service_name = StorProc->get_table_objects('service_names'); my %columns = (); if ($data) { ## use MonarchProfileImport; my %values = (); my $parser = XML::LibXML->new(); my $doc = undef; eval { $doc = $parser->parse_string($data); }; if ($@) { print STDERR $@; # FIX LATER: HTMLifying here is something of a hack, as it presumes a context not in evidence. $@ = HTML::Entities::encode($@); $@ =~ s/\n/
/g; push @errors, "Bad XML string (apply_automation_template):
$@"; } else { my @nodes = $doc->findnodes("//prop"); foreach my $node (@nodes) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; if ( $property eq 'default_profile' ) { unless ( $hostprofile_name{$value} ) { my $folder = '/usr/local/groundwork/core/profiles'; my $file = "host-profile-$value.xml"; if ( -e "$folder/$file" ) { my @msgs = import_profile( '', $folder, $file, '' ); my %hp = StorProc->fetch_one( 'profiles_host', 'name', $value ); $hostprofile_name{$value} = $hp{'hostprofile_id'}; } } if ( $hostprofile_name{$value} ) { $values{'hostprofile_id'} = $hostprofile_name{$value}; } } else { $values{$property} = $value; } } } my $result = StorProc->update_obj( 'import_schema', 'schema_id', $id, \%values ); if ( $result =~ /error/i ) { push @errors, $result } my $column_key = 0; my $match_key = 0; my @columns = $doc->findnodes("//column"); foreach my $column (@columns) { $column_key++; if ( $column->hasChildNodes() ) { my @nodes = $column->getChildnodes(); foreach my $node (@nodes) { if ( $node->hasAttributes() ) { my $property = $node->getAttribute('name'); my $value = $node->textContent; $columns{$column_key}{$property} = $value; } elsif ( $node->hasChildNodes() ) { my @matches = $node->getChildnodes(); $match_key++; foreach my $match (@matches) { if ( $match->hasAttributes() ) { my $property = $match->getAttribute('name'); my $value = $match->textContent; $columns{$column_key}{'match'}{$match_key}{$property} = $value; } elsif ( $match->hasChildNodes() ) { my @objs = $match->getChildnodes(); my @instances = (); foreach my $obj (@objs) { if ( $obj->hasAttributes() ) { my $property = $obj->getAttribute('name'); my $value = $obj->textContent; if ( $property eq 'object_type' ) { if ( $value eq 'Host profile' ) { $columns{$column_key}{'match'}{$match_key}{$property} = $value; } else { $columns{$column_key}{'match'}{$match_key}{$property} = $value; @{ $columns{$column_key}{'match'}{$match_key} { $columns{$column_key}{'match'}{$match_key}{'object_type'} } } = (); } } elsif ( $property eq 'service_name' ) { $columns{$column_key}{'match'}{$match_key}{'service_name'} = $value; } elsif ( $property eq 'service_args' ) { $columns{$column_key}{'match'}{$match_key}{'service_args'} = $value; } else { if ( $property eq 'hostprofile' ) { $columns{$column_key}{'match'}{$match_key}{$property} = $value; } else { push @instances, $value; } } } } @{ $columns{$column_key}{'match'}{$match_key}{ $columns{$column_key}{'match'}{$match_key}{'object_type'} } } = @instances; } } } } } } foreach my $column_key ( keys %columns ) { my @values = ( \undef, $id, $columns{$column_key}{'name'}, $columns{$column_key}{'position'}, $columns{$column_key}{'delimiter'} ); my $column_id = StorProc->insert_obj_id( 'import_column', \@values, 'column_id' ); if ( $column_id =~ /error/i ) { push @errors, $column_id; } else { foreach my $match_key ( keys %{ $columns{$column_key}{'match'} } ) { my $hp_name = $columns{$column_key}{'match'}{$match_key}{'hostprofile'}; unless ( !defined($hp_name) || $hostprofile_name{$hp_name} ) { my $folder = '/usr/local/groundwork/core/profiles'; my $file = "host-profile-$hp_name.xml"; if ( -e "$folder/$file" ) { my @msgs = import_profile( '', $folder, $file, '' ); my %hp = StorProc->fetch_one( 'profiles_host', 'name', $hp_name ); $hostprofile_name{$hp_name} = $hp{'hostprofile_id'}; } } my $hostprofile = $columns{$column_key}{'match'}{$match_key}{'hostprofile'}; my $service_name = $columns{$column_key}{'match'}{$match_key}{'service_name'}; my @values = ( \undef, $column_id, $columns{$column_key}{'match'}{$match_key}{'name'}, $columns{$column_key}{'match'}{$match_key}{'order'}, $columns{$column_key}{'match'}{$match_key}{'match_type'}, $columns{$column_key}{'match'}{$match_key}{'match_string'}, $columns{$column_key}{'match'}{$match_key}{'rule'}, $columns{$column_key}{'match'}{$match_key}{'object_type'}, (defined($hostprofile) ? $hostprofile_name{$hostprofile} : undef), (defined($service_name) ? $service_name{$service_name} : undef), $columns{$column_key}{'match'}{$match_key}{'service_args'} ); my $match_id = StorProc->insert_obj_id( 'import_match', \@values, 'match_id' ); if ( $match_id =~ /error/i ) { push @errors, $match_id; } else { if ( $columns{$column_key}{'match'}{$match_key}{'object_type'} eq 'Contact group' ) { foreach my $obj ( @{ $columns{$column_key}{'match'}{$match_key}{'Contact group'} } ) { if ( $contactgroup_name{$obj} ) { my @values = ( $match_id, $contactgroup_name{$obj} ); my $result = StorProc->insert_obj( 'import_match_contactgroup', \@values ); if ( $result =~ /error/i ) { push @errors, $result; } } } } if ( $columns{$column_key}{'match'}{$match_key}{'object_type'} eq 'Host group' ) { foreach my $obj ( @{ $columns{$column_key}{'match'}{$match_key}{'Host group'} } ) { if ( $hostgroup_name{$obj} ) { my @values = ( $match_id, $hostgroup_name{$obj} ); my $result = StorProc->insert_obj( 'import_match_hostgroup', \@values ); if ( $result =~ /error/i ) { push @errors, $result; } } } } if ( $columns{$column_key}{'match'}{$match_key}{'object_type'} eq 'Group' ) { foreach my $obj ( @{ $columns{$column_key}{'match'}{$match_key}{'Group'} } ) { if ( $group_name{$obj} ) { my @values = ( $match_id, $group_name{$obj} ); my $result = StorProc->insert_obj( 'import_match_group', \@values ); if ( $result =~ /error/i ) { push @errors, $result; } } } } if ( $columns{$column_key}{'match'}{$match_key}{'object_type'} eq 'Service profile' ) { foreach my $obj ( @{ $columns{$column_key}{'match'}{$match_key}{'Service profile'} } ) { unless ( $serviceprofile_name{$obj} ) { my $folder = '/usr/local/groundwork/core/profiles'; my $file = "service-profile-$obj.xml"; if ( -e "$folder/$file" ) { #my @msgs = ProfileImporter->import_profile($folder,$file,''); my @msgs = import_profile( '', $folder, $file, '' ); my %sp = StorProc->fetch_one( 'profiles_service', 'name', $obj ); $serviceprofile_name{$obj} = $sp{'serviceprofile_id'}; } } if ( $serviceprofile_name{$obj} ) { my @values = ( $match_id, $serviceprofile_name{$obj} ); my $result = StorProc->insert_obj( 'import_match_serviceprofile', \@values ); if ( $result =~ /error/i ) { push @errors, $result; } } } } if ( $columns{$column_key}{'match'}{$match_key}{'object_type'} eq 'Parent' ) { foreach my $obj ( @{ $columns{$column_key}{'match'}{$match_key}{'Parent'} } ) { if ( $host_name{$obj} ) { my @values = ( $match_id, $host_name{$obj} ); my $result = StorProc->insert_obj( 'import_match_parent', \@values ); if ( $result =~ /error/i ) { push @errors, $result; } } } } } } } } } } return @errors; } sub import_profile(@) { my $folder = $_[1]; my $xmlfile = $_[2]; $overwrite = $_[3]; unless ($overwrite) { $overwrite = 2 } $file = "$folder/$xmlfile"; my @errors = (); $objects_read = 0; @messages = (); if ( !-f $file || !-r $file ) { push @errors, "Error: This is not a readable file."; } if ( -z $file ) { push @errors, "Error: This file is empty."; } unless ( $errors[0] ) { my $parser = XML::LibXML->new(); eval { $tree = $parser->parse_file($file) }; push @errors, "Error: This is not a valid file type:
$@" if $@; } unless ( $errors[0] ) { $root = $tree->getDocumentElement; %objects = StorProc->get_objects(); if ( $objects{'error'} ) { foreach my $table ( keys %{ $objects{'error'} } ) { push @errors, $objects{'error'}{$table}; } } } unless ( $errors[0] ) { %db_values = StorProc->db_values(); my %monarch_ver = StorProc->fetch_one( 'setup', 'name', 'monarch_version' ); $monarch_ver = $monarch_ver{'value'}; } unless ( $errors[0] ) { @errors = commands(); } unless ( $errors[0] ) { @errors = timeperiods(); } unless ( $errors[0] ) { @errors = host_templates(); } unless ( $errors[0] ) { @errors = hostextinfo_templates(); } unless ( $errors[0] ) { @errors = service_templates(); } unless ( $errors[0] ) { @errors = serviceextinfo_templates(); } unless ( $errors[0] ) { @errors = import_externals('service'); } unless ( $errors[0] ) { @errors = import_externals('host'); } unless ( $errors[0] ) { @errors = services(); } unless ( $errors[0] ) { @errors = service_profiles(); } unless ( $errors[0] ) { @errors = host_profiles(); } unless ( $errors[0] ) { $xmlfile =~ s/^(?:host-profile-|service-profile-|service-)//; my $perfcfg_file = undef; if ( !opendir( DIR, $folder ) ) { push @errors, "Error: cannot open $folder to read ($!)"; } else { while ( my $file = readdir(DIR) ) { if ( $file =~ /^perfconfig-$xmlfile$/ ) { $perfcfg_file = $file; last; } } closedir(DIR); } if ($perfcfg_file) { @errors = parse_perfconfig_xml( "$folder/$perfcfg_file", $overwrite ); } } if ( @errors || $objects_read == 0 ) { my $file_link; my $via_phrase; if ($file) { ( my $relative_file = $file ) =~ s@/usr/local/groundwork/core@@; my $url = Forms->get_file_url($relative_file); if ($url) { $file_link = "$file"; $via_phrase = ' via the link above'; } } unless ($file_link) { $file_link = $file; $via_phrase = ''; } if ( $objects_read == 0 ) { push @errors, "No objects were read from the imported file; check its contents$via_phrase."; } unshift @messages, "Profile import found error(s) in:
$file_link"; push @messages, "Error(s) occurred here during profile import:"; push( @messages, @errors ); push @messages, "Profile import halted. Make corrections and try again."; return @messages; } else { return @messages; } } if ($debug) { my $path = $ARGV[1]; my $file = $ARGV[2]; my $overwrite = $ARGV[3]; my @result = ( my $result ) = StorProc->dbconnect(); my @res = import_profile( '', $path, $file, $overwrite ); push( @result, @res ); $result = StorProc->dbdisconnect(); print "\nFile: $file\n"; print "Monarch ver: $monarch_ver\n"; print "\nResults:\n========================================================================\n"; foreach my $line (@res) { print "\n\t$line"; } print "\n\nEnd=============================================================================\n"; } 1;