From: Francis Dupont Date: Thu, 21 Jun 2018 09:15:48 +0000 (+0200) Subject: [5584] Checkpoint: updated schema, code and partially tests X-Git-Tag: trac5685_base~2^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fe5098fdb3d0039a90c5a4e573e21eed9f44d9d2;p=thirdparty%2Fkea.git [5584] Checkpoint: updated schema, code and partially tests --- diff --git a/configure.ac b/configure.ac index 00842da9bc..fa459cb1e8 100644 --- a/configure.ac +++ b/configure.ac @@ -1492,6 +1492,7 @@ AC_CONFIG_FILES([Makefile src/share/database/scripts/Makefile src/share/database/scripts/cql/Makefile src/share/database/scripts/cql/upgrade_1.0_to_2.0.sh + src/share/database/scripts/cql/upgrade_2.0_to_2.1.sh src/share/database/scripts/mysql/Makefile src/share/database/scripts/mysql/upgrade_1.0_to_2.0.sh src/share/database/scripts/mysql/upgrade_2.0_to_3.0.sh @@ -1501,6 +1502,7 @@ AC_CONFIG_FILES([Makefile src/share/database/scripts/mysql/upgrade_5.0_to_5.1.sh src/share/database/scripts/mysql/upgrade_5.1_to_5.2.sh src/share/database/scripts/mysql/upgrade_5.2_to_6.0.sh + src/share/database/scripts/mysql/upgrade_6.0_to_6.1.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 @@ -1508,6 +1510,7 @@ AC_CONFIG_FILES([Makefile src/share/database/scripts/pgsql/upgrade_3.1_to_3.2.sh src/share/database/scripts/pgsql/upgrade_3.2_to_3.3.sh src/share/database/scripts/pgsql/upgrade_3.3_to_4.0.sh + src/share/database/scripts/pgsql/upgrade_4.0_to_4.1.sh tools/Makefile tools/path_replacer.sh ]) diff --git a/src/lib/dhcpsrv/cql_connection.h b/src/lib/dhcpsrv/cql_connection.h index 68ae833618..53375961a5 100644 --- a/src/lib/dhcpsrv/cql_connection.h +++ b/src/lib/dhcpsrv/cql_connection.h @@ -1,3 +1,4 @@ +// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2015-2017 Deutsche Telekom AG. // // Authors: Razvan Becheriu @@ -48,10 +49,10 @@ constexpr uint32_t CQL_DRIVER_VERSION_MAJOR = CASS_VERSION_MAJOR; constexpr uint32_t CQL_DRIVER_VERSION_MINOR = CASS_VERSION_MINOR; /// @} -/// Define CQL schema version: 2.0 +/// Define CQL schema version: 2.1 /// @{ constexpr uint32_t CQL_SCHEMA_VERSION_MAJOR = 2u; -constexpr uint32_t CQL_SCHEMA_VERSION_MINOR = 0u; +constexpr uint32_t CQL_SCHEMA_VERSION_MINOR = 1u; /// @} /// @brief Defines a single statement or query diff --git a/src/lib/dhcpsrv/cql_lease_mgr.cc b/src/lib/dhcpsrv/cql_lease_mgr.cc index a225585ab2..36e867547f 100644 --- a/src/lib/dhcpsrv/cql_lease_mgr.cc +++ b/src/lib/dhcpsrv/cql_lease_mgr.cc @@ -1,3 +1,4 @@ +// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2015-2018 Deutsche Telekom AG. // // Authors: Razvan Becheriu @@ -25,6 +26,7 @@ #include +using namespace isc::data; using isc::asiolink::IOAddress; namespace isc { @@ -32,6 +34,7 @@ namespace dhcp { static constexpr size_t HOSTNAME_MAX_LEN = 255u; static constexpr size_t ADDRESS6_TEXT_MAX_LEN = 39u; +static constexpr char NULL_USER_CONTEXT[] = ""; /// @brief Common CQL and Lease Data Methods /// @@ -47,7 +50,7 @@ public: CqlLeaseExchange(const CqlConnection &connection) : connection_(connection), valid_lifetime_(0), expire_(0), subnet_id_(0), fqdn_fwd_(cass_false), fqdn_rev_(cass_false), - state_(0) { + state_(0), user_context_(NULL_USER_CONTEXT) { } /// @brief Create BIND array to receive C++ data. @@ -96,6 +99,9 @@ protected: /// @brief Lease state cass_int32_t state_; + + /// @brief User context + std::string user_context_; }; /// @brief Exchange Lease4 information between Kea and CQL @@ -249,9 +255,9 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {INSERT_LEASE4, "INSERT INTO lease4( " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " ") VALUES ( " - "?, ?, ?, ?, ?, ?, ?, ?, ?, ? " + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? " ") " "IF NOT EXISTS "}}, @@ -267,7 +273,8 @@ StatementMap CqlLease4Exchange::tagged_statements_{ "fqdn_fwd = ?, " "fqdn_rev = ?, " "hostname = ?, " - "state = ? " + "state = ?, " + "user_context = ? " "WHERE address = ? " "IF EXISTS "}}, @@ -283,7 +290,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {GET_LEASE4_EXPIRE, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " "FROM lease4 " "WHERE state = ? " "AND expire < ? " @@ -295,7 +302,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {GET_LEASE4, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " "FROM lease4 "}}, // Gets an IPv4 lease with specified IPv4 address @@ -303,7 +310,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {GET_LEASE4_ADDR, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " "FROM lease4 " "WHERE address = ? "}}, @@ -312,7 +319,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {GET_LEASE4_CLIENTID, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " "FROM lease4 " "WHERE client_id = ? " "ALLOW FILTERING "}}, @@ -322,7 +329,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {GET_LEASE4_CLIENTID_SUBID, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " "FROM lease4 " "WHERE client_id = ? " "AND subnet_id = ? " @@ -333,7 +340,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {GET_LEASE4_HWADDR, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " "FROM lease4 " "WHERE hwaddr = ? " "ALLOW FILTERING "}}, @@ -343,7 +350,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {GET_LEASE4_HWADDR_SUBID, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " "FROM lease4 " "WHERE hwaddr = ? " "AND subnet_id = ? " @@ -354,7 +361,7 @@ StatementMap CqlLease4Exchange::tagged_statements_{ {GET_LEASE4_SUBID, "SELECT " "address, hwaddr, client_id, valid_lifetime, expire, subnet_id, " - "fqdn_fwd, fqdn_rev, hostname, state " + "fqdn_fwd, fqdn_rev, hostname, state, user_context " "FROM lease4 " "WHERE subnet_id = ? " "ALLOW FILTERING "}} @@ -437,6 +444,14 @@ CqlLease4Exchange::createBindForInsert(const Lease4Ptr &lease, AnyArray &data) { // state: int state_ = static_cast(lease_->state_); + // user_context: text + ConstElementPtr ctx = lease_->getContext(); + if (ctx) { + user_context_ = ctx->str(); + } else { + user_context_ = NULL_USER_CONTEXT; + } + // Start with a fresh array. data.clear(); data.add(&address_); @@ -449,6 +464,7 @@ CqlLease4Exchange::createBindForInsert(const Lease4Ptr &lease, AnyArray &data) { data.add(&fqdn_rev_); data.add(&hostname_); data.add(&state_); + data.add(&user_context_); } catch (const Exception &ex) { isc_throw(DbOperationError, "CqlLease4Exchange::createBindForInsert(): " @@ -531,6 +547,14 @@ CqlLease4Exchange::createBindForUpdate(const Lease4Ptr &lease, AnyArray &data, // state: int state_ = static_cast(lease_->state_); + // user_context: text + ConstElementPtr ctx = lease_->getContext(); + if (ctx) { + user_context_ = ctx->str(); + } else { + user_context_ = NULL_USER_CONTEXT; + } + // Start with a fresh array. data.clear(); data.add(&hwaddr_); @@ -542,6 +566,7 @@ CqlLease4Exchange::createBindForUpdate(const Lease4Ptr &lease, AnyArray &data, data.add(&fqdn_rev_); data.add(&hostname_); data.add(&state_); + data.add(&user_context_); data.add(&address_); } catch (const Exception &ex) { @@ -609,6 +634,9 @@ CqlLease4Exchange::createBindForSelect(AnyArray &data, StatementTag /* unused */ // state: int data.add(&state_); + + // user_context: text + data.add(&user_context_); } boost::any @@ -645,6 +673,13 @@ CqlLease4Exchange::retrieve() { uint32_t addr4 = static_cast(address_); + ConstElementPtr ctx; + if (!user_context_.empty()) { + ctx = Element::fromJSON(user_context_); + isc_throw(BadValue, "user context '" << user_context_ + << "' is not a JSON map"); + } + Lease4Ptr result(new Lease4(addr4, hwaddr, client_id_.data(), client_id_.size(), valid_lifetime_, 0, 0, cltt, subnet_id_, fqdn_fwd_, fqdn_rev_, @@ -652,6 +687,10 @@ CqlLease4Exchange::retrieve() { result->state_ = state_; + if (ctx) { + result->setContext(ctx); + } + return (result); } catch (const Exception &ex) { isc_throw(DbOperationError, @@ -885,9 +924,9 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "INSERT INTO lease6(" "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " - "hwaddr_source, state " + "hwaddr_source, state, user_context " ") VALUES (" - "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?" + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?" ") " "IF NOT EXISTS "}}, @@ -909,7 +948,8 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "hwaddr = ?, " "hwtype = ?, " "hwaddr_source = ?, " - "state = ? " + "state = ?, " + "user_context = ? " "WHERE address = ? " "IF EXISTS "}}, @@ -926,7 +966,7 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "SELECT " "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " - "hwaddr_source, state " + "hwaddr_source, state, user_context " "FROM lease6 " "WHERE state = ? " "AND expire < ? " @@ -939,7 +979,7 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "SELECT " "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " - "hwaddr_source, state " + "hwaddr_source, state, user_context " "FROM lease6 " "WHERE address = ? " "AND lease_type = ? " @@ -951,7 +991,7 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "SELECT " "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " - "hwaddr_source, state " + "hwaddr_source, state, user_context " "FROM lease6 " "WHERE duid = ? AND iaid = ? " "AND lease_type = ? " @@ -963,7 +1003,7 @@ StatementMap CqlLease6Exchange::tagged_statements_ = { "SELECT " "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, " "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, " - "hwaddr_source, state " + "hwaddr_source, state, user_context " "FROM lease6 " "WHERE duid = ? AND iaid = ? " "AND lease_type = ? " @@ -1072,6 +1112,14 @@ CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) { // state: int state_ = static_cast(lease_->state_); + // user_context: text + ConstElementPtr ctx = lease_->getContext(); + if (ctx) { + user_context_ = ctx->str(); + } else { + user_context_ = NULL_USER_CONTEXT; + } + // Start with a fresh array. data.clear(); @@ -1092,6 +1140,7 @@ CqlLease6Exchange::createBindForInsert(const Lease6Ptr &lease, AnyArray &data) { data.add(&hwtype_); data.add(&hwaddr_source_); data.add(&state_); + data.add(&user_context_); } catch (const Exception &ex) { isc_throw(DbOperationError, "CqlLease6Exchange::createBindForInsert(): " @@ -1205,6 +1254,14 @@ CqlLease6Exchange::createBindForUpdate(const Lease6Ptr &lease, AnyArray &data, // state: int state_ = static_cast(lease_->state_); + // user_context: text + ConstElementPtr ctx = lease_->getContext(); + if (ctx) { + user_context_ = ctx->str(); + } else { + user_context_ = NULL_USER_CONTEXT; + } + // Start with a fresh array. data.clear(); @@ -1224,6 +1281,7 @@ CqlLease6Exchange::createBindForUpdate(const Lease6Ptr &lease, AnyArray &data, data.add(&hwtype_); data.add(&hwaddr_source_); data.add(&state_); + data.add(&user_context_); data.add(&address_); } catch (const Exception &ex) { @@ -1309,6 +1367,9 @@ CqlLease6Exchange::createBindForSelect(AnyArray &data, StatementTag /* unused */ // state: int data.add(&state_); + + // user_context: text + data.add(&user_context_); } boost::any @@ -1360,6 +1421,13 @@ CqlLease6Exchange::retrieve() { hwaddr->source_ = hwaddr_source_; } + ConstElementPtr ctx; + if (!user_context_.empty()) { + ctx = Element::fromJSON(user_context_); + isc_throw(BadValue, "user context '" << user_context_ + << "' is not a JSON map"); + } + // Create the lease and set the cltt (after converting from the // expire time retrieved from the database). Lease6Ptr result( @@ -1373,6 +1441,10 @@ CqlLease6Exchange::retrieve() { result->state_ = state_; + if (ctx) { + result->setContext(ctx); + } + return (result); } catch (const Exception &ex) { isc_throw(DbOperationError, diff --git a/src/lib/dhcpsrv/csv_lease_file4.cc b/src/lib/dhcpsrv/csv_lease_file4.cc index 6f1d5d5335..e54189f144 100644 --- a/src/lib/dhcpsrv/csv_lease_file4.cc +++ b/src/lib/dhcpsrv/csv_lease_file4.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2018 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 @@ -8,6 +8,7 @@ #include using namespace isc::asiolink; +using namespace isc::data; using namespace isc::util; namespace isc { @@ -52,6 +53,10 @@ CSVLeaseFile4::append(const Lease4& lease) { row.writeAt(getColumnIndex("fqdn_rev"), lease.fqdn_rev_); row.writeAt(getColumnIndex("hostname"), lease.hostname_); row.writeAt(getColumnIndex("state"), lease.state_); + // User context is optional. + if (lease.getContext()) { + row.writeAt(getColumnIndex("user_context"), lease.getContext()->str()); + } try { VersionedCSVFile::append(row); @@ -103,6 +108,9 @@ CSVLeaseFile4::next(Lease4Ptr& lease) { " valid for declined leases"); } + // Get the user context (can be NULL). + ConstElementPtr ctx = readContext(row); + lease.reset(new Lease4(readAddress(row), HWAddrPtr(new HWAddr(hwaddr)), client_id_vec.empty() ? NULL : &client_id_vec[0], @@ -116,6 +124,10 @@ CSVLeaseFile4::next(Lease4Ptr& lease) { readHostname(row))); lease->state_ = state; + if (ctx) { + lease->setContext(ctx); + } + } catch (std::exception& ex) { // bump the read error count ++read_errs_; @@ -145,6 +157,7 @@ CSVLeaseFile4::initColumns() { addColumn("fqdn_rev", "1.0"); addColumn("hostname", "1.0"); addColumn("state", "2.0", "0"); + addColumn("user_context", "2.1"); // Any file with less than hostname is invalid setMinimumValidColumns("hostname"); } @@ -217,5 +230,19 @@ CSVLeaseFile4::readState(const util::CSVRow& row) { return (state); } +ConstElementPtr +CSVLeaseFile4::readContext(const util::CSVRow& row) { + std::string user_context = row.readAt(getColumnIndex("user_context")); + if (user_context.empty()) { + return (ConstElementPtr()); + } + ConstElementPtr ctx = Element::fromJSON(user_context); + if (!ctx || (ctx->getType() != Element::map)) { + isc_throw(isc::BadValue, "user context '" << user_context + << "' is not a JSON map"); + } + return (ctx); +} + } // end of namespace isc::dhcp } // end of namespace isc diff --git a/src/lib/dhcpsrv/csv_lease_file4.h b/src/lib/dhcpsrv/csv_lease_file4.h index 2964580b44..ef5d2b4e68 100644 --- a/src/lib/dhcpsrv/csv_lease_file4.h +++ b/src/lib/dhcpsrv/csv_lease_file4.h @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2018 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 @@ -95,6 +95,7 @@ private: /// - fqdn_rev /// - hostname /// - state + /// - user_context void initColumns(); /// @@ -151,6 +152,11 @@ private: /// /// @param row CSV file row holding lease information. uint32_t readState(const util::CSVRow& row); + + /// @brief Reads lease user context from the CSV file row. + /// + /// @param row CSV file row holding lease information. + data::ConstElementPtr readContext(const util::CSVRow& row); //@} }; diff --git a/src/lib/dhcpsrv/csv_lease_file6.cc b/src/lib/dhcpsrv/csv_lease_file6.cc index c1f8cb474a..ea1d5f2454 100644 --- a/src/lib/dhcpsrv/csv_lease_file6.cc +++ b/src/lib/dhcpsrv/csv_lease_file6.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2018 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 @@ -9,6 +9,7 @@ #include using namespace isc::asiolink; +using namespace isc::data; using namespace isc::util; namespace isc { @@ -52,6 +53,10 @@ CSVLeaseFile6::append(const Lease6& lease) { row.writeAt(getColumnIndex("hwaddr"), lease.hwaddr_->toText(false)); } row.writeAt(getColumnIndex("state"), lease.state_); + // User context is optional. + if (lease.getContext()) { + row.writeAt(getColumnIndex("user_context"), lease.getContext()->str()); + } try { VersionedCSVFile::append(row); } catch (const std::exception&) { @@ -99,6 +104,10 @@ CSVLeaseFile6::next(Lease6Ptr& lease) { isc_throw(isc::BadValue, "The Empty DUID is" "only valid for declined leases"); } + ConstElementPtr ctx = readContext(row); + if (ctx) { + lease->setContext(ctx); + } } catch (std::exception& ex) { // bump the read error count ++read_errs_; @@ -132,7 +141,7 @@ CSVLeaseFile6::initColumns() { addColumn("hostname", "1.0"); addColumn("hwaddr", "2.0"); addColumn("state", "3.0", "0"); - + addColumn("user_context", "3.1"); // Any file with less than hostname is invalid setMinimumValidColumns("hostname"); } @@ -244,5 +253,19 @@ CSVLeaseFile6::readState(const util::CSVRow& row) { return (state); } +ConstElementPtr +CSVLeaseFile6::readContext(const util::CSVRow& row) { + std::string user_context = row.readAt(getColumnIndex("user_context")); + if (user_context.empty()) { + return (ConstElementPtr()); + } + ConstElementPtr ctx = Element::fromJSON(user_context); + if (!ctx || (ctx->getType() != Element::map)) { + isc_throw(isc::BadValue, "user context '" << user_context + << "' is not a JSON map"); + } + return (ctx); +} + } // end of namespace isc::dhcp } // end of namespace isc diff --git a/src/lib/dhcpsrv/csv_lease_file6.h b/src/lib/dhcpsrv/csv_lease_file6.h index ac72b1c73e..3fdd71fbff 100644 --- a/src/lib/dhcpsrv/csv_lease_file6.h +++ b/src/lib/dhcpsrv/csv_lease_file6.h @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2018 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 @@ -98,6 +98,7 @@ private: /// - hostname /// - hwaddr /// - state + /// - user_context void initColumns(); /// @@ -175,6 +176,11 @@ private: /// /// @param row CSV file row holding lease information. uint32_t readState(const util::CSVRow& row); + + /// @brief Reads lease user context from the CSV file row. + /// + /// @param row CSV file row holding lease information. + data::ConstElementPtr readContext(const util::CSVRow& row); //@} }; diff --git a/src/lib/dhcpsrv/lease.cc b/src/lib/dhcpsrv/lease.cc index 9f52c6603d..b96613fe2d 100644 --- a/src/lib/dhcpsrv/lease.cc +++ b/src/lib/dhcpsrv/lease.cc @@ -251,6 +251,15 @@ Lease::fromElementCommon(const LeasePtr& lease, const data::ConstElementPtr& ele } lease->state_ = state->intValue(); + + // user context + ConstElementPtr ctx = element->get("user-context"); + if (ctx) { + if (ctx->getType() != Element::map) { + isc_throw(BadValue, "user context is not a map"); + } + lease->setContext(ctx); + } } Lease4::Lease4(const Lease4& other) @@ -275,6 +284,10 @@ Lease4::Lease4(const Lease4& other) client_id_.reset(); } + + if (other.getContext()) { + setContext(other.getContext()); + } } Lease4::Lease4(const isc::asiolink::IOAddress& address, @@ -375,6 +388,10 @@ Lease4::operator=(const Lease4& other) { } else { client_id_.reset(); } + + if (other.getContext()) { + setContext(other.getContext()); + } } return (*this); } @@ -383,6 +400,7 @@ isc::data::ElementPtr Lease4::toElement() const { // Prepare the map ElementPtr map = Element::createMap(); + contextToElement(map); map->set("ip-address", Element::create(addr_.toText())); map->set("subnet-id", Element::create(static_cast(subnet_id_))); map->set("hw-address", Element::create(hwaddr_->toText(false))); @@ -526,6 +544,10 @@ Lease6::toText() const { << "Subnet ID: " << subnet_id_ << "\n" << "State: " << statesToText(state_) << "\n"; + if (getContext()) { + stream << "User context: " << getContext() << "\n"; + } + return (stream.str()); } @@ -543,6 +565,10 @@ Lease4::toText() const { << "Subnet ID: " << subnet_id_ << "\n" << "State: " << statesToText(state_) << "\n"; + if (getContext()) { + stream << "User context: " << getContext() << "\n"; + } + return (stream.str()); } @@ -560,7 +586,8 @@ Lease4::operator==(const Lease4& other) const { hostname_ == other.hostname_ && fqdn_fwd_ == other.fqdn_fwd_ && fqdn_rev_ == other.fqdn_rev_ && - state_ == other.state_); + state_ == other.state_ && + nullOrEqualValues(getContext(), other.getContext())); } bool @@ -580,13 +607,15 @@ Lease6::operator==(const Lease6& other) const { hostname_ == other.hostname_ && fqdn_fwd_ == other.fqdn_fwd_ && fqdn_rev_ == other.fqdn_rev_ && - state_ == other.state_); + state_ == other.state_ && + nullOrEqualValues(getContext(), other.getContext())); } isc::data::ElementPtr Lease6::toElement() const { // Prepare the map ElementPtr map = Element::createMap(); + contextToElement(map); map->set("ip-address", Element::create(addr_.toText())); map->set("type", Element::create(typeToText(type_))); if (type_ == Lease::TYPE_PD) { diff --git a/src/lib/dhcpsrv/lease.h b/src/lib/dhcpsrv/lease.h index d8869b5af8..8f241651d1 100644 --- a/src/lib/dhcpsrv/lease.h +++ b/src/lib/dhcpsrv/lease.h @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace isc { @@ -31,7 +32,7 @@ typedef boost::shared_ptr LeasePtr; /// /// This structure holds all information that is common between IPv4 and IPv6 /// leases. -struct Lease : public isc::data::CfgToElement { +struct Lease : public UserContext, public isc::data::CfgToElement { /// @brief Type of lease or pool typedef enum { diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index 3af59246a8..2b7b5048c3 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -83,12 +83,13 @@ public: /// Version history: /// 1.0 - initial version (released in Kea 0.9) /// 2.0 - hwaddr column added (to be released in Kea 0.9.1) + /// 2.1 - user context column add (to be released in Kea 1.5) /// /// @{ static const int MAJOR_VERSION = 2; /// Defines minor version of the memfile backend. - static const int MINOR_VERSION = 0; + static const int MINOR_VERSION = 1; /// @} diff --git a/src/lib/dhcpsrv/mysql_connection.h b/src/lib/dhcpsrv/mysql_connection.h index b1d22d090b..ac1584b980 100644 --- a/src/lib/dhcpsrv/mysql_connection.h +++ b/src/lib/dhcpsrv/mysql_connection.h @@ -41,7 +41,7 @@ extern const int MLM_MYSQL_FETCH_FAILURE; /// @name Current database schema version values. //@{ const uint32_t MYSQL_SCHEMA_VERSION_MAJOR = 6; -const uint32_t MYSQL_SCHEMA_VERSION_MINOR = 0; +const uint32_t MYSQL_SCHEMA_VERSION_MINOR = 1; //@} diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index 93593e9054..59b0ea04d4 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -26,6 +26,7 @@ using namespace isc; using namespace isc::dhcp; +using namespace isc::data; using namespace std; /// @file @@ -84,6 +85,9 @@ const size_t HOSTNAME_MAX_LEN = 255; /// colon separators. const size_t ADDRESS6_TEXT_MAX_LEN = 39; +/// @brief Maximum length of user context. +const size_t USER_CONTEXT_MAX_LEN = 8192; + boost::array tagged_statements = { { {MySqlLeaseMgr::DELETE_LEASE4, @@ -100,55 +104,55 @@ tagged_statements = { { "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4"}, {MySqlLeaseMgr::GET_LEASE4_ADDR, "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE address = ?"}, {MySqlLeaseMgr::GET_LEASE4_CLIENTID, "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE client_id = ?"}, {MySqlLeaseMgr::GET_LEASE4_CLIENTID_SUBID, "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE client_id = ? AND subnet_id = ?"}, {MySqlLeaseMgr::GET_LEASE4_HWADDR, "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE hwaddr = ?"}, {MySqlLeaseMgr::GET_LEASE4_HWADDR_SUBID, "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE hwaddr = ? AND subnet_id = ?"}, {MySqlLeaseMgr::GET_LEASE4_SUBID, "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE subnet_id = ?"}, {MySqlLeaseMgr::GET_LEASE4_EXPIRE, "SELECT address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE state != ? AND expire < ? " "ORDER BY expire ASC " @@ -159,7 +163,7 @@ tagged_statements = { { "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6"}, {MySqlLeaseMgr::GET_LEASE6_ADDR, "SELECT address, duid, valid_lifetime, " @@ -167,7 +171,7 @@ tagged_statements = { { "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE address = ? AND lease_type = ?"}, {MySqlLeaseMgr::GET_LEASE6_DUID_IAID, @@ -176,7 +180,7 @@ tagged_statements = { { "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE duid = ? AND iaid = ? AND lease_type = ?"}, {MySqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID, @@ -185,7 +189,7 @@ tagged_statements = { { "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE duid = ? AND iaid = ? AND subnet_id = ? " "AND lease_type = ?"}, @@ -195,7 +199,7 @@ tagged_statements = { { "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE subnet_id = ?"}, {MySqlLeaseMgr::GET_LEASE6_EXPIRE, @@ -204,7 +208,7 @@ tagged_statements = { { "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE state != ? AND expire < ? " "ORDER BY expire ASC " @@ -213,22 +217,22 @@ tagged_statements = { { "INSERT INTO lease4(address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"}, + "state, user_context) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"}, {MySqlLeaseMgr::INSERT_LEASE6, "INSERT INTO lease6(address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"}, + "state, user_context) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"}, {MySqlLeaseMgr::UPDATE_LEASE4, "UPDATE lease4 SET address = ?, hwaddr = ?, " "client_id = ?, valid_lifetime = ?, expire = ?, " "subnet_id = ?, fqdn_fwd = ?, fqdn_rev = ?, " "hostname = ?, " - "state = ? " + "state = ?, user_context = ? " "WHERE address = ?"}, {MySqlLeaseMgr::UPDATE_LEASE6, "UPDATE lease6 SET address = ?, duid = ?, " @@ -236,7 +240,7 @@ tagged_statements = { { "pref_lifetime = ?, lease_type = ?, iaid = ?, " "prefix_len = ?, fqdn_fwd = ?, fqdn_rev = ?, " "hostname = ?, hwaddr = ?, hwtype = ?, hwaddr_source = ?, " - "state = ? " + "state = ?, user_context = ? " "WHERE address = ?"}, {MySqlLeaseMgr::ALL_LEASE4_STATS, "SELECT subnet_id, state, leases as state_count" @@ -355,7 +359,7 @@ public: class MySqlLease4Exchange : public MySqlLeaseExchange { /// @brief Set number of database columns for this lease structure - static const size_t LEASE_COLUMNS = 10; + static const size_t LEASE_COLUMNS = 11; public: /// @brief Constructor @@ -366,10 +370,12 @@ public: client_id_length_(0), client_id_null_(MLM_FALSE), subnet_id_(0), valid_lifetime_(0), fqdn_fwd_(false), fqdn_rev_(false), hostname_length_(0), - state_(0) { + state_(0), user_context_length_(0), + user_context_null_(MLM_FALSE) { memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_)); memset(client_id_buffer_, 0, sizeof(client_id_buffer_)); memset(hostname_buffer_, 0, sizeof(hostname_buffer_)); + memset(user_context_, 0, sizeof(user_context_)); std::fill(&error_[0], &error_[LEASE_COLUMNS], MLM_FALSE); // Set the column names (for error messages) @@ -383,7 +389,8 @@ public: columns_[7] = "fqdn_rev"; columns_[8] = "hostname"; columns_[9] = "state"; - BOOST_STATIC_ASSERT(9 < LEASE_COLUMNS); + columns_[10] = "user_context"; + BOOST_STATIC_ASSERT(10 < LEASE_COLUMNS); } /// @brief Create MYSQL_BIND objects for Lease4 Pointer @@ -521,11 +528,25 @@ public: // bind_[9].is_null = &MLM_FALSE; // commented out for performance // reasons, see memset() above + // user_context: text + ConstElementPtr ctx = lease->getContext(); + if (ctx) { + bind_[10].buffer_type = MYSQL_TYPE_STRING; + string ctx_txt = ctx->str(); + strncpy(user_context_, ctx_txt.c_str(), USER_CONTEXT_MAX_LEN - 1); + bind_[10].buffer = user_context_; + bind_[10].buffer_length = ctx_txt.length(); + // bind_[10].is_null = &MLM_FALSE; // commented out for performance + // reasons, see memset() above + } else { + bind_[10].buffer_type = MYSQL_TYPE_NULL; + } + // Add the error flags setErrorIndicators(bind_, error_, LEASE_COLUMNS); // .. and check that we have the numbers correct at compile time. - BOOST_STATIC_ASSERT(9 < LEASE_COLUMNS); + BOOST_STATIC_ASSERT(10 < LEASE_COLUMNS); } catch (const std::exception& ex) { isc_throw(DbOperationError, @@ -630,11 +651,20 @@ public: // bind_[9].is_null = &MLM_FALSE; // commented out for performance // reasons, see memset() above + // user_context: text null + user_context_null_ = MLM_FALSE; + user_context_length_ = sizeof(user_context_); + bind_[10].buffer_type = MYSQL_TYPE_STRING; + bind_[10].buffer = reinterpret_cast(user_context_); + bind_[10].buffer_length = user_context_length_; + bind_[10].length= &user_context_length_; + bind_[10].is_null = &user_context_null_; + // Add the error flags setErrorIndicators(bind_, error_, LEASE_COLUMNS); // .. and check that we have the numbers correct at compile time. - BOOST_STATIC_ASSERT(9 < LEASE_COLUMNS); + BOOST_STATIC_ASSERT(10 < LEASE_COLUMNS); // Add the data to the vector. Note the end element is one after the // end of the array. @@ -671,6 +701,23 @@ public: hwaddr.reset(new HWAddr(hwaddr_buffer_, hwaddr_length_, HTYPE_ETHER)); } + // Convert user_context to string as well. + std::string user_context; + if (user_context_null_ == MLM_FALSE) { + user_context_[user_context_length_] = '\0'; + user_context.assign(user_context_); + } + + // Set the user context if there is one. + ConstElementPtr ctx; + if (!user_context.empty()) { + ctx = Element::fromJSON(user_context); + if (!ctx || (ctx->getType() != Element::map)) { + isc_throw(BadValue, "user context '" << user_context + << "' is not a JSON map"); + } + } + // note that T1 and T2 are not stored Lease4Ptr lease(new Lease4(addr4_, hwaddr, client_id_buffer_, client_id_length_, @@ -680,6 +727,10 @@ public: // Set state. lease->state_ = state_; + if (ctx) { + lease->setContext(ctx); + } + return (lease); } @@ -723,6 +774,9 @@ private: char hostname_buffer_[HOSTNAME_MAX_LEN]; ///< Client hostname unsigned long hostname_length_; ///< Client hostname length uint32_t state_; ///< Lease state + char user_context_[USER_CONTEXT_MAX_LEN]; ///< User context + unsigned long user_context_length_; ///< User context length + my_bool user_context_null_; ///< Is user context null? }; /// @brief Exchange MySQL and Lease6 Data @@ -740,7 +794,7 @@ private: class MySqlLease6Exchange : public MySqlLeaseExchange { /// @brief Set number of database columns for this lease structure - static const size_t LEASE_COLUMNS = 16; + static const size_t LEASE_COLUMNS = 17; public: /// @brief Constructor @@ -753,11 +807,13 @@ public: fqdn_fwd_(false), fqdn_rev_(false), hostname_length_(0), hwaddr_length_(0), hwaddr_null_(MLM_FALSE), hwtype_(0), hwaddr_source_(0), - state_(0) { + state_(0), user_context_length_(0), + user_context_null_(MLM_FALSE) { memset(addr6_buffer_, 0, sizeof(addr6_buffer_)); memset(duid_buffer_, 0, sizeof(duid_buffer_)); memset(hostname_buffer_, 0, sizeof(hostname_buffer_)); memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_)); + memset(user_context_, 0, sizeof(user_context_)); std::fill(&error_[0], &error_[LEASE_COLUMNS], MLM_FALSE); // Set the column names (for error messages) @@ -777,7 +833,8 @@ public: columns_[13] = "hwtype"; columns_[14] = "hwaddr_source"; columns_[15] = "state"; - BOOST_STATIC_ASSERT(15 < LEASE_COLUMNS); + columns_[16] = "user_context"; + BOOST_STATIC_ASSERT(16 < LEASE_COLUMNS); } /// @brief Create MYSQL_BIND objects for Lease6 Pointer @@ -990,11 +1047,25 @@ public: // bind_[15].is_null = &MLM_FALSE; // commented out for performance // reasons, see memset() above + // user_context: text + ConstElementPtr ctx = lease->getContext(); + if (ctx) { + bind_[16].buffer_type = MYSQL_TYPE_STRING; + string ctx_txt = ctx->str(); + strncpy(user_context_, ctx_txt.c_str(), USER_CONTEXT_MAX_LEN - 1); + bind_[16].buffer = user_context_; + bind_[16].buffer_length = ctx_txt.length(); + // bind_[16].is_null = &MLM_FALSE; // commented out for performance + // reasons, see memset() above + } else { + bind_[16].buffer_type = MYSQL_TYPE_NULL; + } + // Add the error flags setErrorIndicators(bind_, error_, LEASE_COLUMNS); // .. and check that we have the numbers correct at compile time. - BOOST_STATIC_ASSERT(15 < LEASE_COLUMNS); + BOOST_STATIC_ASSERT(16 < LEASE_COLUMNS); } catch (const std::exception& ex) { isc_throw(DbOperationError, @@ -1143,11 +1214,20 @@ public: // bind_[15].is_null = &MLM_FALSE; // commented out for performance // reasons, see memset() above + // user_context: text null + user_context_null_ = MLM_FALSE; + user_context_length_ = sizeof(user_context_); + bind_[16].buffer_type = MYSQL_TYPE_STRING; + bind_[16].buffer = reinterpret_cast(user_context_); + bind_[16].buffer_length = user_context_length_; + bind_[16].length= &user_context_length_; + bind_[16].is_null = &user_context_null_; + // Add the error flags setErrorIndicators(bind_, error_, LEASE_COLUMNS); // .. and check that we have the numbers correct at compile time. - BOOST_STATIC_ASSERT(15 < LEASE_COLUMNS); + BOOST_STATIC_ASSERT(16 < LEASE_COLUMNS); // Add the data to the vector. Note the end element is one after the // end of the array. @@ -1210,6 +1290,23 @@ public: hwaddr->source_ = hwaddr_source_; } + // Convert user_context to string as well. + std::string user_context; + if (user_context_null_ == MLM_FALSE) { + user_context_[user_context_length_] = '\0'; + user_context.assign(user_context_); + } + + // Set the user context if there is one. + ConstElementPtr ctx; + if (!user_context.empty()) { + ctx = Element::fromJSON(user_context); + if (!ctx || (ctx->getType() != Element::map)) { + isc_throw(BadValue, "user context '" << user_context + << "' is not a JSON map"); + } + } + // Create the lease and set the cltt (after converting from the // expire time retrieved from the database). Lease6Ptr result(new Lease6(type, addr, duid_ptr, iaid_, @@ -1223,6 +1320,10 @@ public: // Set state. result->state_ = state_; + if (ctx) { + result->setContext(ctx); + } + return (result); } @@ -1273,6 +1374,9 @@ private: uint16_t hwtype_; ///< Hardware type uint32_t hwaddr_source_; ///< Source of the hardware address uint32_t state_; ///< Lease state. + char user_context_[USER_CONTEXT_MAX_LEN]; ///< User context + unsigned long user_context_length_; ///< User context length + my_bool user_context_null_; ///< Is user context null? }; /// @brief MySql derivation of the statistical lease data query diff --git a/src/lib/dhcpsrv/pgsql_connection.h b/src/lib/dhcpsrv/pgsql_connection.h index 659c131942..f7a50def68 100644 --- a/src/lib/dhcpsrv/pgsql_connection.h +++ b/src/lib/dhcpsrv/pgsql_connection.h @@ -17,9 +17,9 @@ namespace isc { namespace dhcp { -/// @brief Define PostgreSQL backend version: 4.0 +/// @brief Define PostgreSQL backend version: 4.1 const uint32_t PG_SCHEMA_VERSION_MAJOR = 4; -const uint32_t PG_SCHEMA_VERSION_MINOR = 0; +const uint32_t PG_SCHEMA_VERSION_MINOR = 1; // Maximum number of parameters that can be used a statement // @todo This allows us to use an initializer list (since we can't diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.cc b/src/lib/dhcpsrv/pgsql_lease_mgr.cc index f6e2a18434..ac652c02bc 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.cc +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.cc @@ -22,6 +22,7 @@ using namespace isc; using namespace isc::dhcp; +using namespace isc::data; using namespace std; namespace { @@ -58,7 +59,7 @@ PgSqlTaggedStatement tagged_statements[] = { "SELECT address, hwaddr, client_id, " "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4"}, // GET_LEASE4_ADDR @@ -67,7 +68,7 @@ PgSqlTaggedStatement tagged_statements[] = { "SELECT address, hwaddr, client_id, " "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE address = $1"}, @@ -77,7 +78,7 @@ PgSqlTaggedStatement tagged_statements[] = { "SELECT address, hwaddr, client_id, " "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE client_id = $1"}, @@ -87,7 +88,7 @@ PgSqlTaggedStatement tagged_statements[] = { "SELECT address, hwaddr, client_id, " "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE client_id = $1 AND subnet_id = $2"}, @@ -97,7 +98,7 @@ PgSqlTaggedStatement tagged_statements[] = { "SELECT address, hwaddr, client_id, " "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE hwaddr = $1"}, @@ -107,7 +108,7 @@ PgSqlTaggedStatement tagged_statements[] = { "SELECT address, hwaddr, client_id, " "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE hwaddr = $1 AND subnet_id = $2"}, @@ -117,7 +118,7 @@ PgSqlTaggedStatement tagged_statements[] = { "SELECT address, hwaddr, client_id, " "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE subnet_id = $1"}, @@ -127,7 +128,7 @@ PgSqlTaggedStatement tagged_statements[] = { "SELECT address, hwaddr, client_id, " "valid_lifetime, extract(epoch from expire)::bigint, subnet_id, " "fqdn_fwd, fqdn_rev, hostname, " - "state " + "state, user_context " "FROM lease4 " "WHERE state != $1 AND expire < $2 " "ORDER BY expire " @@ -140,7 +141,7 @@ PgSqlTaggedStatement tagged_statements[] = { "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6"}, // GET_LEASE6_ADDR @@ -150,7 +151,7 @@ PgSqlTaggedStatement tagged_statements[] = { "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE address = $1 AND lease_type = $2"}, @@ -161,7 +162,7 @@ PgSqlTaggedStatement tagged_statements[] = { "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE duid = $1 AND iaid = $2 AND lease_type = $3"}, @@ -172,7 +173,7 @@ PgSqlTaggedStatement tagged_statements[] = { "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE lease_type = $1 " "AND duid = $2 AND iaid = $3 AND subnet_id = $4"}, @@ -184,7 +185,7 @@ PgSqlTaggedStatement tagged_statements[] = { "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE subnet_id = $1"}, @@ -196,56 +197,56 @@ PgSqlTaggedStatement tagged_statements[] = { "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state " + "state, user_context " "FROM lease6 " "WHERE state != $1 AND expire < $2 " "ORDER BY expire " "LIMIT $3"}, // INSERT_LEASE4 - { 10, { OID_INT8, OID_BYTEA, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8, - OID_BOOL, OID_BOOL, OID_VARCHAR, OID_INT8 }, + { 11, { OID_INT8, OID_BYTEA, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8, + OID_BOOL, OID_BOOL, OID_VARCHAR, OID_INT8, OID_TEXT }, "insert_lease4", "INSERT INTO lease4(address, hwaddr, client_id, " "valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname, " - "state) " - "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)"}, + "state, user_context) " + "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)"}, // INSERT_LEASE6 - { 16, { OID_VARCHAR, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8, + { 17, { OID_VARCHAR, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8, OID_INT8, OID_INT2, OID_INT8, OID_INT2, OID_BOOL, OID_BOOL, - OID_VARCHAR, OID_BYTEA, OID_INT2, OID_INT2, OID_INT8 }, + OID_VARCHAR, OID_BYTEA, OID_INT2, OID_INT2, OID_INT8, OID_TEXT }, "insert_lease6", "INSERT INTO lease6(address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, " "hwaddr, hwtype, hwaddr_source, " - "state) " - "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)"}, + "state, user_context) " + "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)"}, // UPDATE_LEASE4 - { 11, { OID_INT8, OID_BYTEA, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8, - OID_BOOL, OID_BOOL, OID_VARCHAR, OID_INT8, OID_INT8 }, + { 12, { OID_INT8, OID_BYTEA, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8, + OID_BOOL, OID_BOOL, OID_VARCHAR, OID_INT8, OID_TEXT, OID_INT8 }, "update_lease4", "UPDATE lease4 SET address = $1, hwaddr = $2, " "client_id = $3, valid_lifetime = $4, expire = $5, " "subnet_id = $6, fqdn_fwd = $7, fqdn_rev = $8, hostname = $9, " - "state = $10 " - "WHERE address = $11"}, + "state = $10, user_context = $11 " + "WHERE address = $12"}, // UPDATE_LEASE6 - { 17, { OID_VARCHAR, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8, OID_INT8, + { 18, { OID_VARCHAR, OID_BYTEA, OID_INT8, OID_TIMESTAMP, OID_INT8, OID_INT8, OID_INT2, OID_INT8, OID_INT2, OID_BOOL, OID_BOOL, OID_VARCHAR, OID_BYTEA, OID_INT2, OID_INT2, - OID_INT8, OID_VARCHAR }, + OID_INT8, OID_TEXT, OID_VARCHAR }, "update_lease6", "UPDATE lease6 SET address = $1, duid = $2, " "valid_lifetime = $3, expire = $4, subnet_id = $5, " "pref_lifetime = $6, lease_type = $7, iaid = $8, " "prefix_len = $9, fqdn_fwd = $10, fqdn_rev = $11, hostname = $12, " "hwaddr = $13, hwtype = $14, hwaddr_source = $15, " - "state = $16 " - "WHERE address = $17"}, + "state = $16, user_context = $17 " + "WHERE address = $18"}, // ALL_LEASE4_STATS { 0, { OID_NONE }, "all_lease4_stats", @@ -309,7 +310,7 @@ public: : addr_str_(""), valid_lifetime_(0), valid_lifetime_str_(""), expire_(0), expire_str_(""), subnet_id_(0), subnet_id_str_(""), cltt_(0), fqdn_fwd_(false), fqdn_rev_(false), hostname_(""), - state_str_("") { + state_str_(""), user_context_("") { } virtual ~PgSqlLeaseExchange(){} @@ -329,6 +330,7 @@ protected: bool fqdn_rev_; std::string hostname_; std::string state_str_; + std::string user_context_; //@} }; @@ -350,8 +352,9 @@ private: static const size_t FQDN_REV_COL = 7; static const size_t HOSTNAME_COL = 8; static const size_t STATE_COL = 9; + static const size_t USER_CONTEXT_COL = 10; /// @brief Number of columns in the table holding DHCPv4 leases. - static const size_t LEASE_COLUMNS = 10; + static const size_t LEASE_COLUMNS = 11; public: @@ -376,6 +379,7 @@ public: columns_.push_back("fqdn_rev"); columns_.push_back("hostname"); columns_.push_back("state"); + columns_.push_back("user_context"); } /// @brief Creates the bind array for sending Lease4 data to the database. @@ -441,6 +445,14 @@ public: state_str_ = boost::lexical_cast(lease->state_); bind_array.add(state_str_); + ConstElementPtr ctx = lease->getContext(); + if (ctx) { + user_context_ = ctx->str(); + } else { + user_context_ = ""; + } + bind_array.add(user_context_); + } catch (const std::exception& ex) { isc_throw(DbOperationError, "Could not create bind array from Lease4: " @@ -487,6 +499,16 @@ public: HWAddrPtr hwaddr(new HWAddr(hwaddr_buffer_, hwaddr_length_, HTYPE_ETHER)); + user_context_ = getRawColumnValue(r, row, USER_CONTEXT_COL); + ConstElementPtr ctx; + if (!user_context_.empty()) { + ctx = Element::fromJSON(user_context_); + if (!ctx || (ctx->getType() != Element::map)) { + isc_throw(BadValue, "user context '" << user_context_ + << "' is not a JSON map"); + } + } + Lease4Ptr result(new Lease4(addr4_, hwaddr, client_id_buffer_, client_id_length_, valid_lifetime_, 0, 0, cltt_, @@ -495,6 +517,10 @@ public: result->state_ = state; + if (ctx) { + result->setContext(ctx); + } + return (result); } catch (const std::exception& ex) { isc_throw(DbOperationError, @@ -543,9 +569,10 @@ private: static const int HWTYPE_COL = 13; static const int HWADDR_SOURCE_COL = 14; static const int STATE_COL = 15; + static const size_t USER_CONTEXT_COL = 16; //@} /// @brief Number of columns in the table holding DHCPv6 leases. - static const size_t LEASE_COLUMNS = 16; + static const size_t LEASE_COLUMNS = 17; public: PgSqlLease6Exchange() @@ -574,6 +601,7 @@ public: columns_.push_back("hwtype"); columns_.push_back("hwaddr_source"); columns_.push_back("state"); + columns_.push_back("user_context"); } /// @brief Creates the bind array for sending Lease6 data to the database. @@ -670,6 +698,14 @@ public: state_str_ = boost::lexical_cast(lease->state_); bind_array.add(state_str_); + ConstElementPtr ctx = lease->getContext(); + if (ctx) { + user_context_ = ctx->str(); + } else { + user_context_ = ""; + } + bind_array.add(user_context_); + } catch (const std::exception& ex) { isc_throw(DbOperationError, "Could not create bind array from Lease6: " @@ -743,6 +779,16 @@ public: uint32_t state; getColumnValue(r, row , STATE_COL, state); + user_context_ = getRawColumnValue(r, row, USER_CONTEXT_COL); + ConstElementPtr ctx; + if (!user_context_.empty()) { + ctx = Element::fromJSON(user_context_); + if (!ctx || (ctx->getType() != Element::map)) { + isc_throw(BadValue, "user context '" << user_context_ + << "' is not a JSON map"); + } + } + Lease6Ptr result(new Lease6(lease_type_, addr, duid_ptr, iaid_u_.uval_, pref_lifetime_, valid_lifetime_, 0, 0, @@ -752,6 +798,10 @@ public: result->state_ = state; + if (ctx) { + result->setContext(ctx); + } + return (result); } catch (const std::exception& ex) { isc_throw(DbOperationError, diff --git a/src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc b/src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc index a36d448999..bac7f143e7 100644 --- a/src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc +++ b/src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc @@ -100,12 +100,12 @@ CSVLeaseFile4Test::absolutePath(const std::string& filename) { void CSVLeaseFile4Test::writeSampleFile() const { io_.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" "192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1," - "host.example.com,0\n" - "192.0.2.1,,a:11:01:04,200,200,8,1,1,host.example.com,0\n" + "host.example.com,0,\n" + "192.0.2.1,,a:11:01:04,200,200,8,1,1,host.example.com,0,\n" "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,100,100,7," - "0,0,,1\n"); + "0,0,,1,\n"); } // This test checks the capability to read and parse leases from the file. @@ -231,10 +231,11 @@ TEST_F(CSVLeaseFile4Test, recreate) { lf.close(); // Check that the contents of the csv file are correct. EXPECT_EQ("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.3.2,00:01:02:03:04:05,,200,200,8,1,1,host.example.com,2\n" + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.3.2,00:01:02:03:04:05,,200,200,8,1,1,host.example.com," + "2,\n" "192.0.3.10,0d:0e:0a:0d:0b:0e:0e:0f,01:02:03:04,100,100,7,0," - "0,,0\n", + "0,,0,\n", io_.readFile()); } @@ -341,7 +342,7 @@ TEST_F(CSVLeaseFile4Test, tooFewHeaderColumns) { TEST_F(CSVLeaseFile4Test, invalidHeaderColumn) { // Create 1.0 file io_.writeFile("address,hwaddr,BOGUS,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n"); // Open the lease file. CSVLeaseFile4 lf(filename_); @@ -353,10 +354,10 @@ TEST_F(CSVLeaseFile4Test, invalidHeaderColumn) { TEST_F(CSVLeaseFile4Test, downGrade) { // Create 2.0 PLUS a column file io_.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state,FUTURE_COL\n" + "fqdn_fwd,fqdn_rev,hostname,state,user_context,FUTURE_COL\n" "192.0.2.3,06:07:08:09:3a:bc,,200,200,8,1,1," - "three.example.com,2,BOGUS\n"); + "three.example.com,2,,BOGUS\n"); // Lease file should open and report as needing downgrade. CSVLeaseFile4 lf(filename_); @@ -390,9 +391,9 @@ TEST_F(CSVLeaseFile4Test, downGrade) { // if they are in the declined state. TEST_F(CSVLeaseFile4Test, declinedLeaseTest) { io_.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.2.1,,,200,200,8,1,1,host.example.com,0\n" - "192.0.2.1,,,200,200,8,1,1,host.example.com,1\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.2.1,,,200,200,8,1,1,host.example.com,0,\n" + "192.0.2.1,,,200,200,8,1,1,host.example.com,1,\n"); CSVLeaseFile4 lf(filename_); ASSERT_NO_THROW(lf.open()); diff --git a/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc b/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc index a8c3b8d473..f35798d70b 100644 --- a/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc +++ b/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc @@ -100,14 +100,14 @@ void CSVLeaseFile6Test::writeSampleFile() const { io_.writeFile("address,duid,valid_lifetime,expire,subnet_id," "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd," - "fqdn_rev,hostname,hwaddr,state\n" + "fqdn_rev,hostname,hwaddr,state,user_context\n" "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "200,200,8,100,0,7,0,1,1,host.example.com,,1\n" - "2001:db8:1::1,,200,200,8,100,0,7,0,1,1,host.example.com,,1\n" + "200,200,8,100,0,7,0,1,1,host.example.com,,1,\n" + "2001:db8:1::1,,200,200,8,100,0,7,0,1,1,host.example.com,,1,\n" "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05,300,300,6,150," - "0,8,0,0,0,,,1\n" + "0,8,0,0,0,,,1,\n" "3000:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,0,200,8,0,2," - "16,64,0,0,,,1\n"); + "16,64,0,0,,,1,\n"); } // This test checks the capability to read and parse leases from the file. @@ -268,13 +268,13 @@ TEST_F(CSVLeaseFile6Test, recreate) { EXPECT_EQ("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "state,user_context\n" "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "200,200,8,100,0,7,128,1,1,host.example.com,,0\n" + "200,200,8,100,0,7,128,1,1,host.example.com,,0,\n" "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05" - ",300,300,6,150,0,8,128,0,0,,,0\n" + ",300,300,6,150,0,8,128,0,0,,,0,\n" "3000:1:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "300,300,10,150,2,7,64,0,0,,,0\n", + "300,300,10,150,2,7,64,0,0,,,0,\n", io_.readFile()); } @@ -395,7 +395,7 @@ TEST_F(CSVLeaseFile6Test, tooFewHeaderColumns) { TEST_F(CSVLeaseFile6Test, invalidHeaderColumn) { io_.writeFile("address,BOGUS,valid_lifetime,expire,subnet_id,pref_lifetime," "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," - "hwaddr,state\n"); + "hwaddr,state,user_context\n"); // Open should fail. CSVLeaseFile6 lf(filename_); @@ -410,11 +410,11 @@ TEST_F(CSVLeaseFile6Test, downGrade) { // schema 1.0 header "address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," - "hwaddr,state,FUTURE_COL\n" + "hwaddr,state,user_context,FUTURE_COL\n" // schema 3.0 record - has hwaddr and state "2001:db8:1::3,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:03," - "200,200,8,100,0,7,0,1,1,three.example.com,0a:0b:0c:0d:0e,1," + "200,200,8,100,0,7,0,1,1,three.example.com,0a:0b:0c:0d:0e,1,," "BOGUS\n"); // Open should succeed in the event someone is downgrading. @@ -457,13 +457,13 @@ TEST_F(CSVLeaseFile6Test, downGrade) { TEST_F(CSVLeaseFile6Test, declinedLeaseTest) { io_.writeFile("address,duid,valid_lifetime,expire,subnet_id," "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd," - "fqdn_rev,hostname,hwaddr,state\n" + "fqdn_rev,hostname,hwaddr,state,user_context\n" "2001:db8:1::1,00," - "200,200,8,100,0,7,0,1,1,host.example.com,,0\n" + "200,200,8,100,0,7,0,1,1,host.example.com,,0,\n" "2001:db8:1::1,," - "200,200,8,100,0,7,0,1,1,host.example.com,,0\n" + "200,200,8,100,0,7,0,1,1,host.example.com,,0,\n" "2001:db8:1::1,00," - "200,200,8,100,0,7,0,1,1,host.example.com,,1\n"); + "200,200,8,100,0,7,0,1,1,host.example.com,,1,\n"); CSVLeaseFile6 lf(filename_); ASSERT_NO_THROW(lf.open()); diff --git a/src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc b/src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc index e84dbb03f8..4ac5165df0 100644 --- a/src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc +++ b/src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc @@ -143,11 +143,11 @@ protected: /// @brief Sets up the header strings virtual void SetUp() { v4_hdr_ = "address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n"; + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n"; v6_hdr_ = "address,duid,valid_lifetime,expire,subnet_id," "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd," - "fqdn_rev,hostname,hwaddr,state\n"; + "fqdn_rev,hostname,hwaddr,state,user_context\n"; } }; @@ -171,17 +171,17 @@ LeaseFileLoaderTest::absolutePath(const std::string& filename) { TEST_F(LeaseFileLoaderTest, loadWrite4) { std::string test_str; std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,," - "200,200,8,1,1,host.example.com,1\n"; + "200,200,8,1,1,host.example.com,1,\n"; std::string a_2 = "192.0.2.1,06:07:08:09:0a:bc,," - "200,500,8,1,1,host.example.com,1\n"; + "200,500,8,1,1,host.example.com,1,\n"; std::string b_1 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," - "100,100,7,0,0,,1\n"; + "100,100,7,0,0,,1,\n"; std::string b_2 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," - "100,135,7,0,0,,1\n"; + "100,135,7,0,0,,1,\n"; std::string c_1 = "192.0.2.3,,a:11:01:04," - "200,200,8,1,1,host.example.com,0\n"; + "200,200,8,1,1,host.example.com,0,\n"; // Create lease file with leases for 192.0.2.1, 192.0.3.15. The lease // entry for the 192.0.2.3 is invalid (lacks HW address) and should @@ -242,14 +242,14 @@ TEST_F(LeaseFileLoaderTest, loadWrite4) { TEST_F(LeaseFileLoaderTest, loadWrite4LeaseRemove) { std::string test_str; std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,," - "200,200,8,1,1,host.example.com,1\n"; + "200,200,8,1,1,host.example.com,1,\n"; std::string a_2 = "192.0.2.1,06:07:08:09:0a:bc,," - "0,500,8,1,1,host.example.com,1\n"; + "0,500,8,1,1,host.example.com,1,\n"; std::string b_1 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," - "100,100,7,0,0,,1\n"; + "100,100,7,0,0,,1,\n"; std::string b_2 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," - "100,135,7,0,0,,1\n"; + "100,135,7,0,0,,1,\n"; // Create lease file in which one of the entries for 192.0.2.1 @@ -297,19 +297,19 @@ TEST_F(LeaseFileLoaderTest, loadWrite4LeaseRemove) { TEST_F(LeaseFileLoaderTest, loadWrite6) { std::string test_str; std::string a_1 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "200,200,8,100,0,7,0,1,1,host.example.com,,1\n"; + "200,200,8,100,0,7,0,1,1,host.example.com,,1,\n"; std::string a_2 = "2001:db8:1::1,," - "200,200,8,100,0,7,0,1,1,host.example.com,,1\n"; + "200,200,8,100,0,7,0,1,1,host.example.com,,1,\n"; std::string a_3 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "200,400,8,100,0,7,0,1,1,host.example.com,,1\n"; + "200,400,8,100,0,7,0,1,1,host.example.com,,1,\n"; std::string b_1 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," - "300,300,6,150,0,8,0,0,0,,,1\n"; + "300,300,6,150,0,8,0,0,0,,,1,\n"; std::string b_2 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," - "300,800,6,150,0,8,0,0,0,,,1\n"; + "300,800,6,150,0,8,0,0,0,,,1,\n"; std::string c_1 = "3000:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "100,200,8,0,2,16,64,0,0,,,1\n"; + "100,200,8,0,2,16,64,0,0,,,1,\n"; @@ -371,14 +371,14 @@ TEST_F(LeaseFileLoaderTest, loadWrite6) { TEST_F(LeaseFileLoaderTest, loadWrite6LeaseRemove) { std::string test_str; std::string a_1 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "200,200,8,100,0,7,0,1,1,host.example.com,,1\n"; + "200,200,8,100,0,7,0,1,1,host.example.com,,1,\n"; std::string a_2 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," - "0,400,8,100,0,7,0,1,1,host.example.com,,1\n"; + "0,400,8,100,0,7,0,1,1,host.example.com,,1,\n"; std::string b_1 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," - "300,300,6,150,0,8,0,0,0,,,1\n"; + "300,300,6,150,0,8,0,0,0,,,1,\n"; std::string b_2 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," - "300,800,6,150,0,8,0,0,0,,,1\n"; + "300,800,6,150,0,8,0,0,0,,,1,\n"; // Create lease file in which one of the entries for the 2001:db8:1::1 // has valid lifetime set to 0, in which case the lease should be @@ -423,13 +423,14 @@ TEST_F(LeaseFileLoaderTest, loadWrite6LeaseRemove) { TEST_F(LeaseFileLoaderTest, loadMaxErrors) { std::string test_str; std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,," - "200,200,8,1,1,host.example.com,1\n"; + "200,200,8,1,1,host.example.com,1,\n"; std::string a_2 = "192.0.2.1,06:07:08:09:0a:bc,," - "200,500,8,1,1,host.example.com,1\n"; + "200,500,8,1,1,host.example.com,1,\n"; - std::string b_1 = "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com,0\n"; + std::string b_1 = "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com," + "0,\n"; - std::string c_1 = "192.0.2.10,01:02:03:04:05:06,,200,300,8,1,1,,1\n"; + std::string c_1 = "192.0.2.10,01:02:03:04:05:06,,200,300,8,1,1,,1,\n"; // Create a lease file for which there is a number of invalid // entries. b_1 is invalid and gets used multiple times. @@ -493,8 +494,8 @@ TEST_F(LeaseFileLoaderTest, loadMaxErrors) { // and comparing that with the expected value. TEST_F(LeaseFileLoaderTest, loadWriteLeaseWithZeroLifetime) { std::string test_str; - std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1,,1\n"; - std::string b_2 = "192.0.2.3,06:07:08:09:0a:bd,,0,200,8,1,1,,1\n"; + std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1,,1,\n"; + std::string b_2 = "192.0.2.3,06:07:08:09:0a:bd,,0,200,8,1,1,,1,\n"; // Create lease file. The second lease has a valid lifetime of 0. test_str = v4_hdr_ + a_1 + b_2; diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc index 84735a9e11..3b99cedbe4 100644 --- a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc @@ -498,20 +498,20 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup4) { // stored. std::string new_file_contents = "address,hwaddr,client_id,valid_lifetime,expire," - "subnet_id,fqdn_fwd,fqdn_rev,hostname,state\n"; + "subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context\n"; // This string contains the contents of the lease file with exactly // one lease, but two entries. One of the entries should be removed // as a result of lease file cleanup. std::string current_file_contents = new_file_contents + - "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1\n" - "192.0.2.2,02:02:02:02:02:02,,200,800,8,1,1,,1\n"; + "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1,\n" + "192.0.2.2,02:02:02:02:02:02,,200,800,8,1,1,,1,\n"; LeaseFileIO current_file(getLeaseFilePath("leasefile4_0.csv")); current_file.writeFile(current_file_contents); std::string previous_file_contents = new_file_contents + - "192.0.2.3,03:03:03:03:03:03,,200,200,8,1,1,,1\n" - "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,1\n"; + "192.0.2.3,03:03:03:03:03:03,,200,200,8,1,1,,1,\n" + "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,1,\n"; LeaseFileIO previous_file(getLeaseFilePath("leasefile4_0.csv.2")); previous_file.writeFile(previous_file_contents); @@ -548,15 +548,15 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup4) { ASSERT_NO_THROW(lease_mgr->addLease(new_lease)); std::string updated_file_contents = new_file_contents + - "192.0.2.45,00:00:00:00:00:00,,100,100,1,0,0,,0\n"; + "192.0.2.45,00:00:00:00:00:00,,100,100,1,0,0,,0,\n"; EXPECT_EQ(updated_file_contents, current_file.readFile()); // This string contains the contents of the lease file we // expect after the LFC run. It has two leases with one // entry each. std::string result_file_contents = new_file_contents + - "192.0.2.2,02:02:02:02:02:02,,200,800,8,1,1,,1\n" - "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,1\n"; + "192.0.2.2,02:02:02:02:02:02,,200,800,8,1,1,,1,\n" + "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,1,\n"; // The LFC should have created a file with the two leases and moved it // to leasefile4_0.csv.2 @@ -575,24 +575,24 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup6) { std::string new_file_contents = "address,duid,valid_lifetime,expire,subnet_id," "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd," - "fqdn_rev,hostname,hwaddr,state\n"; + "fqdn_rev,hostname,hwaddr,state,user_context\n"; // This string contains the contents of the lease file with exactly // one lease, but two entries. One of the entries should be removed // as a result of lease file cleanup. std::string current_file_contents = new_file_contents + "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,200," - "8,100,0,7,0,1,1,,,1\n" + "8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,800," - "8,100,0,7,0,1,1,,,1\n"; + "8,100,0,7,0,1,1,,,1,\n"; LeaseFileIO current_file(getLeaseFilePath("leasefile6_0.csv")); current_file.writeFile(current_file_contents); std::string previous_file_contents = new_file_contents + "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,200," - "8,100,0,7,0,1,1,,,1\n" + "8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,800," - "8,100,0,7,0,1,1,,,1\n"; + "8,100,0,7,0,1,1,,,1,\n"; LeaseFileIO previous_file(getLeaseFilePath("leasefile6_0.csv.2")); previous_file.writeFile(previous_file_contents); @@ -631,7 +631,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup6) { std::string update_file_contents = new_file_contents + "3000::1,00:00:00:00:00:00:00:00:00:00:00:00:00,400," - "400,2,300,0,123,128,0,0,,,0\n"; + "400,2,300,0,123,128,0,0,,,0,\n"; EXPECT_EQ(update_file_contents, current_file.readFile()); // This string contains the contents of the lease file we @@ -639,9 +639,9 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanup6) { // entry each. std::string result_file_contents = new_file_contents + "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,800," - "8,100,0,7,0,1,1,,,1\n" + "8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,800," - "8,100,0,7,0,1,1,,,1\n"; + "8,100,0,7,0,1,1,,,1,\n"; // The LFC should have created a file with the two leases and moved it // to leasefile6_0.csv.2 @@ -659,11 +659,11 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCleanupStartFail) { // stored. std::string new_file_contents = "address,hwaddr,client_id,valid_lifetime,expire," - "subnet_id,fqdn_fwd,fqdn_rev,hostname,state\n"; + "subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context\n"; // Create the lease file to be used by the backend. std::string current_file_contents = new_file_contents + - "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1\n"; + "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1,\n"; LeaseFileIO current_file(getLeaseFilePath("leasefile4_0.csv")); current_file.writeFile(current_file_contents); @@ -700,15 +700,15 @@ TEST_F(MemfileLeaseMgrTest, leaseFileFinish) { std::string new_file_contents = "address,duid,valid_lifetime,expire,subnet_id," "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd," - "fqdn_rev,hostname,hwaddr,state\n"; + "fqdn_rev,hostname,hwaddr,state,user_context\n"; // This string contains the contents of the current lease file. // It should not be moved. std::string current_file_contents = new_file_contents + "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,200," - "8,100,0,7,0,1,1,,,1\n" + "8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,800," - "8,100,0,7,0,1,1,,,1\n"; + "8,100,0,7,0,1,1,,,1,\n"; LeaseFileIO current_file(getLeaseFilePath("leasefile6_0.csv")); current_file.writeFile(current_file_contents); @@ -716,7 +716,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileFinish) { // be moved to the previous file. std::string finish_file_contents = new_file_contents + "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,800," - "8,100,0,7,0,1,1,,,1\n"; + "8,100,0,7,0,1,1,,,1,\n"; LeaseFileIO finish_file(getLeaseFilePath("leasefile6_0.csv.completed")); finish_file.writeFile(finish_file_contents); @@ -763,15 +763,15 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCopy) { std::string new_file_contents = "address,duid,valid_lifetime,expire,subnet_id," "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd," - "fqdn_rev,hostname,hwaddr,state\n"; + "fqdn_rev,hostname,hwaddr,state,user_context\n"; // This string contains the contents of the current lease file. // It should not be moved. std::string current_file_contents = new_file_contents + "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,200," - "8,100,0,7,0,1,1,,,1\n" + "8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,800," - "8,100,0,7,0,1,1,,,1\n"; + "8,100,0,7,0,1,1,,,1,\n"; LeaseFileIO current_file(getLeaseFilePath("leasefile6_0.csv")); current_file.writeFile(current_file_contents); @@ -781,7 +781,7 @@ TEST_F(MemfileLeaseMgrTest, leaseFileCopy) { // the same. std::string input_file_contents = new_file_contents + "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,800," - "8,100,0,7,0,1,1,,,1\n"; + "8,100,0,7,0,1,1,,,1,\n"; LeaseFileIO input_file(getLeaseFilePath("leasefile6_0.csv.1")); input_file.writeFile(input_file_contents); @@ -1132,22 +1132,22 @@ TEST_F(MemfileLeaseMgrTest, getDeclined6) { TEST_F(MemfileLeaseMgrTest, load4MultipleLeaseFiles) { LeaseFileIO io2(getLeaseFilePath("leasefile4_0.csv.2")); io2.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1\n" - "192.0.2.11,bb:bb:bb:bb:bb:bb,,200,200,8,1,1,,1\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1,\n" + "192.0.2.11,bb:bb:bb:bb:bb:bb,,200,200,8,1,1,,1,\n"); LeaseFileIO io1(getLeaseFilePath("leasefile4_0.csv.1")); io1.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.2.1,01:01:01:01:01:01,,200,200,8,1,1,,1\n" - "192.0.2.11,bb:bb:bb:bb:bb:bb,,200,400,8,1,1,,1\n" - "192.0.2.12,cc:cc:cc:cc:cc:cc,,200,200,8,1,1,,1\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.2.1,01:01:01:01:01:01,,200,200,8,1,1,,1,\n" + "192.0.2.11,bb:bb:bb:bb:bb:bb,,200,400,8,1,1,,1,\n" + "192.0.2.12,cc:cc:cc:cc:cc:cc,,200,200,8,1,1,,1,\n"); LeaseFileIO io(getLeaseFilePath("leasefile4_0.csv")); io.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.2.10,0a:0a:0a:0a:0a:0a,,200,200,8,1,1,,1\n" - "192.0.2.12,cc:cc:cc:cc:cc:cc,,200,400,8,1,1,,1\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.2.10,0a:0a:0a:0a:0a:0a,,200,200,8,1,1,,1,\n" + "192.0.2.12,cc:cc:cc:cc:cc:cc,,200,400,8,1,1,,1,\n"); startBackend(V4); @@ -1190,27 +1190,27 @@ TEST_F(MemfileLeaseMgrTest, load4MultipleLeaseFiles) { TEST_F(MemfileLeaseMgrTest, load4CompletedFile) { LeaseFileIO io2(getLeaseFilePath("leasefile4_0.csv.2")); io2.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1\n" - "192.0.2.11,bb:bb:bb:bb:bb:bb,,200,200,8,1,1,,1\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,1,\n" + "192.0.2.11,bb:bb:bb:bb:bb:bb,,200,200,8,1,1,,1,\n"); LeaseFileIO io1(getLeaseFilePath("leasefile4_0.csv.1")); io1.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.2.1,01:01:01:01:01:01,,200,200,8,1,1,,1\n" - "192.0.2.11,bb:bb:bb:bb:bb:bb,,200,400,8,1,1,,1\n" - "192.0.2.12,cc:cc:cc:cc:cc:cc,,200,200,8,1,1,,1\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.2.1,01:01:01:01:01:01,,200,200,8,1,1,,1,\n" + "192.0.2.11,bb:bb:bb:bb:bb:bb,,200,400,8,1,1,,1,\n" + "192.0.2.12,cc:cc:cc:cc:cc:cc,,200,200,8,1,1,,1,\n"); LeaseFileIO io(getLeaseFilePath("leasefile4_0.csv")); io.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.2.10,0a:0a:0a:0a:0a:0a,,200,200,8,1,1,,1\n" - "192.0.2.12,cc:cc:cc:cc:cc:cc,,200,400,8,1,1,,1\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.2.10,0a:0a:0a:0a:0a:0a,,200,200,8,1,1,,1,\n" + "192.0.2.12,cc:cc:cc:cc:cc:cc,,200,400,8,1,1,,1,\n"); LeaseFileIO ioc(getLeaseFilePath("leasefile4_0.csv.completed")); ioc.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id," - "fqdn_fwd,fqdn_rev,hostname,state\n" - "192.0.2.13,ff:ff:ff:ff:ff:ff,,200,200,8,1,1,,1\n"); + "fqdn_fwd,fqdn_rev,hostname,state,user_context\n" + "192.0.2.13,ff:ff:ff:ff:ff:ff,,200,200,8,1,1,,1,\n"); startBackend(V4); @@ -1266,32 +1266,32 @@ TEST_F(MemfileLeaseMgrTest, load4LFCInProgress) { TEST_F(MemfileLeaseMgrTest, load6MultipleLeaseFiles) { LeaseFileIO io2(getLeaseFilePath("leasefile6_0.csv.2")); io2.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::1,01:01:01:01:01:01:01:01:01:01:01:01:01," - "200,200,8,100,0,7,0,1,1,,,1\n" + "200,200,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); LeaseFileIO io1(getLeaseFilePath("leasefile6_0.csv.1")); io1.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::3,03:03:03:03:03:03:03:03:03:03:03:03:03," - "200,200,8,100,0,7,0,1,1,,,1\n" + "200,200,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02," - "300,800,8,100,0,7,0,1,1,,,1\n" + "300,800,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::4,04:04:04:04:04:04:04:04:04:04:04:04:04," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); LeaseFileIO io(getLeaseFilePath("leasefile6_0.csv")); io.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::4,04:04:04:04:04:04:04:04:04:04:04:04:04," - "400,1000,8,100,0,7,0,1,1,,,1\n" + "400,1000,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::5,05:05:05:05:05:05:05:05:05:05:05:05:05," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); startBackend(V6); @@ -1332,23 +1332,23 @@ TEST_F(MemfileLeaseMgrTest, load6MultipleLeaseFiles) { TEST_F(MemfileLeaseMgrTest, load6MultipleNoSecondFile) { LeaseFileIO io1(getLeaseFilePath("leasefile6_0.csv.1")); io1.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::3,03:03:03:03:03:03:03:03:03:03:03:03:03," - "200,200,8,100,0,7,0,1,1,,,1\n" + "200,200,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02," - "300,800,8,100,0,7,0,1,1,,,1\n" + "300,800,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::4,04:04:04:04:04:04:04:04:04:04:04:04:04," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); LeaseFileIO io(getLeaseFilePath("leasefile6_0.csv")); io.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::4,04:04:04:04:04:04:04:04:04:04:04:04:04," - "400,1000,8,100,0,7,0,1,1,,,1\n" + "400,1000,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::5,05:05:05:05:05:05:05:05:05:05:05:05:05," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); startBackend(V6); @@ -1380,21 +1380,21 @@ TEST_F(MemfileLeaseMgrTest, load6MultipleNoSecondFile) { TEST_F(MemfileLeaseMgrTest, load6MultipleNoFirstFile) { LeaseFileIO io2(getLeaseFilePath("leasefile6_0.csv.2")); io2.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::1,01:01:01:01:01:01:01:01:01:01:01:01:01," - "200,200,8,100,0,7,0,1,1,,,1\n" + "200,200,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); LeaseFileIO io(getLeaseFilePath("leasefile6_0.csv")); io.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::4,04:04:04:04:04:04:04:04:04:04:04:04:04," - "400,1000,8,100,0,7,0,1,1,,,1\n" + "400,1000,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::5,05:05:05:05:05:05:05:05:05:05:05:05:05," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); startBackend(V6); @@ -1428,39 +1428,39 @@ TEST_F(MemfileLeaseMgrTest, load6MultipleNoFirstFile) { TEST_F(MemfileLeaseMgrTest, load6CompletedFile) { LeaseFileIO io2(getLeaseFilePath("leasefile6_0.csv.2")); io2.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::1,01:01:01:01:01:01:01:01:01:01:01:01:01," - "200,200,8,100,0,7,0,1,1,,,1\n" + "200,200,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); LeaseFileIO io1(getLeaseFilePath("leasefile6_0.csv.1")); io1.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::3,03:03:03:03:03:03:03:03:03:03:03:03:03," - "200,200,8,100,0,7,0,1,1,,,1\n" + "200,200,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::2,02:02:02:02:02:02:02:02:02:02:02:02:02," - "300,800,8,100,0,7,0,1,1,,,1\n" + "300,800,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::4,04:04:04:04:04:04:04:04:04:04:04:04:04," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); LeaseFileIO io(getLeaseFilePath("leasefile6_0.csv")); io.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::4,04:04:04:04:04:04:04:04:04:04:04:04:04," - "400,1000,8,100,0,7,0,1,1,,,1\n" + "400,1000,8,100,0,7,0,1,1,,,1,\n" "2001:db8:1::5,05:05:05:05:05:05:05:05:05:05:05:05:05," - "200,200,8,100,0,7,0,1,1,,,1\n"); + "200,200,8,100,0,7,0,1,1,,,1,\n"); LeaseFileIO ioc(getLeaseFilePath("leasefile6_0.csv.completed")); ioc.writeFile("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime," - "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr," - "state\n" + "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname," + "hwaddr,state,user_context\n" "2001:db8:1::125,ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff," - "400,1000,8,100,0,7,0,1,1,,,1\n"); + "400,1000,8,100,0,7,0,1,1,,,1,\n"); startBackend(V6); @@ -1521,7 +1521,7 @@ TEST_F(MemfileLeaseMgrTest, leaseUpgrade4) { std::string header_2_0 = "address,hwaddr,client_id,valid_lifetime,expire," - "subnet_id,fqdn_fwd,fqdn_rev,hostname,state\n"; + "subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context\n"; // Create 1.0 Schema current lease file with two entries for // the same lease @@ -1567,8 +1567,8 @@ TEST_F(MemfileLeaseMgrTest, leaseUpgrade4) { // Verify cleaned, converted contents std::string result_file_contents = header_2_0 + - "192.0.2.2,02:02:02:02:02:02,,200,800,8,1,1,,0\n" - "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,0\n"; + "192.0.2.2,02:02:02:02:02:02,,200,800,8,1,1,,0,\n" + "192.0.2.3,03:03:03:03:03:03,,200,800,8,1,1,,0,\n"; EXPECT_EQ(result_file_contents, input_file.readFile()); } @@ -1587,7 +1587,7 @@ TEST_F(MemfileLeaseMgrTest, leaseUpgrade6) { std::string header_3_0 = "address,duid,valid_lifetime,expire,subnet_id," "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd," - "fqdn_rev,hostname,hwaddr,state\n"; + "fqdn_rev,hostname,hwaddr,state,user_context\n"; // The current lease file is schema 1.0 and has two entries for // the same lease @@ -1638,9 +1638,9 @@ TEST_F(MemfileLeaseMgrTest, leaseUpgrade6) { // Verify cleaned, converted contents std::string result_file_contents = header_3_0 + "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,800," - "8,100,0,7,0,1,1,,,0\n" + "8,100,0,7,0,1,1,,,0,\n" "2001:db8:1::2,01:01:01:01:01:01:01:01:01:01:01:01:01,200,800," - "8,100,0,7,0,1,1,,11:22:33:44:55,0\n"; + "8,100,0,7,0,1,1,,11:22:33:44:55,0,\n"; EXPECT_EQ(result_file_contents, input_file.readFile()); } diff --git a/src/share/database/scripts/cql/Makefile.am b/src/share/database/scripts/cql/Makefile.am index 46f8e26f8e..000eefd4b1 100644 --- a/src/share/database/scripts/cql/Makefile.am +++ b/src/share/database/scripts/cql/Makefile.am @@ -4,6 +4,7 @@ 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 +sqlscripts_DATA += upgrade_2.0_to_2.1.sh sqlscripts_DATA += soft_wipe.cql 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 be163e68cd..1f565f68ae 100644 --- a/src/share/database/scripts/cql/dhcpdb_create.cql +++ b/src/share/database/scripts/cql/dhcpdb_create.cql @@ -1,3 +1,4 @@ +-- Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC") -- Copyright (C) 2015-2018 Deutsche Telekom AG. -- Author: Razvan Becheriu @@ -272,3 +273,27 @@ DELETE FROM schema_version WHERE version=1; INSERT INTO schema_version (version, minor) VALUES(2, 0); -- This line concludes database upgrade to version 2.0 + +-- This line starts database upgrade to version 2.1 + +-- Add a column holding leases for user context. +ALTER TABLE lease4 ADD user_context text; +ALTER TABLE lease6 ADD user_context text; + +-- ----------------------------------------------------- +-- Table `logs` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS logs ( + timeuuid timeuuid, -- creation timeuuid, use dateOf() to get timestamp + address varchar, -- address or prefix + log text, -- the log itself + PRIMARY KEY ((timeuuid)) +); + +-- Create search index for logs table +CREATE INDEX IF NOT EXISTS logsindex ON logs (address); + +DELETE FROM schema_version WHERE version=2; +INSERT INTO schema_version (version, minor) VALUES(2, 1); + +-- This line concludes database upgrade to version 2.1 diff --git a/src/share/database/scripts/cql/dhcpdb_drop.cql b/src/share/database/scripts/cql/dhcpdb_drop.cql index 387451f561..40641549f7 100644 --- a/src/share/database/scripts/cql/dhcpdb_drop.cql +++ b/src/share/database/scripts/cql/dhcpdb_drop.cql @@ -1,3 +1,4 @@ +-- Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC") -- Copyright (C) 2015-2017 Deutsche Telekom AG. -- Author: Razvan Becheriu @@ -25,6 +26,7 @@ DROP TABLE IF EXISTS dhcp4_options; DROP TABLE IF EXISTS dhcp6_options; DROP TABLE IF EXISTS host_identifier_type; DROP TABLE IF EXISTS dhcp_option_scope; +DROP TABLE IF EXISTS logs; DROP INDEX IF EXISTS lease4index1; DROP INDEX IF EXISTS lease4index2; @@ -46,3 +48,5 @@ DROP INDEX IF EXISTS host_reservationsindex4; DROP INDEX IF EXISTS host_reservationsindex5; DROP INDEX IF EXISTS host_reservationsindex6; DROP INDEX IF EXISTS host_reservationsindex7; + +DROP INDEX IF EXISTS logsindex; diff --git a/src/share/database/scripts/cql/soft_wipe.cql b/src/share/database/scripts/cql/soft_wipe.cql index 5c9580843c..722de01d79 100644 --- a/src/share/database/scripts/cql/soft_wipe.cql +++ b/src/share/database/scripts/cql/soft_wipe.cql @@ -1,4 +1,4 @@ --- Copyright (C) 2016 Internet Systems Consortium. +-- Copyright (C) 2016-2018 Internet Systems Consortium. -- -- 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 @@ -24,3 +24,4 @@ TRUNCATE TABLE lease_hwaddr_source; TRUNCATE TABLE lease_state; TRUNCATE TABLE schema_version; TRUNCATE TABLE host_reservations; +TRUNCATE TABLE logs; diff --git a/src/share/database/scripts/cql/upgrade_2.0_to_2.1.sh.in b/src/share/database/scripts/cql/upgrade_2.0_to_2.1.sh.in new file mode 100644 index 0000000000..94a27aa7a5 --- /dev/null +++ b/src/share/database/scripts/cql/upgrade_2.0_to_2.1.sh.in @@ -0,0 +1,45 @@ +#!/bin/sh + +prefix=@prefix@ +# 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 + +version=$(cql_version "$@") + +if [ "${version}" != "2.0" ]; then + printf "This script upgrades 2.0 to 2.1. Reported version is %s. Skipping upgrade.\n" "${version}" + exit 0 +fi + +cqlsh "$@" </dev/null <