blob: 922cab448628c2218db6dc5b95d35755e3134e50 [file] [log] [blame]
#!/usr/bin/perl
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ORT check extension. Checks how many errors there are running the "ort" script on the cache
#
# example cron entry
# 40 * * * * ssh_key_edge_user /opt/traffic_ops/app/bin/checks/ToORTCheck.pl -c "{\"base_url\": \"https://localhost\", \"check_name\": \"ORT\"}" >> /var/log/traffic_ops/extensionCheck.log 2>&1
#
# example cron entry with syslog
# 40 * * * * ssh_key_edge_user /opt/traffic_ops/app/bin/checks/ToORTCheck.pl -c "{\"base_url\": \"https://localhost\", \"check_name\": \"ORT\", \"name\": \"Operational Readiness Test\", \"syslog_facility\": \"local0\"}" > /dev/null 2>&1
use strict;
use warnings;
$|++;
use Data::Dumper;
use Getopt::Std;
use Log::Log4perl qw(:easy);
use JSON;
use Extensions::Helper;
use Sys::Syslog qw(:standard :macros);
my $VERSION = "0.03";
my %args = ();
getopts( "c:f:hl:q", \%args );
if ($args{h}) {
&help();
exit();
}
if ( !defined( $args{c} ) ) {
ERROR "-c not defined";
print "\n\n";
&help();
exit(1);
}
my $jconf = undef;
eval { $jconf = decode_json( $args{c} ) };
if ($@) {
ERROR("Bad json config: $@");
print "\n\n";
&help();
exit(1);
}
my $check_name = $jconf->{check_name};
my $to_user = $jconf->{to_user};
my $to_pass = $jconf->{to_pass};
if ( $check_name ne "ORT" ) {
ERROR "This Check Extension is exclusively for the ORT (Operational Readiness Test) check.";
print "\n\n";
&help();
exit(4);
}
my $sslg = undef;
my $chck_lng_nm;
if (defined($jconf->{syslog_facility})) {
$chck_lng_nm = $jconf->{name};
openlog ('ToChecks', '', $jconf->{syslog_facility});
$sslg = 1;
}
my $force = 0;
if (defined($args{f})) {
$force = $args{f};
}
my $quiet;
if ($args{q}) {
$quiet = 1;
}
Log::Log4perl->easy_init($ERROR);
if ( defined( $args{l} ) ) {
if ( $args{l} == 1 ) { Log::Log4perl->easy_init($INFO); }
elsif ( $args{l} == 2 ) { Log::Log4perl->easy_init($DEBUG); }
elsif ( $args{l} >= 3 ) { Log::Log4perl->easy_init($TRACE); }
else { Log::Log4perl->easy_init($INFO); }
}
DEBUG( "Including DEBUG messages in output. Config is \'" . $args{c} . "\'" );
TRACE( "Including TRACE messages in output. Config is \'" . $args{c} . "\'" );
my $b_url = $jconf->{base_url};
Extensions::Helper->import();
my $ext = Extensions::Helper->new( { base_url => $b_url, token => '91504CE6-8E4A-46B2-9F9F-FE7C15228498' } );
my $jdataserver = $ext->get(Extensions::Helper::SERVERLIST_PATH);
my $glbl_prms = $ext->get( '/api/2.0/profiles/name/global/parameters' );
my $to_url;
foreach my $p (@{$glbl_prms}) {
if ($p->{name} eq 'tm.url') {
$to_url = $p->{value};
}
}
foreach my $server ( @{$jdataserver} ) {
if ( $server->{type} =~ m/^EDGE/ || $server->{type} =~ m/^MID/ ) {
&ort_check( $server->{ipAddress}, $server->{hostName}, $server->{id},
$server->{domainName}, $server->{status} );
}
}
sub ort_check() {
my $ipaddr = shift;
my $host_name = shift;
my $host_id = shift;
my $domain = shift;
my $status = shift;
my $ort_version = "unknown";
my $host_name_fqdn = $host_name.".".$domain;
my $cmd = "/usr/bin/sudo /opt/ort/traffic_ops_ort.pl report WARN ".$to_url." '".$to_user.":".$to_pass."'";
#$cmd = "ssh -t -o \"StrictHostKeyChecking no\" -i ~$username/.ssh/."$key." -l " . $username . " " . $ipaddr . " " . $cmd;
$cmd = "ssh -t -o ConnectTimeout=5 -o \"UserKnownHostsFile /dev/null\" -o \"StrictHostKeyChecking no\" -o \"BatchMode yes\" ".$ipaddr." ".$cmd." 2>&1";
TRACE $host_name . " running " . $cmd;
my $out = '';
my $msg = '';
my ($fatals, $errors, $warns);
if ($force == 0) {
$out = `$cmd`;
my $results = "/var/www/html/ort/" . $host_id;
if ( !-d $results ) {
mkdir($results);
}
# TODO integrate this file into Traffic Ops GUI
my $filename = $results."/results";
open(my $fh, '>', $filename);
if (!$fh) {
ERROR "Could not open file '$filename' $!";
} else {
print $fh $out;
}
close $fh;
my @lines = split( /\n/, $out );
$errors = grep /^ERROR/, @lines;
$fatals = grep /^FATAL/, @lines;
$warns = grep /^WARN/, @lines;
foreach my $line (@lines) {
if ($line =~ m/^Version/) {
chomp($line);
my @tmp = split(" ", $line);
$ort_version = $tmp[-1];
}
}
DEBUG "ORT version: ".$ort_version;
if ($out =~ m/Connection timed out/) {
ERROR "Could not connect to server.";
$msg = "Could not connect to server.";
$errors = -1;
} elsif ($out =~ m/Permission denied/) {
$msg = "Permission Denied";
ERROR "Permission Denied";
$errors = -1;
}
} elsif ($force == 1) {
$msg = "Force: FAIL";
$errors = -1;
} elsif ($force == 2) {
$msg = "Force: OK";
$errors = 1;
$fatals = 1;
$warns = 1;
}
if ($sslg) {
if ($errors < 0) {
my @tmp = ($host_name_fqdn,$check_name,$chck_lng_nm,'FAIL',$status,$ort_version,$msg);
syslog(LOG_ERR, "hostname=%s check=%s name=\"%s\" result=%s status=%s ort_version=%s msg=\"%s\"", @tmp);
} elsif (($errors >= 0) || ($force == 2)) {
my @tmp = ($host_name_fqdn,$check_name,$chck_lng_nm,'OK',$status,$ort_version,$errors,$fatals,$warns,$msg);
syslog(LOG_ERR, "hostname=%s check=%s name=\"%s\" result=%s status=%s ort_version=%s errors=%s fatals=%s warnings=%s msg=\"%s\"", @tmp);
}
}
TRACE $host_name . " score: " . $errors;
$ext->post_result( $host_id, $check_name, $errors ) if (!$quiet);
}
sub ltrim { my $s = shift; $s =~ s/^\s+//; return $s };
sub rtrim { my $s = shift; $s =~ s/\s+$//; return $s };
sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
sub help() {
print "ToORTCheck.pl -c \"{\\\"base_url\\\": \\\"https://localhost\\\", \\\"check_name\\\": \\\"ORT\\\"[, \\\"name\\\": \\\"Operational Readiness Test\\\", \\\"syslog_facility\\\": \\\"local0\\\"]}\" [-f <1-2>] [-l <1-3>]\n";
print "\n";
print "-c json formatted list of variables\n";
print " base_url: required\n";
print " URL of the Traffic Ops server.\n";
print " check_name: required\n";
print " The name of this check.\n";
print " name: optional\n";
print " The long name of this check. used in conjuction with syslog_facility.\n";
print " syslog_facility: optional\n";
print " The syslog facility to send messages. Requires the \"name\" option to\n";
print " be set.\n";
print "-f Force a FAIL or OK message\n";
print " 1: FAIL\n";
print " 2: OK\n";
print "-h Print this message\n";
print "-l Debug level\n";
print "-q Don't post results to Traffic Ops.\n";
print "================================================================================\n";
# the above line of equal signs is 80 columns
print "Note: The user running this script must have an authorized public key on the\n";
print " cache servers and must also have sudoers access.\n";
print "\n";
}