2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 05:55:28 +00:00

[master] Merge branch 'trac3965'

This commit is contained in:
Marcin Siodelski
2015-09-03 11:42:57 +02:00
25 changed files with 1501 additions and 389 deletions

View File

@@ -90,11 +90,11 @@ protected:
cstr_ = base_dir + "/" + "config_file"; // config
v4_hdr_ = "address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
"fqdn_fwd,fqdn_rev,hostname\n";
"fqdn_fwd,fqdn_rev,hostname,state\n";
v6_hdr_ = "address,duid,valid_lifetime,expire,subnet_id,"
"pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,"
"fqdn_rev,hostname,hwaddr\n";
"fqdn_rev,hostname,hwaddr,state\n";
// and remove any outstanding test files
removeTestFile();
@@ -402,26 +402,26 @@ TEST_F(LFCControllerTest, launch4) {
// We have several entries for different leases, the naming is:
// <lease letter>_<version#>
string a_1 = "192.0.2.1,06:07:08:09:0a:bc,,"
"200,200,8,1,1,host.example.com\n";
"200,200,8,1,1,host.example.com,1\n";
string a_2 = "192.0.2.1,06:07:08:09:0a:bc,,"
"200,500,8,1,1,host.example.com\n";
"200,500,8,1,1,host.example.com,1\n";
string a_3 = "192.0.2.1,06:07:08:09:0a:bc,,"
"200,800,8,1,1,host.example.com\n";
"200,800,8,1,1,host.example.com,1\n";
string b_1 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,"
"100,100,7,0,0,\n";
"100,100,7,0,0,,1\n";
string b_2 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,"
"100,135,7,0,0,\n";
"100,135,7,0,0,,1\n";
string b_3 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,"
"100,150,7,0,0,\n";
"100,150,7,0,0,,1\n";
string c_1 = "192.0.2.3,,a:11:01:04,"
"200,200,8,1,1,host.example.com\n";
"200,200,8,1,1,host.example.com,1\n";
string d_1 = "192.0.2.5,16:17:18:19:1a:bc,,"
"200,200,8,1,1,host.example.com\n";
"200,200,8,1,1,host.example.com,1\n";
string d_2 = "192.0.2.5,16:17:18:19:1a:bc,,"
"0,200,8,1,1,host.example.com\n";
"0,200,8,1,1,host.example.com,1\n";
// Subtest 1: both previous and copy available.
// Create the test previous file
@@ -556,27 +556,27 @@ TEST_F(LFCControllerTest, launch6) {
// We have several entries for different leases, the naming is:
// <lease letter>_<version#>.
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,\n";
string a_2 = "2001:db8:1::1,,200,200,8,100,0,7,0,1,1,host.example.com,\n";
"200,200,8,100,0,7,0,1,1,host.example.com,,1\n";
string a_2 = "2001:db8:1::1,,200,200,8,100,0,7,0,1,1,host.example.com,,1\n";
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,\n";
"200,400,8,100,0,7,0,1,1,host.example.com,,1\n";
string a_4 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
"0,200,8,100,0,7,0,1,1,host.example.com,\n";
"0,200,8,100,0,7,0,1,1,host.example.com,,1\n";
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,,\n";
"300,300,6,150,0,8,0,0,0,,,1\n";
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,,\n";
"300,800,6,150,0,8,0,0,0,,,1\n";
string b_3 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05,"
"300,1000,6,150,0,8,0,0,0,,\n";
"300,1000,6,150,0,8,0,0,0,,,1\n";
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,,\n";
"100,200,8,0,2,16,64,0,0,,,1\n";
string c_2 = "3000:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
"100,400,8,0,2,16,64,0,0,,\n";
"100,400,8,0,2,16,64,0,0,,,1\n";
string d_1 = "2001:db8:1::3,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
"200,600,8,100,0,7,0,1,1,host.example.com,\n";
"200,600,8,100,0,7,0,1,1,host.example.com,,1\n";
// Subtest 1: bot previous and copy available
// Create the test previous file

View File

@@ -931,7 +931,6 @@ AllocEngine::reuseExpiredLease(Lease6Ptr& expired, ClientContext6& ctx,
expired->t2_ = ctx.subnet_->getT2();
expired->cltt_ = time(NULL);
expired->subnet_id_ = ctx.subnet_->getID();
expired->fixed_ = false;
expired->hostname_ = ctx.hostname_;
expired->fqdn_fwd_ = ctx.fwd_dns_update_;
expired->fqdn_rev_ = ctx.rev_dns_update_;
@@ -1912,7 +1911,6 @@ AllocEngine::reuseExpiredLease4(Lease4Ptr& expired,
}
updateLease4Information(expired, ctx);
expired->fixed_ = false;
LOG_DEBUG(alloc_engine_logger, ALLOC_ENGINE_DBG_TRACE_DETAIL_DATA,
ALLOC_ENGINE_V4_REUSE_EXPIRED_LEASE_DATA)

View File

@@ -59,6 +59,7 @@ CSVLeaseFile4::append(const Lease4& lease) {
row.writeAt(getColumnIndex("fqdn_fwd"), lease.fqdn_fwd_);
row.writeAt(getColumnIndex("fqdn_rev"), lease.fqdn_rev_);
row.writeAt(getColumnIndex("hostname"), lease.hostname_);
row.writeAt(getColumnIndex("state"), lease.state_);
try {
CSVFile::append(row);
@@ -115,6 +116,7 @@ CSVLeaseFile4::next(Lease4Ptr& lease) {
readFqdnFwd(row),
readFqdnRev(row),
readHostname(row)));
lease->state_ = readState(row);
} catch (std::exception& ex) {
// bump the read error count
@@ -144,6 +146,7 @@ CSVLeaseFile4::initColumns() {
addColumn("fqdn_fwd");
addColumn("fqdn_rev");
addColumn("hostname");
addColumn("state");
}
IOAddress
@@ -212,5 +215,11 @@ CSVLeaseFile4::readHostname(const CSVRow& row) {
return (hostname);
}
uint32_t
CSVLeaseFile4::readState(const util::CSVRow& row) {
uint32_t state = row.readAndConvertAt<uint32_t>(getColumnIndex("state"));
return (state);
}
} // end of namespace isc::dhcp
} // end of namespace isc

View File

@@ -102,6 +102,7 @@ private:
/// - fqdn_fwd
/// - fqdn_rev
/// - hostname
/// - state
void initColumns();
///
@@ -111,48 +112,53 @@ private:
///
/// @brief Reads lease address from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
asiolink::IOAddress readAddress(const util::CSVRow& row);
/// @brief Reads HW address from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
HWAddr readHWAddr(const util::CSVRow& row);
/// @brief Reads client identifier from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
ClientIdPtr readClientId(const util::CSVRow& row);
/// @brief Reads valid lifetime from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
uint32_t readValid(const util::CSVRow& row);
/// @brief Reads cltt value from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
time_t readCltt(const util::CSVRow& row);
/// @brief Reads subnet id from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
SubnetID readSubnetID(const util::CSVRow& row);
/// @brief Reads the FQDN forward flag from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
bool readFqdnFwd(const util::CSVRow& row);
/// @brief Reads the FQDN reverse flag from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
bool readFqdnRev(const util::CSVRow& row);
/// @brief Reads hostname from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
std::string readHostname(const util::CSVRow& row);
/// @brief Reads lease state from the CSV file row.
///
/// @param row CSV file row holding lease information.
uint32_t readState(const util::CSVRow& row);
//@}
};

View File

@@ -59,6 +59,7 @@ CSVLeaseFile6::append(const Lease6& lease) {
// We may not have hardware information
row.writeAt(getColumnIndex("hwaddr"), lease.hwaddr_->toText(false));
}
row.writeAt(getColumnIndex("state"), lease.state_);
try {
CSVFile::append(row);
} catch (const std::exception&) {
@@ -100,6 +101,7 @@ CSVLeaseFile6::next(Lease6Ptr& lease) {
lease->fqdn_fwd_ = readFqdnFwd(row);
lease->fqdn_rev_ = readFqdnRev(row);
lease->hostname_ = readHostname(row);
lease->state_ = readState(row);
} catch (std::exception& ex) {
// bump the read error count
@@ -133,6 +135,7 @@ CSVLeaseFile6::initColumns() {
addColumn("fqdn_rev");
addColumn("hostname");
addColumn("hwaddr");
addColumn("state");
}
Lease::Type
@@ -226,10 +229,7 @@ CSVLeaseFile6::readHWAddr(const CSVRow& row) {
// Let's return a pointer to new freshly created copy.
return (HWAddrPtr(new HWAddr(hwaddr)));
} catch (const CSVFileError&) {
// That's ok, we may be reading old CSV file that didn't store hwaddr
return (HWAddrPtr());
} catch (const BadValue& ex) {
} catch (const std::exception& ex) {
// That's worse. There was something in the file, but its conversion
// to HWAddr failed. Let's log it on warning and carry on.
LOG_WARN(dhcpsrv_logger, DHCPSRV_MEMFILE_READ_HWADDR_FAIL)
@@ -239,21 +239,10 @@ CSVLeaseFile6::readHWAddr(const CSVRow& row) {
}
}
bool
CSVLeaseFile6::validateHeader(const isc::util::CSVRow& header) {
if (!CSVFile::validateHeader(header)) {
// One possible validation failure is that we're reading Kea 0.9
// lease file that didn't have hwaddr column. Let's add it and
// try to revalidate.
isc::util::CSVRow copy = header;
copy.append("hwaddr");
return CSVFile::validateHeader(copy);
} else {
return (true);
}
uint32_t
CSVLeaseFile6::readState(const util::CSVRow& row) {
uint32_t state = row.readAndConvertAt<uint32_t>(getColumnIndex("state"));
return (state);
}
} // end of namespace isc::dhcp

View File

@@ -87,18 +87,6 @@ public:
/// ticket http://kea.isc.org/ticket/2405 is implemented.
bool next(Lease6Ptr& lease);
protected:
/// @brief This function validates the header of the Lease6 CSV file.
///
/// It works similar to @c CSVFile::validateHeader, but if the validation
/// fails, it attempts to add hwaddr column and retry validation.
/// That's useful when attmepting to read CSV file generated in 0.9
/// (did not have hwaddr field) in 0.9.1 or later code.
///
/// @param header A row holding a header.
/// @return true if header matches the columns; false otherwise.
virtual bool validateHeader(const isc::util::CSVRow& header);
private:
/// @brief Initializes columns of the CSV file holding leases.
@@ -117,6 +105,7 @@ private:
/// - fqdn_rev
/// - hostname
/// - hwaddr
/// - state
void initColumns();
///
@@ -126,69 +115,74 @@ private:
///
/// @brief Reads lease type from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
Lease::Type readType(const util::CSVRow& row);
/// @brief Reads lease address from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
asiolink::IOAddress readAddress(const util::CSVRow& row);
/// @brief Reads DUID from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
DuidPtr readDUID(const util::CSVRow& row);
/// @brief Reads IAID from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
uint32_t readIAID(const util::CSVRow& row);
/// @brief Reads preferred lifetime from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
uint32_t readPreferred(const util::CSVRow& row);
/// @brief Reads valid lifetime from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
uint32_t readValid(const util::CSVRow& row);
/// @brief Reads cltt value from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
uint32_t readCltt(const util::CSVRow& row);
/// @brief Reads subnet id from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
SubnetID readSubnetID(const util::CSVRow& row);
/// @brief Reads prefix length from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
uint8_t readPrefixLen(const util::CSVRow& row);
/// @brief Reads the FQDN forward flag from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
bool readFqdnFwd(const util::CSVRow& row);
/// @brief Reads the FQDN reverse flag from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
bool readFqdnRev(const util::CSVRow& row);
/// @brief Reads hostname from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
std::string readHostname(const util::CSVRow& row);
/// @brief Reads HW address from the CSV file row.
///
/// @param row CSV file holding lease values.
/// @param row CSV file row holding lease information.
/// @return pointer to the HWAddr structure that was read
HWAddrPtr readHWAddr(const util::CSVRow& row);
/// @brief Reads lease state from the CSV file row.
///
/// @param row CSV file row holding lease information.
uint32_t readState(const util::CSVRow& row);
//@}
};

View File

@@ -231,6 +231,23 @@ A debug message issued when the server is attempting to delete a lease
for the specified address from the memory file database for the specified
address.
% DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4 deleting reclaimed leases expired more than %1 s ago
A debug message issued when the server is removing reclaimed DHCPv4
leases which have expired longer than a specified period of time.
The argument specified the number of seconds since leases' expiration
before they can be removed.
% DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6 deleting reclaimed leases expired more than %1 s ago
A debug message issued when the server is removing reclaimed DHCPv6
leases which have expired longer than a specified period of time.
The argument specified the number of seconds since leases' expiration
before they can be removed.
% DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START starting deletion of %1 expired-reclaimed leases
A debug message issued wheb the server has found expired-reclaimed
leases to be removed. The number of leases to be removed is logged
in the message.
% DHCPSRV_MEMFILE_GET_ADDR4 obtaining IPv4 lease for address %1
A debug message issued when the server is attempting to obtain an IPv4
lease from the memory file database for the specified address.

View File

@@ -15,6 +15,7 @@
#include <dhcpsrv/lease.h>
#include <util/pointer_util.h>
#include <sstream>
#include <iostream>
using namespace isc::util;
using namespace std;
@@ -22,13 +23,17 @@ using namespace std;
namespace isc {
namespace dhcp {
const uint32_t Lease::STATE_DEFAULT = 0x0;
const uint32_t Lease::STATE_DECLINED = 0x1;
const uint32_t Lease::STATE_EXPIRED_RECLAIMED = 0x2;
Lease::Lease(const isc::asiolink::IOAddress& addr, uint32_t t1, uint32_t t2,
uint32_t valid_lft, SubnetID subnet_id, time_t cltt,
const bool fqdn_fwd, const bool fqdn_rev,
const std::string& hostname, const HWAddrPtr& hwaddr)
:addr_(addr), t1_(t1), t2_(t2), valid_lft_(valid_lft), cltt_(cltt),
subnet_id_(subnet_id), fixed_(false), hostname_(hostname),
fqdn_fwd_(fqdn_fwd), fqdn_rev_(fqdn_rev), hwaddr_(hwaddr) {
subnet_id_(subnet_id), hostname_(hostname), fqdn_fwd_(fqdn_fwd),
fqdn_rev_(fqdn_rev), hwaddr_(hwaddr), state_(STATE_DEFAULT) {
}
@@ -52,11 +57,37 @@ Lease::typeToText(Lease::Type type) {
}
}
bool Lease::expired() const {
std::string
Lease::basicStatesToText(const uint32_t state) {
switch (state) {
case STATE_DEFAULT:
return ("default");
case STATE_DECLINED:
return ("declined");
case STATE_EXPIRED_RECLAIMED:
return ("expired-reclaimed");
default:
// The default case will be handled further on
;
}
std::ostringstream s;
s << "unknown (" << state << ")";
return s.str();
}
// Let's use int64 to avoid problems with negative/large uint32 values
int64_t expire_time = cltt_ + valid_lft_;
return (expire_time < time(NULL));
bool
Lease::expired() const {
return (getExpirationTime() < time(NULL));
}
bool
Lease::stateExpiredReclaimed() const {
return (state_ == STATE_EXPIRED_RECLAIMED);
}
int64_t
Lease::getExpirationTime() const {
return (static_cast<int64_t>(cltt_) + valid_lft_);
}
bool
@@ -69,11 +100,10 @@ Lease::hasIdenticalFqdn(const Lease& other) const {
Lease4::Lease4(const Lease4& other)
: Lease(other.addr_, other.t1_, other.t2_, other.valid_lft_,
other.subnet_id_, other.cltt_, other.fqdn_fwd_,
other.fqdn_rev_, other.hostname_, other.hwaddr_),
ext_(other.ext_) {
other.fqdn_rev_, other.hostname_, other.hwaddr_) {
fixed_ = other.fixed_;
comments_ = other.comments_;
// Copy over fields derived from Lease.
state_ = other.state_;
// Copy the hardware address if it is defined.
if (other.hwaddr_) {
@@ -105,10 +135,13 @@ Lease4::Lease4(const isc::asiolink::IOAddress& address,
: Lease(address, t1, t2, valid_lifetime, subnet_id, cltt, fqdn_fwd,
fqdn_rev, hostname, hw_address),
ext_(0), client_id_(client_id) {
client_id_(client_id) {
}
std::string
Lease4::statesToText(const uint32_t state) {
return (Lease::basicStatesToText(state));
}
const std::vector<uint8_t>&
Lease4::getClientIdVector() const {
@@ -155,12 +188,10 @@ Lease4::operator=(const Lease4& other) {
valid_lft_ = other.valid_lft_;
cltt_ = other.cltt_;
subnet_id_ = other.subnet_id_;
fixed_ = other.fixed_;
hostname_ = other.hostname_;
fqdn_fwd_ = other.fqdn_fwd_;
fqdn_rev_ = other.fqdn_rev_;
comments_ = other.comments_;
ext_ = other.ext_;
state_ = other.state_;
// Copy the hardware address if it is defined.
if (other.hwaddr_) {
@@ -215,6 +246,11 @@ Lease6::Lease6()
duid_(DuidPtr()), preferred_lft_(0) {
}
std::string
Lease6::statesToText(const uint32_t state) {
return (Lease::basicStatesToText(state));
}
const std::vector<uint8_t>&
Lease6::getDuidVector() const {
if (!duid_) {
@@ -239,7 +275,8 @@ Lease6::toText() const {
<< "Valid life: " << valid_lft_ << "\n"
<< "Cltt: " << cltt_ << "\n"
<< "Hardware addr: " << (hwaddr_?hwaddr_->toText(false):"(none)") << "\n"
<< "Subnet ID: " << subnet_id_ << "\n";
<< "Subnet ID: " << subnet_id_ << "\n"
<< "State: " << statesToText(state_) << "\n";
return (stream.str());
}
@@ -255,7 +292,8 @@ Lease4::toText() const {
<< "Cltt: " << cltt_ << "\n"
<< "Hardware addr: " << (hwaddr_ ? hwaddr_->toText(false) : "(none)") << "\n"
<< "Client id: " << (client_id_ ? client_id_->toText() : "(none)") << "\n"
<< "Subnet ID: " << subnet_id_ << "\n";
<< "Subnet ID: " << subnet_id_ << "\n"
<< "State: " << statesToText(state_) << "\n";
return (stream.str());
}
@@ -266,17 +304,15 @@ Lease4::operator==(const Lease4& other) const {
return (nullOrEqualValues(hwaddr_, other.hwaddr_) &&
nullOrEqualValues(client_id_, other.client_id_) &&
addr_ == other.addr_ &&
ext_ == other.ext_ &&
subnet_id_ == other.subnet_id_ &&
t1_ == other.t1_ &&
t2_ == other.t2_ &&
valid_lft_ == other.valid_lft_ &&
cltt_ == other.cltt_ &&
fixed_ == other.fixed_ &&
hostname_ == other.hostname_ &&
fqdn_fwd_ == other.fqdn_fwd_ &&
fqdn_rev_ == other.fqdn_rev_ &&
comments_ == other.comments_);
state_ == other.state_);
}
bool
@@ -293,11 +329,10 @@ Lease6::operator==(const Lease6& other) const {
t2_ == other.t2_ &&
cltt_ == other.cltt_ &&
subnet_id_ == other.subnet_id_ &&
fixed_ == other.fixed_ &&
hostname_ == other.hostname_ &&
fqdn_fwd_ == other.fqdn_fwd_ &&
fqdn_rev_ == other.fqdn_rev_ &&
comments_ == other.comments_);
state_ == other.state_);
}
std::ostream&

View File

@@ -48,6 +48,29 @@ struct Lease {
/// @return text decription
static std::string typeToText(Type type);
/// @name Common lease states constants.
//@{
///
/// @brief A lease in the default state.
static const uint32_t STATE_DEFAULT;
/// @brief Declined lease.
static const uint32_t STATE_DECLINED;
/// @brief Expired and reclaimed lease.
static const uint32_t STATE_EXPIRED_RECLAIMED;
//@}
/// @brief Returns name(s) of the basic lease state(s).
///
/// @param state A numeric value holding a state information.
/// Some states may be composite, i.e. the single state value
/// maps to multiple logical states of the lease.
///
/// @return Comma separated list of state names.
static std::string basicStatesToText(const uint32_t state);
/// @brief Constructor
///
/// @param addr IP address
@@ -108,11 +131,6 @@ struct Lease {
/// Specifies the identification of the subnet to which the lease belongs.
SubnetID subnet_id_;
/// @brief Fixed lease?
///
/// Fixed leases are kept after they are released/expired.
bool fixed_;
/// @brief Client hostname
///
/// This field may be empty
@@ -133,11 +151,16 @@ struct Lease {
/// This information may not be available in certain cases.
HWAddrPtr hwaddr_;
/// @brief Lease comments
/// @brief Holds the lease state(s).
///
/// Currently not used. It may be used for keeping comments made by the
/// system administrator.
std::string comments_;
/// This is the field that holds the lease state(s). Typically, a
/// lease remains in a single states. However, it is posible to
/// define a value for state which indicates that the lease remains
/// in multiple logical states.
///
/// The defined states are represented by the "STATE_*" constants
/// belonging to this class.
uint32_t state_;
/// @brief Convert Lease to Printable Form
///
@@ -148,6 +171,12 @@ struct Lease {
/// @return true if the lease is expired
bool expired() const;
/// @brief Indicates if the lease is in the "expired-reclaimed" state.
///
/// @return true if the lease is in the "expired-reclaimed" state, false
/// otherwise.
bool stateExpiredReclaimed() const;
/// @brief Returns true if the other lease has equal FQDN data.
///
/// @param other Lease which FQDN data is to be compared with our lease.
@@ -165,6 +194,12 @@ struct Lease {
///
/// @return const reference to the hardware address
const std::vector<uint8_t>& getHWAddrVector() const;
/// @brief Returns lease expiration time.
///
/// The lease expiration time is a sum of a client last transmission time
/// and valid lifetime.
int64_t getExpirationTime() const;
};
/// @brief Structure that holds a lease for IPv4 address
@@ -175,16 +210,6 @@ struct Lease {
/// extensively, direct access is warranted.
struct Lease4 : public Lease {
/// @brief Address extension
///
/// It is envisaged that in some cases IPv4 address will be accompanied
/// with some additional data. One example of such use are Address + Port
/// solutions (or Port-restricted Addresses), where several clients may get
/// the same address, but different port ranges. This feature is not
/// expected to be widely used. Under normal circumstances, the value
/// should be 0.
uint32_t ext_;
/// @brief Client identifier
///
/// @todo Should this be a pointer to a client ID or the ID itself?
@@ -211,7 +236,7 @@ struct Lease4 : public Lease {
const bool fqdn_fwd = false, const bool fqdn_rev = false,
const std::string& hostname = "")
: Lease(addr, t1, t2, valid_lft, subnet_id, cltt, fqdn_fwd, fqdn_rev,
hostname, hwaddr), ext_(0) {
hostname, hwaddr) {
if (clientid_len) {
client_id_.reset(new ClientId(clientid, clientid_len));
}
@@ -246,7 +271,7 @@ struct Lease4 : public Lease {
/// @brief Default constructor
///
/// Initialize fields that don't have a default constructor.
Lease4() : Lease(0, 0, 0, 0, 0, 0, false, false, "", HWAddrPtr()), ext_(0)
Lease4() : Lease(0, 0, 0, 0, 0, 0, false, false, "", HWAddrPtr())
{
}
@@ -255,6 +280,16 @@ struct Lease4 : public Lease {
/// @param other the @c Lease4 object to be copied.
Lease4(const Lease4& other);
/// @brief Returns name of the lease states specific to DHCPv4.
///
/// @todo Currently it simply returns common states for DHCPv4 and DHCPv6.
/// This method will have to be extended to handle DHCPv4 specific states
/// when they are defined.
///
/// @param state Numeric value holding lease states.
/// @return Comma separated list of lease state names.
static std::string statesToText(const uint32_t state);
/// @brief Returns a client identifier.
///
/// @warning Since the function returns the reference to a vector (not a
@@ -440,6 +475,16 @@ struct Lease6 : public Lease {
/// Initialize fields that don't have a default constructor.
Lease6();
/// @brief Returns name of the lease states specific to DHCPv6.
///
/// @todo Currently it simply returns common states for DHCPv4 and DHCPv6.
/// This method will have to be extended to handle DHCPv6 specific states
/// when they are defined.
///
/// @param state Numeric value holding lease states.
/// @return Comma separated list of lease state names.
static std::string statesToText(const uint32_t state);
/// @brief Returns a reference to a vector representing a DUID.
///
/// @warning Since the function returns the reference to a vector (not a

View File

@@ -291,7 +291,6 @@ public:
virtual Lease6Collection getLeases6(Lease::Type type, const DUID& duid,
uint32_t iaid, SubnetID subnet_id) const = 0;
/// @brief returns zero or one IPv6 lease for a given duid+iaid+subnet_id
///
/// This function is mostly intended to be used in unit-tests during the
@@ -318,6 +317,33 @@ public:
Lease6Ptr getLease6(Lease::Type type, const DUID& duid,
uint32_t iaid, SubnetID subnet_id) const;
/// @brief Returns a collection of expired DHCPv6 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// returned haven't been reclaimed, i.e. the database query must exclude
/// reclaimed leases from the results returned.
///
/// @param [out] expired_leases A container to which expired leases returned
/// by the database backend are added.
/// @param max_leases A maximum number of leases to be returned. If this
/// value is set to 0, all expired (but not reclaimed) leases are returned.
virtual void getExpiredLeases6(Lease6Collection& expired_leases,
const size_t max_leases) const = 0;
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// returned haven't been reclaimed, i.e. the database query must exclude
/// reclaimed leases from the results returned.
///
/// @param [out] expired_leases A container to which expired leases returned
/// by the database backend are added.
/// @param max_leases A maximum number of leases to be returned. If this
/// value is set to 0, all expired (but not reclaimed) leases are returned.
virtual void getExpiredLeases4(Lease4Collection& expired_leases,
const size_t max_leases) const = 0;
/// @brief Updates IPv4 lease.
///
/// @param lease4 The lease to be updated.
@@ -338,6 +364,24 @@ public:
/// @return true if deletion was successful, false if no such lease exists
virtual bool deleteLease(const isc::asiolink::IOAddress& addr) = 0;
/// @brief Deletes all expired and reclaimed DHCPv4 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
///
/// @return Number of leases deleted.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs) = 0;
/// @brief Deletes all expired and reclaimed DHCPv6 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
///
/// @return Number of leases deleted.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs) = 0;
/// @brief Return backend type
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)

View File

@@ -25,6 +25,7 @@
#include <cstring>
#include <errno.h>
#include <iostream>
#include <limits>
#include <sstream>
namespace {
@@ -320,10 +321,9 @@ Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress& addr) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
typedef Lease4Storage::nth_index<0>::type SearchIndex;
const SearchIndex& idx = storage4_.get<0>();
Lease4Storage::iterator l = idx.find(addr);
if (l == storage4_.end()) {
const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
Lease4StorageAddressIndex::iterator l = idx.find(addr);
if (l == idx.end()) {
return (Lease4Ptr());
} else {
return (Lease4Ptr(new Lease4(**l)));
@@ -334,10 +334,9 @@ Lease4Collection
Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
typedef Lease4Storage::nth_index<0>::type SearchIndex;
Lease4Collection collection;
const SearchIndex& idx = storage4_.get<0>();
for(SearchIndex::const_iterator lease = idx.begin();
const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
for(Lease4StorageAddressIndex::const_iterator lease = idx.begin();
lease != idx.end(); ++lease) {
// Every Lease4 has a hardware address, so we can compare it
@@ -355,14 +354,11 @@ Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
.arg(hwaddr.toText());
// We are going to use index #1 of the multi index container.
// We define SearchIndex locally in this function because
// currently only this function uses this index.
typedef Lease4Storage::nth_index<1>::type SearchIndex;
// Get the index.
const SearchIndex& idx = storage4_.get<1>();
// Get the index by HW Address and Subnet Identifier.
const Lease4StorageHWAddressSubnetIdIndex& idx =
storage4_.get<HWAddressSubnetIdIndexTag>();
// Try to find the lease using HWAddr and subnet id.
SearchIndex::const_iterator lease =
Lease4StorageHWAddressSubnetIdIndex::const_iterator lease =
idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
// Lease was not found. Return empty pointer to the caller.
if (lease == idx.end()) {
@@ -377,10 +373,9 @@ Lease4Collection
Memfile_LeaseMgr::getLease4(const ClientId& client_id) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_GET_CLIENTID).arg(client_id.toText());
typedef Lease4Storage::nth_index<0>::type SearchIndex;
Lease4Collection collection;
const SearchIndex& idx = storage4_.get<0>();
for(SearchIndex::const_iterator lease = idx.begin();
const Lease4StorageAddressIndex& idx = storage4_.get<AddressIndexTag>();
for(Lease4StorageAddressIndex::const_iterator lease = idx.begin();
lease != idx.end(); ++ lease) {
// client-id is not mandatory in DHCPv4. There can be a lease that does
@@ -402,14 +397,11 @@ Memfile_LeaseMgr::getLease4(const ClientId& client_id,
.arg(hwaddr.toText())
.arg(subnet_id);
// We are going to use index #3 of the multi index container.
// We define SearchIndex locally in this function because
// currently only this function uses this index.
typedef Lease4Storage::nth_index<3>::type SearchIndex;
// Get the index.
const SearchIndex& idx = storage4_.get<3>();
// Get the index by client id, HW address and subnet id.
const Lease4StorageClientIdHWAddressSubnetIdIndex& idx =
storage4_.get<ClientIdHWAddressSubnetIdIndexTag>();
// Try to get the lease using client id, hardware address and subnet id.
SearchIndex::const_iterator lease =
Lease4StorageClientIdHWAddressSubnetIdIndex::const_iterator lease =
idx.find(boost::make_tuple(client_id.getClientId(), hwaddr.hwaddr_,
subnet_id));
@@ -429,14 +421,11 @@ Memfile_LeaseMgr::getLease4(const ClientId& client_id,
DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
.arg(client_id.toText());
// We are going to use index #2 of the multi index container.
// We define SearchIndex locally in this function because
// currently only this function uses this index.
typedef Lease4Storage::nth_index<2>::type SearchIndex;
// Get the index.
const SearchIndex& idx = storage4_.get<2>();
// Get the index by client and subnet id.
const Lease4StorageClientIdSubnetIdIndex& idx =
storage4_.get<ClientIdSubnetIdIndexTag>();
// Try to get the lease using client id and subnet id.
SearchIndex::const_iterator lease =
Lease4StorageClientIdSubnetIdIndex::const_iterator lease =
idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
// Lease was not found. Return empty pointer to the caller.
if (lease == idx.end()) {
@@ -470,15 +459,15 @@ Memfile_LeaseMgr::getLeases6(Lease::Type type,
.arg(duid.toText())
.arg(Lease::typeToText(type));
// We are going to use index #1 of the multi index container.
typedef Lease6Storage::nth_index<1>::type SearchIndex;
// Get the index.
const SearchIndex& idx = storage6_.get<1>();
// Get the index by DUID, IAID, lease type.
const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
// Try to get the lease using the DUID, IAID and lease type.
std::pair<SearchIndex::iterator, SearchIndex::iterator> l =
std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
Lease6StorageDuidIaidTypeIndex::const_iterator> l =
idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
Lease6Collection collection;
for(SearchIndex::iterator lease = l.first; lease != l.second; ++lease) {
for(Lease6StorageDuidIaidTypeIndex::const_iterator lease =
l.first; lease != l.second; ++lease) {
collection.push_back(Lease6Ptr(new Lease6(**lease)));
}
@@ -496,15 +485,15 @@ Memfile_LeaseMgr::getLeases6(Lease::Type type,
.arg(duid.toText())
.arg(Lease::typeToText(type));
// We are going to use index #1 of the multi index container.
typedef Lease6Storage::nth_index<1>::type SearchIndex;
// Get the index.
const SearchIndex& idx = storage6_.get<1>();
// Get the index by DUID, IAID, lease type.
const Lease6StorageDuidIaidTypeIndex& idx = storage6_.get<DuidIaidTypeIndexTag>();
// Try to get the lease using the DUID, IAID and lease type.
std::pair<SearchIndex::iterator, SearchIndex::iterator> l =
std::pair<Lease6StorageDuidIaidTypeIndex::const_iterator,
Lease6StorageDuidIaidTypeIndex::const_iterator> l =
idx.equal_range(boost::make_tuple(duid.getDuid(), iaid, type));
Lease6Collection collection;
for(SearchIndex::iterator lease = l.first; lease != l.second; ++lease) {
for(Lease6StorageDuidIaidTypeIndex::const_iterator lease =
l.first; lease != l.second; ++lease) {
// Filter out the leases which subnet id doesn't match.
if((*lease)->subnet_id_ == subnet_id) {
collection.push_back(Lease6Ptr(new Lease6(**lease)));
@@ -514,12 +503,60 @@ Memfile_LeaseMgr::getLeases6(Lease::Type type,
return (collection);
}
void
Memfile_LeaseMgr::getExpiredLeases6(Lease6Collection& expired_leases,
const size_t max_leases) const {
// Obtain the index which segragates leases by state and time.
const Lease6StorageExpirationIndex& index = storage6_.get<ExpirationIndexTag>();
// Retrieve leases which are not reclaimed and which haven't expired. The
// 'less-than' operator will be used for both components of the index. So,
// for the 'state' 'false' is less than 'true'. Also the leases with
// expiration time lower than current time will be returned.
Lease6StorageExpirationIndex::const_iterator ub =
index.upper_bound(boost::make_tuple(false, time(NULL)));
// Copy only the number of leases indicated by the max_leases parameter.
for (Lease6StorageExpirationIndex::const_iterator lease = index.begin();
(lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
max_leases));
++lease) {
expired_leases.push_back(Lease6Ptr(new Lease6(**lease)));
}
}
void
Memfile_LeaseMgr::getExpiredLeases4(Lease4Collection& expired_leases,
const size_t max_leases) const {
// Obtain the index which segragates leases by state and time.
const Lease4StorageExpirationIndex& index = storage4_.get<ExpirationIndexTag>();
// Retrieve leases which are not reclaimed and which haven't expired. The
// 'less-than' operator will be used for both components of the index. So,
// for the 'state' 'false' is less than 'true'. Also the leases with
// expiration time lower than current time will be returned.
Lease4StorageExpirationIndex::const_iterator ub =
index.upper_bound(boost::make_tuple(false, time(NULL)));
// Copy only the number of leases indicated by the max_leases parameter.
for (Lease4StorageExpirationIndex::const_iterator lease = index.begin();
(lease != ub) && ((max_leases == 0) || (std::distance(index.begin(), lease) <
max_leases));
++lease) {
expired_leases.push_back(Lease4Ptr(new Lease4(**lease)));
}
}
void
Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
Lease4Storage::iterator lease_it = storage4_.find(lease->addr_);
// Obtain 'by address' index.
Lease4StorageAddressIndex& index = storage4_.get<AddressIndexTag>();
// Lease must exist if it is to be updated.
Lease4StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
if (lease_it == storage4_.end()) {
isc_throw(NoSuchLease, "failed to update the lease with address "
<< lease->addr_ << " - no such lease");
@@ -532,7 +569,8 @@ Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
lease_file4_->append(*lease);
}
**lease_it = *lease;
// Use replace() to re-index leases.
index.replace(lease_it, Lease4Ptr(new Lease4(*lease)));
}
void
@@ -540,8 +578,12 @@ Memfile_LeaseMgr::updateLease6(const Lease6Ptr& lease) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
Lease6Storage::iterator lease_it = storage6_.find(lease->addr_);
if (lease_it == storage6_.end()) {
// Obtain 'by address' index.
Lease6StorageAddressIndex& index = storage6_.get<AddressIndexTag>();
// Lease must exist if it is to be updated.
Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_);
if (lease_it == index.end()) {
isc_throw(NoSuchLease, "failed to update the lease with address "
<< lease->addr_ << " - no such lease");
}
@@ -553,7 +595,8 @@ Memfile_LeaseMgr::updateLease6(const Lease6Ptr& lease) {
lease_file6_->append(*lease);
}
**lease_it = *lease;
// Use replace() to re-index leases.
index.replace(lease_it, Lease6Ptr(new Lease6(*lease)));
}
bool
@@ -603,6 +646,89 @@ Memfile_LeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
}
}
uint64_t
Memfile_LeaseMgr::deleteExpiredReclaimedLeases4(const uint32_t secs) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4)
.arg(secs);
return (deleteExpiredReclaimedLeases<
Lease4StorageExpirationIndex, Lease4
>(secs, V4, storage4_, lease_file4_));
}
uint64_t
Memfile_LeaseMgr::deleteExpiredReclaimedLeases6(const uint32_t secs) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6)
.arg(secs);
return (deleteExpiredReclaimedLeases<
Lease6StorageExpirationIndex, Lease6
>(secs, V6, storage6_, lease_file6_));
}
template<typename IndexType, typename LeaseType, typename StorageType,
typename LeaseFileType>
uint64_t
Memfile_LeaseMgr::deleteExpiredReclaimedLeases(const uint32_t secs,
const Universe& universe,
StorageType& storage,
LeaseFileType& lease_file) const {
// Obtain the index which segragates leases by state and time.
IndexType& index = storage.template get<ExpirationIndexTag>();
// This returns the first element which is greater than the specified
// tuple (true, time(NULL) - secs). However, the range between the
// beginnng of the index and returned element also includes all the
// elements for which the first value is false (lease state is NOT
// reclaimed), because false < true. All elements between the
// beginning of the index and the element returned, for which the
// first value is true, represent the reclaimed leases which should
// be deleted, because their expiration time + secs has occured earlier
// than current time.
typename IndexType::const_iterator upper_limit =
index.upper_bound(boost::make_tuple(true, time(NULL) - secs));
// Now, we have to exclude all elements of the index which represent
// leases in the state other than reclaimed - with the first value
// in the index equal to false. Note that elements in the index are
// ordered from the lower to the higher ones. So, all elements with
// the first value of false are placed before the elements with the
// value of true. Hence, we have to find the first element which
// contains value of true. The time value is the lowest possible.
typename IndexType::const_iterator lower_limit =
index.upper_bound(boost::make_tuple(true, std::numeric_limits<int64_t>::min()));
// If there are some elements in this range, delete them.
uint64_t num_leases = static_cast<uint64_t>(std::distance(lower_limit, upper_limit));
if (num_leases > 0) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START)
.arg(num_leases);
// If lease persistence is enabled, we also have to mark leases
// as deleted in the lease file. We do this by setting the
// lifetime to 0.
if (persistLeases(universe)) {
for (typename IndexType::const_iterator lease = lower_limit;
lease != upper_limit; ++lease) {
// Copy lease to not affect the lease in the container.
LeaseType lease_copy(**lease);
// Set the valid lifetime to 0 to indicate the removal
// of the lease.
lease_copy.valid_lft_ = 0;
lease_file->append(lease_copy);
}
}
// Erase leases from memory.
index.erase(lower_limit, upper_limit);
}
// Return number of leases deleted.
return (num_leases);
}
std::string
Memfile_LeaseMgr::getDescription() const {
return (std::string("This is a dummy memfile backend implementation.\n"
@@ -871,6 +997,5 @@ void Memfile_LeaseMgr::lfcExecute(boost::shared_ptr<LeaseFileType>& lease_file)
}
}
} // end of namespace isc::dhcp
} // end of namespace isc

View File

@@ -259,6 +259,33 @@ public:
uint32_t iaid,
SubnetID subnet_id) const;
/// @brief Returns a collection of expired DHCPv6 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// returned haven't been reclaimed, i.e. the database query must exclude
/// reclaimed leases from the results returned.
///
/// @param [out] expired_leases A container to which expired leases returned
/// by the database backend are added.
/// @param max_leases A maximum number of leases to be returned. If this
/// value is set to 0, all expired (but not reclaimed) leases are returned.
virtual void getExpiredLeases6(Lease6Collection& expired_leases,
const size_t max_leases) const;
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// returned haven't been reclaimed, i.e. the database query must exclude
/// reclaimed leases from the results returned.
///
/// @param [out] expired_leases A container to which expired leases returned
/// by the database backend are added.
/// @param max_leases A maximum number of leases to be returned. If this
/// value is set to 0, all expired (but not reclaimed) leases are returned.
virtual void getExpiredLeases4(Lease4Collection& expired_leases,
const size_t max_leases) const;
/// @brief Updates IPv4 lease.
///
/// @warning This function does not validate the pointer to the lease.
@@ -287,6 +314,61 @@ public:
/// @return true if deletion was successful, false if no such lease exists
virtual bool deleteLease(const isc::asiolink::IOAddress& addr);
/// @brief Deletes all expired-reclaimed DHCPv4 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
///
/// @return Number of leases deleted.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs);
/// @brief Deletes all expired-reclaimed DHCPv6 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
///
/// @return Number of leases deleted.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs);
private:
/// @brief Deletes all expired-reclaimed leases.
///
/// This private method is called by both of the public methods:
/// @c deleteExpiredReclaimedLeases4 and
/// @c deleteExpiredReclaimedLeases6 to remove all expired
/// reclaimed DHCPv4 or DHCPv6 leases respectively.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
/// @param universe V4 or V6.
/// @param storage Reference to the container where leases are held.
/// Some expired-reclaimed leases will be removed from this container.
/// @param lease_file Reference to a DHCPv4 or DHCPv6 lease file
/// instance where leases should be marked as deleted.
///
/// @return Number of leases deleted.
///
/// @tparam IndexType Index type to be used to search for the
/// expired-reclaimed leases, i.e.
/// @c Lease4StorageExpirationIndex or @c Lease6StorageExpirationIndex.
/// @tparam LeaseType Lease type, i.e. @c Lease4 or @c Lease6.
/// @tparam StorageType Type of storage where leases are held, i.e.
/// @c Lease4Storage or @c Lease6Storage.
/// @tparam LeaseFileType Type of the lease file, i.e. DHCPv4 or
/// DHCPv6 lease file type.
template<typename IndexType, typename LeaseType, typename StorageType,
typename LeaseFileType>
uint64_t deleteExpiredReclaimedLeases(const uint32_t secs,
const Universe& universe,
StorageType& storage,
LeaseFileType& lease_file) const;
public:
/// @brief Return backend type
///
/// Returns the type of the backend.

View File

@@ -12,8 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef INMEMORY_LEASE_STORAGE_H
#define INMEMORY_LEASE_STORAGE_H
#ifndef MEMFILE_LEASE_STORAGE_H
#define MEMFILE_LEASE_STORAGE_H
#include <asiolink/io_address.h>
#include <dhcpsrv/lease.h>
@@ -31,11 +31,40 @@
namespace isc {
namespace dhcp {
/// @brief Tag for indexes by address.
struct AddressIndexTag { };
/// @brief Tag for indexes by DUID, IAID, lease type tuple.
struct DuidIaidTypeIndexTag { };
/// @brief Tag for indexes by expiration time.
struct ExpirationIndexTag { };
/// @brief Tag for indexes by HW address, subnet identifier tuple.
struct HWAddressSubnetIdIndexTag { };
/// @brief Tag for indexes by client and subnet identifiers.
struct ClientIdSubnetIdIndexTag { };
/// @brief Tag for indexes by client id, HW address and subnet id.
struct ClientIdHWAddressSubnetIdIndexTag { };
/// @name Multi index containers holding DHCPv4 and DHCPv6 leases.
///
//@{
/// @brief A multi index container holding DHCPv6 leases.
///
/// The leases in the container may be accessed using different indexes:
/// - using an IPv6 address,
/// - using a composite index: DUID, IAID and lease type.
/// - using a composite index: boolean flag indicating if the state is
/// "expired-reclaimed" and expiration time.
///
/// Indexes can be accessed using the index number (from 0 to 2) or a
/// name tag. It is recommended to use the tags to access indexes as
/// they do not depend on the order of indexes in the container.
typedef boost::multi_index_container<
// It holds pointers to Lease6 objects.
Lease6Ptr,
@@ -44,11 +73,13 @@ typedef boost::multi_index_container<
// This index sorts leases by IPv6 addresses represented as
// IOAddress objects.
boost::multi_index::ordered_unique<
boost::multi_index::tag<AddressIndexTag>,
boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_>
>,
// Specification of the second index starts here.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<DuidIaidTypeIndexTag>,
// This is a composite index that will be used to search for
// the lease using three attributes: DUID, IAID and lease type.
boost::multi_index::composite_key<
@@ -62,6 +93,24 @@ typedef boost::multi_index_container<
boost::multi_index::member<Lease6, uint32_t, &Lease6::iaid_>,
boost::multi_index::member<Lease6, Lease::Type, &Lease6::type_>
>
>,
// Specification of the third index starts here.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<ExpirationIndexTag>,
// This is a composite index that will be used to search for
// the expired leases. Depending on the value of the first component
// of the search key, the reclaimed or not reclaimed leases will can
// be searched.
boost::multi_index::composite_key<
Lease6,
// The boolean value specifying if lease is reclaimed or not.
boost::multi_index::const_mem_fun<Lease, bool,
&Lease::stateExpiredReclaimed>,
// Lease expiration time.
boost::multi_index::const_mem_fun<Lease, int64_t,
&Lease::getExpirationTime>
>
>
>
> Lease6Storage; // Specify the type name of this container.
@@ -73,6 +122,12 @@ typedef boost::multi_index_container<
/// - composite index: HW address and subnet id,
/// - composite index: client id and subnet id,
/// - composite index: HW address, client id and subnet id
/// - using a composite index: boolean flag indicating if the state is
/// "expired-reclaimed" and expiration time.
///
/// Indexes can be accessed using the index number (from 0 to 4) or a
/// name tag. It is recommended to use the tags to access indexes as
/// they do not depend on the order of indexes in the container.
typedef boost::multi_index_container<
// It holds pointers to Lease4 objects.
Lease4Ptr,
@@ -82,6 +137,7 @@ typedef boost::multi_index_container<
// This index sorts leases by IPv4 addresses represented as
// IOAddress objects.
boost::multi_index::ordered_unique<
boost::multi_index::tag<AddressIndexTag>,
// The IPv4 address are held in addr_ members that belong to
// Lease class.
boost::multi_index::member<Lease, isc::asiolink::IOAddress, &Lease::addr_>
@@ -89,6 +145,7 @@ typedef boost::multi_index_container<
// Specification of the second index starts here.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<HWAddressSubnetIdIndexTag>,
// This is a composite index that combines two attributes of the
// Lease4 object: hardware address and subnet id.
boost::multi_index::composite_key<
@@ -109,6 +166,7 @@ typedef boost::multi_index_container<
// Specification of the third index starts here.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<ClientIdSubnetIdIndexTag>,
// This is a composite index that uses two values to search for a
// lease: client id and subnet id.
boost::multi_index::composite_key<
@@ -124,6 +182,7 @@ typedef boost::multi_index_container<
// Specification of the fourth index starts here.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<ClientIdHWAddressSubnetIdIndexTag>,
// This is a composite index that uses three values to search for a
// lease: client id, HW address and subnet id.
boost::multi_index::composite_key<
@@ -141,11 +200,63 @@ typedef boost::multi_index_container<
// The subnet id is accessed through the subnet_id_ member.
boost::multi_index::member<Lease, SubnetID, &Lease::subnet_id_>
>
>,
// Specification of the fifth index starts here.
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<ExpirationIndexTag>,
// This is a composite index that will be used to search for
// the expired leases. Depending on the value of the first component
// of the search key, the reclaimed or not reclaimed leases will can
// be searched.
boost::multi_index::composite_key<
Lease4,
// The boolean value specifying if lease is reclaimed or not.
boost::multi_index::const_mem_fun<Lease, bool,
&Lease::stateExpiredReclaimed>,
// Lease expiration time.
boost::multi_index::const_mem_fun<Lease, int64_t,
&Lease::getExpirationTime>
>
>
>
> Lease4Storage; // Specify the type name for this container.
//@}
/// @name Indexes used by the multi index containers
///
//@{
/// @brief DHCPv6 lease storage index by address.
typedef Lease6Storage::index<AddressIndexTag>::type Lease6StorageAddressIndex;
/// @brief DHCPv6 lease storage index by DUID, IAID, lease type.
typedef Lease6Storage::index<DuidIaidTypeIndexTag>::type Lease6StorageDuidIaidTypeIndex;
/// @brief DHCPv6 lease storage index by expiration time.
typedef Lease6Storage::index<ExpirationIndexTag>::type Lease6StorageExpirationIndex;
/// @brief DHCPv4 lease storage index by address.
typedef Lease4Storage::index<AddressIndexTag>::type Lease4StorageAddressIndex;
/// @brief DHCPv4 lease storage index by exiration time.
typedef Lease4Storage::index<ExpirationIndexTag>::type Lease4StorageExpirationIndex;
/// @brief DHCPv4 lease storage index by HW address and subnet identifier.
typedef Lease4Storage::index<HWAddressSubnetIdIndexTag>::type
Lease4StorageHWAddressSubnetIdIndex;
/// @brief DHCPv4 lease storage index by client and subnet identifier.
typedef Lease4Storage::index<ClientIdSubnetIdIndexTag>::type
Lease4StorageClientIdSubnetIdIndex;
/// @brief DHCPv4 lease storage index by client id, HW address and subnet id.
typedef Lease4Storage::index<ClientIdHWAddressSubnetIdIndexTag>::type
Lease4StorageClientIdHWAddressSubnetIdIndex;
//@}
} // end of isc::dhcp namespace
} // end of isc namespace
#endif // INMEMORY_LEASE_STORAGE_H
#endif // MEMFILE_LEASE_STORAGE_H

View File

@@ -1932,6 +1932,18 @@ MySqlLeaseMgr::getLeases6(Lease::Type lease_type,
return (result);
}
void
MySqlLeaseMgr::getExpiredLeases6(Lease6Collection&, const size_t) const {
isc_throw(NotImplemented, "MySqlLeaseMgr::getExpiredLeases6 is currently"
" not implemented");
}
void
MySqlLeaseMgr::getExpiredLeases4(Lease4Collection&, const size_t) const {
isc_throw(NotImplemented, "MySqlLeaseMgr::getExpiredLeases4 is currently"
" not implemented");
}
// Update lease methods. These comprise common code that handles the actual
// update, and type-specific methods that set up the parameters for the prepared
// statement depending on the type of lease.
@@ -2074,6 +2086,19 @@ MySqlLeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
}
}
uint64_t
MySqlLeaseMgr::deleteExpiredReclaimedLeases4(const uint32_t) {
isc_throw(NotImplemented, "MySqlLeaseMgr::deleteExpiredReclaimedLeases4"
" is not implemented");
}
uint64_t
MySqlLeaseMgr::deleteExpiredReclaimedLeases6(const uint32_t) {
isc_throw(NotImplemented, "MySqlLeaseMgr::deleteExpiredReclaimedLeases6"
" is not implemented");
}
// Miscellaneous database methods.
std::string

View File

@@ -317,6 +317,33 @@ public:
virtual Lease6Collection getLeases6(Lease::Type type, const DUID& duid,
uint32_t iaid, SubnetID subnet_id) const;
/// @brief Returns a collection of expired DHCPv6 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// returned haven't been reclaimed, i.e. the database query must exclude
/// reclaimed leases from the results returned.
///
/// @param [out] expired_leases A container to which expired leases returned
/// by the database backend are added.
/// @param max_leases A maximum number of leases to be returned. If this
/// value is set to 0, all expired (but not reclaimed) leases are returned.
virtual void getExpiredLeases6(Lease6Collection& expired_leases,
const size_t max_leases) const;
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// returned haven't been reclaimed, i.e. the database query must exclude
/// reclaimed leases from the results returned.
///
/// @param [out] expired_leases A container to which expired leases returned
/// by the database backend are added.
/// @param max_leases A maximum number of leases to be returned. If this
/// value is set to 0, all expired (but not reclaimed) leases are returned.
virtual void getExpiredLeases4(Lease4Collection& expired_leases,
const size_t max_leases) const;
/// @brief Updates IPv4 lease.
///
/// Updates the record of the lease in the database (as identified by the
@@ -354,6 +381,24 @@ public:
/// failed.
virtual bool deleteLease(const isc::asiolink::IOAddress& addr);
/// @brief Deletes all expired-reclaimed DHCPv4 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
///
/// @return Number of leases deleted.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs);
/// @brief Deletes all expired-reclaimed DHCPv6 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
///
/// @return Number of leases deleted.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs);
/// @brief Return backend type
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)

View File

@@ -1382,6 +1382,19 @@ PgSqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID& duid,
return (result);
}
void
PgSqlLeaseMgr::getExpiredLeases6(Lease6Collection&, const size_t) const {
isc_throw(NotImplemented, "PgSqlLeaseMgr::getExpiredLeases6 is currently"
" not implemented");
}
void
PgSqlLeaseMgr::getExpiredLeases4(Lease4Collection&, const size_t) const {
isc_throw(NotImplemented, "PgSqlLeaseMgr::getExpiredLeases4 is currently"
" not implemented");
}
template <typename LeasePtr>
void
PgSqlLeaseMgr::updateLeaseCommon(StatementIndex stindex,
@@ -1494,6 +1507,18 @@ PgSqlLeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
return (deleteLeaseCommon(DELETE_LEASE6, bind_array));
}
uint64_t
PgSqlLeaseMgr::deleteExpiredReclaimedLeases4(const uint32_t) {
isc_throw(NotImplemented, "PgSqlLeaseMgr::deleteExpiredReclaimedLeases4"
" is not implemented");
}
uint64_t
PgSqlLeaseMgr::deleteExpiredReclaimedLeases6(const uint32_t) {
isc_throw(NotImplemented, "PgSqlLeaseMgr::deleteExpiredReclaimedLeases6"
" is not implemented");
}
string
PgSqlLeaseMgr::getName() const {
string name = "";

View File

@@ -322,6 +322,33 @@ public:
virtual Lease6Collection getLeases6(Lease::Type type, const DUID& duid,
uint32_t iaid, SubnetID subnet_id) const;
/// @brief Returns a collection of expired DHCPv6 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// returned haven't been reclaimed, i.e. the database query must exclude
/// reclaimed leases from the results returned.
///
/// @param [out] expired_leases A container to which expired leases returned
/// by the database backend are added.
/// @param max_leases A maximum number of leases to be returned. If this
/// value is set to 0, all expired (but not reclaimed) leases are returned.
virtual void getExpiredLeases6(Lease6Collection& expired_leases,
const size_t max_leases) const;
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// returned haven't been reclaimed, i.e. the database query must exclude
/// reclaimed leases from the results returned.
///
/// @param [out] expired_leases A container to which expired leases returned
/// by the database backend are added.
/// @param max_leases A maximum number of leases to be returned. If this
/// value is set to 0, all expired (but not reclaimed) leases are returned.
virtual void getExpiredLeases4(Lease4Collection& expired_leases,
const size_t max_leases) const;
/// @brief Updates IPv4 lease.
///
/// Updates the record of the lease in the database (as identified by the
@@ -359,6 +386,24 @@ public:
/// failed.
virtual bool deleteLease(const isc::asiolink::IOAddress& addr);
/// @brief Deletes all expired-reclaimed DHCPv4 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
///
/// @return Number of leases deleted.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t secs);
/// @brief Deletes all expired-reclaimed DHCPv6 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
///
/// @return Number of leases deleted.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t secs);
/// @brief Return backend type
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)

View File

@@ -111,12 +111,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\n"
"fqdn_fwd,fqdn_rev,hostname,state\n"
"192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1,"
"host.example.com\n"
"192.0.2.1,,a:11:01:04,200,200,8,1,1,host.example.com\n"
"host.example.com,0\n"
"192.0.2.1,,a:11:01:04,200,200,8,1,1,host.example.com,1\n"
"192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,100,100,7,"
"0,0,\n");
"0,0,,1\n");
}
// This test checks the capability to read and parse leases from the file.
@@ -153,6 +153,7 @@ TEST_F(CSVLeaseFile4Test, parse) {
EXPECT_TRUE(lease->fqdn_fwd_);
EXPECT_TRUE(lease->fqdn_rev_);
EXPECT_EQ("host.example.com", lease->hostname_);
EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_);
}
// Second lease is malformed - HW address is empty.
@@ -182,6 +183,7 @@ TEST_F(CSVLeaseFile4Test, parse) {
EXPECT_FALSE(lease->fqdn_fwd_);
EXPECT_FALSE(lease->fqdn_rev_);
EXPECT_TRUE(lease->hostname_.empty());
EXPECT_EQ(Lease::STATE_DECLINED, lease->state_);
}
// There are no more leases. Reading should cause no error, but the returned
@@ -217,6 +219,7 @@ TEST_F(CSVLeaseFile4Test, recreate) {
NULL, 0,
200, 50, 80, 0, 8, true, true,
"host.example.com"));
lease->state_ = Lease::STATE_EXPIRED_RECLAIMED;
{
SCOPED_TRACE("First write");
ASSERT_NO_THROW(lf->append(*lease));
@@ -238,10 +241,10 @@ 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\n"
"192.0.3.2,00:01:02:03:04:05,,200,200,8,1,1,host.example.com\n"
"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"
"192.0.3.10,0d:0e:0a:0d:0b:0e:0e:0f,01:02:03:04,100,100,7,0,"
"0,\n",
"0,,0\n",
io_.readFile());
}

View File

@@ -110,14 +110,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\n"
"fqdn_rev,hostname,hwaddr,state\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\n"
"2001:db8:1::1,,200,200,8,100,0,7,0,1,1,host.example.com\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,\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,,\n");
"16,64,0,0,,,1\n");
}
// This test checks the capability to read and parse leases from the file.
@@ -277,13 +277,14 @@ 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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,\n"
"200,200,8,100,0,7,0,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,,\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,,\n",
"300,300,10,150,2,7,64,0,0,,,0\n",
io_.readFile());
}

View File

@@ -79,11 +79,8 @@ GenericLeaseMgrTest::initializeLease4(std::string address) {
lease->addr_ = IOAddress(address);
// Initialize unused fields.
lease->ext_ = 0; // Not saved
lease->t1_ = 0; // Not saved
lease->t2_ = 0; // Not saved
lease->fixed_ = false; // Unused
lease->comments_ = std::string(""); // Unused
// Set other parameters. For historical reasons, address 0 is not used.
if (address == straddress4_[0]) {
@@ -199,8 +196,6 @@ GenericLeaseMgrTest::initializeLease6(std::string address) {
// Initialize unused fields.
lease->t1_ = 0; // Not saved
lease->t2_ = 0; // Not saved
lease->fixed_ = false; // Unused
lease->comments_ = std::string(""); // Unused
// Set other parameters. For historical reasons, address 0 is not used.
if (address == straddress6_[0]) {
@@ -1304,8 +1299,6 @@ GenericLeaseMgrTest::testLease6LeaseTypeCheck() {
// Initialize unused fields.
empty_lease->t1_ = 0; // Not saved
empty_lease->t2_ = 0; // Not saved
empty_lease->fixed_ = false; // Unused
empty_lease->comments_ = std::string(""); // Unused
empty_lease->iaid_ = 142;
empty_lease->duid_ = DuidPtr(new DUID(*duid));
empty_lease->subnet_id_ = 23;
@@ -1657,6 +1650,439 @@ GenericLeaseMgrTest::testVersion(int major, int minor) {
EXPECT_EQ(minor, lmptr_->getVersion().second);
}
void
GenericLeaseMgrTest::testGetExpiredLeases4() {
// Get the leases to be used for the test.
vector<Lease4Ptr> leases = createLeases4();
// Make sure we have at least 6 leases there.
ASSERT_GE(leases.size(), 6);
// Use the same current time for all leases.
time_t current_time = time(NULL);
// Add them to the database
for (size_t i = 0; i < leases.size(); ++i) {
// Mark every other lease as expired.
if (i % 2 == 0) {
// Set client last transmission time to the value older than the
// 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;
} else {
// Set current time as cltt for remaining leases. These leases are
// not expired.
leases[i]->cltt_ = current_time;
}
ASSERT_TRUE(lmptr_->addLease(leases[i]));
}
// Retrieve at most 1000 expired leases.
Lease4Collection expired_leases;
ASSERT_NO_THROW(lmptr_->getExpiredLeases4(expired_leases, 1000));
// Leases with even indexes should be returned as expired.
ASSERT_EQ(static_cast<size_t>(leases.size() / 2), expired_leases.size());
// The expired leases should be returned from the most to least expired.
// This matches the reverse order to which they have been added.
for (Lease4Collection::reverse_iterator lease = expired_leases.rbegin();
lease != expired_leases.rend(); ++lease) {
int index = static_cast<int>(std::distance(expired_leases.rbegin(), lease));
// Multiple current index by two, because only leases with even indexes
// should have been returned.
EXPECT_EQ(leases[2 * index]->addr_, (*lease)->addr_);
}
// 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
// in the correct order.
for (int i = 0; i < leases.size(); ++i) {
// Update the time of expired leases with even indexes.
if (i % 2 == 0) {
leases[i]->cltt_ = current_time - leases[i]->valid_lft_ - 1000 + i;
} else {
// Make sure remaining leases remain unexpired.
leases[i]->cltt_ = current_time + 100;
}
ASSERT_NO_THROW(lmptr_->updateLease4(leases[i]));
}
// 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<size_t>(leases.size() / 2), expired_leases.size());
// This time leases should be returned in the non-reverse order.
for (Lease4Collection::iterator lease = expired_leases.begin();
lease != expired_leases.end(); ++lease) {
int index = static_cast<int>(std::distance(expired_leases.begin(), lease));
EXPECT_EQ(leases[2 * index]->addr_, (*lease)->addr_);
}
// Remember expired leases returned.
std::vector<Lease4Ptr> saved_expired_leases = expired_leases;
// Remove expired leases again.
expired_leases.clear();
// Limit the number of leases to be returned to 2.
ASSERT_NO_THROW(lmptr_->getExpiredLeases4(expired_leases, 2));
// Make sure we have exactly 2 leases returned.
ASSERT_EQ(2, expired_leases.size());
// Test that most expired leases have been returned.
for (Lease4Collection::iterator lease = expired_leases.begin();
lease != expired_leases.end(); ++lease) {
int index = static_cast<int>(std::distance(expired_leases.begin(), lease));
EXPECT_EQ(leases[2 * index]->addr_, (*lease)->addr_);
}
// Mark every other expired lease as reclaimed.
for (int i = 0; i < saved_expired_leases.size(); ++i) {
if (i % 2 != 0) {
saved_expired_leases[i]->state_ = Lease::STATE_EXPIRED_RECLAIMED;
}
ASSERT_NO_THROW(lmptr_->updateLease4(saved_expired_leases[i]));
}
expired_leases.clear();
// This the returned leases should exclude reclaimed ones. So the number
// of returned leases should be roughly half of the expired leases.
ASSERT_NO_THROW(lmptr_->getExpiredLeases4(expired_leases, 0));
ASSERT_EQ(static_cast<size_t>(saved_expired_leases.size() / 2),
expired_leases.size());
// Make sure that returned leases are those that are not reclaimed, i.e.
// those that have even index.
for (Lease4Collection::iterator lease = expired_leases.begin();
lease != expired_leases.end(); ++lease) {
int index = static_cast<int>(std::distance(expired_leases.begin(), lease));
EXPECT_EQ(saved_expired_leases[2 * index]->addr_, (*lease)->addr_);
}
}
void
GenericLeaseMgrTest::testGetExpiredLeases6() {
// Get the leases to be used for the test.
vector<Lease6Ptr> leases = createLeases6();
// Make sure we have at least 6 leases there.
ASSERT_GE(leases.size(), 6);
// Use the same current time for all leases.
time_t current_time = time(NULL);
// Add them to the database
for (size_t i = 0; i < leases.size(); ++i) {
// Mark every other lease as expired.
if (i % 2 == 0) {
// Set client last transmission time to the value older than the
// 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;
} else {
// Set current time as cltt for remaining leases. These leases are
// not expired.
leases[i]->cltt_ = current_time;
}
ASSERT_TRUE(lmptr_->addLease(leases[i]));
}
// Retrieve at most 1000 expired leases.
Lease6Collection expired_leases;
ASSERT_NO_THROW(lmptr_->getExpiredLeases6(expired_leases, 1000));
// Leases with even indexes should be returned as expired.
ASSERT_EQ(static_cast<size_t>(leases.size() / 2), expired_leases.size());
// The expired leases should be returned from the most to least expired.
// This matches the reverse order to which they have been added.
for (Lease6Collection::reverse_iterator lease = expired_leases.rbegin();
lease != expired_leases.rend(); ++lease) {
int index = static_cast<int>(std::distance(expired_leases.rbegin(), lease));
// Multiple current index by two, because only leases with even indexes
// should have been returned.
EXPECT_EQ(leases[2 * index]->addr_, (*lease)->addr_);
}
// 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
// in the correct order.
for (int i = 0; i < leases.size(); ++i) {
// Update the time of expired leases with even indexes.
if (i % 2 == 0) {
leases[i]->cltt_ = current_time - leases[i]->valid_lft_ - 1000 + i;
} else {
// Make sure remaining leases remain unexpired.
leases[i]->cltt_ = current_time + 100;
}
ASSERT_NO_THROW(lmptr_->updateLease6(leases[i]));
}
// 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<size_t>(leases.size() / 2), expired_leases.size());
// This time leases should be returned in the non-reverse order.
for (Lease6Collection::iterator lease = expired_leases.begin();
lease != expired_leases.end(); ++lease) {
int index = static_cast<int>(std::distance(expired_leases.begin(), lease));
EXPECT_EQ(leases[2 * index]->addr_, (*lease)->addr_);
}
// Remember expired leases returned.
std::vector<Lease6Ptr> saved_expired_leases = expired_leases;
// Remove expired leases again.
expired_leases.clear();
// Limit the number of leases to be returned to 2.
ASSERT_NO_THROW(lmptr_->getExpiredLeases6(expired_leases, 2));
// Make sure we have exactly 2 leases returned.
ASSERT_EQ(2, expired_leases.size());
// Test that most expired leases have been returned.
for (Lease6Collection::iterator lease = expired_leases.begin();
lease != expired_leases.end(); ++lease) {
int index = static_cast<int>(std::distance(expired_leases.begin(), lease));
EXPECT_EQ(leases[2 * index]->addr_, (*lease)->addr_);
}
// Mark every other expired lease as reclaimed.
for (int i = 0; i < saved_expired_leases.size(); ++i) {
if (i % 2 != 0) {
saved_expired_leases[i]->state_ = Lease::STATE_EXPIRED_RECLAIMED;
}
ASSERT_NO_THROW(lmptr_->updateLease6(saved_expired_leases[i]));
}
expired_leases.clear();
// This the returned leases should exclude reclaimed ones. So the number
// of returned leases should be roughly half of the expired leases.
ASSERT_NO_THROW(lmptr_->getExpiredLeases6(expired_leases, 0));
ASSERT_EQ(static_cast<size_t>(saved_expired_leases.size() / 2),
expired_leases.size());
// Make sure that returned leases are those that are not reclaimed, i.e.
// those that have even index.
for (Lease6Collection::iterator lease = expired_leases.begin();
lease != expired_leases.end(); ++lease) {
int index = static_cast<int>(std::distance(expired_leases.begin(), lease));
EXPECT_EQ(saved_expired_leases[2 * index]->addr_, (*lease)->addr_);
}
}
void
GenericLeaseMgrTest::testDeleteExpiredReclaimedLeases4() {
// Get the leases to be used for the test.
vector<Lease4Ptr> leases = createLeases4();
// Make sure we have at least 6 leases there.
ASSERT_GE(leases.size(), 6);
time_t current_time = time(NULL);
// Add them to the database
for (size_t i = 0; i < leases.size(); ++i) {
// Mark every other lease as expired.
if (i % 2 == 0) {
// Set client last transmission time to the value older than the
// valid lifetime to make it expired. We also substract the value
// of 10, 20, 30, 40 etc, depending on the lease index. This
// simulates different expiration times for various leases.
leases[i]->cltt_ = current_time - leases[i]->valid_lft_ - i * 10;
// Set reclaimed state.
leases[i]->state_ = Lease::STATE_EXPIRED_RECLAIMED;
} else {
// Other leases are left as not expired - client last transmission
// time set to current time.
leases[i]->cltt_ = current_time;
}
ASSERT_TRUE(lmptr_->addLease(leases[i]));
}
// Keep reclaimed lease for 15 seconds after expiration.
const uint32_t lease_affinity_time = 15;
// Delete expired and reclaimed leases which have expired earlier than
// 15 seconds ago. This should affect leases with index 2, 3, 4 etc.
uint64_t deleted_num;
uint64_t should_delete_num = 0;
ASSERT_NO_THROW(
deleted_num = lmptr_->deleteExpiredReclaimedLeases4(lease_affinity_time)
);
for (size_t i = 0; i < leases.size(); ++i) {
// Obtain lease from the server.
Lease4Ptr lease = lmptr_->getLease4(leases[i]->addr_);
// If the lease is reclaimed and the expiration time passed more than
// 15 seconds ago, the lease should have been deleted.
if (leases[i]->stateExpiredReclaimed() &&
((leases[i]->getExpirationTime() + lease_affinity_time) < current_time)) {
EXPECT_FALSE(lease) << "The following lease should have been"
" deleted: " << leases[i]->toText();
++should_delete_num;
} else {
// If the lease is not reclaimed or it has expired less than
// 15 seconds ago, the lease should still be there.
EXPECT_TRUE(lease) << "The following lease shouldn't have been"
" deleted: " << leases[i]->toText();
}
}
// Check that the number of leases deleted is correct.
EXPECT_EQ(deleted_num, should_delete_num);
// Make sure we can make another attempt, when there are no more leases
// to be deleted.
ASSERT_NO_THROW(
deleted_num = lmptr_->deleteExpiredReclaimedLeases4(lease_affinity_time)
);
// No lease should have been deleted.
EXPECT_EQ(0, deleted_num);
// Reopen the database. This to ensure that the leases have been deleted
// from the persistent storage.
reopen(V4);
for (size_t i = 0; i < leases.size(); ++i) {
/// @todo Leases with empty HW address are dropped by the memfile
/// backend. We will have to reevaluate if this is right behavior
/// of the backend when client identifier is present.
if (leases[i]->hwaddr_ && leases[i]->hwaddr_->hwaddr_.empty()) {
continue;
}
// Obtain lease from the server.
Lease4Ptr lease = lmptr_->getLease4(leases[i]->addr_);
// If the lease is reclaimed and the expiration time passed more than
// 15 seconds ago, the lease should have been deleted.
if (leases[i]->stateExpiredReclaimed() &&
((leases[i]->getExpirationTime() + lease_affinity_time) < current_time)) {
EXPECT_FALSE(lease) << "The following lease should have been"
" deleted: " << leases[i]->toText();
} else {
// If the lease is not reclaimed or it has expired less than
// 15 seconds ago, the lease should still be there.
EXPECT_TRUE(lease) << "The following lease shouldn't have been"
" deleted: " << leases[i]->toText();
}
}
}
void
GenericLeaseMgrTest::testDeleteExpiredReclaimedLeases6() {
// Get the leases to be used for the test.
vector<Lease6Ptr> leases = createLeases6();
// Make sure we have at least 6 leases there.
ASSERT_GE(leases.size(), 6);
time_t current_time = time(NULL);
// Add them to the database
for (size_t i = 0; i < leases.size(); ++i) {
// Mark every other lease as expired.
if (i % 2 == 0) {
// Set client last transmission time to the value older than the
// valid lifetime to make it expired. We also substract the value
// of 10, 20, 30, 40 etc, depending on the lease index. This
// simulates different expiration times for various leases.
leases[i]->cltt_ = current_time - leases[i]->valid_lft_ - i * 10;
// Set reclaimed state.
leases[i]->state_ = Lease::STATE_EXPIRED_RECLAIMED;
} else {
// Other leases are left as not expired - client last transmission
// time set to current time.
leases[i]->cltt_ = current_time;
}
ASSERT_TRUE(lmptr_->addLease(leases[i]));
}
// Keep reclaimed lease for 15 seconds after expiration.
const uint32_t lease_affinity_time = 15;
// Delete expired and reclaimed leases which have expired earlier than
// 15 seconds ago. This should affect leases with index 2, 3, 4 etc.
uint64_t deleted_num;
uint64_t should_delete_num = 0;
ASSERT_NO_THROW(
deleted_num = lmptr_->deleteExpiredReclaimedLeases6(lease_affinity_time)
);
for (size_t i = 0; i < leases.size(); ++i) {
// Obtain lease from the server.
Lease6Ptr lease = lmptr_->getLease6(leases[i]->type_, leases[i]->addr_);
// If the lease is reclaimed and the expiration time passed more than
// 15 seconds ago, the lease should have been deleted.
if (leases[i]->stateExpiredReclaimed() &&
((leases[i]->getExpirationTime() + lease_affinity_time) < current_time)) {
EXPECT_FALSE(lease) << "The following lease should have been"
" deleted: " << leases[i]->toText();
++should_delete_num;
} else {
// If the lease is not reclaimed or it has expired less than
// 15 seconds ago, the lease should still be there.
EXPECT_TRUE(lease) << "The following lease shouldn't have been"
" deleted: " << leases[i]->toText();
}
}
// Check that the number of deleted leases is correct.
EXPECT_EQ(should_delete_num, deleted_num);
// Make sure we can make another attempt, when there are no more leases
// to be deleted.
ASSERT_NO_THROW(
deleted_num = lmptr_->deleteExpiredReclaimedLeases6(lease_affinity_time)
);
// No lease should have been deleted.
EXPECT_EQ(0, deleted_num);
// Reopen the database. This to ensure that the leases have been deleted
// from the persistent storage.
reopen(V6);
for (size_t i = 0; i < leases.size(); ++i) {
// Obtain lease from the server.
Lease6Ptr lease = lmptr_->getLease6(leases[i]->type_, leases[i]->addr_);
// If the lease is reclaimed and the expiration time passed more than
// 15 seconds ago, the lease should have been deleted.
if (leases[i]->stateExpiredReclaimed() &&
((leases[i]->getExpirationTime() + lease_affinity_time) < current_time)) {
EXPECT_FALSE(lease) << "The following lease should have been"
" deleted: " << leases[i]->toText();
} else {
// If the lease is not reclaimed or it has expired less than
// 15 seconds ago, the lease should still be there.
EXPECT_TRUE(lease) << "The following lease shouldn't have been"
" deleted: " << leases[i]->toText();
}
}
}
}; // namespace test
}; // namespace dhcp

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -265,6 +265,42 @@ public:
/// @param minor Expected minor version to be reported.
void testVersion(int major, int minor);
/// @brief Checks that the expired DHCPv4 leases can be retrieved.
///
/// This test checks the following:
/// - all expired and not reclaimed leases are retured
/// - number of leases returned can be limited
/// - leases are returned in the order from the most expired to the
/// least expired
/// - reclaimed leases are not returned.
void testGetExpiredLeases4();
/// @brief Checks that the expired DHCPv6 leases can be retrieved.
///
/// This test checks the following:
/// - all expired and not reclaimed leases are retured
/// - number of leases returned can be limited
/// - leases are returned in the order from the most expired to the
/// least expired
/// - reclaimed leases are not returned.
void testGetExpiredLeases6();
/// @brief Checks that selected expired-reclaimed DHCPv6 leases
/// are removed.
///
/// This creates a number of DHCPv6 leases and marks some of them
/// as expired-reclaimed. It later verifies that the expired-reclaimed
/// leases can be removed.
void testDeleteExpiredReclaimedLeases6();
/// @brief Checks that selected expired-reclaimed DHCPv4 leases
/// are removed.
///
/// This creates a number of DHCPv4 leases and marks some of them
/// as expired-reclaimed. It later verifies that the expired-reclaimed
/// leases can be removed.
void testDeleteExpiredReclaimedLeases4();
/// @brief String forms of IPv4 addresses
std::vector<std::string> straddress4_;

View File

@@ -151,11 +151,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\n";
"fqdn_fwd,fqdn_rev,hostname,state\n";
v6_hdr_ = "address,duid,valid_lifetime,expire,subnet_id,"
"pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,"
"fqdn_rev,hostname,hwaddr\n";
"fqdn_rev,hostname,hwaddr,state\n";
}
};
@@ -179,17 +179,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\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\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,\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,\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\n";
"200,200,8,1,1,host.example.com,1\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
@@ -250,14 +250,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\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\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,\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,\n";
"100,135,7,0,0,,1\n";
// Create lease file in which one of the entries for 192.0.2.1
@@ -305,19 +305,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,\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,\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,\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,,\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,,\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,,\n";
"100,200,8,0,2,16,64,0,0,,,1\n";
@@ -379,14 +379,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,\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,\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,,\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,,\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
@@ -431,13 +431,13 @@ 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\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\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\n";
std::string b_1 = "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com,1\n";
std::string c_1 = "192.0.2.10,01:02:03:04:05:06,,200,300,8,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.
@@ -501,8 +501,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,\n";
std::string b_2 = "192.0.2.3,06:07:08:09:0a:bd,,0,200,8,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;

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -173,6 +173,23 @@ public:
return (leases6_);
}
/// @brief Returns expired DHCPv6 leases.
///
/// This method is not implemented.
virtual void getExpiredLeases6(Lease6Collection&, const size_t) const {
isc_throw(NotImplemented, "ConcreteLeaseMgr::getExpiredLeases6 is not"
" implemented");
}
/// @brief Returns expired DHCPv4 leases.
///
/// This method is not implemented.
virtual void getExpiredLeases4(Lease4Collection&, const size_t) const {
isc_throw(NotImplemented, "ConcreteLeaseMgr::getExpiredLeases4 is not"
" implemented");
}
/// @brief Updates IPv4 lease.
///
/// @param lease4 The lease to be updated.
@@ -197,6 +214,26 @@ public:
return (false);
}
/// @brief Deletes all expired and reclaimed DHCPv4 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t) {
isc_throw(NotImplemented, "ConcreteLeaseMgr::deleteExpiredReclaimedLeases4"
" is not implemented");
}
/// @brief Deletes all expired and reclaimed DHCPv6 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t) {
isc_throw(NotImplemented, "ConcreteLeaseMgr::deleteExpiredReclaimedLeases6"
" is not implemented");
}
/// @brief Returns backend type.
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)

View File

@@ -96,7 +96,6 @@ TEST_F(Lease4Test, constructor) {
"hostname.example.com.");
EXPECT_EQ(ADDRESS[i], static_cast<uint32_t>(lease.addr_));
EXPECT_EQ(0, lease.ext_);
EXPECT_TRUE(util::equalValues(hwaddr_, lease.hwaddr_));
EXPECT_TRUE(util::equalValues(clientid_, lease.client_id_));
EXPECT_EQ(0, lease.t1_);
@@ -104,11 +103,10 @@ TEST_F(Lease4Test, constructor) {
EXPECT_EQ(VALID_LIFETIME, lease.valid_lft_);
EXPECT_EQ(current_time, lease.cltt_);
EXPECT_EQ(SUBNET_ID, lease.subnet_id_);
EXPECT_FALSE(lease.fixed_);
EXPECT_EQ("hostname.example.com.", lease.hostname_);
EXPECT_TRUE(lease.fqdn_fwd_);
EXPECT_TRUE(lease.fqdn_rev_);
EXPECT_TRUE(lease.comments_.empty());
EXPECT_EQ(Lease::STATE_DEFAULT, lease.state_);
}
}
@@ -126,6 +124,10 @@ TEST_F(Lease4Test, copyConstructor) {
Lease4 lease(0xffffffff, hwaddr_, clientid_, VALID_LIFETIME, 0, 0, current_time,
SUBNET_ID);
// Declined is a non-default state. We'll see if the state will be copied
// or the default state will be set for the copied lease.
lease.state_ = Lease::STATE_DECLINED;
// Use copy constructor to copy the lease.
Lease4 copied_lease(lease);
@@ -163,8 +165,14 @@ TEST_F(Lease4Test, operatorAssign) {
Lease4 lease(0xffffffff, hwaddr_, clientid_, VALID_LIFETIME, 0, 0, current_time,
SUBNET_ID);
// Use assignment operator to assign the lease.
Lease4 copied_lease = lease;
// Declined is a non-default state. We'll see if the state will be copied
// or the default state will be set for the copied lease.
lease.state_ = Lease::STATE_DECLINED;
// Create a default lease.
Lease4 copied_lease;
// Use assignment operator to assign new lease.
copied_lease = lease;
// Both leases should be now equal. When doing this check we assume that
// the equality operator works correctly.
@@ -284,13 +292,6 @@ TEST_F(Lease4Test, operatorEquals) {
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
++lease1.ext_;
EXPECT_FALSE(lease1 == lease2);
EXPECT_TRUE(lease1 != lease2);
lease1.ext_ = lease2.ext_;
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
++lease1.hwaddr_->hwaddr_[0];
EXPECT_FALSE(lease1 == lease2);
EXPECT_TRUE(lease1 != lease2);
@@ -343,13 +344,6 @@ TEST_F(Lease4Test, operatorEquals) {
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
lease1.fixed_ = !lease1.fixed_;
EXPECT_FALSE(lease1 == lease2);
EXPECT_TRUE(lease1 != lease2);
lease1.fixed_ = lease2.fixed_;
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
lease1.hostname_ += std::string("Something random");
EXPECT_FALSE(lease1 == lease2);
EXPECT_TRUE(lease1 != lease2);
@@ -371,10 +365,10 @@ TEST_F(Lease4Test, operatorEquals) {
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
lease1.comments_ += std::string("Something random");
lease1.state_ += 1;
EXPECT_FALSE(lease1 == lease2);
EXPECT_TRUE(lease1 != lease2);
lease1.comments_ = lease2.comments_;
lease2.state_ += 1;
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
}
@@ -430,7 +424,8 @@ TEST_F(Lease4Test, toText) {
<< "Cltt: 12345678\n"
<< "Hardware addr: " << hwaddr_->toText(false) << "\n"
<< "Client id: " << clientid_->toText() << "\n"
<< "Subnet ID: 789\n";
<< "Subnet ID: 789\n"
<< "State: default\n";
EXPECT_EQ(expected.str(), lease.toText());
@@ -445,10 +440,18 @@ TEST_F(Lease4Test, toText) {
<< "Cltt: 12345678\n"
<< "Hardware addr: (none)\n"
<< "Client id: (none)\n"
<< "Subnet ID: 789\n";
<< "Subnet ID: 789\n"
<< "State: default\n";
EXPECT_EQ(expected.str(), lease.toText());
}
// Verify that the lease states are correctly returned in the textual format.
TEST_F(Lease4Test, stateToText) {
EXPECT_EQ("default", Lease4::statesToText(Lease::STATE_DEFAULT));
EXPECT_EQ("declined", Lease4::statesToText(Lease::STATE_DECLINED));
EXPECT_EQ("expired-reclaimed", Lease4::statesToText(Lease::STATE_EXPIRED_RECLAIMED));
}
/// @brief Creates an instance of the lease with certain FQDN data.
///
/// @param hostname Hostname.
@@ -467,7 +470,7 @@ Lease6 createLease6(const std::string& hostname, const bool fqdn_fwd,
// Lease6 is also defined in lease_mgr.h, so is tested in this file as well.
// This test checks if the Lease6 structure can be instantiated correctly
TEST(Lease6, Lease6ConstructorDefault) {
TEST(Lease6Test, Lease6ConstructorDefault) {
// check a variety of addresses with different bits set.
const char* ADDRESS[] = {
@@ -514,7 +517,7 @@ TEST(Lease6, Lease6ConstructorDefault) {
// This test verifies that the Lease6 constructor which accepts FQDN data,
// sets the data correctly for the lease.
TEST(Lease6, Lease6ConstructorWithFQDN) {
TEST(Lease6Test, Lease6ConstructorWithFQDN) {
// check a variety of addresses with different bits set.
const char* ADDRESS[] = {
@@ -563,7 +566,7 @@ TEST(Lease6, Lease6ConstructorWithFQDN) {
/// Checks that the operator==() correctly compares two leases for equality.
/// As operator!=() is also defined for this class, every check on operator==()
/// is followed by the reverse check on operator!=().
TEST(Lease6, OperatorEquals) {
TEST(Lease6Test, operatorEquals) {
// check a variety of addresses with different bits set.
const IOAddress addr("2001:db8:1::456");
@@ -665,13 +668,6 @@ TEST(Lease6, OperatorEquals) {
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
lease1.fixed_ = !lease1.fixed_;
EXPECT_FALSE(lease1 == lease2);
EXPECT_TRUE(lease1 != lease2);
lease1.fixed_ = lease2.fixed_;
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
lease1.hostname_ += std::string("Something random");
EXPECT_FALSE(lease1 == lease2);
EXPECT_TRUE(lease1 != lease2);
@@ -693,16 +689,16 @@ TEST(Lease6, OperatorEquals) {
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
lease1.comments_ += std::string("Something random");
lease1.state_ += 1;
EXPECT_FALSE(lease1 == lease2);
EXPECT_TRUE(lease1 != lease2);
lease1.comments_ = lease2.comments_;
lease2.state_ += 1;
EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
EXPECT_FALSE(lease1 != lease2); // ... leases equal
}
// Checks if lease expiration is calculated properly
TEST(Lease6, Lease6Expired) {
TEST(Lease6Test, Lease6Expired) {
const IOAddress addr("2001:db8:1::456");
const uint8_t duid_array[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
const DuidPtr duid(new DUID(duid_array, sizeof(duid_array)));
@@ -727,7 +723,7 @@ TEST(Lease6, Lease6Expired) {
// Verify that the DUID can be returned as a vector object and if DUID is NULL
// the empty vector is returned.
TEST(Lease6, getDuidVector) {
TEST(Lease6Test, getDuidVector) {
// Create a lease.
Lease6 lease;
// By default, the lease should have client id set to NULL. If it doesn't,
@@ -746,7 +742,7 @@ TEST(Lease6, getDuidVector) {
}
// Verify the behavior of the function which checks FQDN data for equality.
TEST(Lease6, hasIdenticalFqdn) {
TEST(Lease6Test, hasIdenticalFqdn) {
Lease6 lease = createLease6("myhost.example.com.", true, true);
EXPECT_TRUE(lease.hasIdenticalFqdn(createLease6("myhost.example.com.",
true, true)));
@@ -763,7 +759,7 @@ TEST(Lease6, hasIdenticalFqdn) {
}
// Verify that toText() method reports Lease4 structure properly.
TEST(Lease6, toText) {
TEST(Lease6Test, toText) {
HWAddrPtr hwaddr(new HWAddr(HWADDR, sizeof(HWADDR), HTYPE_ETHER));
@@ -773,6 +769,7 @@ TEST(Lease6, toText) {
Lease6 lease(Lease::TYPE_NA, IOAddress("2001:db8::1"), duid, 123456,
400, 800, 100, 200, 5678, hwaddr, 128);
lease.cltt_ = 12345678;
lease.state_ = Lease::STATE_DECLINED;
std::stringstream expected;
expected << "Type: IA_NA(" << static_cast<int>(Lease::TYPE_NA) << ")\n"
@@ -783,7 +780,8 @@ TEST(Lease6, toText) {
<< "Valid life: 800\n"
<< "Cltt: 12345678\n"
<< "Hardware addr: " << hwaddr->toText(false) << "\n"
<< "Subnet ID: 5678\n";
<< "Subnet ID: 5678\n"
<< "State: declined\n";
EXPECT_EQ(expected.str(), lease.toText());
@@ -798,8 +796,17 @@ TEST(Lease6, toText) {
<< "Valid life: 800\n"
<< "Cltt: 12345678\n"
<< "Hardware addr: (none)\n"
<< "Subnet ID: 5678\n";
<< "Subnet ID: 5678\n"
<< "State: declined\n";
EXPECT_EQ(expected.str(), lease.toText());
}
// Verify that the lease states are correctly returned in the textual format.
TEST(Lease6Test, stateToText) {
EXPECT_EQ("default", Lease6::statesToText(Lease::STATE_DEFAULT));
EXPECT_EQ("declined", Lease6::statesToText(Lease::STATE_DECLINED));
EXPECT_EQ("expired-reclaimed", Lease6::statesToText(Lease::STATE_EXPIRED_RECLAIMED));
}
}; // end of anonymous namespace

View File

@@ -404,20 +404,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\n";
"subnet_id,fqdn_fwd,fqdn_rev,hostname,state\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,,\n"
"192.0.2.2,02:02:02:02:02:02,,200,800,8,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,,\n"
"192.0.2.3,03:03:03:03:03:03,,200,800,8,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);
@@ -453,15 +453,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,\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,\n"
"192.0.2.3,03:03:03:03:03:03,,200,800,8,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
@@ -480,24 +480,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\n";
"fqdn_rev,hostname,hwaddr,state\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,,\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,,\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,,\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,,\n";
"8,100,0,7,0,1,1,,,1\n";
LeaseFileIO previous_file(getLeaseFilePath("leasefile6_0.csv.2"));
previous_file.writeFile(previous_file_contents);
@@ -536,7 +536,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,,\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
@@ -544,9 +544,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,,\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,,\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
@@ -564,11 +564,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\n";
"subnet_id,fqdn_fwd,fqdn_rev,hostname,state\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,,\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);
@@ -605,15 +605,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\n";
"fqdn_rev,hostname,hwaddr,state\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,,\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,,\n";
"8,100,0,7,0,1,1,,,1\n";
LeaseFileIO current_file(getLeaseFilePath("leasefile6_0.csv"));
current_file.writeFile(current_file_contents);
@@ -621,7 +621,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,,\n";
"8,100,0,7,0,1,1,,,1\n";
LeaseFileIO finish_file(getLeaseFilePath("leasefile6_0.csv.completed"));
finish_file.writeFile(finish_file_contents);
@@ -668,15 +668,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\n";
"fqdn_rev,hostname,hwaddr,state\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,,\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,,\n";
"8,100,0,7,0,1,1,,,1\n";
LeaseFileIO current_file(getLeaseFilePath("leasefile6_0.csv"));
current_file.writeFile(current_file_contents);
@@ -686,7 +686,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,,\n";
"8,100,0,7,0,1,1,,,1\n";
LeaseFileIO input_file(getLeaseFilePath("leasefile6_0.csv.1"));
input_file.writeFile(input_file_contents);
@@ -872,15 +872,48 @@ TEST_F(MemfileLeaseMgrTest, getLeases6DuidIaid) {
testGetLeases6DuidIaid();
}
// Check that the system can cope with a DUID of allowed size.
/// @todo: test disabled, because Memfile_LeaseMgr::getLeases6(Lease::Type,
/// const DUID& duid, uint32_t iaid) const is not implemented yet.
/// @brief Check that the system can cope with a DUID of allowed size.
TEST_F(MemfileLeaseMgrTest, getLeases6DuidSize) {
startBackend(V6);
testGetLeases6DuidSize();
}
/// @brief Check that the expired DHCPv4 leases can be retrieved.
///
/// This test adds a number of leases to the lease database and marks
/// some of them as expired. Then it queries for expired leases and checks
/// whether only expired leases are returned, and that they are returned in
/// the order from most to least expired. It also checks that the lease
/// which is marked as 'reclaimed' is not returned.
TEST_F(MemfileLeaseMgrTest, getExpiredLeases4) {
startBackend(V4);
testGetExpiredLeases4();
}
/// @brief Check that the expired DHCPv6 leases can be retrieved.
///
/// This test adds a number of leases to the lease database and marks
/// some of them as expired. Then it queries for expired leases and checks
/// whether only expired leases are returned, and that they are returned in
/// the order from most to least expired. It also checks that the lease
/// which is marked as 'reclaimed' is not returned.
TEST_F(MemfileLeaseMgrTest, getExpiredLeases6) {
startBackend(V6);
testGetExpiredLeases6();
}
/// @brief Check that expired reclaimed DHCPv6 leases are removed.
TEST_F(MemfileLeaseMgrTest, deleteExpiredReclaimedLeases6) {
startBackend(V6);
testDeleteExpiredReclaimedLeases6();
}
/// @brief Check that expired reclaimed DHCPv4 leases are removed.
TEST_F(MemfileLeaseMgrTest, deleteExpiredReclaimedLeases4) {
startBackend(V4);
testDeleteExpiredReclaimedLeases4();
}
/// @brief Check that getLease6 methods discriminate by lease type.
///
/// Adds six leases, two per lease type all with the same duid and iad but
@@ -975,43 +1008,6 @@ TEST_F(MemfileLeaseMgrTest, testLease6Mac) {
testLease6MAC();
}
/// @brief Tests whether memfile is able to work with old CSV file (without mac)
///
/// Ticket #3555 introduced MAC address support in Lease6. Instead of developing
/// an upgrade script, the code is written in a way that allows reading old CSV
/// (i.e. format that was used in Kea 0.9), hence no upgrade is necessary.
TEST_F(MemfileLeaseMgrTest, testUpgrade0_9_0_to_0_9_1) {
// Let's write a CSV file without hwaddr column. Sorry about the long
// lines, but nobody was around to whine about 80 columns limit when CSV
// format was invented :).
string csv_nohwaddr =
"address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname\n"
"2001:db8::1,42:42:42:42:42:42:42:42,3677,127133,73,3600,1,42,0,0,1,myhost.example.com.\n"
"2001:db8::2,3a:3a:3a:3a:3a:3a:3a:3a,5412,239979,73,1800,2,89,7,0,0,myhost.example.com.\n"
"2001:db8::3,1f:20:21:22:23:24:25:26,7000,241567,37,7200,0,4294967294,28,1,0,myhost.example.com.\n";
ofstream csv(getLeaseFilePath("leasefile6_0.csv").c_str(), ios::out | ios::trunc);
ASSERT_TRUE(csv.is_open());
csv << csv_nohwaddr;
csv.close();
startBackend(V6);
// None of the leases should have any hardware addresses assigned.
Lease6Ptr stored1 = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]);
ASSERT_TRUE(stored1);
EXPECT_FALSE(stored1->hwaddr_);
Lease6Ptr stored2 = lmptr_->getLease6(leasetype6_[2], ioaddress6_[2]);
ASSERT_TRUE(stored2);
EXPECT_FALSE(stored2->hwaddr_);
Lease6Ptr stored3 = lmptr_->getLease6(leasetype6_[3], ioaddress6_[3]);
ASSERT_TRUE(stored3);
EXPECT_FALSE(stored3->hwaddr_);
}
// Check that memfile reports version correctly.
TEST_F(MemfileLeaseMgrTest, versionCheck) {
@@ -1033,22 +1029,22 @@ TEST_F(MemfileLeaseMgrTest, versionCheck) {
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\n"
"192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,\n"
"192.0.2.11,bb:bb:bb:bb:bb:bb,,200,200,8,1,1,,\n");
"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");
LeaseFileIO io1(getLeaseFilePath("leasefile4_0.csv.1"));
io1.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
"fqdn_fwd,fqdn_rev,hostname\n"
"192.0.2.1,01:01:01:01:01:01,,200,200,8,1,1,,\n"
"192.0.2.11,bb:bb:bb:bb:bb:bb,,200,400,8,1,1,,\n"
"192.0.2.12,cc:cc:cc:cc:cc:cc,,200,200,8,1,1,,\n");
"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");
LeaseFileIO io(getLeaseFilePath("leasefile4_0.csv"));
io.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
"fqdn_fwd,fqdn_rev,hostname\n"
"192.0.2.10,0a:0a:0a:0a:0a:0a,,200,200,8,1,1,,\n"
"192.0.2.12,cc:cc:cc:cc:cc:cc,,200,400,8,1,1,,\n");
"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");
startBackend(V4);
@@ -1091,27 +1087,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\n"
"192.0.2.2,02:02:02:02:02:02,,200,200,8,1,1,,\n"
"192.0.2.11,bb:bb:bb:bb:bb:bb,,200,200,8,1,1,,\n");
"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");
LeaseFileIO io1(getLeaseFilePath("leasefile4_0.csv.1"));
io1.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
"fqdn_fwd,fqdn_rev,hostname\n"
"192.0.2.1,01:01:01:01:01:01,,200,200,8,1,1,,\n"
"192.0.2.11,bb:bb:bb:bb:bb:bb,,200,400,8,1,1,,\n"
"192.0.2.12,cc:cc:cc:cc:cc:cc,,200,200,8,1,1,,\n");
"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");
LeaseFileIO io(getLeaseFilePath("leasefile4_0.csv"));
io.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
"fqdn_fwd,fqdn_rev,hostname\n"
"192.0.2.10,0a:0a:0a:0a:0a:0a,,200,200,8,1,1,,\n"
"192.0.2.12,cc:cc:cc:cc:cc:cc,,200,400,8,1,1,,\n");
"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");
LeaseFileIO ioc(getLeaseFilePath("leasefile4_0.csv.completed"));
ioc.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
"fqdn_fwd,fqdn_rev,hostname\n"
"192.0.2.13,ff:ff:ff:ff:ff:ff,,200,200,8,1,1,,\n");
"fqdn_fwd,fqdn_rev,hostname,state\n"
"192.0.2.13,ff:ff:ff:ff:ff:ff,,200,200,8,1,1,,1\n");
startBackend(V4);
@@ -1167,29 +1163,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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\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,,\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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\n");
"200,200,8,100,0,7,0,1,1,,,1\n");
startBackend(V6);
@@ -1230,21 +1229,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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\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,,\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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\n");
"200,200,8,100,0,7,0,1,1,,,1\n");
startBackend(V6);
@@ -1276,19 +1277,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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\n");
"200,200,8,100,0,7,0,1,1,,,1\n");
startBackend(V6);
@@ -1322,35 +1325,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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\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,,\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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\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,,\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\n"
"lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,"
"state\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,,\n");
"400,1000,8,100,0,7,0,1,1,,,1\n");
startBackend(V6);