mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +00:00
[master] Merge branch 'trac963'
This commit is contained in:
commit
49ba2cf8ac
12
configure.ac
12
configure.ac
@ -1015,6 +1015,9 @@ AC_CONFIG_FILES([Makefile
|
|||||||
src/bin/cfgmgr/plugins/Makefile
|
src/bin/cfgmgr/plugins/Makefile
|
||||||
src/bin/cfgmgr/plugins/tests/Makefile
|
src/bin/cfgmgr/plugins/tests/Makefile
|
||||||
src/bin/cfgmgr/tests/Makefile
|
src/bin/cfgmgr/tests/Makefile
|
||||||
|
src/bin/dbutil/Makefile
|
||||||
|
src/bin/dbutil/tests/Makefile
|
||||||
|
src/bin/dbutil/tests/testdata/Makefile
|
||||||
src/bin/host/Makefile
|
src/bin/host/Makefile
|
||||||
src/bin/loadzone/Makefile
|
src/bin/loadzone/Makefile
|
||||||
src/bin/loadzone/tests/correct/Makefile
|
src/bin/loadzone/tests/correct/Makefile
|
||||||
@ -1028,8 +1031,8 @@ AC_CONFIG_FILES([Makefile
|
|||||||
src/bin/ddns/tests/Makefile
|
src/bin/ddns/tests/Makefile
|
||||||
src/bin/dhcp6/Makefile
|
src/bin/dhcp6/Makefile
|
||||||
src/bin/dhcp6/tests/Makefile
|
src/bin/dhcp6/tests/Makefile
|
||||||
src/bin/dhcp4/Makefile
|
src/bin/dhcp4/Makefile
|
||||||
src/bin/dhcp4/tests/Makefile
|
src/bin/dhcp4/tests/Makefile
|
||||||
src/bin/resolver/Makefile
|
src/bin/resolver/Makefile
|
||||||
src/bin/resolver/tests/Makefile
|
src/bin/resolver/tests/Makefile
|
||||||
src/bin/sockcreator/Makefile
|
src/bin/sockcreator/Makefile
|
||||||
@ -1143,6 +1146,9 @@ AC_OUTPUT([doc/version.ent
|
|||||||
src/bin/cmdctl/run_b10-cmdctl.sh
|
src/bin/cmdctl/run_b10-cmdctl.sh
|
||||||
src/bin/cmdctl/tests/cmdctl_test
|
src/bin/cmdctl/tests/cmdctl_test
|
||||||
src/bin/cmdctl/cmdctl.spec.pre
|
src/bin/cmdctl/cmdctl.spec.pre
|
||||||
|
src/bin/dbutil/dbutil.py
|
||||||
|
src/bin/dbutil/run_dbutil.sh
|
||||||
|
src/bin/dbutil/tests/dbutil_test.sh
|
||||||
src/bin/ddns/ddns.py
|
src/bin/ddns/ddns.py
|
||||||
src/bin/xfrin/tests/xfrin_test
|
src/bin/xfrin/tests/xfrin_test
|
||||||
src/bin/xfrin/xfrin.py
|
src/bin/xfrin/xfrin.py
|
||||||
@ -1226,6 +1232,8 @@ AC_OUTPUT([doc/version.ent
|
|||||||
chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
|
chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
|
||||||
chmod +x src/bin/bind10/run_bind10.sh
|
chmod +x src/bin/bind10/run_bind10.sh
|
||||||
chmod +x src/bin/cmdctl/tests/cmdctl_test
|
chmod +x src/bin/cmdctl/tests/cmdctl_test
|
||||||
|
chmod +x src/bin/dbutil/run_dbutil.sh
|
||||||
|
chmod +x src/bin/dbutil/tests/dbutil_test.sh
|
||||||
chmod +x src/bin/xfrin/tests/xfrin_test
|
chmod +x src/bin/xfrin/tests/xfrin_test
|
||||||
chmod +x src/bin/xfrout/tests/xfrout_test
|
chmod +x src/bin/xfrout/tests/xfrout_test
|
||||||
chmod +x src/bin/zonemgr/tests/zonemgr_test
|
chmod +x src/bin/zonemgr/tests/zonemgr_test
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = bind10 bindctl cfgmgr ddns loadzone msgq host cmdctl auth xfrin \
|
SUBDIRS = bind10 bindctl cfgmgr ddns loadzone msgq host cmdctl auth xfrin \
|
||||||
xfrout usermgr zonemgr stats tests resolver sockcreator dhcp4 dhcp6
|
xfrout usermgr zonemgr stats tests resolver sockcreator dhcp4 dhcp6 dbutil
|
||||||
|
|
||||||
check-recursive: all-recursive
|
check-recursive: all-recursive
|
||||||
|
38
src/bin/dbutil/Makefile.am
Normal file
38
src/bin/dbutil/Makefile.am
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
SUBDIRS = . tests
|
||||||
|
|
||||||
|
bin_SCRIPTS = b10-dbutil
|
||||||
|
man_MANS = b10-dbutil.8
|
||||||
|
|
||||||
|
nodist_pylogmessage_PYTHON = $(PYTHON_LOGMSGPKG_DIR)/work/dbutil_messages.py
|
||||||
|
pylogmessagedir = $(pyexecdir)/isc/log_messages/
|
||||||
|
|
||||||
|
EXTRA_DIST = $(man_MANS) b10-dbutil.xml dbutil_messages.mes
|
||||||
|
|
||||||
|
noinst_SCRIPTS = run_dbutil.sh
|
||||||
|
|
||||||
|
CLEANFILES = b10-dbutil b10-dbutil.pyc
|
||||||
|
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/dbutil_messages.py
|
||||||
|
CLEANFILES += $(PYTHON_LOGMSGPKG_DIR)/work/dbutil_messages.pyc
|
||||||
|
|
||||||
|
if ENABLE_MAN
|
||||||
|
|
||||||
|
b10-dbutil.8: b10-dbutil.xml
|
||||||
|
xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-dbutil.xml
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Define rule to build logging source files from message file
|
||||||
|
$(PYTHON_LOGMSGPKG_DIR)/work/dbutil_messages.py : dbutil_messages.mes
|
||||||
|
$(top_builddir)/src/lib/log/compiler/message \
|
||||||
|
-d $(PYTHON_LOGMSGPKG_DIR)/work -p $(srcdir)/dbutil_messages.mes
|
||||||
|
|
||||||
|
b10-dbutil: dbutil.py $(PYTHON_LOGMSGPKG_DIR)/work/dbutil_messages.py
|
||||||
|
$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|" \
|
||||||
|
-e "s|@@SYSCONFDIR@@|@sysconfdir@|" \
|
||||||
|
-e "s|@@LIBEXECDIR@@|$(pkglibexecdir)|" dbutil.py >$@
|
||||||
|
chmod a+x $@
|
||||||
|
|
||||||
|
CLEANDIRS = __pycache__
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -rf $(CLEANDIRS)
|
92
src/bin/dbutil/b10-dbutil.8
Normal file
92
src/bin/dbutil/b10-dbutil.8
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
'\" t
|
||||||
|
.\" Title: b10-dbutil
|
||||||
|
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
|
||||||
|
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
||||||
|
.\" Date: March 20, 2012
|
||||||
|
.\" Manual: BIND10
|
||||||
|
.\" Source: BIND10
|
||||||
|
.\" Language: English
|
||||||
|
.\"
|
||||||
|
.TH "B10\-DBUTIL" "8" "March 20, 2012" "BIND10" "BIND10"
|
||||||
|
.\" -----------------------------------------------------------------
|
||||||
|
.\" * Define some portability stuff
|
||||||
|
.\" -----------------------------------------------------------------
|
||||||
|
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
.\" http://bugs.debian.org/507673
|
||||||
|
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
|
||||||
|
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
.ie \n(.g .ds Aq \(aq
|
||||||
|
.el .ds Aq '
|
||||||
|
.\" -----------------------------------------------------------------
|
||||||
|
.\" * set default formatting
|
||||||
|
.\" -----------------------------------------------------------------
|
||||||
|
.\" disable hyphenation
|
||||||
|
.nh
|
||||||
|
.\" disable justification (adjust text to left margin only)
|
||||||
|
.ad l
|
||||||
|
.\" -----------------------------------------------------------------
|
||||||
|
.\" * MAIN CONTENT STARTS HERE *
|
||||||
|
.\" -----------------------------------------------------------------
|
||||||
|
.SH "NAME"
|
||||||
|
b10-dbutil \- Zone Database Maintenance Utility
|
||||||
|
.SH "SYNOPSIS"
|
||||||
|
.HP \w'\fBb10\-dbutil\ \-\-check\fR\ 'u
|
||||||
|
\fBb10\-dbutil \-\-check\fR [\-\-verbose] [\-\-quiet] [\fIdbfile\fR]
|
||||||
|
.HP \w'\fBb10\-dbutil\ \-\-upgrade\fR\ 'u
|
||||||
|
\fBb10\-dbutil \-\-upgrade\fR [\-\-noconfirm] [\-\-verbose] [\-\-quiet] [\fIdbfile\fR]
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
\fBb10\-dbutil\fR
|
||||||
|
utility is a general administration utility for SQL databases\&. (Currently only SQLite is supported by BIND 10\&.) It can report the current verion of the schema, and upgrade an existing database to the latest version of the schema\&.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
\fBb10\-dbutil\fR
|
||||||
|
operates in one of two modes, check mode or upgrade mode\&.
|
||||||
|
.PP
|
||||||
|
In check mode (\fBb10\-dbutil \-\-check\fR), the utility reads the version of the database schema from the database and prints it\&. It will tell you whether the schema is at the latest version supported by BIND 10\&. Exit status is 0 if the schema is at the correct version, 1 if the schema is at an older version, 2 if the schema is at a version not yet supported by this version of b10\-dbutil\&. Any higher value indicates an error during command\-line parsing or execution\&.
|
||||||
|
.PP
|
||||||
|
When the upgrade function is selected (\fBb10\-dbutil \-\-upgrade\fR), the utility takes a copy of the database, then upgrades it to the latest version of the schema\&. The contents of the database remain intact\&. (The backup file is a file in the same directory as the database file\&. It has the same name, with "\&.backup" appended to it\&. If a file of that name already exists, the file will have the suffix "\&.backup\-1"\&. If that exists, the file will be suffixed "\&.backup\-2", and so on)\&. Exit status is 0 if the upgrade is either succesful or aborted by the user, and non\-zero if there is an error\&.
|
||||||
|
.PP
|
||||||
|
When upgrading the database, it is
|
||||||
|
\fIstrongly\fR
|
||||||
|
recommended that BIND 10 not be running while the upgrade is in progress\&.
|
||||||
|
.SH "ARGUMENTS"
|
||||||
|
.PP
|
||||||
|
The arguments are as follows:
|
||||||
|
.PP
|
||||||
|
\fB\-\-check\fR
|
||||||
|
.RS 4
|
||||||
|
Selects the version check function, which reports the current version of the database\&. This is incompatible with the \-\-upgrade option\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
\fB\-\-noconfirm\fR
|
||||||
|
.RS 4
|
||||||
|
Only valid with \-\-upgrade, this disables the prompt\&. Normally the utility will print a warning that an upgrade is about to take place and request that you type "Yes" to continue\&. If this switch is given on the command line, no prompt will be issued: the utility will just perform the upgrade\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
\fB\-\-upgrade\fR
|
||||||
|
.RS 4
|
||||||
|
Selects the upgrade function, which upgrades the database to the latest version of the schema\&. This is incompatible with the \-\-upgrade option\&.
|
||||||
|
.sp
|
||||||
|
The upgrade function will upgrade a BIND 10 database \- no matter how old the schema \- preserving all data\&. A backup file is created before the upgrade (with the same name as the database, but with "\&.backup" suffixed to it)\&. If the upgrade fails, this file can be copied back to restore the original database\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
\fB\-\-verbose\fR
|
||||||
|
.RS 4
|
||||||
|
Enable verbose mode\&. Each SQL command issued by the utility will be printed to stderr before it is executed\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
\fB\-\-quiet\fR
|
||||||
|
.RS 4
|
||||||
|
Enable quiet mode\&. No output is printed, except errors during command\-line argument parsing, or the user confirmation dialog\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
\fB\fIdbfile\fR\fR
|
||||||
|
.RS 4
|
||||||
|
Name of the database file to check of upgrade\&.
|
||||||
|
.RE
|
||||||
|
.SH "COPYRIGHT"
|
||||||
|
.br
|
||||||
|
Copyright \(co 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
.br
|
192
src/bin/dbutil/b10-dbutil.xml
Normal file
192
src/bin/dbutil/b10-dbutil.xml
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||||
|
[<!ENTITY mdash "—">]>
|
||||||
|
<!--
|
||||||
|
- Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
-
|
||||||
|
- Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
- purpose with or without fee is hereby granted, provided that the above
|
||||||
|
- copyright notice and this permission notice appear in all copies.
|
||||||
|
-
|
||||||
|
- THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
- AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
- PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<refentry>
|
||||||
|
|
||||||
|
<refentryinfo>
|
||||||
|
<date>March 20, 2012</date>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>b10-dbutil</refentrytitle>
|
||||||
|
<manvolnum>8</manvolnum>
|
||||||
|
<refmiscinfo>BIND10</refmiscinfo>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>b10-dbutil</refname>
|
||||||
|
<refpurpose>Zone Database Maintenance Utility</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<docinfo>
|
||||||
|
<copyright>
|
||||||
|
<year>2012</year>
|
||||||
|
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
|
||||||
|
</copyright>
|
||||||
|
</docinfo>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>b10-dbutil --check</command>
|
||||||
|
<arg>--verbose</arg>
|
||||||
|
<arg>--quiet</arg>
|
||||||
|
<arg><replaceable choice='req'>dbfile</replaceable></arg>
|
||||||
|
</cmdsynopsis>
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>b10-dbutil --upgrade</command>
|
||||||
|
<arg>--noconfirm</arg>
|
||||||
|
<arg>--verbose</arg>
|
||||||
|
<arg>--quiet</arg>
|
||||||
|
<arg><replaceable choice='req'>dbfile</replaceable></arg>
|
||||||
|
</cmdsynopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>DESCRIPTION</title>
|
||||||
|
<para>
|
||||||
|
The <command>b10-dbutil</command> utility is a general administration
|
||||||
|
utility for SQL databases. (Currently only SQLite is supported by
|
||||||
|
BIND 10.) It can report the current verion of the schema, and upgrade
|
||||||
|
an existing database to the latest version of the schema.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<command>b10-dbutil</command> operates in one of two modes, check mode
|
||||||
|
or upgrade mode.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In check mode (<command>b10-dbutil --check</command>), the
|
||||||
|
utility reads the version of the database schema from the database
|
||||||
|
and prints it. It will tell you whether the schema is at the latest
|
||||||
|
version supported by BIND 10. Exit status is 0 if the schema is at
|
||||||
|
the correct version, 1 if the schema is at an older version, 2 if
|
||||||
|
the schema is at a version not yet supported by this version of
|
||||||
|
b10-dbutil. Any higher value indicates an error during command-line
|
||||||
|
parsing or execution.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
When the upgrade function is selected
|
||||||
|
(<command>b10-dbutil --upgrade</command>), the
|
||||||
|
utility takes a copy of the database, then upgrades it to the latest
|
||||||
|
version of the schema. The contents of the database remain intact.
|
||||||
|
(The backup file is a file in the same directory as the database
|
||||||
|
file. It has the same name, with ".backup" appended to it. If a
|
||||||
|
file of that name already exists, the file will have the suffix
|
||||||
|
".backup-1". If that exists, the file will be suffixed ".backup-2",
|
||||||
|
and so on). Exit status is 0 if the upgrade is either succesful or
|
||||||
|
aborted by the user, and non-zero if there is an error.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
When upgrading the database, it is <emphasis>strongly</emphasis>
|
||||||
|
recommended that BIND 10 not be running while the upgrade is in
|
||||||
|
progress.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>ARGUMENTS</title>
|
||||||
|
|
||||||
|
<para>The arguments are as follows:</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--check</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Selects the version check function, which reports the
|
||||||
|
current version of the database. This is incompatible
|
||||||
|
with the --upgrade option.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--noconfirm</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Only valid with --upgrade, this disables the prompt.
|
||||||
|
Normally the utility will print a warning that an upgrade is
|
||||||
|
about to take place and request that you type "Yes" to continue.
|
||||||
|
If this switch is given on the command line, no prompt will
|
||||||
|
be issued: the utility will just perform the upgrade.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--upgrade</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Selects the upgrade function, which upgrades the database
|
||||||
|
to the latest version of the schema. This is incompatible
|
||||||
|
with the --upgrade option.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The upgrade function will upgrade a BIND 10 database - no matter how
|
||||||
|
old the schema - preserving all data. A backup file is created
|
||||||
|
before the upgrade (with the same name as the database, but with
|
||||||
|
".backup" suffixed to it). If the upgrade fails, this file can
|
||||||
|
be copied back to restore the original database.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--verbose</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Enable verbose mode. Each SQL command issued by the
|
||||||
|
utility will be printed to stderr before it is executed.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--quiet</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Enable quiet mode. No output is printed, except errors during
|
||||||
|
command-line argument parsing, or the user confirmation dialog.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option><replaceable choice='req'>dbfile</replaceable></option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Name of the database file to check of upgrade.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
608
src/bin/dbutil/dbutil.py.in
Executable file
608
src/bin/dbutil/dbutil.py.in
Executable file
@ -0,0 +1,608 @@
|
|||||||
|
#!@PYTHON@
|
||||||
|
|
||||||
|
# Copyright (C) 2012 Internet Systems Consortium.
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and distribute this software for any
|
||||||
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
|
# copyright notice and this permission notice appear in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
|
||||||
|
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||||
|
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||||
|
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||||
|
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
"""
|
||||||
|
@file Dabase Utilities
|
||||||
|
|
||||||
|
This file holds the "dbutil" program, a general utility program for doing
|
||||||
|
management of the BIND 10 database. There are two modes of operation:
|
||||||
|
|
||||||
|
b10-dbutil --check [--verbose] database
|
||||||
|
b10-dbutil --upgrade [--noconfirm] [--verbose] database
|
||||||
|
|
||||||
|
The first form checks the version of the given database. The second form
|
||||||
|
upgrades the database to the latest version of the schema, omitting the
|
||||||
|
warning prompt if --noconfirm is given.
|
||||||
|
|
||||||
|
For maximum safety, prior to the upgrade a backup database is created.
|
||||||
|
The is the database name with ".backup" appended to it (or ".backup-n" if
|
||||||
|
".backup" already exists). This is used to restore the database if the
|
||||||
|
upgrade fails.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Exit codes
|
||||||
|
# These are defined here because one of them is already used before most
|
||||||
|
# of the import statements.
|
||||||
|
EXIT_SUCCESS = 0
|
||||||
|
EXIT_NEED_UPDATE = 1
|
||||||
|
EXIT_VERSION_TOO_HIGH = 2
|
||||||
|
EXIT_COMMAND_ERROR = 3
|
||||||
|
EXIT_READ_ERROR = 4
|
||||||
|
EXIT_UPGRADE_ERROR = 5
|
||||||
|
EXIT_UNCAUGHT_EXCEPTION = 6
|
||||||
|
|
||||||
|
import sys; sys.path.append("@@PYTHONPATH@@")
|
||||||
|
|
||||||
|
# Normally, python exits with a status code of 1 on uncaught exceptions
|
||||||
|
# Since we reserve exit status 1 for 'database needs upgrade', we
|
||||||
|
# override the excepthook to exit with a different status
|
||||||
|
def my_except_hook(a, b, c):
|
||||||
|
sys.__excepthook__(a,b,c)
|
||||||
|
sys.exit(EXIT_UNCAUGHT_EXCEPTION)
|
||||||
|
sys.excepthook = my_except_hook
|
||||||
|
|
||||||
|
import os, sqlite3, shutil
|
||||||
|
from optparse import OptionParser
|
||||||
|
import isc.util.process
|
||||||
|
import isc.log
|
||||||
|
from isc.log_messages.dbutil_messages import *
|
||||||
|
|
||||||
|
isc.log.init("b10-dbutil")
|
||||||
|
logger = isc.log.Logger("dbutil")
|
||||||
|
isc.util.process.rename()
|
||||||
|
|
||||||
|
TRACE_BASIC = logger.DBGLVL_TRACE_BASIC
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Version String
|
||||||
|
# This is the version displayed to the user. It comprises the module name,
|
||||||
|
# the module version number, and the overall BIND 10 version number (set in
|
||||||
|
# configure.ac)
|
||||||
|
VERSION = "b10-dbutil 20120319 (BIND 10 @PACKAGE_VERSION@)"
|
||||||
|
|
||||||
|
# @brief Statements to Update the Database
|
||||||
|
# These are in the form of a list of dictionaries, each of which contains the
|
||||||
|
# information to perform an incremental upgrade from one version of the
|
||||||
|
# database to the next. The information is:
|
||||||
|
#
|
||||||
|
# a) from: (major, minor) version that the database is expected to be at
|
||||||
|
# to perform this upgrade.
|
||||||
|
# b) to: (major, minor) version of the database to which this set of statements
|
||||||
|
# upgrades the database to. (This is used for documentation purposes,
|
||||||
|
# and to update the schema_version table when the upgrade is complete.)
|
||||||
|
# c) statements: List of SQL statments to perform the upgrade.
|
||||||
|
#
|
||||||
|
# The incremental upgrades are performed one after the other. If the version
|
||||||
|
# of the database does not exactly match that required for the incremental
|
||||||
|
# upgrade, the upgrade is skipped. For this reason, the list must be in
|
||||||
|
# ascending order (e.g. upgrade 1.0 to 2.0, 2.0 to 2.1, 2.1 to 2.2 etc.).
|
||||||
|
#
|
||||||
|
# Note that apart from the 1.0 to 2.0 upgrade, no upgrade need alter the
|
||||||
|
# schema_version table: that is done by the upgrade process using the
|
||||||
|
# information in the "to" field.
|
||||||
|
UPGRADES = [
|
||||||
|
{'from': (1, 0), 'to': (2, 0),
|
||||||
|
'statements': [
|
||||||
|
|
||||||
|
# Move to the latest "V1" state of the database if not there
|
||||||
|
# already.
|
||||||
|
"CREATE TABLE IF NOT EXISTS diffs (" +
|
||||||
|
"id INTEGER PRIMARY KEY, " +
|
||||||
|
"zone_id INTEGER NOT NULL," +
|
||||||
|
"version INTEGER NOT NULL, " +
|
||||||
|
"operation INTEGER NOT NULL, " +
|
||||||
|
"name STRING NOT NULL COLLATE NOCASE, " +
|
||||||
|
"rrtype STRING NOT NULL COLLATE NOCASE, " +
|
||||||
|
"ttl INTEGER NOT NULL, " +
|
||||||
|
"rdata STRING NOT NULL)",
|
||||||
|
|
||||||
|
# Within SQLite with can only rename tables and add columns; we
|
||||||
|
# can't drop columns nor can we alter column characteristics.
|
||||||
|
# So the strategy is to rename the table, create the new table,
|
||||||
|
# then copy all data across. This means creating new indexes
|
||||||
|
# as well; these are created after the data has been copied.
|
||||||
|
|
||||||
|
# zones table
|
||||||
|
"DROP INDEX zones_byname",
|
||||||
|
"ALTER TABLE zones RENAME TO old_zones",
|
||||||
|
"CREATE TABLE zones (" +
|
||||||
|
"id INTEGER PRIMARY KEY, " +
|
||||||
|
"name TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"rdclass TEXT NOT NULL COLLATE NOCASE DEFAULT 'IN', " +
|
||||||
|
"dnssec BOOLEAN NOT NULL DEFAULT 0)",
|
||||||
|
"INSERT INTO ZONES " +
|
||||||
|
"SELECT id, name, rdclass, dnssec FROM old_zones",
|
||||||
|
"CREATE INDEX zones_byname ON zones (name)",
|
||||||
|
"DROP TABLE old_zones",
|
||||||
|
|
||||||
|
# records table
|
||||||
|
"DROP INDEX records_byname",
|
||||||
|
"DROP INDEX records_byrname",
|
||||||
|
"ALTER TABLE records RENAME TO old_records",
|
||||||
|
"CREATE TABLE records (" +
|
||||||
|
"id INTEGER PRIMARY KEY, " +
|
||||||
|
"zone_id INTEGER NOT NULL, " +
|
||||||
|
"name TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"rname TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"ttl INTEGER NOT NULL, " +
|
||||||
|
"rdtype TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"sigtype TEXT COLLATE NOCASE, " +
|
||||||
|
"rdata TEXT NOT NULL)",
|
||||||
|
"INSERT INTO records " +
|
||||||
|
"SELECT id, zone_id, name, rname, ttl, rdtype, sigtype, " +
|
||||||
|
"rdata FROM old_records",
|
||||||
|
"CREATE INDEX records_byname ON records (name)",
|
||||||
|
"CREATE INDEX records_byrname ON records (rname)",
|
||||||
|
"CREATE INDEX records_bytype_and_rname ON records (rdtype, rname)",
|
||||||
|
"DROP TABLE old_records",
|
||||||
|
|
||||||
|
# nsec3 table
|
||||||
|
"DROP INDEX nsec3_byhash",
|
||||||
|
"ALTER TABLE nsec3 RENAME TO old_nsec3",
|
||||||
|
"CREATE TABLE nsec3 (" +
|
||||||
|
"id INTEGER PRIMARY KEY, " +
|
||||||
|
"zone_id INTEGER NOT NULL, " +
|
||||||
|
"hash TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"owner TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"ttl INTEGER NOT NULL, " +
|
||||||
|
"rdtype TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"rdata TEXT NOT NULL)",
|
||||||
|
"INSERT INTO nsec3 " +
|
||||||
|
"SELECT id, zone_id, hash, owner, ttl, rdtype, rdata " +
|
||||||
|
"FROM old_nsec3",
|
||||||
|
"CREATE INDEX nsec3_byhash ON nsec3 (hash)",
|
||||||
|
"DROP TABLE old_nsec3",
|
||||||
|
|
||||||
|
# diffs table
|
||||||
|
"ALTER TABLE diffs RENAME TO old_diffs",
|
||||||
|
"CREATE TABLE diffs (" +
|
||||||
|
"id INTEGER PRIMARY KEY, " +
|
||||||
|
"zone_id INTEGER NOT NULL, " +
|
||||||
|
"version INTEGER NOT NULL, " +
|
||||||
|
"operation INTEGER NOT NULL, " +
|
||||||
|
"name TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"rrtype TEXT NOT NULL COLLATE NOCASE, " +
|
||||||
|
"ttl INTEGER NOT NULL, " +
|
||||||
|
"rdata TEXT NOT NULL)",
|
||||||
|
"INSERT INTO diffs " +
|
||||||
|
"SELECT id, zone_id, version, operation, name, rrtype, " +
|
||||||
|
"ttl, rdata FROM old_diffs",
|
||||||
|
"DROP TABLE old_diffs",
|
||||||
|
|
||||||
|
# Schema table. This is updated to include a second column for
|
||||||
|
# future changes. The idea is that if a version of BIND 10 is
|
||||||
|
# written for schema M.N, it should be able to work for all
|
||||||
|
# versions of N; if not, M must be incremented.
|
||||||
|
#
|
||||||
|
# For backwards compatibility, the column holding the major
|
||||||
|
# version number is left named "version".
|
||||||
|
"ALTER TABLE schema_version " +
|
||||||
|
"ADD COLUMN minor INTEGER NOT NULL DEFAULT 0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# To extend this, leave the above statements in place and add another
|
||||||
|
# dictionary to the list. The "from" version should be (2, 0), the "to"
|
||||||
|
# version whatever the version the update is to, and the SQL statements are
|
||||||
|
# the statements required to perform the upgrade. This way, the upgrade
|
||||||
|
# program will be able to upgrade both a V1.0 and a V2.0 database.
|
||||||
|
]
|
||||||
|
|
||||||
|
class DbutilException(Exception):
|
||||||
|
"""
|
||||||
|
@brief Exception class to indicate error exit
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Database:
|
||||||
|
"""
|
||||||
|
@brief Database Encapsulation
|
||||||
|
|
||||||
|
Encapsulates the SQL database, both the connection and the cursor. The
|
||||||
|
methods will cause a program exit on any error.
|
||||||
|
"""
|
||||||
|
def __init__(self, db_file):
|
||||||
|
"""
|
||||||
|
@brief Constructor
|
||||||
|
|
||||||
|
@param db_file Name of the database file
|
||||||
|
"""
|
||||||
|
self.connection = None
|
||||||
|
self.cursor = None
|
||||||
|
self.db_file = db_file
|
||||||
|
self.backup_file = None
|
||||||
|
|
||||||
|
def open(self):
|
||||||
|
"""
|
||||||
|
@brief Open Database
|
||||||
|
|
||||||
|
Opens the passed file as an sqlite3 database and stores a connection
|
||||||
|
and a cursor.
|
||||||
|
"""
|
||||||
|
if not os.path.exists(self.db_file):
|
||||||
|
raise DbutilException("database " + self.db_file +
|
||||||
|
" does not exist");
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.connection = sqlite3.connect(self.db_file)
|
||||||
|
self.connection.isolation_level = None # set autocommit
|
||||||
|
self.cursor = self.connection.cursor()
|
||||||
|
except sqlite3.OperationalError as ex:
|
||||||
|
raise DbutilException("unable to open " + self.db_file +
|
||||||
|
" - " + str(ex))
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""
|
||||||
|
@brief Closes the database
|
||||||
|
"""
|
||||||
|
if self.connection is not None:
|
||||||
|
self.connection.close()
|
||||||
|
|
||||||
|
def execute(self, statement):
|
||||||
|
"""
|
||||||
|
@brief Execute Statement
|
||||||
|
|
||||||
|
Executes the given statement, exiting the program on error.
|
||||||
|
|
||||||
|
@param statement SQL statement to execute
|
||||||
|
"""
|
||||||
|
logger.debug(TRACE_BASIC, DBUTIL_EXECUTE, statement)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.cursor.execute(statement)
|
||||||
|
except Exception as ex:
|
||||||
|
logger.error(DBUTIL_STATEMENT_ERROR, statement, ex)
|
||||||
|
raise DbutilException(str(ex))
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
"""
|
||||||
|
@brief Return result of last execute
|
||||||
|
|
||||||
|
Returns a single row that is the result of the last "execute".
|
||||||
|
"""
|
||||||
|
return self.cursor.fetchone()
|
||||||
|
|
||||||
|
def backup(self):
|
||||||
|
"""
|
||||||
|
@brief Backup Database
|
||||||
|
|
||||||
|
Attempts to copy the given database file to a backup database, the
|
||||||
|
backup database file being the file name with ".backup" appended.
|
||||||
|
If the ".backup" file exists, a new name is constructed by appending
|
||||||
|
".backup-n" (n starting at 1) and the action repeated until an
|
||||||
|
unused filename is found.
|
||||||
|
|
||||||
|
@param db_file Database file to backup
|
||||||
|
"""
|
||||||
|
if not os.path.exists(self.db_file):
|
||||||
|
raise DbutilException("database " + self.db_file +
|
||||||
|
" does not exist");
|
||||||
|
|
||||||
|
self.backup_file = self.db_file + ".backup"
|
||||||
|
count = 0
|
||||||
|
while os.path.exists(self.backup_file):
|
||||||
|
count = count + 1
|
||||||
|
self.backup_file = self.db_file + ".backup-" + str(count)
|
||||||
|
|
||||||
|
# Do the backup
|
||||||
|
shutil.copyfile(self.db_file, self.backup_file)
|
||||||
|
logger.info(DBUTIL_BACKUP, self.db_file, self.backup_file)
|
||||||
|
|
||||||
|
def prompt_user():
|
||||||
|
"""
|
||||||
|
@brief Prompt the User
|
||||||
|
|
||||||
|
Explains about the upgrade and requests authorisation to continue.
|
||||||
|
|
||||||
|
@return True if user entered 'Yes', False if 'No'
|
||||||
|
"""
|
||||||
|
sys.stdout.write(
|
||||||
|
"""You have selected the upgrade option. This will upgrade the schema of the
|
||||||
|
selected BIND 10 zone database to the latest version.
|
||||||
|
|
||||||
|
The utility will take a copy of the zone database file before executing so, in
|
||||||
|
the event of a problem, you will be able to restore the zone database from
|
||||||
|
the backup. To ensure that the integrity of this backup, please ensure that
|
||||||
|
BIND 10 is not running before continuing.
|
||||||
|
""")
|
||||||
|
yes_entered = False
|
||||||
|
no_entered = False
|
||||||
|
while (not yes_entered) and (not no_entered):
|
||||||
|
sys.stdout.write("Enter 'Yes' to proceed with the upgrade, " +
|
||||||
|
"'No' to exit the program: \n")
|
||||||
|
response = sys.stdin.readline()
|
||||||
|
if response.lower() == "yes\n":
|
||||||
|
yes_entered = True
|
||||||
|
elif response.lower() == "no\n":
|
||||||
|
no_entered = True
|
||||||
|
else:
|
||||||
|
sys.stdout.write("Please enter 'Yes' or 'No'\n")
|
||||||
|
|
||||||
|
return yes_entered
|
||||||
|
|
||||||
|
|
||||||
|
def version_string(version):
|
||||||
|
"""
|
||||||
|
@brief Format Database Version
|
||||||
|
|
||||||
|
Converts a (major, minor) tuple into a 'Vn.m' string.
|
||||||
|
|
||||||
|
@param version Version tuple to convert
|
||||||
|
|
||||||
|
@return Version string
|
||||||
|
"""
|
||||||
|
return "V" + str(version[0]) + "." + str(version[1])
|
||||||
|
|
||||||
|
|
||||||
|
def compare_versions(first, second):
|
||||||
|
"""
|
||||||
|
@brief Compare Versions
|
||||||
|
|
||||||
|
Compares two database version numbers.
|
||||||
|
|
||||||
|
@param first First version number to check (in the form of a
|
||||||
|
"(major, minor)" tuple).
|
||||||
|
@param second Second version number to check (in the form of a
|
||||||
|
"(major, minor)" tuple).
|
||||||
|
|
||||||
|
@return -1, 0, +1 if "first" is <, ==, > "second"
|
||||||
|
"""
|
||||||
|
if first == second:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
elif ((first[0] < second[0]) or
|
||||||
|
((first[0] == second[0]) and (first[1] < second[1]))):
|
||||||
|
return -1
|
||||||
|
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def get_latest_version():
|
||||||
|
"""
|
||||||
|
@brief Returns the version to which this utility can upgrade the database
|
||||||
|
|
||||||
|
This is the 'to' version held in the last element of the upgrades list
|
||||||
|
"""
|
||||||
|
return UPGRADES[-1]['to']
|
||||||
|
|
||||||
|
|
||||||
|
def get_version(db):
|
||||||
|
"""
|
||||||
|
@brief Return version of database
|
||||||
|
|
||||||
|
@return Version of database in form (major version, minor version)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Get the version information.
|
||||||
|
db.execute("SELECT * FROM schema_version")
|
||||||
|
result = db.result()
|
||||||
|
if result is None:
|
||||||
|
raise DbutilException("nothing in schema_version table")
|
||||||
|
|
||||||
|
major = result[0]
|
||||||
|
if (major == 1):
|
||||||
|
# If the version number is 1, there will be no "minor" column, so
|
||||||
|
# assume a minor version number of 0.
|
||||||
|
minor = 0
|
||||||
|
else:
|
||||||
|
minor = result[1]
|
||||||
|
|
||||||
|
result = db.result()
|
||||||
|
if result is not None:
|
||||||
|
raise DbutilException("too many rows in schema_version table")
|
||||||
|
|
||||||
|
return (major, minor)
|
||||||
|
|
||||||
|
|
||||||
|
def check_version(db):
|
||||||
|
"""
|
||||||
|
@brief Check the version
|
||||||
|
|
||||||
|
Checks the version of the database and the latest version, and advises if
|
||||||
|
an upgrade is needed.
|
||||||
|
|
||||||
|
@param db Database object
|
||||||
|
|
||||||
|
returns 0 if the database is up to date
|
||||||
|
returns EXIT_NEED_UPDATE if the database needs updating
|
||||||
|
returns EXIT_VERSION_TOO_HIGH if the database is at a later version
|
||||||
|
than this program knows about
|
||||||
|
These return values are intended to be passed on to sys.exit.
|
||||||
|
"""
|
||||||
|
current = get_version(db)
|
||||||
|
latest = get_latest_version()
|
||||||
|
|
||||||
|
match = compare_versions(current, latest)
|
||||||
|
if match == 0:
|
||||||
|
logger.info(DBUTIL_VERSION_CURRENT, version_string(current))
|
||||||
|
logger.info(DBUTIL_CHECK_OK)
|
||||||
|
return EXIT_SUCCESS
|
||||||
|
elif match < 0:
|
||||||
|
logger.info(DBUTIL_VERSION_LOW, version_string(current),
|
||||||
|
version_string(latest))
|
||||||
|
logger.info(DBUTIL_CHECK_UPGRADE_NEEDED)
|
||||||
|
return EXIT_NEED_UPDATE
|
||||||
|
else:
|
||||||
|
logger.warn(DBUTIL_VERSION_HIGH, version_string(current),
|
||||||
|
version_string(get_latest_version()))
|
||||||
|
logger.info(DBUTIL_UPGRADE_DBUTIL)
|
||||||
|
return EXIT_VERSION_TOO_HIGH
|
||||||
|
|
||||||
|
def perform_upgrade(db, upgrade):
|
||||||
|
"""
|
||||||
|
@brief Perform upgrade
|
||||||
|
|
||||||
|
Performs the upgrade. At the end of the upgrade, updates the schema_version
|
||||||
|
table with the expected version.
|
||||||
|
|
||||||
|
@param db Database object
|
||||||
|
@param upgrade Upgrade dictionary, holding "from", "to" and "statements".
|
||||||
|
"""
|
||||||
|
logger.info(DBUTIL_UPGRADING, version_string(upgrade['from']),
|
||||||
|
version_string(upgrade['to']))
|
||||||
|
for statement in upgrade['statements']:
|
||||||
|
db.execute(statement)
|
||||||
|
|
||||||
|
# Update the version information
|
||||||
|
db.execute("DELETE FROM schema_version")
|
||||||
|
db.execute("INSERT INTO schema_version VALUES (" +
|
||||||
|
str(upgrade['to'][0]) + "," + str(upgrade['to'][1]) + ")")
|
||||||
|
|
||||||
|
|
||||||
|
def perform_all_upgrades(db):
|
||||||
|
"""
|
||||||
|
@brief Performs all the upgrades
|
||||||
|
|
||||||
|
@brief db Database object
|
||||||
|
|
||||||
|
For each upgrade, checks that the database is at the expected version.
|
||||||
|
If so, calls perform_upgrade to update the database.
|
||||||
|
"""
|
||||||
|
match = compare_versions(get_version(db), get_latest_version())
|
||||||
|
if match == 0:
|
||||||
|
logger.info(DBUTIL_UPGRADE_NOT_NEEDED)
|
||||||
|
|
||||||
|
elif match > 0:
|
||||||
|
logger.warn(DBUTIL_UPGRADE_NOT_POSSIBLE)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Work our way through all upgrade increments
|
||||||
|
count = 0
|
||||||
|
for upgrade in UPGRADES:
|
||||||
|
if compare_versions(get_version(db), upgrade['from']) == 0:
|
||||||
|
perform_upgrade(db, upgrade)
|
||||||
|
count = count + 1
|
||||||
|
|
||||||
|
if count > 0:
|
||||||
|
logger.info(DBUTIL_UPGRADE_SUCCESFUL)
|
||||||
|
else:
|
||||||
|
# Should not get here, as we established earlier that the database
|
||||||
|
# was not at the latest version so we should have upgraded.
|
||||||
|
raise DbutilException("internal error in upgrade tool - no " +
|
||||||
|
"upgrade was performed on an old version " +
|
||||||
|
"the database")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_command():
|
||||||
|
"""
|
||||||
|
@brief Parse Command
|
||||||
|
|
||||||
|
Parses the command line and sets the global command options.
|
||||||
|
|
||||||
|
@return Tuple of parser options and parser arguments
|
||||||
|
"""
|
||||||
|
usage = ("usage: %prog --check [options] db_file\n" +
|
||||||
|
" %prog --upgrade [--noconfirm] [options] db_file")
|
||||||
|
parser = OptionParser(usage = usage, version = VERSION)
|
||||||
|
parser.add_option("-c", "--check", action="store_true",
|
||||||
|
dest="check", default=False,
|
||||||
|
help="Print database version and check if it " +
|
||||||
|
"needs upgrading")
|
||||||
|
parser.add_option("-n", "--noconfirm", action="store_true",
|
||||||
|
dest="noconfirm", default=False,
|
||||||
|
help="Do not prompt for confirmation before upgrading")
|
||||||
|
parser.add_option("-u", "--upgrade", action="store_true",
|
||||||
|
dest="upgrade", default=False,
|
||||||
|
help="Upgrade the database file to the latest version")
|
||||||
|
parser.add_option("-v", "--verbose", action="store_true",
|
||||||
|
dest="verbose", default=False,
|
||||||
|
help="Print SQL statements as they are executed")
|
||||||
|
parser.add_option("-q", "--quiet", action="store_true",
|
||||||
|
dest="quiet", default=False,
|
||||||
|
help="Don't print any info, warnings or errors")
|
||||||
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
# Set the database file on which to operate
|
||||||
|
if (len(args) > 1):
|
||||||
|
logger.error(DBUTIL_TOO_MANY_ARGUMENTS)
|
||||||
|
parser.print_usage()
|
||||||
|
sys.exit(EXIT_COMMAND_ERROR)
|
||||||
|
elif len(args) == 0:
|
||||||
|
logger.error(DBUTIL_NO_FILE)
|
||||||
|
parser.print_usage()
|
||||||
|
sys.exit(EXIT_COMMAND_ERROR)
|
||||||
|
|
||||||
|
# Check for conflicting options. If some are found, output a suitable
|
||||||
|
# error message and print the usage.
|
||||||
|
if options.check and options.upgrade:
|
||||||
|
logger.error(DBUTIL_COMMAND_UPGRADE_CHECK)
|
||||||
|
elif (not options.check) and (not options.upgrade):
|
||||||
|
logger.error(DBUTIL_COMMAND_NONE)
|
||||||
|
elif (options.check and options.noconfirm):
|
||||||
|
logger.error(DBUTIL_CHECK_NOCONFIRM)
|
||||||
|
else:
|
||||||
|
return (options, args)
|
||||||
|
|
||||||
|
# Only get here on conflicting options
|
||||||
|
parser.print_usage()
|
||||||
|
sys.exit(EXIT_COMMAND_ERROR)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
(options, args) = parse_command()
|
||||||
|
|
||||||
|
if options.verbose:
|
||||||
|
isc.log.init("b10-dbutil", "DEBUG", 99)
|
||||||
|
logger = isc.log.Logger("dbutil")
|
||||||
|
elif options.quiet:
|
||||||
|
# We don't use FATAL, so setting the logger to use
|
||||||
|
# it should essentially make it silent.
|
||||||
|
isc.log.init("b10-dbutil", "FATAL")
|
||||||
|
logger = isc.log.Logger("dbutil")
|
||||||
|
|
||||||
|
db = Database(args[0])
|
||||||
|
exit_code = EXIT_SUCCESS
|
||||||
|
|
||||||
|
logger.info(DBUTIL_FILE, args[0])
|
||||||
|
if options.check:
|
||||||
|
# Check database - open, report, and close
|
||||||
|
try:
|
||||||
|
db.open()
|
||||||
|
exit_code = check_version(db)
|
||||||
|
db.close()
|
||||||
|
except Exception as ex:
|
||||||
|
logger.error(DBUTIL_CHECK_ERROR, ex)
|
||||||
|
exit_code = EXIT_READ_ERROR
|
||||||
|
|
||||||
|
elif options.upgrade:
|
||||||
|
# Upgrade. Check if this is what they really want to do
|
||||||
|
if not options.noconfirm:
|
||||||
|
proceed = prompt_user()
|
||||||
|
if not proceed:
|
||||||
|
logger.info(DBUTIL_UPGRADE_CANCELED)
|
||||||
|
sys.exit(EXIT_SUCCESS)
|
||||||
|
|
||||||
|
# It is. Do a backup then do the upgrade.
|
||||||
|
in_progress = False
|
||||||
|
try:
|
||||||
|
db.backup()
|
||||||
|
db.open()
|
||||||
|
in_progress = True
|
||||||
|
perform_all_upgrades(db)
|
||||||
|
db.close()
|
||||||
|
except Exception as ex:
|
||||||
|
if in_progress:
|
||||||
|
logger.error(DBUTIL_UPGRADE_FAILED, ex)
|
||||||
|
logger.warn(DBUTIL_DATABASE_MAY_BE_CORRUPT, db.db_file,
|
||||||
|
db.backup_file)
|
||||||
|
else:
|
||||||
|
logger.error(DBUTIL_UPGRADE_PREPARATION_FAILED, ex)
|
||||||
|
logger.info(DBUTIL_UPGRADE_NOT_ATTEMPTED)
|
||||||
|
exit_code = EXIT_UPGRADE_ERROR
|
||||||
|
|
||||||
|
sys.exit(exit_code)
|
114
src/bin/dbutil/dbutil_messages.mes
Normal file
114
src/bin/dbutil/dbutil_messages.mes
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
|
# copyright notice and this permission notice appear in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
# No namespace declaration - these constants go in the global namespace
|
||||||
|
# of the ddns messages python module.
|
||||||
|
|
||||||
|
# When you add a message to this file, it is a good idea to run
|
||||||
|
# <topsrcdir>/tools/reorder_message_file.py to make sure the
|
||||||
|
# messages are in the correct order.
|
||||||
|
|
||||||
|
% DBUTIL_BACKUP created backup of %1 in %2
|
||||||
|
A backup for the given database file was created. Same of original file and
|
||||||
|
backup are given in the output message.
|
||||||
|
|
||||||
|
% DBUTIL_CHECK_ERROR unable to check database version: %1
|
||||||
|
There was an error while trying to check the current version of the database
|
||||||
|
schema. The error is shown in the message.
|
||||||
|
|
||||||
|
% DBUTIL_CHECK_NOCONFIRM --noconfirm is not compatible with --check
|
||||||
|
b10-dbutil was called with --check and --noconfirm. --noconfirm only has
|
||||||
|
meaning with --upgrade, so this is considered an error.
|
||||||
|
|
||||||
|
% DBUTIL_CHECK_OK this is the latest version of the database schema. No upgrade is required
|
||||||
|
The database schema version has been checked, and is up to date.
|
||||||
|
No action is required.
|
||||||
|
|
||||||
|
% DBUTIL_CHECK_UPGRADE_NEEDED re-run this program with the --upgrade switch to upgrade
|
||||||
|
The database schema version is not up to date, and an update is required.
|
||||||
|
Please run the dbutil tool again, with the --upgrade argument.
|
||||||
|
|
||||||
|
% DBUTIL_COMMAND_NONE must select one of --check or --upgrade
|
||||||
|
b10-dbutil was called with neither --check nor --upgrade. One action must be
|
||||||
|
provided.
|
||||||
|
|
||||||
|
% DBUTIL_COMMAND_UPGRADE_CHECK --upgrade is not compatible with --check
|
||||||
|
b10-dbutil was called with both the commands --upgrade and --check. Only one
|
||||||
|
action can be performed at a time.
|
||||||
|
|
||||||
|
% DBUTIL_DATABASE_MAY_BE_CORRUPT database file %1 may be corrupt, restore it from backup (%2)
|
||||||
|
The upgrade failed while it was in progress; the database may now be in an
|
||||||
|
inconsistent state, and it is advised to restore it from the backup that was
|
||||||
|
created when b10-dbutil started.
|
||||||
|
|
||||||
|
% DBUTIL_EXECUTE Executing SQL statement: %1
|
||||||
|
Debug message; the given SQL statement is executed
|
||||||
|
|
||||||
|
% DBUTIL_FILE Database file: %1
|
||||||
|
The database file that is being checked.
|
||||||
|
|
||||||
|
% DBUTIL_NO_FILE must supply name of the database file to upgrade
|
||||||
|
b10-dbutil was called without a database file. Currently, it cannot find this
|
||||||
|
file on its own, and it must be provided.
|
||||||
|
|
||||||
|
% DBUTIL_STATEMENT_ERROR failed to execute %1: %2
|
||||||
|
The given database statement failed to execute. The error is shown in the
|
||||||
|
message.
|
||||||
|
|
||||||
|
% DBUTIL_TOO_MANY_ARGUMENTS too many arguments to the command, maximum of one expected
|
||||||
|
There were too many command-line arguments to b10-dbutil
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADE_CANCELED upgrade canceled; database has not been changed
|
||||||
|
The user aborted the upgrade, and b10-dbutil will now exit.
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADE_DBUTIL please get the latest version of b10-dbutil and re-run
|
||||||
|
A database schema was found that was newer than this version of dbutil, which
|
||||||
|
is apparently out of date and should be upgraded itself.
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADE_FAILED upgrade failed: %1
|
||||||
|
While the upgrade was in progress, an unexpected error occurred. The error
|
||||||
|
is shown in the message.
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADE_NOT_ATTEMPTED database upgrade was not attempted
|
||||||
|
Due to the earlier failure, the database schema upgrade was not attempted,
|
||||||
|
and b10-dbutil will now exit.
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADE_NOT_NEEDED database already at latest version, no upgrade necessary
|
||||||
|
b10-dbutil was told to upgrade the database schema, but it is already at the
|
||||||
|
latest version.
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADE_NOT_POSSIBLE database at a later version than this utility can support
|
||||||
|
b10-dbutil was told to upgrade the database schema, but it is at a higher
|
||||||
|
version than this tool currently supports. Please update b10-dbutil and try
|
||||||
|
again.
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADE_PREPARATION_FAILED upgrade preparation failed: %1
|
||||||
|
An unexpected error occurred while b10-dbutil was preparing to upgrade the
|
||||||
|
database schema. The error is shown in the message
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADE_SUCCESFUL database upgrade successfully completed
|
||||||
|
The database schema update was completed successfully.
|
||||||
|
|
||||||
|
% DBUTIL_UPGRADING upgrading database from %1 to %2
|
||||||
|
An upgrade is in progress, the versions of the current upgrade action are shown.
|
||||||
|
|
||||||
|
% DBUTIL_VERSION_CURRENT database version %1
|
||||||
|
The current version of the database schema.
|
||||||
|
|
||||||
|
% DBUTIL_VERSION_HIGH database is at a later version (%1) than this program can cope with (%2)
|
||||||
|
The database schema is at a higher version than b10-dbutil knows about.
|
||||||
|
|
||||||
|
% DBUTIL_VERSION_LOW database version %1, latest version is %2.
|
||||||
|
The database schema is not up to date, the current version and the latest
|
||||||
|
version are in the message.
|
40
src/bin/dbutil/run_dbutil.sh.in
Executable file
40
src/bin/dbutil/run_dbutil.sh.in
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
# Copyright (C) 2010 Internet Systems Consortium.
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and distribute this software for any
|
||||||
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
|
# copyright notice and this permission notice appear in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
|
||||||
|
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||||
|
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||||
|
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||||
|
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
|
||||||
|
export PYTHON_EXEC
|
||||||
|
|
||||||
|
DBUTIL_PATH=@abs_top_builddir@/src/bin/dbutil
|
||||||
|
|
||||||
|
PYTHONPATH=@abs_top_srcdir@/src/bin:@abs_top_builddir@/src/lib/python/isc/log_messages:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/bin:@abs_top_srcdir@/src/lib/python
|
||||||
|
export PYTHONPATH
|
||||||
|
|
||||||
|
# If necessary (rare cases), explicitly specify paths to dynamic libraries
|
||||||
|
# required by loadable python modules.
|
||||||
|
SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
|
||||||
|
if test $SET_ENV_LIBRARY_PATH = yes; then
|
||||||
|
@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:@abs_top_builddir@/src/lib/datasrc/.libs:$@ENV_LIBRARY_PATH@
|
||||||
|
export @ENV_LIBRARY_PATH@
|
||||||
|
fi
|
||||||
|
|
||||||
|
B10_FROM_SOURCE=@abs_top_srcdir@
|
||||||
|
export B10_FROM_SOURCE
|
||||||
|
|
||||||
|
BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
|
||||||
|
export BIND10_MSGQ_SOCKET_FILE
|
||||||
|
|
||||||
|
exec ${PYTHON_EXEC} -O ${DBUTIL_PATH}/b10-dbutil "$@"
|
6
src/bin/dbutil/tests/Makefile.am
Normal file
6
src/bin/dbutil/tests/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
SUBDIRS = . testdata
|
||||||
|
|
||||||
|
# Tests of the update script.
|
||||||
|
|
||||||
|
check-local:
|
||||||
|
$(SHELL) $(abs_builddir)/dbutil_test.sh
|
482
src/bin/dbutil/tests/dbutil_test.sh.in
Executable file
482
src/bin/dbutil/tests/dbutil_test.sh.in
Executable file
@ -0,0 +1,482 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
|
# copyright notice and this permission notice appear in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
# Checks that the logger will limit the output of messages less severe than
|
||||||
|
# the severity/debug setting.
|
||||||
|
|
||||||
|
testname="Database Upgrade Test"
|
||||||
|
echo $testname
|
||||||
|
|
||||||
|
failcount=0
|
||||||
|
tempfile=@abs_builddir@/dbutil_test_tempfile_$$
|
||||||
|
backupfile=${tempfile}.backup
|
||||||
|
testdata=@abs_srcdir@/testdata
|
||||||
|
verfile=@abs_builddir@/dbutil_test_verfile_$$
|
||||||
|
|
||||||
|
# @brief Record a success
|
||||||
|
succeed() {
|
||||||
|
echo "--- PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Record a fail
|
||||||
|
#
|
||||||
|
# @param $1 Optional additional reason to output
|
||||||
|
fail() {
|
||||||
|
if [ "$1" != "" ]
|
||||||
|
then
|
||||||
|
echo "ERROR: $1"
|
||||||
|
fi
|
||||||
|
echo "*** FAIL"
|
||||||
|
failcount=`expr $failcount + 1`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Record a pass if the argument is zero
|
||||||
|
#
|
||||||
|
# @param $1 Value to test
|
||||||
|
passzero() {
|
||||||
|
if [ $1 -eq 0 ]; then
|
||||||
|
succeed
|
||||||
|
else
|
||||||
|
fail
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Record a fail if the argument is non-zero
|
||||||
|
#
|
||||||
|
# @param $1 Value to test
|
||||||
|
failzero() {
|
||||||
|
if [ $1 -ne 0 ]; then
|
||||||
|
succeed
|
||||||
|
else
|
||||||
|
fail
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Copy File
|
||||||
|
#
|
||||||
|
# Executes a "cp" operation followed by a "chmod" to make the target writeable.
|
||||||
|
#
|
||||||
|
# @param $1 Source file
|
||||||
|
# @param $2 Target file
|
||||||
|
copy_file () {
|
||||||
|
cp $1 $2
|
||||||
|
chmod a+w $2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Check backup file
|
||||||
|
#
|
||||||
|
# Record a failure if the backup file does not exist or if it is different
|
||||||
|
# to the data file. (N.B. No success is recorded if they are the same.)
|
||||||
|
#
|
||||||
|
# @param $1 Source database file
|
||||||
|
# @param $2 Backup file
|
||||||
|
check_backup() {
|
||||||
|
if [ ! -e $1 ]
|
||||||
|
then
|
||||||
|
fail "database file $1 not found"
|
||||||
|
|
||||||
|
elif [ ! -e $2 ]
|
||||||
|
then
|
||||||
|
fail "backup file $2 not found"
|
||||||
|
|
||||||
|
else
|
||||||
|
diff $1 $2 > /dev/null
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
fail "database file $1 different to backup file $2"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Check No Backup File
|
||||||
|
#
|
||||||
|
# Record a failure if the backup file exists. (N.B. No success is recorded if
|
||||||
|
# it does not.)
|
||||||
|
#
|
||||||
|
# @param $1 Source database file (unused, present for symmetry)
|
||||||
|
# @param $2 Backup file
|
||||||
|
check_no_backup() {
|
||||||
|
if [ -e $2 ]
|
||||||
|
then
|
||||||
|
fail "backup of database $2 exists when it should not"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Get Database Schema
|
||||||
|
#
|
||||||
|
# As the schema stored in the database is format-dependent - how it is printed
|
||||||
|
# depends on how the commands were entered (on one line, split across two
|
||||||
|
# lines etc.) - comparing schema is awkward.
|
||||||
|
#
|
||||||
|
# The function sets the local variable db_schema to the output of the
|
||||||
|
# .schema command, with spaces removed and upper converted to lowercase.
|
||||||
|
#
|
||||||
|
# The database is copied before the schema is taken (and removed after)
|
||||||
|
# as SQLite3 assummes a writeable database, which may not be the case if
|
||||||
|
# getting the schema from a reference copy.
|
||||||
|
#
|
||||||
|
# @param $1 Database for which the schema is required
|
||||||
|
get_schema() {
|
||||||
|
db1=@abs_builddir@/dbutil_test_schema_$$
|
||||||
|
copy_file $1 $db1
|
||||||
|
|
||||||
|
db_schema=`sqlite3 $db1 '.schema' | \
|
||||||
|
awk '{line = line $0} END {print line}' | \
|
||||||
|
sed -e 's/ //g' | \
|
||||||
|
tr [:upper:] [:lower:]`
|
||||||
|
rm -f $db1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Successful Schema Upgrade Test
|
||||||
|
#
|
||||||
|
# This test is done where the upgrade is expected to be successful - when
|
||||||
|
# the end result of the test is that the test database is upgraded to a
|
||||||
|
# database of the expected schema.
|
||||||
|
#
|
||||||
|
# Note: the caller must ensure that $tempfile and $backupfile do not exist
|
||||||
|
# on entry, and is responsible for removing them afterwards.
|
||||||
|
#
|
||||||
|
# @param $1 Database to upgrade
|
||||||
|
# @param $2 Expected backup file
|
||||||
|
upgrade_ok_test() {
|
||||||
|
copy_file $1 $tempfile
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm $tempfile
|
||||||
|
if [ $? -eq 0 ]
|
||||||
|
then
|
||||||
|
# Compare schema with the reference
|
||||||
|
get_schema $testdata/v2_0.sqlite3
|
||||||
|
expected_schema=$db_schema
|
||||||
|
get_schema $tempfile
|
||||||
|
actual_schema=$db_schema
|
||||||
|
if [ "$expected_schema" = "$actual_schema" ]
|
||||||
|
then
|
||||||
|
succeed
|
||||||
|
else
|
||||||
|
fail "upgraded schema not as expected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check the version is set correctly
|
||||||
|
check_version $tempfile "V2.0"
|
||||||
|
|
||||||
|
# Check that a backup was made
|
||||||
|
check_backup $1 $2
|
||||||
|
else
|
||||||
|
# Error should have been output already
|
||||||
|
fail
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Unsuccessful Upgrade Test
|
||||||
|
#
|
||||||
|
# Checks that an upgrade of the specified database fails.
|
||||||
|
#
|
||||||
|
# Note: the caller must ensure that $tempfile and $backupfile do not exist
|
||||||
|
# on entry, and is responsible for removing them afterwards.
|
||||||
|
#
|
||||||
|
# @param $1 Database to upgrade
|
||||||
|
# @param $2 Expected backup file
|
||||||
|
upgrade_fail_test() {
|
||||||
|
copy_file $1 $tempfile
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm $tempfile
|
||||||
|
failzero $?
|
||||||
|
check_backup $1 $backupfile
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Record Count Test
|
||||||
|
#
|
||||||
|
# Checks that the count of records in each table is preserved in the upgrade.
|
||||||
|
#
|
||||||
|
# Note 1: This test assumes that the "diffs" table is present.
|
||||||
|
# Note 2: The caller must ensure that $tempfile and $backupfile do not exist
|
||||||
|
# on entry, and is responsible for removing them afterwards.
|
||||||
|
#
|
||||||
|
# @brief $1 Database to upgrade
|
||||||
|
record_count_test() {
|
||||||
|
copy_file $1 $tempfile
|
||||||
|
|
||||||
|
diffs_count=`sqlite3 $tempfile 'select count(*) from diffs'`
|
||||||
|
nsec3_count=`sqlite3 $tempfile 'select count(*) from nsec3'`
|
||||||
|
records_count=`sqlite3 $tempfile 'select count(*) from records'`
|
||||||
|
zones_count=`sqlite3 $tempfile 'select count(*) from zones'`
|
||||||
|
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm $tempfile
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
# Reason for failure should already have been output
|
||||||
|
fail
|
||||||
|
else
|
||||||
|
new_diffs_count=`sqlite3 $tempfile 'select count(*) from diffs'`
|
||||||
|
new_nsec3_count=`sqlite3 $tempfile 'select count(*) from nsec3'`
|
||||||
|
new_records_count=`sqlite3 $tempfile 'select count(*) from records'`
|
||||||
|
new_zones_count=`sqlite3 $tempfile 'select count(*) from zones'`
|
||||||
|
|
||||||
|
if [ $diffs_count -ne $new_diffs_count ]
|
||||||
|
then
|
||||||
|
fail "diffs table was not completely copied"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $nsec3_count -ne $new_nsec3_count ]
|
||||||
|
then
|
||||||
|
fail "nsec3 table was not completely copied"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $records_count -ne $new_records_count ]
|
||||||
|
then
|
||||||
|
fail "records table was not completely copied"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $zones_count -ne $new_zones_count ]
|
||||||
|
then
|
||||||
|
fail "zones table was not completely copied"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# As an extra check, test that the backup was successful
|
||||||
|
check_backup $1 $backupfile
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Version Check
|
||||||
|
#
|
||||||
|
# Checks that the database is at the specified version (and so checks the
|
||||||
|
# --check function). On success, a pass is recorded.
|
||||||
|
#
|
||||||
|
# @param $1 Database to check
|
||||||
|
# @param $2 Expected version string
|
||||||
|
check_version() {
|
||||||
|
copy_file $1 $verfile
|
||||||
|
../run_dbutil.sh --check $verfile
|
||||||
|
if [ $? -gt 2 ]
|
||||||
|
then
|
||||||
|
fail "version check failed on database $1; return code $?"
|
||||||
|
else
|
||||||
|
../run_dbutil.sh --check $verfile 2>&1 | grep "$2" > /dev/null
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
fail "database $1 not at expected version $2 (output: $?)"
|
||||||
|
else
|
||||||
|
succeed
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -f $verfile
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# @brief Version Check Fail
|
||||||
|
#
|
||||||
|
# Does a version check but expected the check to fail
|
||||||
|
#
|
||||||
|
# @param $1 Database to check
|
||||||
|
# @param $2 Backup file
|
||||||
|
check_version_fail() {
|
||||||
|
copy_file $1 $verfile
|
||||||
|
../run_dbutil.sh --check $verfile
|
||||||
|
failzero $?
|
||||||
|
check_no_backup $tempfile $backupfile
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Main test sequence
|
||||||
|
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
# Test 1 - check that the utility fails if the database does not exist
|
||||||
|
echo "1.1. Non-existent database - check"
|
||||||
|
../run_dbutil.sh --check $tempfile
|
||||||
|
failzero $?
|
||||||
|
check_no_backup $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "1.2. Non-existent database - upgrade"
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm $tempfile
|
||||||
|
failzero $?
|
||||||
|
check_no_backup $tempfile $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
# Test 2 - should fail to check an empty file and fail to upgrade it
|
||||||
|
echo "2.1. Database is an empty file - check"
|
||||||
|
touch $tempfile
|
||||||
|
check_version_fail $tempfile $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "2.2. Database is an empty file - upgrade"
|
||||||
|
touch $tempfile
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm $tempfile
|
||||||
|
failzero $?
|
||||||
|
# A backup is performed before anything else, so the backup should exist.
|
||||||
|
check_backup $tempfile $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "3.1. Database is not an SQLite file - check"
|
||||||
|
echo "This is not an sqlite3 database" > $tempfile
|
||||||
|
check_version_fail $tempfile $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "3.2. Database is not an SQLite file - upgrade"
|
||||||
|
echo "This is not an sqlite3 database" > $tempfile
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm $tempfile
|
||||||
|
failzero $?
|
||||||
|
# ...and as before, a backup should have been created
|
||||||
|
check_backup $tempfile $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "4.1. Database is an SQLite3 file without the schema table - check"
|
||||||
|
check_version_fail $testdata/no_schema.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "4.1. Database is an SQLite3 file without the schema table - upgrade"
|
||||||
|
upgrade_fail_test $testdata/no_schema.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "5.1. Database is an old V1 database - check"
|
||||||
|
check_version $testdata/old_v1.sqlite3 "V1.0"
|
||||||
|
check_no_backup $tempfile $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "5.2. Database is an old V1 database - upgrade"
|
||||||
|
upgrade_ok_test $testdata/old_v1.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "6.1. Database is new V1 database - check"
|
||||||
|
check_version $testdata/new_v1.sqlite3 "V1.0"
|
||||||
|
check_no_backup $tempfile $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "6.2. Database is a new V1 database - upgrade"
|
||||||
|
upgrade_ok_test $testdata/new_v1.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "7.1. Database is V2.0 database - check"
|
||||||
|
check_version $testdata/v2_0.sqlite3 "V2.0"
|
||||||
|
check_no_backup $tempfile $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "7.2. Database is a V2.0 database - upgrade"
|
||||||
|
upgrade_ok_test $testdata/v2_0.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "8.1. Database is V2.0 database with empty schema table - check"
|
||||||
|
check_version_fail $testdata/empty_version.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "8.2. Database is V2.0 database with empty schema table - upgrade"
|
||||||
|
upgrade_fail_test $testdata/empty_version.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "9.1. Database is V2.0 database with over-full schema table - check"
|
||||||
|
check_version_fail $testdata/too_many_version.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "9.2. Database is V2.0 database with over-full schema table - upgrade"
|
||||||
|
upgrade_fail_test $testdata/too_many_version.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "10.0. Upgrade corrupt database"
|
||||||
|
upgrade_fail_test $testdata/corrupt.sqlite3 $backupfile
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "11. Record count test"
|
||||||
|
record_count_test $testdata/new_v1.sqlite3
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
echo "12. Backup file already exists"
|
||||||
|
touch $backupfile
|
||||||
|
touch ${backupfile}-1
|
||||||
|
upgrade_ok_test $testdata/v2_0.sqlite3 ${backupfile}-2
|
||||||
|
rm -f $tempfile $backupfile ${backupfile}-1 ${backupfile}-2
|
||||||
|
|
||||||
|
|
||||||
|
echo "13.1 Command-line errors"
|
||||||
|
copy_file $testdata/old_v1.sqlite3 $tempfile
|
||||||
|
../run_dbutil.sh $tempfile
|
||||||
|
failzero $?
|
||||||
|
../run_dbutil.sh --upgrade --check $tempfile
|
||||||
|
failzero $?
|
||||||
|
../run_dbutil.sh --noconfirm --check $tempfile
|
||||||
|
failzero $?
|
||||||
|
../run_dbutil.sh --check
|
||||||
|
failzero $?
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm
|
||||||
|
failzero $?
|
||||||
|
../run_dbutil.sh --check $tempfile $backupfile
|
||||||
|
failzero $?
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm $tempfile $backupfile
|
||||||
|
failzero $?
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "13.2 verbose flag"
|
||||||
|
copy_file $testdata/old_v1.sqlite3 $tempfile
|
||||||
|
../run_dbutil.sh --upgrade --noconfirm --verbose $tempfile
|
||||||
|
passzero $?
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "13.3 quiet flag"
|
||||||
|
copy_file $testdata/old_v1.sqlite3 $tempfile
|
||||||
|
../run_dbutil.sh --check --quiet $tempfile 2>&1 | grep .
|
||||||
|
failzero $?
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "13.3 Interactive prompt - yes"
|
||||||
|
copy_file $testdata/old_v1.sqlite3 $tempfile
|
||||||
|
../run_dbutil.sh --upgrade $tempfile << .
|
||||||
|
Yes
|
||||||
|
.
|
||||||
|
passzero $?
|
||||||
|
check_version $tempfile "V2.0"
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
echo "13.4 Interactive prompt - no"
|
||||||
|
copy_file $testdata/old_v1.sqlite3 $tempfile
|
||||||
|
../run_dbutil.sh --upgrade $tempfile << .
|
||||||
|
no
|
||||||
|
.
|
||||||
|
passzero $?
|
||||||
|
diff $testdata/old_v1.sqlite3 $tempfile > /dev/null
|
||||||
|
passzero $?
|
||||||
|
rm -f $tempfile $backupfile
|
||||||
|
|
||||||
|
|
||||||
|
# Report the result
|
||||||
|
if [ $failcount -eq 0 ]; then
|
||||||
|
echo "PASS: $testname"
|
||||||
|
elif [ $failcount -eq 1 ]; then
|
||||||
|
echo "FAIL: $testname - 1 test failed"
|
||||||
|
else
|
||||||
|
echo "FAIL: $testname - $failcount tests failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit with appropriate error status
|
||||||
|
exit $failcount
|
12
src/bin/dbutil/tests/testdata/Makefile.am
vendored
Normal file
12
src/bin/dbutil/tests/testdata/Makefile.am
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
EXTRA_DIST =
|
||||||
|
EXTRA_DIST += corrupt.sqlite3
|
||||||
|
EXTRA_DIST += empty_schema.sqlite3
|
||||||
|
EXTRA_DIST += empty_v1.sqlite3
|
||||||
|
EXTRA_DIST += empty_version.sqlite3
|
||||||
|
EXTRA_DIST += invalid_v1.sqlite3
|
||||||
|
EXTRA_DIST += new_v1.sqlite3
|
||||||
|
EXTRA_DIST += no_schema.sqlite3
|
||||||
|
EXTRA_DIST += old_v1.sqlite3
|
||||||
|
EXTRA_DIST += README
|
||||||
|
EXTRA_DIST += too_many_version.sqlite3
|
||||||
|
EXTRA_DIST += v2_0.sqlite3
|
41
src/bin/dbutil/tests/testdata/README
vendored
Normal file
41
src/bin/dbutil/tests/testdata/README
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
The versioning of BIND 10 databases to date has not been the best:
|
||||||
|
|
||||||
|
The original database is known here as the "old V1" schema. It had a
|
||||||
|
schema_version table, with the single "version" value set to 1.
|
||||||
|
|
||||||
|
The schema was then updated with a "diffs" table. This is referred to
|
||||||
|
here as the "new V1" schema.
|
||||||
|
|
||||||
|
The Spring 2012 release of BIND 10 modified the schema. The
|
||||||
|
schema_version table was updated to include a "minor" column, holding the
|
||||||
|
minor version number. Other changes to the database included redefining
|
||||||
|
"STRING" columns as "TEXT" columns. This is referred to as the "V2.0
|
||||||
|
schema".
|
||||||
|
|
||||||
|
The following test data files are present:
|
||||||
|
|
||||||
|
empty_schema.sqlite3: A database conforming to the new V1 schema.
|
||||||
|
However, there is nothing in the schema_version table.
|
||||||
|
|
||||||
|
empty_v1.sqlite3: A database conforming to the new V1 schema.
|
||||||
|
The database is empty, except for the schema_version table, where the
|
||||||
|
"version" column is set to 1.
|
||||||
|
|
||||||
|
empty_version.sqlite3: A database conforming to the V2.0 schema but without
|
||||||
|
anything in the schema_version table.
|
||||||
|
|
||||||
|
no_schema.sqlite3: A valid SQLite3 database, but without a schema_version
|
||||||
|
table.
|
||||||
|
|
||||||
|
old_v1.sqlite3: A valid SQLite3 database conforming to the old V1 schema.
|
||||||
|
It does not have a diffs table.
|
||||||
|
|
||||||
|
invalid_v1.sqlite3: A valid SQLite3 database that, although the schema
|
||||||
|
is marked as V1, does not have the nsec3 table.
|
||||||
|
|
||||||
|
new_v1.sqlite3: A valid SQLite3 database with data in all the tables
|
||||||
|
(although the single rows in both the nsec3 and diffs table make no
|
||||||
|
sense, but are valid).
|
||||||
|
|
||||||
|
too_many_version.sqlite3: A database conforming to the V2.0 schema but with
|
||||||
|
too many rows of data.
|
BIN
src/bin/dbutil/tests/testdata/corrupt.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/corrupt.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/empty_schema.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/empty_schema.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/empty_v1.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/empty_v1.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/empty_version.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/empty_version.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/invalid_v1.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/invalid_v1.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/new_v1.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/new_v1.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/no_schema.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/no_schema.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/old_v1.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/old_v1.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/too_many_version.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/too_many_version.sqlite3
vendored
Normal file
Binary file not shown.
BIN
src/bin/dbutil/tests/testdata/v2_0.sqlite3
vendored
Normal file
BIN
src/bin/dbutil/tests/testdata/v2_0.sqlite3
vendored
Normal file
Binary file not shown.
@ -9,6 +9,15 @@
|
|||||||
.\"
|
.\"
|
||||||
.TH "B10\-XFROUT" "8" "March 16\&. 2012" "BIND10" "BIND10"
|
.TH "B10\-XFROUT" "8" "March 16\&. 2012" "BIND10" "BIND10"
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
|
.\" * Define some portability stuff
|
||||||
|
.\" -----------------------------------------------------------------
|
||||||
|
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
.\" http://bugs.debian.org/507673
|
||||||
|
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
|
||||||
|
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
.ie \n(.g .ds Aq \(aq
|
||||||
|
.el .ds Aq '
|
||||||
|
.\" -----------------------------------------------------------------
|
||||||
.\" * set default formatting
|
.\" * set default formatting
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
.\" disable hyphenation
|
.\" disable hyphenation
|
||||||
|
@ -14,6 +14,7 @@ EXTRA_DIST += config_messages.py
|
|||||||
EXTRA_DIST += notify_out_messages.py
|
EXTRA_DIST += notify_out_messages.py
|
||||||
EXTRA_DIST += libxfrin_messages.py
|
EXTRA_DIST += libxfrin_messages.py
|
||||||
EXTRA_DIST += server_common_messages.py
|
EXTRA_DIST += server_common_messages.py
|
||||||
|
EXTRA_DIST += dbutil_messages.py
|
||||||
|
|
||||||
CLEANFILES = __init__.pyc
|
CLEANFILES = __init__.pyc
|
||||||
CLEANFILES += bind10_messages.pyc
|
CLEANFILES += bind10_messages.pyc
|
||||||
|
1
src/lib/python/isc/log_messages/dbutil_messages.py
Normal file
1
src/lib/python/isc/log_messages/dbutil_messages.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from work.dbutil_messages import *
|
Loading…
x
Reference in New Issue
Block a user