238 lines
6.9 KiB
Perl
238 lines
6.9 KiB
Perl
#!/usr/bin/perl -w
|
|
|
|
# Copyright (c) 2006, 2017, Oracle and/or its affiliates. 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.0,
|
|
# as published by the Free Software Foundation.
|
|
#
|
|
# This program is also distributed with certain software (including
|
|
# but not limited to OpenSSL) that is licensed under separate terms,
|
|
# as designated in a particular file or component or in included license
|
|
# documentation. The authors of MySQL hereby grant you an additional
|
|
# permission to link the program and your derivative works with the
|
|
# separately licensed software that they have included with MySQL.
|
|
#
|
|
# 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, version 2.0, 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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
use strict;
|
|
use Getopt::Long;
|
|
|
|
sub usage
|
|
{
|
|
print STDERR "Usage:\n";
|
|
print STDERR "\tndb_error_reporter config.ini [username] [--fs] [--connection-timeout=#] [--skip-nodegroup=#] [--dry-scp] [--help]\n\n";
|
|
print STDERR "\tusername is a user that you can use to ssh into\n";
|
|
print STDERR "\t all of your nodes with.\n\n";
|
|
print STDERR "\t--fs means include the filesystems in the report\n";
|
|
print STDERR "\t WARNING: This may require a lot of disk space.\n";
|
|
print STDERR "\t Only use this option when asked to.\n\n";
|
|
print STDERR "\t--connection-timeout is the timeout in seconds\n";
|
|
print STDERR "\t to connect to a node\n\n";
|
|
print STDERR "\t--skip-nodegroup allows you to skip all the nodes\n";
|
|
print STDERR "\t belonging to a specific nodegroup\n\n";
|
|
print STDERR "\t--dry-scp allows running the script for testing without\n";
|
|
print STDERR "\t scp from the remote hosts\n\n";
|
|
print STDERR "\t--help prints this message and exits\n\n";
|
|
exit(1);
|
|
}
|
|
|
|
my $config_get_fs= 0;
|
|
my $config_connect_timeout;
|
|
my @config_skip_nodegroups;
|
|
my $config_dry_scp= 0;
|
|
my $config_help= 0;
|
|
|
|
my %options= (
|
|
"--fs" => \$config_get_fs,
|
|
"--connection-timeout=i" => \$config_connect_timeout,
|
|
"--skip-nodegroup=i@" => \@config_skip_nodegroups,
|
|
"--dry-scp" => \$config_dry_scp,
|
|
"--help|usage|?" => \$config_help,
|
|
);
|
|
|
|
GetOptions(%options) or usage();
|
|
|
|
# If --help provided, print usage and exit
|
|
if($config_help)
|
|
{
|
|
print STDERR "This program creates an archive from data node and management node files.\n\n";
|
|
usage();
|
|
}
|
|
|
|
# At least one positional argument must be given
|
|
# but never more than 2
|
|
if(@ARGV < 1 || @ARGV > 2)
|
|
{
|
|
usage();
|
|
}
|
|
|
|
# First positional argument is name of the config file
|
|
my $config_file= $ARGV[0];
|
|
if(!stat($config_file))
|
|
{
|
|
print STDERR "Cannot open configuration file.\n\n";
|
|
usage();
|
|
}
|
|
|
|
# Second positional argument may contain scp username
|
|
my $config_scp_user= '';
|
|
if(defined($ARGV[1]))
|
|
{
|
|
$config_scp_user.= $ARGV[1].'@';
|
|
}
|
|
|
|
use File::Basename;
|
|
my $dirname= dirname(__FILE__);
|
|
my $ndb_config= "$dirname/ndb_config";
|
|
my $config_query = "$ndb_config --config-file=$config_file --nodes --query=nodeid ";
|
|
my $ndbd_query_cmd = "$config_query --type=ndbd";
|
|
my $mgmd_query_cmd = "$config_query --type=ndb_mgmd";
|
|
# Check config parsing sanity with dry-run
|
|
if (system("$ndbd_query_cmd > /dev/null") != 0 ||
|
|
system("$mgmd_query_cmd > /dev/null") != 0)
|
|
{
|
|
print STDERR "Configuration file parsing failed.\n\n";
|
|
exit(1);
|
|
}
|
|
|
|
my @nodes= split ' ',`$ndbd_query_cmd`;
|
|
my $ndbd_count = @nodes;
|
|
push @nodes, split ' ',`$mgmd_query_cmd`;
|
|
my $mgmd_count = @nodes - $ndbd_count;
|
|
|
|
if($ndbd_count == 0 ||
|
|
$mgmd_count == 0)
|
|
{
|
|
print STDERR "Error extracting mgmd and data node ids from config file.";
|
|
exit(1);
|
|
}
|
|
|
|
sub config {
|
|
my $nodeid= shift;
|
|
my $query= shift;
|
|
my $res= `$ndb_config --config-file=$config_file --nodeid=$nodeid --query=$query`;
|
|
chomp $res;
|
|
$res;
|
|
}
|
|
|
|
my @t= localtime();
|
|
my $reportdir= sprintf('ndb_error_report_%u%02u%02u%02u%02u%02u',
|
|
($t[5]+1900),($t[4]+1),$t[3],$t[2],$t[1],$t[0]);
|
|
|
|
if(stat($reportdir) || stat($reportdir.'tar.bz2'))
|
|
{
|
|
print STDERR "It looks like another ndb_error_report process is running.\n";
|
|
print STDERR "If that is not the case, remove the ndb_error_report directory";
|
|
print STDERR " and run ndb_error_report again.\n\n";
|
|
exit(1);
|
|
}
|
|
|
|
mkdir($reportdir);
|
|
|
|
sub scp
|
|
{
|
|
my ($host, $from_dir, $to_dir, $recurse) = @_;
|
|
|
|
my $scp_options = '';
|
|
$scp_options .= ' -p '; # Preserve times from original
|
|
if (defined($config_connect_timeout))
|
|
{
|
|
$scp_options .= " -o ConnectTimeout=$config_connect_timeout ";
|
|
}
|
|
if ($recurse)
|
|
{
|
|
$scp_options .= ' -r ';
|
|
}
|
|
|
|
my $cmd = "scp $scp_options $config_scp_user$host:$from_dir $to_dir";
|
|
if ($config_dry_scp)
|
|
{
|
|
# --dry-scp just prints the scp command
|
|
print $cmd, "\n";
|
|
return;
|
|
}
|
|
system($cmd);
|
|
}
|
|
|
|
sub skip_nodegroup
|
|
{
|
|
my $nodegroup= shift;
|
|
foreach my $skip_nodegroup(@config_skip_nodegroups)
|
|
{
|
|
if($nodegroup eq $skip_nodegroup)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
foreach my $node (@nodes)
|
|
{
|
|
my $nodegroup= config($node, 'nodegroup');
|
|
if(skip_nodegroup($nodegroup))
|
|
{
|
|
print("\n\n Node $node belongs to nodegroup $nodegroup: skipping.");
|
|
next;
|
|
}
|
|
print "\n\n Copying data from node $node".
|
|
(($config_get_fs)?" with filesystem":"").
|
|
"\n\n";
|
|
|
|
my $from_path = "ndb_$node*"; # Copy everything starting with ndb_<nodeid>
|
|
my $datadir = config($node,'datadir');
|
|
if ($datadir)
|
|
{
|
|
# Prepend datadir
|
|
$from_path = "$datadir/$from_path";
|
|
}
|
|
scp(config($node,'host'), $from_path,
|
|
"$reportdir/", $config_get_fs);
|
|
|
|
# Extract cluster log name from LogDestination(if any)
|
|
foreach my $file_handler (grep(s/^FILE://i, split(/;/, config($node, 'LogDestination'))))
|
|
{
|
|
foreach my $file_name (grep(s/^filename=//i, split(/,/, $file_handler)))
|
|
{
|
|
# Check whether the file has an absolute path - otherwise the file
|
|
# will be located in $datadir
|
|
if (substr($file_name, 0, 1) ne '/')
|
|
{
|
|
$file_name = $datadir.'/'.$file_name;
|
|
}
|
|
print " Copying cluster log from '$file_name' on node $node...\n";
|
|
scp(config($node,'host'),
|
|
"$file_name*",
|
|
"$reportdir/", 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
print "\n\n Copying configuration file...\n\n\t$config_file\n\n";
|
|
system "cp -p $config_file $reportdir/";
|
|
|
|
my $r = system 'bzip2 2>&1 > /dev/null < /dev/null';
|
|
my $outfile;
|
|
if($r==0)
|
|
{
|
|
$outfile= "$reportdir.tar.bz2";
|
|
system "tar cf - $reportdir|bzip2 > $outfile";
|
|
}
|
|
else
|
|
{
|
|
$outfile= "$reportdir.tar.gz";
|
|
system "tar cf - $reportdir|gzip > $outfile";
|
|
}
|
|
|
|
system "rm -rf $reportdir";
|
|
|
|
print "\n\nPlease attach $outfile to your error report\n\n";
|