src/share/database/scripts/mysql/upgrade_5.2_to_6.0.sh
src/share/database/scripts/mysql/upgrade_6.0_to_7.0.sh
src/share/database/scripts/mysql/upgrade_7.0_to_8.0.sh
+ src/share/database/scripts/mysql/wipe_data.sh
src/share/database/scripts/pgsql/Makefile
src/share/database/scripts/pgsql/upgrade_1.0_to_2.0.sh
src/share/database/scripts/pgsql/upgrade_2.0_to_3.0.sh
-// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
ConfigBackendDHCPv4Mgr::create();
// Recreate database schema.
- destroyMySQLSchema();
createMySQLSchema();
}
MySqlConfigBackendDHCPv4Test()
: test_subnets_(), test_networks_(), timestamps_(), audit_entries_() {
// Recreate database schema.
- destroyMySQLSchema();
createMySQLSchema();
try {
-// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
/// @brief Constructor.
CfgMySQLDbAccessTest() {
// Ensure schema is the correct one.
- destroyMySQLSchema();
createMySQLSchema();
}
HostMgrTest::testGetAll(BaseHostDataSource& data_source1,
BaseHostDataSource& data_source2) {
// Initially, no reservations should be present.
- ConstHostCollection hosts =
+ ConstHostCollection hosts =
HostMgr::instance().getAll(Host::IDENT_HWADDR,
&hwaddrs_[1]->hwaddr_[0],
hwaddrs_[1]->hwaddr_.size());
/// appropriate schema and create a basic host manager to
/// wipe out any prior instance
virtual void SetUp() {
- DatabaseConnection::db_lost_callback = 0;
+ DatabaseConnection::db_lost_callback = 0;
destroySchema();
createSchema();
// Wipe out any pre-existing mgr
/// Invoked by gtest upon test exit, we destroy the schema
/// we created.
virtual void TearDown() {
- DatabaseConnection::db_lost_callback = 0;
+ DatabaseConnection::db_lost_callback = 0;
destroySchema();
}
HostMgrTest::SetUp();
// Ensure schema is the correct one.
- db::test::destroyMySQLSchema();
db::test::createMySQLSchema();
// Connect to the database
/// @brief Clears the database and opens connection to it.
void initializeTest() {
// Ensure schema is the correct one.
- destroyMySQLSchema();
createMySQLSchema();
// Connect to the database
TEST(MySqlHostDataSource, OpenDatabase) {
// Schema needs to be created for the test to work.
- destroyMySQLSchema();
createMySQLSchema();
// Check that host manager open the database opens correctly and tidy up.
-// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
/// @brief Clears the database and opens connection to it.
void initializeTest() {
// Ensure schema is the correct one.
- destroyMySQLSchema();
createMySQLSchema();
// Connect to the database
/// opened: the fixtures assume that and check basic operations.
TEST(MySqlOpenTest, OpenDatabase) {
// Schema needs to be created for the test to work.
- destroyMySQLSchema(true);
createMySQLSchema(true);
// Check that lease manager open the database opens correctly and tidy up.
VALID_USER, VALID_PASSWORD));
}
-void destroyMySQLSchema(bool show_err) {
- runMySQLScript(DATABASE_SCRIPTS_DIR, "mysql/dhcpdb_drop.mysql", show_err);
+void destroyMySQLSchema(bool show_err, bool force) {
+ // If force is true or wipeData() fails, destory the schema.
+ if (force || wipeData(show_err)) {
+ runMySQLScript(DATABASE_SCRIPTS_DIR, "mysql/dhcpdb_drop.mysql", show_err);
+ }
+}
+
+void createMySQLSchema(bool show_err, bool force) {
+ // If force is true or wipeData() fails, recreate the schema.
+ if (force || wipeData(show_err)) {
+ destroyMySQLSchema(show_err, true);
+ runMySQLScript(DATABASE_SCRIPTS_DIR, "mysql/dhcpdb_create.mysql", show_err);
+ }
}
-void createMySQLSchema(bool show_err) {
- runMySQLScript(DATABASE_SCRIPTS_DIR, "mysql/dhcpdb_create.mysql", show_err);
+bool wipeData(bool show_err) {
+ std::ostringstream cmd;
+ cmd << "sh " << DATABASE_SCRIPTS_DIR << "/";
+
+ std::ostringstream version;
+ version << MYSQL_SCHEMA_VERSION_MAJOR << "." << MYSQL_SCHEMA_VERSION_MINOR;
+
+ cmd << "mysql/wipe_data.sh" << " " << version.str()
+ << " -N -B --user=keatest --password=keatest keatest";
+ if (!show_err) {
+ cmd << " 2>/dev/null ";
+ }
+
+ int retval = ::system(cmd.str().c_str());
+ if (retval) {
+ std::cerr << "wipeData failed:[" << cmd.str() << "]" << std::endl;
+ }
+
+ return(retval);
}
void runMySQLScript(const std::string& path, const std::string& script_name,
/// @return valid MySQL connection string.
std::string validMySQLConnectionString();
-/// @brief Clear everything from the database
+/// @brief Clear the unit test database
///
-/// Submits the current schema drop script:
+/// Either calls @c wipeData to wipe the data from the
+/// database /or destroys the database itself by submitting the
+/// SQL script:
///
-/// <TEST_ADMIN_SCRIPTS_DIR>/mysql/dhcpdb_drop.mysql
+/// <TEST_ADMIN_SCRIPTS_DIR>/mysql/dhcpdb_drop.sh
///
-/// to the unit test MySQL database. If the script fails, the invoking test
-/// will fail. The output of stderr is suppressed unless the parameter,
+/// If wipeData() is called and fails, it will destroy
+/// the schema. If the schema destruction fails, the
+/// invoking test should fail.
+///
+/// The output stderr is suppressed unless the parameter,
/// show_err is true.
///
/// @param show_err flag which governs whether or not stderr is suppressed.
-void destroyMySQLSchema(bool show_err = false);
+/// @param force if true, the function will simply destroy the schema.
+void destroyMySQLSchema(bool show_err = false, bool force = false);
-/// @brief Create the MySQL Schema
+/// @brief Create the unit test MySQL Schema
///
-/// Submits the current schema creation script:
+/// Ensures the unit test database is a empty and version-correct.
+/// Unless, the force parameter is true, it will first attempt
+/// to wipe the data from the database by calling @c wipeData.
+/// If this call succeeds the function returns, otherwise it will
+/// will call @c destroyMySQLSchema to forcibly remove the
+/// existing schema and then submits the SQL script:
///
/// <TEST_ADMIN_SCRIPTS_DIR>/mysql/dhcpdb_create.mysql
///
-/// to the unit test MySQL database. If the script fails, the invoking test
-/// will fail. The output of stderr is suppressed unless the parameter,
-/// show_err is true.
+/// to the unit test MySQL database.
+///
+/// @param show_err flag which governs whether or not stderr is suppressed.
+/// @param force flag when true, the function will recreate the database
+/// schema.
+void createMySQLSchema(bool show_err = false, bool force = false);
+
+
+/// @brief Attempts to wipe data from the MySQL unit test database
+///
+/// Runs the shell script
+///
+/// <TEST_ADMIN_SCRIPTS_DIR>/mysql/wipe_data.sh
+///
+/// This will fail if there is no schema, if the existing schema
+/// version is incorrect (i.e. does not match MYSQL_SCHEMA_VERSION_MAJOR
+/// and MYSQL_SCHEMA_VERSION_MINOR), or a SQL error occurs. Otherwise,
+/// the script is should delete all transient data, leaving intact
+/// reference tables.
///
/// @param show_err flag which governs whether or not stderr is suppressed.
-void createMySQLSchema(bool show_err = false);
+bool wipeData(bool show_err = false);
/// @brief Run a MySQL SQL script against the MySQL unit test database
///
sqlscripts_DATA += upgrade_5.2_to_6.0.sh
sqlscripts_DATA += upgrade_6.0_to_7.0.sh
sqlscripts_DATA += upgrade_7.0_to_8.0.sh
+sqlscripts_DATA += wipe_data.sh
DISTCLEANFILES = upgrade_1.0_to_2.0.sh
DISTCLEANFILES += upgrade_2.0_to_3.0.sh
DISTCLEANFILES += upgrade_5.2_to_6.0.sh
DISTCLEANFILES += upgrade_6.0_to_7.0.sh
DISTCLEANFILES += upgrade_7.0_to_8.0.sh
+DISTCLEANFILES += wipe_data.sh
EXTRA_DIST = ${sqlscripts_DATA}
-- hand, if the global option is being added, the
-- audit entry for the option must be created because
-- it is the sole object modified in that case.
+-- Session variable disable_audit is used to disable
+-- the procedure when wiping the database during
+-- unit tests. This avoids issues with revision_id
+-- being null.
-- -----------------------------------------------------
DROP PROCEDURE IF EXISTS createAuditRevisionDHCP4;
DELIMITER $$
IN cascade_transaction TINYINT(1))
BEGIN
DECLARE srv_id BIGINT(20);
- SELECT id INTO srv_id FROM dhcp4_server WHERE tag = server_tag;
- INSERT INTO dhcp4_audit_revision (modification_ts, server_id, log_message)
- VALUES (audit_ts, srv_id, audit_log_message);
- SET @audit_revision_id = LAST_INSERT_ID();
- SET @cascade_transaction = cascade_transaction;
+ IF @disable_audit IS NULL OR @disable_audit = 0 THEN
+ SELECT id INTO srv_id FROM dhcp4_server WHERE tag = server_tag;
+ INSERT INTO dhcp4_audit_revision (modification_ts, server_id, log_message)
+ VALUES (audit_ts, srv_id, audit_log_message);
+ SET @audit_revision_id = LAST_INSERT_ID();
+ SET @cascade_transaction = cascade_transaction;
+ END IF;
END $$
DELIMITER ;
-- - modification_type_val: string value indicating the
-- type of the change, i.e. "create", "update" or
-- "delete".
+-- Session variable disable_audit is used to disable
+-- the procedure when wiping the database during
+-- unit tests. This avoids issues with revision_id
+-- being null.
-- ----------------------------------------------------
DROP PROCEDURE IF EXISTS createAuditEntryDHCP4;
DELIMITER $$
IN object_id_val BIGINT(20) UNSIGNED,
IN modification_type_val VARCHAR(32))
BEGIN
- INSERT INTO dhcp4_audit (object_type, object_id, modification_type, revision_id)
- VALUES (object_type_val, object_id_val, \
+ IF @disable_audit IS NULL OR @disable_audit = 0 THEN
+ INSERT INTO dhcp4_audit (object_type, object_id, modification_type, revision_id)
+ VALUES (object_type_val, object_id_val, \
(SELECT id FROM modification WHERE modification_type = modification_type_val), \
@audit_revision_id);
+ END IF;
END $$
DELIMITER ;
-- hand, if the global option is being added, the
-- audit entry for the option must be created because
-- it is the sole object modified in that case.
+-- Session variable disable_audit is used to disable
+-- the procedure when wiping the database during
+-- unit tests. This avoids issues with revision_id
+-- being null.
-- -----------------------------------------------------
DROP PROCEDURE IF EXISTS createAuditRevisionDHCP6;
DELIMITER $$
IN cascade_transaction TINYINT(1))
BEGIN
DECLARE srv_id BIGINT(20);
- SELECT id INTO srv_id FROM dhcp6_server WHERE tag = server_tag;
- INSERT INTO dhcp6_audit_revision (modification_ts, server_id, log_message)
- VALUES (audit_ts, srv_id, audit_log_message);
- SET @audit_revision_id = LAST_INSERT_ID();
- SET @cascade_transaction = cascade_transaction;
+ IF @disable_audit IS NULL OR @disable_audit = 0 THEN
+ SELECT id INTO srv_id FROM dhcp6_server WHERE tag = server_tag;
+ INSERT INTO dhcp6_audit_revision (modification_ts, server_id, log_message)
+ VALUES (audit_ts, srv_id, audit_log_message);
+ SET @audit_revision_id = LAST_INSERT_ID();
+ SET @cascade_transaction = cascade_transaction;
+ END IF;
END $$
DELIMITER ;
-- - modification_type_val: string value indicating the
-- type of the change, i.e. "create", "update" or
-- "delete".
+-- Session variable disable_audit is used to disable
+-- the procedure when wiping the database during
+-- unit tests. This avoids issues with revision_id
+-- being null.
-- ----------------------------------------------------
DROP PROCEDURE IF EXISTS createAuditEntryDHCP6;
DELIMITER $$
IN object_id_val BIGINT(20) UNSIGNED,
IN modification_type_val VARCHAR(32))
BEGIN
- INSERT INTO dhcp6_audit (object_type, object_id, modification_type, revision_id)
- VALUES (object_type_val, object_id_val, \
+ IF @disable_audit IS NULL OR @disable_audit = 0 THEN
+ INSERT INTO dhcp6_audit (object_type, object_id, modification_type, revision_id)
+ VALUES (object_type_val, object_id_val, \
(SELECT id FROM modification WHERE modification_type = modification_type_val), \
@audit_revision_id);
+ END IF;
END $$
DELIMITER ;
-- hand, if the global option is being added, the
-- audit entry for the option must be created because
-- it is the sole object modified in that case.
+-- Session variable disable_audit is used to disable
+-- the procedure when wiping the database during
+-- unit tests. This avoids issues with revision_id
+-- being null.
-- -----------------------------------------------------
DROP PROCEDURE IF EXISTS createAuditRevisionDHCP4;
DELIMITER $$
IN cascade_transaction TINYINT(1))
BEGIN
DECLARE srv_id BIGINT(20);
- SELECT id INTO srv_id FROM dhcp4_server WHERE tag = server_tag;
- INSERT INTO dhcp4_audit_revision (modification_ts, server_id, log_message)
- VALUES (audit_ts, srv_id, audit_log_message);
- SET @audit_revision_id = LAST_INSERT_ID();
- SET @cascade_transaction = cascade_transaction;
+ IF @disable_audit IS NULL OR @disable_audit = 0 THEN
+ SELECT id INTO srv_id FROM dhcp4_server WHERE tag = server_tag;
+ INSERT INTO dhcp4_audit_revision (modification_ts, server_id, log_message)
+ VALUES (audit_ts, srv_id, audit_log_message);
+ SET @audit_revision_id = LAST_INSERT_ID();
+ SET @cascade_transaction = cascade_transaction;
+ END IF;
END $$
DELIMITER ;
-- - modification_type_val: string value indicating the
-- type of the change, i.e. "create", "update" or
-- "delete".
+-- Session variable disable_audit is used to disable
+-- the procedure when wiping the database during
+-- unit tests. This avoids issues with revision_id
+-- being null.
-- ----------------------------------------------------
DROP PROCEDURE IF EXISTS createAuditEntryDHCP4;
DELIMITER $$
IN object_id_val BIGINT(20) UNSIGNED,
IN modification_type_val VARCHAR(32))
BEGIN
- INSERT INTO dhcp4_audit (object_type, object_id, modification_type, revision_id)
- VALUES (object_type_val, object_id_val, \
- (SELECT id FROM modification WHERE modification_type = modification_type_val), \
- @audit_revision_id);
+ IF @disable_audit IS NULL OR @disable_audit = 0 THEN
+ INSERT INTO dhcp4_audit (object_type, object_id, modification_type, revision_id)
+ VALUES (object_type_val, object_id_val, \
+ (SELECT id FROM modification WHERE modification_type = modification_type_val), \
+ @audit_revision_id);
+ END IF;
END $$
DELIMITER ;
-- hand, if the global option is being added, the
-- audit entry for the option must be created because
-- it is the sole object modified in that case.
+-- Session variable disable_audit is used to disable
+-- the procedure when wiping the database during
+-- unit tests. This avoids issues with revision_id
+-- being null.
-- -----------------------------------------------------
DROP PROCEDURE IF EXISTS createAuditRevisionDHCP6;
DELIMITER $$
IN cascade_transaction TINYINT(1))
BEGIN
DECLARE srv_id BIGINT(20);
- SELECT id INTO srv_id FROM dhcp6_server WHERE tag = server_tag;
- INSERT INTO dhcp6_audit_revision (modification_ts, server_id, log_message)
- VALUES (audit_ts, srv_id, audit_log_message);
- SET @audit_revision_id = LAST_INSERT_ID();
- SET @cascade_transaction = cascade_transaction;
+ IF @disable_audit IS NULL OR @disable_audit = 0 THEN
+ SELECT id INTO srv_id FROM dhcp6_server WHERE tag = server_tag;
+ INSERT INTO dhcp6_audit_revision (modification_ts, server_id, log_message)
+ VALUES (audit_ts, srv_id, audit_log_message);
+ SET @audit_revision_id = LAST_INSERT_ID();
+ SET @cascade_transaction = cascade_transaction;
+ END IF;
END $$
DELIMITER ;
-- - modification_type_val: string value indicating the
-- type of the change, i.e. "create", "update" or
-- "delete".
+-- Session variable disable_audit is used to disable
+-- the procedure when wiping the database during
+-- unit tests. This avoids issues with revision_id
+-- being null.
-- ----------------------------------------------------
DROP PROCEDURE IF EXISTS createAuditEntryDHCP6;
DELIMITER $$
IN object_id_val BIGINT(20) UNSIGNED,
IN modification_type_val VARCHAR(32))
BEGIN
- INSERT INTO dhcp6_audit (object_type, object_id, modification_type, revision_id)
- VALUES (object_type_val, object_id_val, \
+ IF @disable_audit IS NULL OR @disable_audit = 0 THEN
+ INSERT INTO dhcp6_audit (object_type, object_id, modification_type, revision_id)
+ VALUES (object_type_val, object_id_val, \
(SELECT id FROM modification WHERE modification_type = modification_type_val), \
@audit_revision_id);
+ END IF;
END $$
DELIMITER ;
--- /dev/null
+# Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#!/bin/sh
+
+# This script is primarily used for MySQL unit tests, which need to
+# ensure an empty, but schema correct database for each test. It
+# deletes ALL transient data from an existing Kea MySQL schema,
+# including leases, reservations, etc... Use at your own peril.
+# Reference tables will be left in-tact.
+
+# Include utilities. Use installed version if available and
+# use build version if it isn't.
+if [ -e @datarootdir@/@PACKAGE_NAME@/scripts/admin-utils.sh ]; then
+ . @datarootdir@/@PACKAGE_NAME@/scripts/admin-utils.sh
+else
+ . @abs_top_builddir@/src/bin/admin/admin-utils.sh
+fi
+
+# First argument is must be the expected schema version <major>.<minor>
+exp_version="$1"
+shift;
+
+# Remaining arguments are used as mysql command line arguments
+
+# If the existing schema doesn't match, the fail
+VERSION=`mysql_version "$@"`
+if [ "$VERSION" != "$exp_version" ]; then
+ printf "Reported version is $VERSION is wrong, expected $exp_version.\n"
+ exit 1
+fi
+
+# Delete transient data from tables. Per MySQL documentation TRUNCATE
+# destroys and there recreates tables. As schema updates are typically
+# very slow, we're use deletes here. We turn off foreign key checks to
+# worrying about table order. We also set the session variable
+# disable_audit to turn off Back audit procedures, to avoid attempting
+# to create entries for deleted records.
+mysql "$@" <<EOF
+START TRANSACTION;
+SET SESSION FOREIGN_KEY_CHECKS = 0;
+SET @disable_audit = 1;
+
+DELETE FROM dhcp4_global_parameter;
+DELETE FROM dhcp4_global_parameter_server;
+DELETE FROM dhcp4_option_def;
+DELETE FROM dhcp4_option_def_server;
+DELETE FROM dhcp4_options;
+DELETE FROM dhcp4_options_server;
+DELETE FROM dhcp4_pool;
+# preserve special server "all"
+DELETE FROM dhcp4_server WHERE tag != "all";
+DELETE FROM dhcp4_shared_network;
+DELETE FROM dhcp4_shared_network_server;
+DELETE FROM dhcp4_subnet;
+DELETE FROM dhcp4_subnet_server;
+DELETE FROM dhcp4_audit_revision;
+DELETE FROM dhcp4_audit;
+DELETE FROM dhcp6_global_parameter;
+DELETE FROM dhcp6_global_parameter_server;
+DELETE FROM dhcp6_option_def;
+DELETE FROM dhcp6_option_def_server;
+DELETE FROM dhcp6_options;
+DELETE FROM dhcp6_options_server;
+DELETE FROM dhcp6_pd_pool;
+DELETE FROM dhcp6_pool;
+# preserve special server "all"
+DELETE FROM dhcp6_server WHERE tag != "all";
+DELETE FROM dhcp6_shared_network;
+DELETE FROM dhcp6_shared_network_server;
+DELETE FROM dhcp6_subnet;
+DELETE FROM dhcp6_subnet_server;
+DELETE FROM dhcp6_audit;
+DELETE FROM dhcp6_audit_revision;
+DELETE FROM hosts;
+DELETE FROM ipv6_reservations;
+DELETE FROM lease4;
+DELETE FROM lease4_stat;
+DELETE FROM lease6;
+DELETE FROM lease6_stat;
+DELETE FROM logs;
+COMMIT;
+EOF
+
+RESULT=$?
+
+exit $RESULT