From: Andrei Pavel Date: Wed, 14 Dec 2016 13:54:32 +0000 (+0200) Subject: Cassandra update X-Git-Tag: trac5425a_base~11^2~1^2~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8c71bbbc9d083a098dd86d61bc3259bd33556a57;p=thirdparty%2Fkea.git Cassandra update Replaced unrecommended backticks with $() in cql_version() in bash scripts. *_execute() and *_execute_script() functions from src/bin/admin/admin-utils.sh now pass the parameters to the underlying backend binary whenever they are given rather than when there are 2 or more. Corrected cql_version() return error in src/bin/admin/admin-utils.sh. Removed redundant "USE" from cql_init() in src/bin/admin/kea-admin.in. Inserted a newline in src/bin/admin/tests/Makefile.am to separate unrelated targets. Style changes in cql_*_test() functions in src/bin/admin/tests/cql_tests.sh.in. src/bin/admin/tests/dhcpdb_create_1.0.cql: "perfromance" typo Added comment headers Added index on expire since it is used in WHERE clauses (further performance testing may be required) Removed dhcp4_options and dhcp6_options table since they are not required for Cassandra Added DROP INDEX in src/share/database/scripts/cql/dhcpdb_drop.cql. Added sql_common.h Added cql_exchange.h and cql_exchange.cc which mediate communication with Cassandra. Added cql_lease_mgr.h and cql_lease_mgr.cc Parameterized reconnect-wait-time, connect-timeout, request-timeout, tcp-keepalive, tcp-nodelay for Cassandra in kea.conf. Changes are in src/lib/dhcpsrv/cql_connection.cc and src/lib/dhcpsrv/parsers/dbaccess_parser.cc. Reformated x != NULL into !x as specified in the Kea style guidelines src/lib/dhcpsrv/cql_connection.cc: Added range check for port Added CqlConnection:setConsistency Added CqlConnection::startTransaction which is a noop Added CqlTransaction method implementations. Corrected ending brace of namespace declaration, it doesn't need semicolon. src/lib/dhcpsrv/cql_connection.h: Added explicit on CqlConnection constructor. Unlikely that this class will ever be derived, but it's good practice. Changed some comments. Added CqlTransaction class definition. src/lib/dhcpsrv/cql_lease_mgr.cc: Formatted the entire code. Changed data types to cass_ types. Added some log messages. Moved structs, enums and typedefs from src/lib/dhcpsrv/lease_mgr.h to src/lib/dhcpsrv/sql_common.h Added some missing tests in src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc --- diff --git a/configure.ac b/configure.ac index 47d6c16359..0dbbe0e05a 100644 --- a/configure.ac +++ b/configure.ac @@ -1666,6 +1666,7 @@ AC_CONFIG_FILES([compatcheck/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 src/share/database/scripts/cql/Makefile + src/share/database/scripts/cql/upgrade_1.0_to_2.0.sh tools/Makefile tools/path_replacer.sh ]) diff --git a/doc/guide/admin.xml b/doc/guide/admin.xml index f2b7c88e9b..f9ee56e2e7 100644 --- a/doc/guide/admin.xml +++ b/doc/guide/admin.xml @@ -172,7 +172,7 @@ Memfile MySQL PostgreSQL - CQL(Cassandra) + CQL (Cassandra) @@ -214,7 +214,7 @@ no yes yes - no + yes @@ -409,6 +409,8 @@ $ kea-admin lease-upgrade mysql -u database-userPostgreSQL + PostgreSQL is able to store leases, host reservations and options + defined on a per host basis. A PostgreSQL database must be set up if you want Kea to store lease and other information in PostgreSQL. This step can be safely ignored if you are using other database backends. @@ -590,7 +592,7 @@ $ kea-admin lease-upgrade pgsql -u database-user Cassandra, or Cassandra Query Language (CQL), is the newest backend added to Kea. Since it was added recently and has not undergone as much - testing as other backends, it is considered experimental: please use + testing as other backends, it is considered experimental. Please use with caution. The Casandra backend is currently able to store leases, host reservations and options defined on a per host basis. diff --git a/doc/guide/dhcp4-srv.xml b/doc/guide/dhcp4-srv.xml index b59f58c2d4..c7da52d69f 100644 --- a/doc/guide/dhcp4-srv.xml +++ b/doc/guide/dhcp4-srv.xml @@ -477,8 +477,7 @@ If a timeout is given though, it should be an integer greater than zero. purpose, be it lease or hosts information. This arrangement gives the most flexibility. Kea can be used to keep leases and host reservations separately, but can also point to the same database. Currently the - supported hosts database types are MySQL and PostgreSQL. The Cassandra - backend does not support host reservations yet. + supported hosts database types are MySQL, PostgreSQL and CQL (Cassandra). Please note that usage of hosts storage is optional. A user can define all host reservations in the configuration file. That is the recommended way @@ -2977,9 +2976,9 @@ It is merely echoed by the server Storing Host Reservations in MySQL, PostgreSQL or CQL (Cassandra) - It is possible to store host reservations in MySQL or PostgreSQL database. See + It is possible to store host reservations in MySQL, PostgreSQL or Cassandra. See for information on how to configure Kea to use - reservations stored in MySQL or PostgreSQL. Kea does not provide any dedicated + reservations stored in MySQL, PostgreSQL or Cassandra. Kea does not provide any dedicated tools for managing reservations in a database. The Kea wiki provides detailed information and examples of how reservations can be inserted into the diff --git a/doc/guide/dhcp6-srv.xml b/doc/guide/dhcp6-srv.xml index 9c7ca469ce..2a2490da95 100644 --- a/doc/guide/dhcp6-srv.xml +++ b/doc/guide/dhcp6-srv.xml @@ -1156,7 +1156,7 @@ temporarily override a list of interface names and listen on all interfaces. s46-br90ipv6-addressfalse s46-dmr91ipv6-prefixfalse s46-v4v6bind92record (ipv4-address, ipv6-prefix)false -s46-portparams93record(uint8, psid)false +s46-portparams93record (uint8, psid)false s46-cont-mape94emptyfalse s46-cont-mapt95emptyfalse s46-cont-lw96emptyfalse @@ -2908,13 +2908,13 @@ should include options from the isc option space: with classification using expressions. -
- Storing Host Reservations in MySQL or PostgreSQL +
+ Storing Host Reservations in MySQL, PostgreSQL or CQL (Cassandra) - It is possible to store host reservations in MySQL or PostgreSQL. See for information on how to configure Kea to use - reservations stored in MySQL or PostgreSQL. Kea does not provide any dedicated + It is possible to store host reservations in MySQL, PostgreSQL or Cassandra. See + for information on how to configure Kea to use + reservations stored in MySQL, PostgreSQL or Cassandra. Kea does not provide any dedicated tools for managing reservations in a database. The Kea wiki provides detailed information and examples of how reservations can be inserted into the @@ -2925,12 +2925,6 @@ should include options from the isc option space: arbitrarily set to 4096 bytes.
-
- Storing Host Reservations in CQL (Cassandra) - Kea currently does not support storing reservations in - Cassandra (CQL). -
-
Fine Tuning DHCPv6 Host Reservation diff --git a/src/bin/admin/tests/dhcpdb_create_1.0.cql b/src/bin/admin/tests/dhcpdb_create_1.0.cql index 2d6c45a93a..85f9089eff 100644 --- a/src/bin/admin/tests/dhcpdb_create_1.0.cql +++ b/src/bin/admin/tests/dhcpdb_create_1.0.cql @@ -175,9 +175,8 @@ INSERT INTO lease_state (state, name) VALUES (2, 'expired-reclaimed'); -- This table is only modified during schema upgrades. For historical reasons -- (related to the names of the columns in the BIND 10 DNS database file), the -- first column is called "version" and not "major". --- Note: This MUST be kept synchronized with --- src/share/database/scripts/cql/dhcpdb_create.cql which defines the schema for --- the unit tests. +-- Note: This MUST be kept in step with src/share/database/scripts/cassandra/dhcpdb_create.cql, +-- which defines the schema for the unit tests. -- ----------------------------------------------------- -- Table `schema_version` -- ----------------------------------------------------- diff --git a/src/lib/dhcpsrv/cql_connection.h b/src/lib/dhcpsrv/cql_connection.h index 9adcbc9c90..aa6e5a411d 100644 --- a/src/lib/dhcpsrv/cql_connection.h +++ b/src/lib/dhcpsrv/cql_connection.h @@ -48,7 +48,7 @@ struct CqlTaggedStatement { const uint32_t CQL_DRIVER_VERSION_MAJOR = CASS_VERSION_MAJOR; const uint32_t CQL_DRIVER_VERSION_MINOR = CASS_VERSION_MINOR; -/// Define CQL schema version: 1.0 +/// Define CQL schema version: 2.0 const uint32_t CQL_SCHEMA_VERSION_MAJOR = 2; const uint32_t CQL_SCHEMA_VERSION_MINOR = 0; diff --git a/src/lib/dhcpsrv/cql_exchange.h b/src/lib/dhcpsrv/cql_exchange.h index 191dc5fcac..2d2e5e4b1c 100644 --- a/src/lib/dhcpsrv/cql_exchange.h +++ b/src/lib/dhcpsrv/cql_exchange.h @@ -39,7 +39,7 @@ typedef CassError (*CqlBindFunction)(CassStatement* statement, /// SELECT statements. typedef CassError (*CqlGetFunction)(const CassValue* value, void* data); -/// @brief Pair containing major and minor versions. +/// @brief Pair containing major and minor versions typedef std::pair VersionPair; /// @brief Wrapper over the bind and get functions that interface with Cassandra diff --git a/src/lib/dhcpsrv/cql_host_data_source.cc b/src/lib/dhcpsrv/cql_host_data_source.cc index e6b86c5abf..0b9352a53c 100644 --- a/src/lib/dhcpsrv/cql_host_data_source.cc +++ b/src/lib/dhcpsrv/cql_host_data_source.cc @@ -54,7 +54,7 @@ typedef std::vector CassHostIdentifier; /// @brief Host identifier converted to Cassandra data type typedef std::vector CassOptionBuffer; -/// @brief key for @ref HostMap containing objects which uniquely identify a +/// @brief key for HostMap containing objects which uniquely identify a /// host: host identifier, host identifier type, subnets for IPv4 and IPv6 typedef boost::tuplesetHostId(id); + host->setHostId(id); - const IPv6Resrv reservation = retrieveReservation(); - if (reservation != NULL_IPV6_RESERVATION && - !host->hasReservation(reservation)) { - host->addReservation(reservation); - } + const IPv6Resrv reservation = retrieveReservation(); + if (reservation != NULL_IPV6_RESERVATION && + !host->hasReservation(reservation)) { + host->addReservation(reservation); + } - OptionDescriptorPtr option_descriptor_ptr = retrieveOption(); - if (option_descriptor_ptr) { - if (option_descriptor_ptr->option_->getUniverse() == Option::V4) { - host->getCfgOption4()->add(*option_descriptor_ptr, option_space_); - } else if (option_descriptor_ptr->option_->getUniverse() == - Option::V6) { - host->getCfgOption6()->add(*option_descriptor_ptr, option_space_); - } + OptionDescriptorPtr option_descriptor_ptr = retrieveOption(); + if (option_descriptor_ptr) { + if (option_descriptor_ptr->option_->getUniverse() == Option::V4) { + host->getCfgOption4()->add(*option_descriptor_ptr, option_space_); + } else if (option_descriptor_ptr->option_->getUniverse() == + Option::V6) { + host->getCfgOption6()->add(*option_descriptor_ptr, option_space_); } - } catch (const std::exception& exception) { - LOG_ERROR(dhcpsrv_logger, DHCPSRV_CQL_HOST_RETRIEVE_ERROR) - .arg(exception.what()); - throw; } return reinterpret_cast(host); @@ -1291,7 +1285,7 @@ protected: /// @param option_space option space for the current denormalized table /// entry's option /// @param option_descriptor option descriptor containing information for - /// the current denormalized table entry's option + /// the current denormalized table entry's option virtual void insertHost( const HostPtr& host, const OptionalValue& subnet_id = OptionalValue(), @@ -1320,7 +1314,7 @@ private: }; // class CqlHostDataSourceImpl -/// @brief hash function for @ref HostMap +/// @brief hash function for HostMap /// /// @param key being hashed /// @@ -1344,7 +1338,7 @@ hash_value(const HostKey& key) { return static_cast(md5); } -/// @brief equals operator for @ref HostKey +/// @brief equals operator for HostKey /// /// @param key1 left hand side operand /// @param key2 right hand side operand @@ -1374,6 +1368,9 @@ CqlHostDataSourceImpl::~CqlHostDataSourceImpl() { void CqlHostDataSourceImpl::add(const HostPtr& host) { + // Start transaction. + CqlTransaction transaction(dbconn_); + // Get option space names and vendor space names and combine them within a // single list. // For IPv4: @@ -1407,6 +1404,7 @@ CqlHostDataSourceImpl::add(const HostPtr& host) { insertHostWithReservations(host, NULL, option_spaces4, cfg_option4, option_spaces6, cfg_option6); } + transaction.commit(); } ConstHostPtr diff --git a/src/lib/dhcpsrv/cql_lease_mgr.h b/src/lib/dhcpsrv/cql_lease_mgr.h index 8fcf5c8d96..bd5c4b9743 100644 --- a/src/lib/dhcpsrv/cql_lease_mgr.h +++ b/src/lib/dhcpsrv/cql_lease_mgr.h @@ -590,11 +590,11 @@ private: /// declare them as "mutable".) /// @brief Exchange object for IPv4 boost::scoped_ptr exchange4_; - /// @brief Exchange object for IPv4 + /// @brief Exchange object for IPv6 boost::scoped_ptr exchange6_; /// @brief Exchange object for version boost::scoped_ptr versionExchange_; - //// @} + /// @} }; } // namespace dhcp diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes index ca5f9c7eb2..32d3d43d6c 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.mes +++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes @@ -172,6 +172,9 @@ with the specified address to the Cassandra backend database. A debug message issued when the server is about to add an IPv6 lease with the specified address to the Cassandra backend database. +% DHCPSRV_CQL_BEGIN_TRANSACTION committing to Cassandra database. +The server has issued a begin transaction call. + % DHCPSRV_CQL_COMMIT committing to Cassandra database A commit call been issued on the server. For Cassandra, this is a no-op. @@ -261,10 +264,6 @@ subnet ID and hardware address. A debug message issued when the server is about to obtain schema version information from the Cassandra database. -% DHCPSRV_CQL_HOST_RETRIEVE_ERROR Unable to retrieve host reservation or option: %1 -A host couldn't be fully retrieved. An exception was thrown, but the server -should continue running. - % DHCPSRV_CQL_ROLLBACK rolling back Cassandra database The code has issued a rollback call. For Cassandra, this is a no-op. diff --git a/src/lib/dhcpsrv/parsers/dbaccess_parser.cc b/src/lib/dhcpsrv/parsers/dbaccess_parser.cc index 329d0c50e5..2056b94b83 100644 --- a/src/lib/dhcpsrv/parsers/dbaccess_parser.cc +++ b/src/lib/dhcpsrv/parsers/dbaccess_parser.cc @@ -82,6 +82,7 @@ DbAccessParser::build(isc::data::ConstElementPtr config_value) { timeout = param.second->intValue(); values_copy[param.first] = boost::lexical_cast(timeout); + } else { values_copy[param.first] = param.second->stringValue(); } diff --git a/src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc index fa2edfa3a8..a556b9959b 100644 --- a/src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc @@ -18,11 +18,11 @@ #include #include -#include #include #include -#include +#include #include +#include #include #include @@ -53,7 +53,6 @@ public: /// /// Deletes everything from the database and opens it. CqlLeaseMgrTest() { - // Ensure schema is the correct one. destroyCqlSchema(false, true); createCqlSchema(false, true); @@ -95,13 +94,13 @@ public: lmptr_ = &(LeaseMgrFactory::instance()); } - // This is the CQL implementation for GenericLeaseMgrTest::testGetExpiredLeases4(). + // This is the CQL implementation for + // GenericLeaseMgrTest::testGetExpiredLeases4(). // The GenericLeaseMgrTest implementation checks for the order of expired // leases to be from the most expired to the least expired. Cassandra // doesn't support ORDER BY without imposing a EQ / IN restriction on the // columns. Because of that, the order check has been excluded. - void - testCqlGetExpiredLeases4() { + void testCqlGetExpiredLeases4() { // Get the leases to be used for the test. vector leases = createLeases4(); // Make sure we have at least 6 leases there. @@ -118,10 +117,12 @@ public: // valid lifetime to make it expired. The expiration time also // depends on the lease index, so as we can later check that the // leases are ordered by the expiration time. - leases[i]->cltt_ = current_time - leases[i]->valid_lft_ - 10 - i; + leases[i]->cltt_ = + current_time - leases[i]->valid_lft_ - 10 - i; } else { - // Set current time as cltt for remaining leases. These leases are + // Set current time as cltt for remaining leases. These leases + // are // not expired. leases[i]->cltt_ = current_time; } @@ -132,19 +133,22 @@ public: Lease4Collection expired_leases; ASSERT_NO_THROW(lmptr_->getExpiredLeases4(expired_leases, 1000)); // Leases with even indexes should be returned as expired. - ASSERT_EQ(static_cast(leases.size() / 2U), expired_leases.size()); + ASSERT_EQ(static_cast(leases.size() / 2U), + expired_leases.size()); // Update current time for the next test. current_time = time(NULL); // Also, remove expired leases collected during the previous test. expired_leases.clear(); - // This time let's reverse the expiration time and see if they will be returned + // This time let's reverse the expiration time and see if they will be + // returned // in the correct order. for (size_t i = 0U; i < leases.size(); ++i) { // Update the time of expired leases with even indexes. if (i % 2U == 0U) { - leases[i]->cltt_ = current_time - leases[i]->valid_lft_ - 1000 + i; + leases[i]->cltt_ = + current_time - leases[i]->valid_lft_ - 1000 + i; } else { // Make sure remaining leases remain unexpired. leases[i]->cltt_ = current_time + 100; @@ -152,11 +156,13 @@ public: ASSERT_NO_THROW(lmptr_->updateLease4(leases[i])); } - // Retrieve expired leases again. The limit of 0 means return all expired + // Retrieve expired leases again. The limit of 0 means return all + // expired // leases. ASSERT_NO_THROW(lmptr_->getExpiredLeases4(expired_leases, 0)); // The same leases should be returned. - ASSERT_EQ(static_cast(leases.size() / 2U), expired_leases.size()); + ASSERT_EQ(static_cast(leases.size() / 2U), + expired_leases.size()); // Remember expired leases returned. std::vector saved_expired_leases = expired_leases; @@ -173,7 +179,8 @@ public: // Mark every other expired lease as reclaimed. for (size_t i = 0U; i < saved_expired_leases.size(); ++i) { if (i % 2U != 0U) { - saved_expired_leases[i]->state_ = Lease::STATE_EXPIRED_RECLAIMED; + saved_expired_leases[i]->state_ = + Lease::STATE_EXPIRED_RECLAIMED; } ASSERT_NO_THROW(lmptr_->updateLease4(saved_expired_leases[i])); } @@ -190,18 +197,19 @@ public: // those that have even index. for (Lease4Collection::iterator lease = expired_leases.begin(); lease != expired_leases.end(); ++lease) { - int index = static_cast(std::distance(expired_leases.begin(), lease)); + int index = + static_cast(std::distance(expired_leases.begin(), lease)); EXPECT_EQ(saved_expired_leases[2 * index]->addr_, (*lease)->addr_); } } - // This is the CQL implementation for GenericLeaseMgrTest::testGetExpiredLeases4(). + // This is the CQL implementation for + // GenericLeaseMgrTest::testGetExpiredLeases4(). // The GenericLeaseMgrTest implementation checks for the order of expired // leases to be from the most expired to the least expired. Cassandra // doesn't support ORDER BY without imposing a EQ / IN restriction on the // columns. Because of that, the order check has been excluded. - void - testCqlGetExpiredLeases6() { + void testCqlGetExpiredLeases6() { // Get the leases to be used for the test. vector leases = createLeases6(); // Make sure we have at least 6 leases there. @@ -218,10 +226,12 @@ public: // valid lifetime to make it expired. The expiration time also // depends on the lease index, so as we can later check that the // leases are ordered by the expiration time. - leases[i]->cltt_ = current_time - leases[i]->valid_lft_ - 10 - i; + leases[i]->cltt_ = + current_time - leases[i]->valid_lft_ - 10 - i; } else { - // Set current time as cltt for remaining leases. These leases are + // Set current time as cltt for remaining leases. These leases + // are // not expired. leases[i]->cltt_ = current_time; } @@ -232,19 +242,22 @@ public: Lease6Collection expired_leases; ASSERT_NO_THROW(lmptr_->getExpiredLeases6(expired_leases, 1000)); // Leases with even indexes should be returned as expired. - ASSERT_EQ(static_cast(leases.size() / 2U), expired_leases.size()); + ASSERT_EQ(static_cast(leases.size() / 2U), + expired_leases.size()); // Update current time for the next test. current_time = time(NULL); // Also, remove expired leases collected during the previous test. expired_leases.clear(); - // This time let's reverse the expiration time and see if they will be returned + // This time let's reverse the expiration time and see if they will be + // returned // in the correct order. for (size_t i = 0U; i < leases.size(); ++i) { // Update the time of expired leases with even indexes. if (i % 2U == 0U) { - leases[i]->cltt_ = current_time - leases[i]->valid_lft_ - 1000 + i; + leases[i]->cltt_ = + current_time - leases[i]->valid_lft_ - 1000 + i; } else { // Make sure remaining leases remain unexpired. @@ -253,11 +266,13 @@ public: ASSERT_NO_THROW(lmptr_->updateLease6(leases[i])); } - // Retrieve expired leases again. The limit of 0 means return all expired + // Retrieve expired leases again. The limit of 0 means return all + // expired // leases. ASSERT_NO_THROW(lmptr_->getExpiredLeases6(expired_leases, 0)); // The same leases should be returned. - ASSERT_EQ(static_cast(leases.size() / 2U), expired_leases.size()); + ASSERT_EQ(static_cast(leases.size() / 2U), + expired_leases.size()); // Remember expired leases returned. std::vector saved_expired_leases = expired_leases; @@ -274,7 +289,8 @@ public: // Mark every other expired lease as reclaimed. for (size_t i = 0U; i < saved_expired_leases.size(); ++i) { if (i % 2U != 0U) { - saved_expired_leases[i]->state_ = Lease::STATE_EXPIRED_RECLAIMED; + saved_expired_leases[i]->state_ = + Lease::STATE_EXPIRED_RECLAIMED; } ASSERT_NO_THROW(lmptr_->updateLease6(saved_expired_leases[i])); } @@ -289,7 +305,8 @@ public: // those that have even index. for (Lease6Collection::iterator lease = expired_leases.begin(); lease != expired_leases.end(); ++lease) { - int index = static_cast(std::distance(expired_leases.begin(), lease)); + int index = + static_cast(std::distance(expired_leases.begin(), lease)); EXPECT_EQ(saved_expired_leases[2 * index]->addr_, (*lease)->addr_); } } @@ -304,7 +321,6 @@ public: /// Unlike other backend implementations, this one doesn't check for lacking /// parameters. In that scenario, Cassandra defaults to configured parameters. TEST(CqlOpenTest, OpenDatabase) { - // Schema needs to be created for the test to work. destroyCqlSchema(false, true); createCqlSchema(false, true); @@ -313,7 +329,7 @@ TEST(CqlOpenTest, OpenDatabase) { // If it fails, print the error message. try { LeaseMgrFactory::create(validCqlConnectionString()); - EXPECT_NO_THROW((void) LeaseMgrFactory::instance()); + EXPECT_NO_THROW((void)LeaseMgrFactory::instance()); LeaseMgrFactory::destroy(); } catch (const isc::Exception& ex) { FAIL() << "*** ERROR: unable to open database, reason:\n" @@ -325,10 +341,11 @@ TEST(CqlOpenTest, OpenDatabase) { // Check that lease manager open the database opens correctly with a longer // timeout. If it fails, print the error message. try { - string connection_string = validCqlConnectionString() + string(" ") + - string(VALID_TIMEOUT); + std::string connection_string = validCqlConnectionString() + + std::string(" ") + + std::string(VALID_TIMEOUT); LeaseMgrFactory::create(connection_string); - EXPECT_NO_THROW((void) LeaseMgrFactory::instance()); + EXPECT_NO_THROW((void)LeaseMgrFactory::instance()); LeaseMgrFactory::destroy(); } catch (const isc::Exception& ex) { FAIL() << "*** ERROR: unable to open database, reason:\n" @@ -344,12 +361,13 @@ TEST(CqlOpenTest, OpenDatabase) { // Check that wrong specification of backend throws an exception. // (This is really a check on LeaseMgrFactory, but is convenient to // perform here.) - EXPECT_THROW(LeaseMgrFactory::create(connectionString( - NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)), + EXPECT_THROW( + LeaseMgrFactory::create(connectionString(NULL, VALID_NAME, VALID_HOST, + INVALID_USER, VALID_PASSWORD)), InvalidParameter); - - EXPECT_THROW(LeaseMgrFactory::create(connectionString( - INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)), + EXPECT_THROW( + LeaseMgrFactory::create(connectionString( + INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)), InvalidType); // Check that invalid login data does not cause an exception, CQL should use @@ -514,7 +532,8 @@ TEST_F(CqlLeaseMgrTest, getLease4ClientIdSubnetId) { /// @brief Basic Lease4 Checks /// -/// Checks that the addLease, getLease4(by address), getLease4(hwaddr, subnet_id), +/// Checks that the addLease, getLease4(by address), getLease4(hwaddr, +/// subnet_id), /// updateLease4() and deleteLease (IPv4 address) can handle NULL client-id. /// (client-id is optional and may not be present) TEST_F(CqlLeaseMgrTest, lease4NullClientId) { diff --git a/src/lib/dhcpsrv/testutils/cql_schema.cc b/src/lib/dhcpsrv/testutils/cql_schema.cc index b03c8a4814..8a4468e39e 100644 --- a/src/lib/dhcpsrv/testutils/cql_schema.cc +++ b/src/lib/dhcpsrv/testutils/cql_schema.cc @@ -5,15 +5,19 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include -#include + #include + #include #include + +#include + #include #include #include -#include +#include using namespace std; @@ -25,11 +29,12 @@ const char* CQL_VALID_TYPE = "type=cql"; string validCqlConnectionString() { - return (connectionString(CQL_VALID_TYPE, VALID_NAME, VALID_HOST, - VALID_USER, VALID_PASSWORD)); + return (connectionString(CQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, + VALID_PASSWORD)); } -bool softWipeEnabled() { +bool +softWipeEnabled() { const char* const env = getenv("KEA_TEST_CASSANDRA_WIPE"); if (env && (string(env) == string("soft"))) { return (true); @@ -38,26 +43,28 @@ bool softWipeEnabled() { return (false); } -void destroyCqlSchema(bool force_wipe, bool show_err) { +void +destroyCqlSchema(bool force_wipe, bool show_err) { if (force_wipe || !softWipeEnabled()) { // Do full wipe runCqlScript(DATABASE_SCRIPTS_DIR, "cql/dhcpdb_drop.cql", show_err); } else { - // do soft wipe (just remove the data, not the structures) runCqlScript(DATABASE_SCRIPTS_DIR, "cql/soft_wipe.cql", show_err); } } -void createCqlSchema(bool force_wipe, bool show_err) { +void +createCqlSchema(bool force_wipe, bool show_err) { if (force_wipe || !softWipeEnabled()) { - runCqlScript(DATABASE_SCRIPTS_DIR, "cql/dhcpdb_create.cql", - show_err); + runCqlScript(DATABASE_SCRIPTS_DIR, "cql/dhcpdb_create.cql", show_err); } } -void runCqlScript(const std::string& path, const std::string& script_name, - bool show_err) { +void +runCqlScript(const std::string& path, + const std::string& script_name, + bool show_err) { std::ostringstream cmd; cmd << "cqlsh -u keatest -p keatest -k keatest"; if (!show_err) { @@ -76,7 +83,6 @@ void runCqlScript(const std::string& path, const std::string& script_name, ASSERT_EQ(0, retval) << "runCqlSchema failed:" << cmd.str(); } - -}; -}; -}; +} // namespace test +} // namespace dhcp +} // namespace isc diff --git a/src/lib/dhcpsrv/testutils/cql_schema.h b/src/lib/dhcpsrv/testutils/cql_schema.h index 9b92ea1528..91377f96db 100644 --- a/src/lib/dhcpsrv/testutils/cql_schema.h +++ b/src/lib/dhcpsrv/testutils/cql_schema.h @@ -54,7 +54,7 @@ void createCqlSchema(bool force_wipe, bool show_err = false); /// @brief Run a CQL script against the CQL unit test database /// -/// Submits the given SQL script to CQL via cqlsh CLI. The output of +/// Submits the given CQL script to CQL via cqlsh CLI. The output of /// stderr is suppressed unless the parameter, show_err is true. The is done /// to suppress warnings that might otherwise make test output needlessly /// noisy. A gtest assertion occurs if the script fails to execute. diff --git a/src/share/database/scripts/cql/Makefile.am b/src/share/database/scripts/cql/Makefile.am index 8a32f195b1..369b371b53 100644 --- a/src/share/database/scripts/cql/Makefile.am +++ b/src/share/database/scripts/cql/Makefile.am @@ -3,6 +3,7 @@ SUBDIRS = . sqlscriptsdir = ${datarootdir}/${PACKAGE_NAME}/scripts/cql sqlscripts_DATA = dhcpdb_create.cql sqlscripts_DATA += dhcpdb_drop.cql +sqlscripts_DATA += upgrade_1.0_to_2.0.sh EXTRA_DIST = ${sqlscripts_DATA} diff --git a/src/share/database/scripts/cql/dhcpdb_create.cql b/src/share/database/scripts/cql/dhcpdb_create.cql index 3d46022eac..1a1d35bed1 100644 --- a/src/share/database/scripts/cql/dhcpdb_create.cql +++ b/src/share/database/scripts/cql/dhcpdb_create.cql @@ -44,7 +44,7 @@ -- ----------------------------------------------------- -- Table `lease4` -- ----------------------------------------------------- -CREATE TABLE lease4 ( +CREATE TABLE IF NOT EXISTS lease4 ( address int, hwaddr blob, client_id blob, @@ -59,11 +59,11 @@ CREATE TABLE lease4 ( ); -- Create search indexes for lease4 table -CREATE INDEX lease4index1 ON lease4 (client_id); -CREATE INDEX lease4index2 ON lease4 (subnet_id); -CREATE INDEX lease4index3 ON lease4 (hwaddr); -CREATE INDEX lease4index4 ON lease4 (expire); -CREATE INDEX lease4index5 ON lease4 (state); +CREATE INDEX IF NOT EXISTS lease4index1 ON lease4 (client_id); +CREATE INDEX IF NOT EXISTS lease4index2 ON lease4 (subnet_id); +CREATE INDEX IF NOT EXISTS lease4index3 ON lease4 (hwaddr); +CREATE INDEX IF NOT EXISTS lease4index4 ON lease4 (expire); +CREATE INDEX IF NOT EXISTS lease4index5 ON lease4 (state); -- Holds the IPv6 leases. -- N.B. The use of a VARCHAR for the address is temporary for development: @@ -71,7 +71,7 @@ CREATE INDEX lease4index5 ON lease4 (state); -- ----------------------------------------------------- -- Table `lease6` -- ----------------------------------------------------- -CREATE TABLE lease6 ( +CREATE TABLE IF NOT EXISTS lease6 ( address varchar, duid blob, valid_lifetime bigint, @@ -92,12 +92,12 @@ CREATE TABLE lease6 ( ); -- Create search indexes for lease6 table -CREATE INDEX lease6index1 ON lease6 (lease_type); -CREATE INDEX lease6index2 ON lease6 (duid); -CREATE INDEX lease6index3 ON lease6 (iaid); -CREATE INDEX lease6index4 ON lease6 (subnet_id); -CREATE INDEX lease6index5 ON lease6 (expire); -CREATE INDEX lease6index6 ON lease6 (state); +CREATE INDEX IF NOT EXISTS lease6index1 ON lease6 (lease_type); +CREATE INDEX IF NOT EXISTS lease6index2 ON lease6 (duid); +CREATE INDEX IF NOT EXISTS lease6index3 ON lease6 (iaid); +CREATE INDEX IF NOT EXISTS lease6index4 ON lease6 (subnet_id); +CREATE INDEX IF NOT EXISTS lease6index5 ON lease6 (expire); +CREATE INDEX IF NOT EXISTS lease6index6 ON lease6 (state); -- ... and a definition of lease6 types. This table is a convenience for -- users of the database - if they want to view the lease table and use the @@ -107,7 +107,7 @@ CREATE INDEX lease6index6 ON lease6 (state); -- ----------------------------------------------------- -- Table `lease6_types` -- ----------------------------------------------------- -CREATE TABLE lease6_types ( +CREATE TABLE IF NOT EXISTS lease6_types ( lease_type int, -- Lease type code. name varchar, -- Name of the lease type PRIMARY KEY (lease_type) @@ -125,7 +125,7 @@ INSERT INTO lease6_types (lease_type, name) VALUES (2, 'IA_PD'); -- Prefix del -- ----------------------------------------------------- -- Table `lease_hwaddr_source` -- ----------------------------------------------------- -CREATE TABLE lease_hwaddr_source ( +CREATE TABLE IF NOT EXISTS lease_hwaddr_source ( hwaddr_source int, name varchar, PRIMARY KEY (hwaddr_source) @@ -158,7 +158,7 @@ INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (64, 'HWADDR_SOURCE -- ----------------------------------------------------- -- Table `lease_state` -- ----------------------------------------------------- -CREATE TABLE lease_state ( +CREATE TABLE IF NOT EXISTS lease_state ( state int, name varchar, PRIMARY KEY (state) @@ -176,7 +176,7 @@ INSERT INTO lease_state (state, name) VALUES (2, 'expired-reclaimed'); -- ----------------------------------------------------- -- Table `schema_version` -- ----------------------------------------------------- -CREATE TABLE schema_version ( +CREATE TABLE IF NOT EXISTS schema_version ( version int, minor int, PRIMARY KEY (version) @@ -191,7 +191,7 @@ INSERT INTO schema_version (version, minor) VALUES (1, 0); -- ----------------------------------------------------- -- Table `host_reservations` -- ----------------------------------------------------- -CREATE TABLE host_reservations ( +CREATE TABLE IF NOT EXISTS host_reservations ( id bigint, host_identifier blob, host_identifier_type int, @@ -215,13 +215,13 @@ CREATE TABLE host_reservations ( option_subnet_id int, PRIMARY KEY (id) ); -CREATE INDEX host_reservationsindex1 ON host_reservations (host_identifier); -CREATE INDEX host_reservationsindex2 ON host_reservations (host_identifier_type); -CREATE INDEX host_reservationsindex3 ON host_reservations (host_ipv4_subnet_id); -CREATE INDEX host_reservationsindex4 ON host_reservations (host_ipv6_subnet_id); -CREATE INDEX host_reservationsindex5 ON host_reservations (host_ipv4_address); -CREATE INDEX host_reservationsindex6 ON host_reservations (reserved_ipv6_prefix_address); -CREATE INDEX host_reservationsindex7 ON host_reservations (reserved_ipv6_prefix_length); +CREATE INDEX IF NOT EXISTS host_reservationsindex1 ON host_reservations (host_identifier); +CREATE INDEX IF NOT EXISTS host_reservationsindex2 ON host_reservations (host_identifier_type); +CREATE INDEX IF NOT EXISTS host_reservationsindex3 ON host_reservations (host_ipv4_subnet_id); +CREATE INDEX IF NOT EXISTS host_reservationsindex4 ON host_reservations (host_ipv6_subnet_id); +CREATE INDEX IF NOT EXISTS host_reservationsindex5 ON host_reservations (host_ipv4_address); +CREATE INDEX IF NOT EXISTS host_reservationsindex6 ON host_reservations (reserved_ipv6_prefix_address); +CREATE INDEX IF NOT EXISTS host_reservationsindex7 ON host_reservations (reserved_ipv6_prefix_length); DELETE FROM schema_version WHERE version=1; INSERT INTO schema_version (version, minor) VALUES(2, 0); diff --git a/src/share/database/scripts/cql/dhcpdb_drop.cql b/src/share/database/scripts/cql/dhcpdb_drop.cql index 4f2fbee46a..7a93e3df17 100644 --- a/src/share/database/scripts/cql/dhcpdb_drop.cql +++ b/src/share/database/scripts/cql/dhcpdb_drop.cql @@ -18,11 +18,8 @@ DROP TABLE IF EXISTS lease4; DROP TABLE IF EXISTS lease6; DROP TABLE IF EXISTS lease6_types; DROP TABLE IF EXISTS lease_hwaddr_source; -DROP TABLE IF EXISTS schema_version; -DROP TABLE IF EXISTS ipv6_reservations; -DROP TABLE IF EXISTS hosts; -DROP TABLE IF EXISTS host_identifier_type; DROP TABLE IF EXISTS lease_state; +DROP TABLE IF EXISTS schema_version; DROP TABLE IF EXISTS host_reservations; DROP INDEX IF EXISTS lease4index1; diff --git a/src/share/database/scripts/cql/soft_wipe.cql b/src/share/database/scripts/cql/soft_wipe.cql index e3dd6c402e..5c9580843c 100644 --- a/src/share/database/scripts/cql/soft_wipe.cql +++ b/src/share/database/scripts/cql/soft_wipe.cql @@ -19,6 +19,8 @@ TRUNCATE TABLE lease4; TRUNCATE TABLE lease6; -TRUNCATE TABLE hosts; -TRUNCATE TABLE dhcp4_options; -TRUNCATE TABLE dhcp6_options; +TRUNCATE TABLE lease6_types; +TRUNCATE TABLE lease_hwaddr_source; +TRUNCATE TABLE lease_state; +TRUNCATE TABLE schema_version; +TRUNCATE TABLE host_reservations; diff --git a/src/share/database/scripts/cql/upgrade_1.0_to_2.0.sh.in b/src/share/database/scripts/cql/upgrade_1.0_to_2.0.sh.in index b08d4f1266..ac30776527 100644 --- a/src/share/database/scripts/cql/upgrade_1.0_to_2.0.sh.in +++ b/src/share/database/scripts/cql/upgrade_1.0_to_2.0.sh.in @@ -9,10 +9,10 @@ else . @abs_top_builddir@/src/bin/admin/admin-utils.sh fi -VERSION=`cql_version "$@"` +version=$(cql_version "$@") -if [ "$VERSION" != "1.0" ]; then - printf "This script upgrades 1.0 to 2.0. Reported version is $VERSION. Skipping upgrade.\n" +if [ "${version}" != "1.0" ]; then + printf "This script upgrades 1.0 to 2.0. Reported version is %s. Skipping upgrade.\n" "${version}" exit 0 fi @@ -20,7 +20,7 @@ cqlsh "$@" <