diff --git a/src/bin/dbutil/Makefile.am b/src/bin/dbutil/Makefile.am index 5c05757487..001332064d 100644 --- a/src/bin/dbutil/Makefile.am +++ b/src/bin/dbutil/Makefile.am @@ -3,11 +3,16 @@ 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 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 @@ -16,7 +21,12 @@ b10-dbutil.8: b10-dbutil.xml endif -b10-dbutil: dbutil.py +# 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 >$@ diff --git a/src/bin/dbutil/b10-dbutil.8 b/src/bin/dbutil/b10-dbutil.8 index 4fce304916..d706ee5c64 100644 --- a/src/bin/dbutil/b10-dbutil.8 +++ b/src/bin/dbutil/b10-dbutil.8 @@ -74,7 +74,7 @@ The upgrade function will upgrade a BIND 10 database \- no matter how old the sc .PP \fB\-\-verbose\fR .RS 4 -Enable verbose mode\&. Each SQL command issued by the utility will be printed to before it is executed\&. +Enable verbose mode\&. Each SQL command issued by the utility will be printed to stdout before it is executed\&. .RE .PP \fB\fIdbfile\fR\fR diff --git a/src/bin/dbutil/dbutil.py.in b/src/bin/dbutil/dbutil.py.in index 215fe31e66..3f97df9145 100755 --- a/src/bin/dbutil/dbutil.py.in +++ b/src/bin/dbutil/dbutil.py.in @@ -38,7 +38,11 @@ import sys; sys.path.append("@@PYTHONPATH@@") 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() # @brief Version String @@ -55,7 +59,6 @@ EXIT_COMMAND_ERROR = 3 EXIT_READ_ERROR = 4 EXIT_UPGRADE_ERROR = 5 - # @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 @@ -190,55 +193,6 @@ class DbutilException(Exception): """ pass -# Functions for outputting messages in a consistent format. As this is intended -# to be an interactive utility, it was not considered necessary to use the full -# logging framework for messages. - -def output(writer, prefix, text, ex = None): - """ - @brief Write error message to output stream - - @param writer Function to do the writing - @param prefix Prefix to the message - @param text Text to output - @param ex Possible exception holding additiona information - """ - writer(prefix + ": " + text) - if ex is not None: - writer(" - " + str(ex)) - writer("\n") - - -def error(text, ex = None): - """ - @brief Write error message to stderr. - - @param text Text to output - @param ex Possible exception holding additiona information - """ - output(sys.stderr.write, "ERROR", text, ex) - - -def warn(text, ex = None): - """ - @brief Write warning message to stderr. - - @param text Text to output - @param ex Possible exception holding additiona information - """ - output(sys.stderr.write, "WARN", text, ex) - - -def info(text, ex = None): - """ - @brief Write informational message to stdout. - - @param text Text to output - @param ex Possible exception holding additiona information - """ - output(sys.stdout.write, "INFO", text, ex) - - class Database: """ @brief Database Encapsulation @@ -297,12 +251,12 @@ class Database: @param statement SQL statement to execute """ if self.verbose: - sys.stdout.write(statement + "\n") + logger.debug(40, DBUTIL_EXECUTE, statement) try: self.cursor.execute(statement) except Exception as ex: - error("failed to execute " + statement) + logger.error(DBUTIL_STATEMENT_ERROR, statement, ex) raise DbutilException(str(ex)) def result(self): @@ -337,7 +291,7 @@ class Database: # Do the backup shutil.copyfile(self.db_file, self.backup_file) - info("database " + self.db_file + " backed up to " + self.backup_file) + logger.info(DBUTIL_BACKUP, self.db_file, self.backup_file) def prompt_user(): """ @@ -360,7 +314,7 @@ BIND 10 is not running before continuing. 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: ") + "'No' to exit the program: \n") response = sys.stdin.readline() if response.lower() == "yes\n": yes_entered = True @@ -466,20 +420,18 @@ def check_version(db): match = compare_versions(current, latest) if match == 0: - info("database version " + version_string(current)) - info("this is the latest version of the database schema, " + - "no upgrade is required") + logger.info(DBUTIL_VERSION_CURRENT, version_string(current)) + logger.info(DBUTIL_CHECK_OK) return EXIT_SUCCESS elif match < 0: - info("database version " + version_string(current) + - ", latest version is " + version_string(latest)) - info("re-run this program with the --upgrade switch to upgrade") + logger.info(DBUTIL_VERSION_LOW, version_string(current), + version_string(latest)) + logger.info(DBUTIL_CHECK_UPGRADE_NEEDED) return EXIT_NEED_UPDATE else: - warn("database is at a later version (" + version_string(current) + - ") than this program can cope with (" + - version_string(get_latest_version()) + ")") - info("please get the latest version of b10-dbutil and re-run") + 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): @@ -492,10 +444,8 @@ def perform_upgrade(db, upgrade): @param db Database object @param upgrade Upgrade dictionary, holding "from", "to" and "statements". """ - increment = (version_string(upgrade['from']) + " to " + - version_string(upgrade['to'])) - action = "upgrading database from " + increment - info(action) + logger.info(DBUTIL_UPGRADING, version_string(upgrade['from']), + version_string(upgrade['to'])) for statement in upgrade['statements']: db.execute(statement) @@ -516,10 +466,10 @@ def perform_all_upgrades(db): """ match = compare_versions(get_version(db), get_latest_version()) if match == 0: - info("database already at latest version, no upgrade necessary") + logger.info(DBUTIL_UPGRADE_NOT_NEEDED) elif match > 0: - warn("database at a later version than this utility can support") + logger.warn(DBUTIL_UPGRADE_NOT_POSSIBLE) else: # Work our way through all upgrade increments @@ -530,7 +480,7 @@ def perform_all_upgrades(db): count = count + 1 if count > 0: - info("database upgrade successfully completed") + 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. @@ -567,22 +517,22 @@ def parse_command(): # Set the database file on which to operate if (len(args) > 1): - error("too many arguments to the command, maximum of one expected") + logger.error(DBUTIL_TOO_MANY_ARGUMENTS) parser.print_usage() sys.exit(EXIT_COMMAND_ERROR) elif len(args) == 0: - error("must supply name of the database file to upgrade") + 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: - error("--upgrade is not compatible with --check") + logger.error(DBUTIL_COMMAND_UPGRADE_CHECK) elif (not options.check) and (not options.upgrade): - error("must select one of --check or --upgrade") + logger.error(DBUTIL_COMMAND_NONE) elif (options.check and options.noconfirm): - error("--noconfirm is not compatible with --check") + logger.error(DBUTIL_CHECK_NOCONFIRM) else: return (options, args) @@ -596,6 +546,7 @@ if __name__ == "__main__": db = Database(args[0], options.verbose) exit_code = EXIT_SUCCESS + logger.info(DBUTIL_FILE, args[0]) if options.check: # Check database - open, report, and close try: @@ -603,7 +554,7 @@ if __name__ == "__main__": exit_code = check_version(db) db.close() except Exception as ex: - error("unable to check database version - " + str(ex)) + logger.error(DBUTIL_CHECK_ERROR, ex) exit_code = EXIT_READ_ERROR elif options.upgrade: @@ -611,7 +562,7 @@ if __name__ == "__main__": if not options.noconfirm: proceed = prompt_user() if not proceed: - info("upgrade abandoned - database has not been changed\n") + logger.info(DBUTIL_UPGRADE_CANCELED) sys.exit(EXIT_SUCCESS) # It is. Do a backup then do the upgrade. @@ -624,14 +575,14 @@ if __name__ == "__main__": db.close() except Exception as ex: if in_progress: - error("upgrade failed - " + str(ex)) - warn("database may be corrupt, restore it from backup") + logger.error(DBUTIL_UPGRADE_FAILED, ex) + logger.warn(DBUTIL_DATABASE_MAY_BE_CORRUPTED) else: - error("upgrade preparation failed - " + str(ex)) - info("database upgrade was not attempted") + logger.error(DBUTIL_UPGRADE_PREPARATION_FAILED, ex) + logger.info(DBUTIL_UPGRADE_NOT_ATTEMPTED) exit_code = EXIT_UPGRADE_ERROR else: - error("internal error, neither --check nor --upgrade selected") + logger.error(DBUTIL_NO_ACTION_SPECIFIED) exit_code = EXIT_COMMAND_ERROR sys.exit(exit_code) diff --git a/src/bin/dbutil/dbutil_messages.mes b/src/bin/dbutil/dbutil_messages.mes new file mode 100644 index 0000000000..f5496b08b0 --- /dev/null +++ b/src/bin/dbutil/dbutil_messages.mes @@ -0,0 +1,117 @@ +# 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 +# /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_CORRUPTED database may be corrupt, restore it from backup +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_ACTION_SPECIFIED Command error: neither --check nor --upgrade selected +b10-dbutil was called without either --check or --upgrade. + +% 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. diff --git a/src/bin/dbutil/tests/dbutil_test.sh.in b/src/bin/dbutil/tests/dbutil_test.sh.in index 7e13949041..2a68777143 100755 --- a/src/bin/dbutil/tests/dbutil_test.sh.in +++ b/src/bin/dbutil/tests/dbutil_test.sh.in @@ -273,10 +273,10 @@ check_version() { then fail "version check failed on database $1; return code $?" else - ../run_dbutil.sh --check $verfile | grep "$2" > /dev/null + ../run_dbutil.sh --check $verfile 2>&1 | grep "$2" > /dev/null if [ $? -ne 0 ] then - fail "database $1 not at expected version $2" + fail "database $1 not at expected version $2 (output: $?)" else succeed fi diff --git a/src/lib/python/isc/log_messages/dbutil_messages.py b/src/lib/python/isc/log_messages/dbutil_messages.py new file mode 100644 index 0000000000..c06dfef6cf --- /dev/null +++ b/src/lib/python/isc/log_messages/dbutil_messages.py @@ -0,0 +1 @@ +from work.dbutil_messages import *