You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
db-schema/ngcp-check-rev-applied

236 lines
5.7 KiB

#!/usr/bin/perl -w
use strict;
use warnings;
use Carp;
use Config::Tiny;
use DBI;
use English qw( -no_match_vars );
use Getopt::Long;
use List::MoreUtils qw{ any };
use Pod::Usage;
my $dbhost = 'localhost';
my $dbname = 'ngcp';
my $debug = 0;
my $exit_code = 0;
my $help = 0;
my $man = 0;
my $node = undef;
my $result_date = undef;
my $result_host = undef;
my $result_id = undef;
my $result_rev = undef;
my @revision;
my @result_list;
my $schema = undef;
GetOptions(
'dbhost=s' => \$dbhost,
'dbname=s' => \$dbname,
'debug|d' => \$debug,
'help|?' => \$help,
'man' => \$man,
'node=s' => \$node,
'revision=s{1,}' => \@revision,
'schema=s' => \$schema,
) or pod2usage(2);
pod2usage( -exitval => 2, -verbose => 0 ) if $help;
pod2usage( -exitval => 2, -verbose => 2 ) if $man;
pod2usage(2) if !@revision;
pod2usage(2) if !defined $schema;
# connect as user sipwise to DB
my $Config = Config::Tiny->read('/etc/mysql/sipwise.cnf')
or croak "Could not read /etc/mysql/sipwise.cnf: $ERRNO";
my $dbuser = 'sipwise';
my $dbpwd = $Config->{_}->{SIPWISE_DB_PASSWORD};
if ( !defined $dbpwd ) {
croak "Couldn't identify password for user sipwise to connect to database.";
}
$dbpwd =~ s/^['"](.*)['"]$/$1/; # get rid of possibly surrounding quotes
my $dbh =
DBI->connect( "dbi:mysql:dbname=$dbname;host=$dbhost", $dbuser, $dbpwd )
or croak "Couldn't connect to database: " . DBI->errstr;
$schema = $dbh->quote_identifier($schema);
my $sql_clause = ""; # if no node is specified then use empty SQL statement
if ( defined $node ) {
$sql_clause = "where node = ?";
}
my $sth = $dbh->prepare("SELECT * FROM $schema $sql_clause")
or croak "Couldn't prepare statement: " . $dbh->errstr;
if ( defined $node ) {
$sth->bind_param( 1, $node );
}
$sth->execute()
or croak "Couldn't execute statement: " . $sth->errstr;
$sth->bind_columns( \$result_id, \$result_rev, \$result_host, \$result_date );
while ( $sth->fetch ) {
foreach my $rev (@revision) {
# adjust for MySQL handling (we're interested only in the ID in MySQL speak)
# the regex handling is ugly, some love to it would be nice...
my $short_rev = $rev;
$short_rev =~ s/.*\///; # drop anything until and incl. the first slash
$short_rev =~ s/\..*//; # drop anything starting at the first '.'
$short_rev =~ s/_.*//; # drop anything starting at the first '_'
$short_rev =~ s/^0+//; # strip any trailing zeros from the id
if ( $result_rev =~ /^${short_rev}$/msx ) {
if ( defined $node ) {
if ( $result_host =~ /$node/msx ) {
push @result_list, $rev;
}
}
else {
push @result_list, $rev;
}
}
}
}
foreach my $rev (@revision) {
if ( any { /^${rev}$/msx } @result_list ) {
if ( defined $node ) {
print "Revision $rev already executed on host $node\n";
}
else {
print "Revision $rev already executed\n";
}
}
else {
if ( defined $node ) {
print "No match for revision $rev on host $node\n";
$exit_code = 1;
}
else {
print "No match for revision $rev\n";
$exit_code = 1;
}
}
}
$sth->finish;
$dbh->disconnect;
exit($exit_code);
__END__
=head1 NAME
ngcp-check-rev-applied - check which db/config revisions have been executed
=head1 SYNOPSIS
ngcp-check-rev-applied --schema <schema> --revision <id> [<2nd_id> [<3rd_id> [...]]
[--node <name>] [--dbname <db>] [--dbhost <host>]
=head1 DESCRIPTION
This program queries the ngcp database to check for db/config revisions that
have been applied. If the specified ID is present (or when multiple IDs are
specified: all of them are present) the exit code is 0, otherwise (the specified
ID is not present, or when multiple IDs are specified:: one of them is not
present) the exit code is 1.
=head1 USAGE EXAMPLES
=over 8
=item Check db_schema table for revision 23:
% ngcp-check-rev-applied --schema db_schema --revision 23
=item Check cfg_schema table for revision 42 and use output of `hostname`
to limit the specified ID to the current host:
% ngcp-check-rev-applied --schema cfg_schema --revision 42 --node $(hostname)
=item Check db_schema table for revisions 11, 23 and 42:
% ngcp-check-rev-applied --schema db_schema --revision 11 23 42 --debug
No match for revision 11.
No match for revision 23.
Revision 42 already executed.
=back
=head1 EXIT_CODES
=over 8
=item B<0>
The requested ID is present. If multiple IDs have been specified all of them are present.
=item B<1>
The requested ID is *NOT* present. If multiple IDs have been specified at least
one of the specified IDs it *NOT* present.
=item B<2>
Error or invalid usage of command line options.
=item B<255>
Error while running database query.
=back
=head1 OPTIONS
=over 8
=item B<--dbhost> <host>
Query specified host instead of the default (being "localhost").
=item B<--dbname> <db>
Use specified database instead of the default (being "ngcp").
=item B<--debug>
Be more verbose during execution.
=item B<--help>
Print help message and exit.
=item B<--man>
Display manpage using pod2man.
=item B<--node> <name>
Restrict querying ID to specified node name.
This is relevant only in high availability environments
to check for (non-)replicated revisions.
=item B<--revision> <id>
Query database for specified ID. Multiple IDs can be specified white-space
separated (e.g.: '--revision 11 23 42').
=item B<--schema> <name>
Use specified schema as table name to look for specified ID.
Supported table names: cfg_schema, db_schema
=back
=cut