mirror of https://github.com/sipwise/db-schema.git
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.
236 lines
5.7 KiB
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
|