TT#71209 Enhance compare dbs tools

Use compare_dbs as a wrapper to check all the used schemes.

Add different formats of output to compare_dbs.pl - tap and human
readable one.
Process all the schemes in one run of compare_dbs.pl and do it in one db
connection.
If the tap formatter is used - output the result of all schemes in a
single file.

Change-Id: I2696680aa30b56658f130bd1cea116099c086753
changes/86/37086/13
Mykola Malkov 5 years ago
parent 21d7cbbce2
commit 43155235d7

@ -1,2 +1,4 @@
templates/* /etc/ngcp-config/templates/etc/ngcp-system-tests/
ngcp-system-tests /usr/bin/
sbin/ngcp-mysql-compare-dbs /usr/sbin/
helper/compare_dbs.pl /usr/share/ngcp-system-tests/

@ -8,10 +8,14 @@ use Data::Compare;
use Getopt::Long;
use Carp;
my $credentials_file = '/etc/mysql/sipwise_extra.cnf';
my $argv = {
result => 'result.tap',
pass_db1 => '',
pass_db2 => '',
formatter => '',
schemes => '',
pass_db1 => '',
pass_db2 => '',
user_db1 => '',
user_db2 => '',
};
get_options();
@ -128,54 +132,60 @@ __SQL__
my @objs_list = qw( tables columns indexes constraints triggers views routines );
my $dbh1 = DBI->connect( $argv->{connect_db1}, $argv->{user_db1}, $argv->{pass_db1},
{ RaiseError => 1 } ) or
croak("Can't connect to db1: $argv->{connect_db1}, $argv->{user_db1}, $argv->{pass_db1} ");
if ($argv->{schemes} eq '') {
warn " --schemes is empty\n\n";
print_usage();
exit 1;
}
my $dbh2 = DBI->connect( $argv->{connect_db2}, $argv->{user_db2}, $argv->{pass_db2},
{ RaiseError => 1 } ) or
croak("Can't connect to db2: $argv->{connect_db2}, $argv->{user_db2}, $argv->{pass_db2} ");
my $dbh1 = DBI->connect(
"DBI:mysql:;host=sp1;mysql_read_default_file=$credentials_file",
$argv->{user_db1},
$argv->{pass_db1},
{ RaiseError => 1 } ) or
croak("Can't connect to db1: DBI:mysql:;host=sp1;mysql_read_default_file=$credentials_file, $argv->{user_db1}, $argv->{pass_db1} ");
my $exit = 0;
my $dbh2 = DBI->connect(
"DBI:mysql:;host=sp2;mysql_read_default_file=$credentials_file",
$argv->{user_db2},
$argv->{pass_db2},
{ RaiseError => 1 } ) or
croak("Can't connect to db2: DBI:mysql:;host=sp2;mysql_read_default_file=$credentials_file, $argv->{user_db2}, $argv->{pass_db2} ");
my ($sth1, $sth2);
my ($struct1, $struct2);
my $res = [];
foreach my $obj ( @objs_list ) {
$struct1 = $dbh1->selectall_hashref( $queries->{$obj}, 'key_col' );
$struct2 = $dbh2->selectall_hashref( $queries->{$obj}, 'key_col' );
my $exit = 0;
foreach my $schema ( split( / /, $argv->{schemes} ) ) {
$dbh1->do("USE $schema");
$dbh2->do("USE $schema");
unless ( Compare($struct1, $struct2) ) {
$exit = 1;
print_diff($struct1, $struct2, $obj, $res);
my ($sth1, $sth2);
my ($struct1, $struct2);
foreach my $obj ( @objs_list ) {
$struct1 = $dbh1->selectall_hashref( $queries->{$obj}, 'key_col' );
$struct2 = $dbh2->selectall_hashref( $queries->{$obj}, 'key_col' );
unless ( Compare($struct1, $struct2) ) {
$exit = 1;
print_diff($struct1, $struct2, $obj, $res, $schema);
}
}
}
my $number = scalar(@{$res});
my $counter = 1;
open( my $fh, '>', $argv->{result} );
if ( $number > 0 ) {
print {$fh} "1..$number\n";
foreach my $err ( @{$res} ) {
print {$fh} "not ok $counter $err\n";
$counter++;
}
if ( $argv->{formatter} eq 'tap' ) {
tap_output();
}
else {
print {$fh} "1..1\n";
print {$fh} "ok 1 Schemes are equal\n";
human_output();
}
close($fh);
exit $exit;
sub get_options {
GetOptions(
'result=s' => \$argv->{'result'},
'connect_db1=s' => \$argv->{'connect_db1'},
'formatter=s' => \$argv->{'formatter'},
'schemes=s' => \$argv->{'schemes'},
'user_db1=s' => \$argv->{'user_db1'},
'pass_db1=s' => \$argv->{'pass_db1'},
'connect_db2=s' => \$argv->{'connect_db2'},
'user_db2=s' => \$argv->{'user_db2'},
'pass_db2=s' => \$argv->{'pass_db2'},
'help|h' => sub{ print_usage(); exit(0); },
@ -184,12 +194,14 @@ sub get_options {
sub print_usage {
my $usage =<<__USAGE__
This script compares two databases by structure and prints result in TAP format.
This script compares two databases by structure and prints result.
compare_db.pl [options]
OPTIONS
--result TAP file with results
--connect_db1 DSN of the 1st schema
--formatter=[tap] The format of output.
Supported values:
tap - print in a TAP format.
--schemes List of schemes which should be compared.
--user_db1 User of the 1st schema
--pass_db1 Password of the 1st schema
--connect_db2 DSN of the 2nd schema
@ -205,16 +217,16 @@ __USAGE__
}
sub print_diff {
my ($obj1, $obj2, $object_name, $result) = @_;
my ($obj1, $obj2, $object_name, $result, $schema) = @_;
foreach my $key ( sort( keys( %{$obj1} ) ) ) {
unless ( exists($obj2->{$key}) ) {
push( @{$result}, "$object_name element: $key is missing in Schema2" );
push( @{$result}, "Schema $schema, $object_name element: $key is missing in Schema2" );
next;
}
foreach my $c_name ( sort( keys( %{ $obj1->{$key} } ) ) ) {
unless ( exists($obj2->{$key}->{$c_name}) ) {
push( @{$result}, "$object_name element: $key.$c_name is missing in Schema2" );
push( @{$result}, "Schema $schema, $object_name element: $key.$c_name is missing in Schema2" );
next;
}
@ -225,20 +237,21 @@ sub print_diff {
$obj2->{$key}->{$c_name} = 'NULL' if ( ! defined($obj2->{$key}->{$c_name}) );
if ( $obj1->{$key}->{$c_name} ne $obj2->{$key}->{$c_name} ) {
push( @{$result}, "$object_name elements: $key.$c_name are not equal: "
. "Schema1=$obj1->{$key}->{$c_name} vs Schema2=$obj2->{$key}->{$c_name}" );
push( @{$result}, "Schema $schema, $object_name elements: $key.$c_name are not equal:\n ---\n"
. " Schema1: $obj1->{$key}->{$c_name}\n"
. " Schema2: $obj2->{$key}->{$c_name}" );
}
}
}
foreach my $key ( sort( keys( %{$obj2} ) ) ) {
unless ( exists($obj1->{$key}) ) {
push( @{$result}, "$object_name element: $key is missing in Schema1" );
push( @{$result}, "Schema $schema, $object_name element: $key is missing in Schema1" );
next;
}
foreach my $c_name ( sort( keys( %{ $obj2->{$key} } ) ) ) {
unless ( exists($obj1->{$key}->{$c_name}) ) {
push( @{$result}, "$object_name element: $key.$c_name is missing in Schema1" );
push( @{$result}, "Schema $schema, $object_name element: $key.$c_name is missing in Schema1" );
next;
}
}
@ -246,3 +259,32 @@ sub print_diff {
return 1;
}
sub tap_output {
my $number = scalar(@{$res});
my $counter = 1;
if ( $number > 0 ) {
print "1..$number\n";
foreach my $err ( @{$res} ) {
print "not ok $counter $err\n";
$counter++;
}
}
else {
print "1..1\n";
print "ok 1 All schemes are equal\n";
}
}
sub human_output {
my $number = scalar(@{$res});
if ( $number > 0 ) {
print "The following errors were found:\n\n";
foreach my $err ( @{$res} ) {
print "$err\n";
}
}
else {
print "All schemes $argv->{schemes} are equal\n";
}
}

@ -1,49 +0,0 @@
#!/bin/bash
set -euo pipefail
rm -rf results
mkdir results
if ! [[ -r /etc/ngcp-backup-tools/db-backup.conf ]]; then
echo "Cannot read mandatory config file /etc/ngcp-backup-tools/db-backup.conf" 2>&1
exit 1
fi
. /etc/ngcp-backup-tools/db-backup.conf
location="$(dirname "$0")"
version="$(cat /etc/ngcp_version)"
case "${version}" in
2.8|3.*|mr[3-7].*|mr8.0.*)
if [[ ! -r /etc/mysql/sipwise.cnf ]]; then
echo "Cannot read mandatory config file /etc/mysql/sipwise.cnf" 2>&1
exit 1
fi
. /etc/mysql/sipwise.cnf
for db in "${NGCP_DB_BACKUP_FINAL_LIST[@]}"; do
"${location}/compare_dbs.pl" \
--result="results/result_${db}.tap" \
--connect_db1="DBI:mysql:database=${db};host=sp1" \
--user_db1='sipwise' \
--pass_db1="${SIPWISE_DB_PASSWORD}" \
--connect_db2="DBI:mysql:database=${db};host=sp2" \
--user_db2='sipwise' \
--pass_db2="${SIPWISE_DB_PASSWORD}" \
|| true
done
;;
*)
MYSQL_CREDENTIALS='/etc/mysql/sipwise_extra.cnf'
if [[ ! -r "${MYSQL_CREDENTIALS}" ]]; then
echo "Cannot read mandatory config file '${MYSQL_CREDENTIALS}'" 2>&1
exit 1
fi
for db in "${NGCP_DB_BACKUP_FINAL_LIST[@]}"; do
"${location}/compare_dbs.pl" \
--result="results/result_${db}.tap" \
--connect_db1="DBI:mysql:database=${db};host=sp1;mysql_read_default_file=${MYSQL_CREDENTIALS}" \
--connect_db2="DBI:mysql:database=${db};host=sp2;mysql_read_default_file=${MYSQL_CREDENTIALS}" \
|| true
done
;;
esac

@ -0,0 +1,65 @@
#!/bin/bash
set -euo pipefail
usage() {
cat - <<__USAGE__
$(basename "$0") used to compare mysql schemes between two hosts.
Usage: $(basename "$0") [options]
Options:
--formatter=[tap] - Specify the output format.
Skip it to get human readable output.
-h|--help - Show this message.
__USAGE__
}
FORMATTER=''
args=$(getopt -n "$(basename "$0")" -o h -l help,formatter: -- "$@")
eval set -- "${args}"
while true; do
case "${1}" in
--formatter)
FORMATTER="${2}"
shift 2
;;
-h|--help)
usage
exit 0
;;
--)
shift
break
;;
*)
log_error "Unknown parameter '${1}'"
exit 1
;;
esac
done
DB_BACKUP_LIST='/etc/ngcp-backup-tools/db-backup.conf'
if [[ ! -r "${DB_BACKUP_LIST}" ]]; then
echo "Cannot read mandatory config file ${DB_BACKUP_LIST}" 2>&1
exit 1
fi
MYSQL_CREDENTIALS='/etc/mysql/sipwise_extra.cnf'
if [[ ! -r "${MYSQL_CREDENTIALS}" ]]; then
echo "Cannot read mandatory config file '${MYSQL_CREDENTIALS}'" 2>&1
exit 1
fi
. "${DB_BACKUP_LIST}"
declare -a opts
if [[ -n "${FORMATTER}" ]]; then
opts+=(--formatter="${FORMATTER}")
fi
/usr/share/ngcp-system-tests/compare_dbs.pl \
--schemes="${NGCP_DB_BACKUP_FINAL_LIST[*]}" \
"${opts[@]}" || true
Loading…
Cancel
Save