Browse Source

[3709] allocateLease4 now uses ClientContext4

Tomek Mrugalski 10 years ago
parent
commit
7394da5b3d

+ 6 - 8
src/bin/dhcp4/dhcp4_srv.cc

@@ -1077,13 +1077,11 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
     // may be used instead. If fake_allocation is set to false, the lease will
     // be inserted into the LeaseMgr as well.
     /// @todo pass the actual FQDN data.
-    Lease4Ptr old_lease;
-    Lease4Ptr lease = alloc_engine_->allocateLease4(subnet, client_id, hwaddr,
-                                                    hint, fqdn_fwd, fqdn_rev,
-                                                    hostname,
-                                                    fake_allocation,
-                                                    callout_handle,
-                                                    old_lease);
+    AllocEngine::ClientContext4 ctx(subnet, client_id, hwaddr, hint, fqdn_fwd,
+                                    fqdn_rev, hostname, fake_allocation);
+    ctx.callout_handle_ = callout_handle;
+
+    Lease4Ptr lease = alloc_engine_->allocateLease4(ctx);
 
     if (lease) {
         // We have a lease! Let's set it in the packet and send it back to
@@ -1172,7 +1170,7 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
         // real allocation.
         if (!fake_allocation && CfgMgr::instance().ddnsEnabled()) {
             try {
-                createNameChangeRequests(lease, old_lease);
+                createNameChangeRequests(lease, ctx.old_lease_);
             } catch (const Exception& ex) {
                 LOG_ERROR(dhcp4_logger, DHCP4_NCR_CREATION_FAILED)
                     .arg(ex.what());

+ 26 - 58
src/lib/dhcpsrv/alloc_engine.cc

@@ -801,54 +801,27 @@ AllocEngine::removeNonreservedLeases6(ClientContext6& ctx,
 }
 
 Lease4Ptr
-AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid,
-                            const HWAddrPtr& hwaddr, const IOAddress& hint,
-                            const bool fwd_dns_update, const bool rev_dns_update,
-                            const std::string& hostname, bool fake_allocation,
-                            const isc::hooks::CalloutHandlePtr& callout_handle,
-                            Lease4Ptr& old_lease) {
+AllocEngine::allocateLease4(ClientContext4& ctx) {
 
     // The NULL pointer indicates that the old lease didn't exist. It may
     // be later set to non NULL value if existing lease is found in the
     // database.
-    old_lease.reset();
+    ctx.old_lease_.reset();
 
     try {
 
         // Set allocator.
         AllocatorPtr allocator = getAllocator(Lease::TYPE_V4);
 
-        if (!subnet) {
+        if (!ctx.subnet_) {
             isc_throw(BadValue, "Can't allocate IPv4 address without subnet");
         }
 
-        if (!hwaddr) {
+        if (!ctx.hwaddr_) {
             isc_throw(BadValue, "HWAddr must be defined");
         }
 
-        /// @todo The context for lease allocation should really be created
-        /// by the DHCPv4 server and passed to this function. The reason for
-        /// this is that the server should retrieve the Host object for the
-        /// client because the Host object contains the data not only useful
-        /// for the address allocation but also hostname and DHCP options
-        /// for the client. The Host object should be passed in the context.
-        /// Making this change would require a change to the allocateLease4
-        /// API which would in turn require lots of changes in unit tests.
-        /// The ticket introducing a context and host reservation in the
-        /// allocation engine is complex enough by itself to warrant that
-        /// the API change is done with a separate ticket (#3709).
-        ClientContext4 ctx;
-        ctx.subnet_ = subnet;
-        ctx.clientid_ = clientid;
-        ctx.hwaddr_ = hwaddr;
-        ctx.requested_address_ = hint;
-        ctx.fwd_dns_update_ = fwd_dns_update;
-        ctx.rev_dns_update_ = rev_dns_update;
-        ctx.hostname_ = hostname;
-        ctx.fake_allocation_ = fake_allocation;
-        ctx.callout_handle_ = callout_handle;
-        ctx.old_lease_ = old_lease;
-        ctx.host_ = HostMgr::instance().get4(subnet->getID(), hwaddr);
+        ctx.host_ = HostMgr::instance().get4(ctx.subnet_->getID(), ctx.hwaddr_);
 
         // If there is a reservation for this client we want to allocate the
         // reserved address to the client, rather than any other address.
@@ -876,9 +849,9 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
         // Check if the client has any leases in the lease database, using HW
         // address or client identifier.
         LeaseMgr& lease_mgr = LeaseMgrFactory::instance();
-        Lease4Ptr existing = lease_mgr.getLease4(*hwaddr, ctx.subnet_->getID());
-        if (!existing && clientid) {
-            existing = lease_mgr.getLease4(*clientid, ctx.subnet_->getID());
+        Lease4Ptr existing = lease_mgr.getLease4(*ctx.hwaddr_, ctx.subnet_->getID());
+        if (!existing && ctx.clientid_) {
+            existing = lease_mgr.getLease4(*ctx.clientid_, ctx.subnet_->getID());
         }
 
         // If client has a lease there are two choices. The server may need
@@ -896,7 +869,6 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
             // send DHCPNAK to indicate that the client should try to
             // start over the allocation process.
             if (ctx.interrupt_processing_) {
-                old_lease = ctx.old_lease_;
                 return (Lease4Ptr());
 
             // If we tried to reallocate the reserved lease we return
@@ -904,7 +876,6 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
             // We also return when allocation passed, no matter if this
             // was a reserved address or not.
             } else  if (ctx.host_ || existing) {
-                old_lease = ctx.old_lease_;
                 return (existing);
             }
         }
@@ -913,7 +884,7 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
         // proceed with a new allocation. We will try to allocate a
         // reserved address or an address from a dynamic pool if there is
         // no reservation.
-        if (ctx.host_ || subnet->inPool(Lease::TYPE_V4, ctx.requested_address_)) {
+        if (ctx.host_ || ctx.subnet_->inPool(Lease::TYPE_V4, ctx.requested_address_)) {
             // If a client is requesting specific IP address, but the
             // reservation was made for a different address the server returns
             // NAK to the client. By returning NULL lease here we indicate to
@@ -955,11 +926,13 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
                 if (!existing) {
                     // The candidate address is currently unused. Let's create a
                     // lease for it.
-                    Lease4Ptr lease = createLease4(subnet, clientid, hwaddr,
-                                                   candidate, fwd_dns_update,
-                                                   rev_dns_update,
-                                                   hostname, callout_handle,
-                                                   fake_allocation);
+                    Lease4Ptr lease = createLease4(ctx.subnet_, ctx.clientid_,
+                                                   ctx.hwaddr_, candidate,
+                                                   ctx.fwd_dns_update_,
+                                                   ctx.rev_dns_update_,
+                                                   ctx.hostname_,
+                                                   ctx.callout_handle_,
+                                                   ctx.fake_allocation_);
 
                     // If we have allocated the lease let's return it. Also,
                     // always return when tried to allocate reserved address,
@@ -977,7 +950,7 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
                 } else {
                     if (existing->expired()) {
                         // Save the old lease, before reusing it.
-                        old_lease.reset(new Lease4(*existing));
+                        ctx.old_lease_.reset(new Lease4(*existing));
                         return (reuseExpiredLease(existing, ctx));
 
                         // The existing lease is not expired (is in use by some
@@ -1001,24 +974,19 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
         // - we find a free address
         // - we find an address for which the lease has expired
         // - we exhaust the number of tries
-        //
-        /// @todo: We used to use hardcoded number of attempts (100). Now we dynamically
-        /// calculate the number of possible leases in all pools in this subnet and
-        /// try that number of times at most. It would be useful to that value if
-        /// attempts_, specified by the user could override that value (and keep
-        /// dynamic if they're set to 0).
-        uint64_t i = subnet->getPoolCapacity(Lease::TYPE_V4);
+        uint64_t i = ctx.subnet_->getPoolCapacity(Lease::TYPE_V4);
         do {
             // Decrease the number of remaining attempts here so as we guarantee
             // that it is decreased when the code below uses "continue".
             --i;
-            IOAddress candidate = allocator->pickAddress(subnet, clientid,
+            IOAddress candidate = allocator->pickAddress(ctx.subnet_,
+                                                         ctx.clientid_,
                                                          ctx.requested_address_);
 
             // Check if this address is reserved. There is no need to check for
             // whom it is reserved, because if it has been reserved for us we would
             // have already allocated a lease.
-            if (HostMgr::instance().get4(subnet->getID(), candidate)) {
+            if (HostMgr::instance().get4(ctx.subnet_->getID(), candidate)) {
                 // Don't allocate a reserved address.
                 continue;
             }
@@ -1027,10 +995,10 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
             if (!existing) {
                 // there's no existing lease for selected candidate, so it is
                 // free. Let's allocate it.
-                Lease4Ptr lease = createLease4(subnet, clientid, hwaddr,
-                                               candidate, fwd_dns_update,
-                                               rev_dns_update, hostname,
-                                               callout_handle, fake_allocation);
+                Lease4Ptr lease = createLease4(ctx.subnet_, ctx.clientid_, ctx.hwaddr_,
+                                               candidate, ctx.fwd_dns_update_,
+                                               ctx.rev_dns_update_, ctx.hostname_,
+                                               ctx.callout_handle_, ctx.fake_allocation_);
                 if (lease) {
                     return (lease);
                 }
@@ -1041,7 +1009,7 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
             } else {
                 if (existing->expired()) {
                     // Save old lease before reusing it.
-                    old_lease.reset(new Lease4(*existing));
+                    ctx.old_lease_.reset(new Lease4(*existing));
                     return (reuseExpiredLease(existing, ctx));
                 }
             }

+ 58 - 35
src/lib/dhcpsrv/alloc_engine.h

@@ -225,6 +225,40 @@ protected:
     /// information to the allocation engine methods is that adding
     /// new information doesn't modify the API of the allocation engine.
     struct ClientContext4 {
+        /// @brief Default constructor.
+        ClientContext4()
+            : subnet_(), clientid_(), hwaddr_(), requested_address_("0.0.0.0"),
+              fwd_dns_update_(false), rev_dns_update_(false),
+              hostname_(""), callout_handle_(), fake_allocation_(false),
+              old_lease_(), host_(), interrupt_processing_(false) {
+        }
+
+        /// @brief Constructor with parameters
+        /// @param subnet subnet the allocation should come from (mandatory)
+        /// @param clientid Client identifier (optional)
+        /// @param hwaddr Client's hardware address info (mandatory)
+        /// @param hint A hint that the client provided (may be 0.0.0.0)
+        /// @param fwd_dns_update Indicates whether forward DNS
+        ///      update will be performed for the client (true) or not (false).
+        /// @param rev_dns_update Indicates whether reverse DNS
+        ///      update will be performed for the client (true) or not (false).
+        /// @param hostname A string carrying hostname to be used for DNS updates.
+        /// @param fake_allocation Is this real i.e. REQUEST (false)
+        ///      or just picking an address for DISCOVER that is not really
+        ///      allocated (true)
+        ClientContext4(const SubnetPtr& subnet, const ClientIdPtr& clientid,
+                       const HWAddrPtr& hwaddr,
+                       const asiolink::IOAddress& requested_addr,
+                       const bool fwd_dns_update, const bool rev_dns_update,
+                       const std::string& hostname, const bool fake_allocation)
+            : subnet_(subnet), clientid_(clientid), hwaddr_(hwaddr),
+            requested_address_(requested_addr),
+            fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update),
+            hostname_(hostname), callout_handle_(),
+            fake_allocation_(fake_allocation), old_lease_(), host_(),
+            interrupt_processing_(false) {
+        }
+
         /// @brief Subnet selected for the client by the server.
         SubnetPtr subnet_;
 
@@ -283,14 +317,6 @@ protected:
         /// @c AllocEngine::renewLease4 sets this flag so as the
         /// upstream methods return the NULL lease pointer to the server.
         bool interrupt_processing_;
-
-        /// @brief Default constructor.
-        ClientContext4()
-            : subnet_(), clientid_(), hwaddr_(), requested_address_("0.0.0.0"),
-              fwd_dns_update_(false), rev_dns_update_(false),
-              hostname_(""), callout_handle_(), fake_allocation_(false),
-              old_lease_(), host_(), interrupt_processing_(false) {
-        }
     };
 
     /// @brief Defines a single hint (an address + prefix-length).
@@ -552,35 +578,32 @@ protected:
     /// returned, it is an indication that allocation engine reused/renewed an
     /// existing lease.
     ///
-    /// @todo Replace parameters with a single parameter of a
-    /// @c ClientContext4 type.
-    ///
-    /// @param subnet subnet the allocation should come from
-    /// @param clientid Client identifier
-    /// @param hwaddr Client's hardware address info
-    /// @param hint A hint that the client provided
-    /// @param fwd_dns_update Indicates whether forward DNS update will be
-    ///        performed for the client (true) or not (false).
-    /// @param rev_dns_update Indicates whether reverse DNS update will be
-    ///        performed for the client (true) or not (false).
-    /// @param hostname A string carrying hostname to be used for DNS updates.
-    /// @param fake_allocation Is this real i.e. REQUEST (false) or just picking
-    ///        an address for DISCOVER that is not really allocated (true)
-    /// @param callout_handle A callout handle (used in hooks). A lease callouts
-    ///        will be executed if this parameter is passed.
-    /// @param [out] old_lease Holds the pointer to a previous instance of a
-    ///        lease. The NULL pointer indicates that lease didn't exist prior
-    ///        to calling this function (e.g. new lease has been allocated).
+    /// @param ctx client context that passes all necessary information. See
+    ///        @ref ClientContext4 for details.
+    ///
+    /// The following fields of @ref ClientContext4 are used:
+    ///
+    /// @ref ClientContext4::subnet_ subnet the allocation should come from
+    /// @ref ClientContext4::clientid_ Client identifier
+    /// @ref ClientContext4::hwaddr_ Client's hardware address info
+    /// @ref ClientContext4::hint_ A hint that the client provided
+    /// @ref ClientContext4::fwd_dns_update_ Indicates whether forward DNS
+    ///      update will be performed for the client (true) or not (false).
+    /// @ref ClientContext4::rev_dns_update_ Indicates whether reverse DNS
+    ///      update will be performed for the client (true) or not (false).
+    /// @ref ClientContext4::hostname_ A string carrying hostname to be used for
+    ///      DNS updates.
+    /// @ref ClientContext4::fake_allocation_ Is this real i.e. REQUEST (false)
+    ///      or just picking an address for DISCOVER that is not really
+    ///      allocated (true)
+    /// @ref ClientContext4::callout_handle_ A callout handle (used in hooks).
+    ///      A lease callouts will be executed if this parameter is passed.
+    /// @ref ClientContext4::old_lease_ [out] Holds the pointer to a previous
+    ///      instance of a lease. The NULL pointer indicates that lease didn't
+    ///      exist prior to calling this function (e.g. new lease has been allocated).
     ///
     /// @return Allocated IPv4 lease (or NULL if allocation failed).
-    Lease4Ptr
-    allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid,
-                   const HWAddrPtr& hwaddr,
-                   const isc::asiolink::IOAddress& hint,
-                   const bool fwd_dns_update, const bool rev_dns_update,
-                   const std::string& hostname, bool fake_allocation,
-                   const isc::hooks::CalloutHandlePtr& callout_handle,
-                   Lease4Ptr& old_lease);
+    Lease4Ptr allocateLease4(ClientContext4& ctx);
 
     /// @brief Renews an DHCPv4 lease.
     ///

+ 225 - 258
src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc

@@ -57,14 +57,12 @@ TEST_F(AllocEngine4Test, simpleAlloc4) {
                                                  100, false)));
     ASSERT_TRUE(engine);
 
-    Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("0.0.0.0"),
-                                               false, true,
-                                               "somehost.example.com.",
-                                               false, CalloutHandlePtr(),
-                                               old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
+                                    false, true, "somehost.example.com.", false);
+
+    Lease4Ptr lease = engine->allocateLease4(ctx);
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -87,14 +85,14 @@ TEST_F(AllocEngine4Test, fakeAlloc4) {
                                                  100, false)));
     ASSERT_TRUE(engine);
 
-    Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("0.0.0.0"),
-                                               false, true, "host.example.com.",
-                                               true, CalloutHandlePtr(),
-                                               old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, true,
+                                    "host.example.com.", true);
+
+    Lease4Ptr lease = engine->allocateLease4(ctx);
 
     // The new lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -116,16 +114,16 @@ TEST_F(AllocEngine4Test, allocWithValidHint4) {
                                                  100, false)));
     ASSERT_TRUE(engine);
 
-    Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("192.0.2.105"),
-                                               true, true, "host.example.com.",
-                                               false, CalloutHandlePtr(),
-                                               old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.105"), true, true,
+                                    "host.example.com.", false);
+    Lease4Ptr lease = engine->allocateLease4(ctx);
+
     // Check that we got a lease
     ASSERT_TRUE(lease);
 
     // We have allocated the new lease, so the old lease should not exist.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 
     // We should get what we asked for
     EXPECT_EQ(lease->addr_.toText(), "192.0.2.105");
@@ -162,14 +160,13 @@ TEST_F(AllocEngine4Test, allocWithUsedHint4) {
     // Another client comes in and request an address that is in pool, but
     // unfortunately it is used already. The same address must not be allocated
     // twice.
-    Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("192.0.2.106"),
-                                               false, false, "",
-                                               false, CalloutHandlePtr(),
-                                               old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.106"), false, false,
+                                    "", false);
+    Lease4Ptr lease = engine->allocateLease4(ctx);
 
     // New lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 
     // Check that we got a lease
     ASSERT_TRUE(lease);
@@ -203,16 +200,15 @@ TEST_F(AllocEngine4Test, allocBogusHint4) {
     // Client would like to get a 3000::abc lease, which does not belong to any
     // supported lease. Allocation engine should ignore it and carry on
     // with the normal allocation
-    Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("10.1.1.1"),
-                                               false, false, "",
-                                               false, CalloutHandlePtr(),
-                                               old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("10.1.1.1"), false, false,
+                                    "", false);
+    Lease4Ptr lease = engine->allocateLease4(ctx);
     // Check that we got a lease
     ASSERT_TRUE(lease);
 
     // We have allocated a new lease, so the old lease should not exist.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 
     // We should NOT get what we asked for, because it is used already
     EXPECT_NE("10.1.1.1", lease->addr_.toText());
@@ -237,33 +233,32 @@ TEST_F(AllocEngine4Test, allocateLease4Nulls) {
     ASSERT_TRUE(engine);
 
     // Allocations without subnet are not allowed
-    Lease4Ptr lease = engine->allocateLease4(SubnetPtr(), clientid_, hwaddr_,
-                                               IOAddress("0.0.0.0"),
-                                               false, false, "",
-                                               false, CalloutHandlePtr(),
-                                               old_lease_);
+    AllocEngine::ClientContext4 ctx1(SubnetPtr(), clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", false);
+    Lease4Ptr lease = engine->allocateLease4(ctx1);
+
     EXPECT_FALSE(lease);
 
     // Allocations without HW address are not allowed
-    lease = engine->allocateLease4(subnet_, clientid_, HWAddrPtr(),
-                                     IOAddress("0.0.0.0"),
-                                     false, false, "",
-                                     false, CalloutHandlePtr(),
-                                     old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, clientid_, HWAddrPtr(),
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", false);
+    lease = engine->allocateLease4(ctx2);
     EXPECT_FALSE(lease);
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx2.old_lease_);
 
     // Allocations without client-id are allowed
-    clientid_ = ClientIdPtr();
-    lease = engine->allocateLease4(subnet_, ClientIdPtr(), hwaddr_,
-                                     IOAddress("0.0.0.0"),
-                                     true, true, "myhost.example.com.",
-                                     false, CalloutHandlePtr(),
-                                     old_lease_);
+    clientid_.reset();
+    AllocEngine::ClientContext4 ctx3(subnet_, ClientIdPtr(), hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", false);
+    lease = engine->allocateLease4(ctx3);
+
     // Check that we got a lease
     ASSERT_TRUE(lease);
     // New lease has been allocated, so the old lease should not exist.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx3.old_lease_);
 
     // Do all checks on the lease
     checkLease4(lease);
@@ -367,17 +362,16 @@ TEST_F(AllocEngine4Test, smallPool4) {
     subnet_->addPool(pool_);
     cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
 
-    Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("0.0.0.0"),
-                                               true, true, "host.example.com.",
-                                               false, CalloutHandlePtr(),
-                                               old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "host.example.com.", false);
+    Lease4Ptr lease = engine->allocateLease4(ctx);
 
     // Check that we got that single lease
     ASSERT_TRUE(lease);
 
     // We have allocated new lease, so the old lease should not exist.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 
     EXPECT_EQ("192.0.2.17", lease->addr_.toText());
 
@@ -425,13 +419,12 @@ TEST_F(AllocEngine4Test, outOfAddresses4) {
     // There is just a single address in the pool and allocated it to someone
     // else, so the allocation should fail
 
-    Lease4Ptr lease2 = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                                IOAddress("0.0.0.0"),
-                                                false, false, "",
-                                                false, CalloutHandlePtr(),
-                                                old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "host.example.com.", false);
+    Lease4Ptr lease2 = engine->allocateLease4(ctx);
     EXPECT_FALSE(lease2);
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 }
 
 // This test checks if an expired lease can be reused in DISCOVER (fake allocation)
@@ -469,11 +462,10 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
     ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
 
     // CASE 1: Asking for any address
-    lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                     IOAddress("0.0.0.0"),
-                                     false, false, "",
-                                     true, CalloutHandlePtr(),
-                                     old_lease_);
+    AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", true);
+    lease = engine->allocateLease4(ctx1);
     // Check that we got that single lease
     ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
@@ -481,26 +473,25 @@ TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
     // We are reusing expired lease, the old (expired) instance should be
     // returned. The returned instance should be the same as the original
     // lease.
-    ASSERT_TRUE(old_lease_);
-    EXPECT_TRUE(original_lease == *old_lease_);
+    ASSERT_TRUE(ctx1.old_lease_);
+    EXPECT_TRUE(original_lease == *ctx1.old_lease_);
 
     // Do all checks on the lease (if subnet-id, preferred/valid times are ok etc.)
     checkLease4(lease);
 
     // CASE 2: Asking specifically for this address
-    lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                     IOAddress(addr),
-                                     false, false, "",
-                                     true, CalloutHandlePtr(),
-                                     old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
+                                    IOAddress(addr), false, false,
+                                    "", true);
+    lease = engine->allocateLease4(ctx2);
     // Check that we got that single lease
     ASSERT_TRUE(lease);
     EXPECT_EQ(addr, lease->addr_);
 
     // We are updating expired lease. The copy of the old lease should be
     // returned and it should be equal to the original lease.
-    ASSERT_TRUE(old_lease_);
-    EXPECT_TRUE(*old_lease_ == original_lease);
+    ASSERT_TRUE(ctx2.old_lease_);
+    EXPECT_TRUE(*ctx2.old_lease_ == original_lease);
 }
 
 // This test checks if an expired lease can be reused in REQUEST (actual allocation)
@@ -530,11 +521,10 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
     ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
 
     // A client comes along, asking specifically for this address
-    lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                     IOAddress(addr),
-                                     false, true, "host.example.com.",
-                                     false, CalloutHandlePtr(),
-                                     old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress(addr), false, false,
+                                    "host.example.com.", false);
+    lease = engine->allocateLease4(ctx);
 
     // Check that he got that single lease
     ASSERT_TRUE(lease);
@@ -549,8 +539,8 @@ TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
 
     // The allocation engine should return a copy of the old lease. This
     // lease should be equal to the original lease.
-    ASSERT_TRUE(old_lease_);
-    EXPECT_TRUE(*old_lease_ == original_lease);
+    ASSERT_TRUE(ctx.old_lease_);
+    EXPECT_TRUE(*ctx.old_lease_ == original_lease);
 }
 
 /// @todo write renewLease6
@@ -627,11 +617,11 @@ TEST_F(AllocEngine4Test, reservedAddressNoHint) {
     // Try to allocate a lease without specifying a hint. This is actually
     // incorrect behavior of the client to not send an address it wants to
     // obtain but the server should handle this gracefully.
-    Lease4Ptr lease = engine.allocateLease4(subnet_, clientid_, hwaddr_,
-                                            IOAddress("0.0.0.0"),
-                                            false, false, "",
-                                            false, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", false);
+    Lease4Ptr lease = engine.allocateLease4(ctx);
+
     ASSERT_TRUE(lease);
     EXPECT_EQ("192.0.2.123", lease->addr_.toText());
 
@@ -643,7 +633,7 @@ TEST_F(AllocEngine4Test, reservedAddressNoHint) {
 
     // Initially, there was no lease for this client, so the returned old
     // lease should be NULL.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 }
 
 // This test checks behavior of the allocation engine in the following scenario:
@@ -663,11 +653,11 @@ TEST_F(AllocEngine4Test,reservedAddressNoHintFakeAllocation) {
 
     // Query allocation engine for the lease to be assigned to this
     // client without specifying the address to be assigned.
-    Lease4Ptr lease = engine.allocateLease4(subnet_, clientid_, hwaddr_,
-                                            IOAddress("0.0.0.0"),
-                                            false, false, "",
-                                            true, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", true);
+    Lease4Ptr lease = engine.allocateLease4(ctx);
+
     ASSERT_TRUE(lease);
     // The allocation engine should return a reserved address.
     EXPECT_EQ("192.0.2.123", lease->addr_.toText());
@@ -678,7 +668,7 @@ TEST_F(AllocEngine4Test,reservedAddressNoHintFakeAllocation) {
 
     // Client had no lease in the database, so the old lease returned should
     // be NULL.
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -700,23 +690,22 @@ TEST_F(AllocEngine4Test, reservedAddressHint) {
 
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, false);
 
-    Lease4Ptr lease = engine.allocateLease4(subnet_, clientid_, hwaddr_,
-                                            IOAddress("192.0.2.234"),
-                                            false, false, "",
-                                            false, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.234"), false, false,
+                                    "", false);
+    Lease4Ptr lease = engine.allocateLease4(ctx1);
+
     // The client requested a different address than reserved, so
     // the allocation engine should return NULL lease. When the server
     // receives a NULL lease for the client, it will send a DHCPNAK.
     ASSERT_FALSE(lease);
-    ASSERT_FALSE(old_lease_);
+    ASSERT_FALSE(ctx1.old_lease_);
 
     // Now, request a correct address. The client should obtain it.
-    lease = engine.allocateLease4(subnet_, clientid_, hwaddr_,
-                                  IOAddress("192.0.2.123"),
-                                  false, false, "",
-                                  false, CalloutHandlePtr(),
-                                  old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.123"), false, false,
+                                    "", false);
+    lease = engine.allocateLease4(ctx2);
     ASSERT_TRUE(lease);
     EXPECT_EQ("192.0.2.123", lease->addr_.toText());
 
@@ -726,7 +715,7 @@ TEST_F(AllocEngine4Test, reservedAddressHint) {
     ASSERT_TRUE(from_mgr);
     detailCompareLease(lease, from_mgr);
 
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx2.old_lease_);
 }
 
 // This test checks the behavior of the allocation engine in the following
@@ -748,11 +737,11 @@ TEST_F(AllocEngine4Test, reservedAddressHintFakeAllocation) {
 
     // Query the allocation engine for the lease to be assigned to the client
     // and specify a hint being a different address than the reserved one.
-    Lease4Ptr lease = engine.allocateLease4(subnet_, clientid_, hwaddr_,
-                                            IOAddress("192.0.2.234"),
-                                            false, false, "",
-                                            true, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.234"), false, false,
+                                    "", true);
+    Lease4Ptr lease = engine.allocateLease4(ctx);
+
     ASSERT_TRUE(lease);
     // Allocation engine should return reserved address.
     EXPECT_EQ("192.0.2.123", lease->addr_.toText());
@@ -761,7 +750,7 @@ TEST_F(AllocEngine4Test, reservedAddressHintFakeAllocation) {
     // to the lease database.
     EXPECT_FALSE(LeaseMgrFactory::instance().getLease4(lease->addr_));
 
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx.old_lease_);
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -791,12 +780,11 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLease) {
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, false);
 
     // Request allocation of the reserved address.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                                      hwaddr_,
-                                                      IOAddress("192.0.2.123"),
-                                                      false, false, "",
-                                                      false, CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.123"), false, false,
+                                    "", false);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx);
+
     ASSERT_TRUE(allocated_lease);
     // The engine should have allocated the reserved address.
     EXPECT_EQ("192.0.2.123", allocated_lease->addr_.toText());
@@ -809,9 +797,9 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLease) {
 
     // The previous lease should have been replaced by a new one. The previous
     // lease should be returned by the allocation engine to the caller.
-    ASSERT_TRUE(old_lease_);
-    EXPECT_EQ("192.0.2.101", old_lease_->addr_.toText());
-    detailCompareLease(old_lease_, lease);
+    ASSERT_TRUE(ctx.old_lease_);
+    EXPECT_EQ("192.0.2.101", ctx.old_lease_->addr_.toText());
+    detailCompareLease(ctx.old_lease_, lease);
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -840,16 +828,14 @@ TEST_F(AllocEngine4Test, reservedAddressHijacked) {
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, false);
 
     // Try to allocate the reserved lease to client B.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                                      hwaddr_,
-                                                      IOAddress("192.0.2.123"),
-                                                      false, false, "",
-                                                      false, CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.123"), false, false,
+                                    "", false);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
     // The lease is allocated to someone else, so the allocation should not
     // succeed.
     ASSERT_FALSE(allocated_lease);
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx1.old_lease_);
 
     // Make sure that the allocation engine didn't modify the lease of the
     // client A.
@@ -859,14 +845,12 @@ TEST_F(AllocEngine4Test, reservedAddressHijacked) {
 
     // Try doing the same thing, but this time do not request any specific
     // address. It should have the same effect.
-    allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                            hwaddr_,
-                                            IOAddress("0.0.0.0"),
-                                            false, false, "",
-                                            false, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", false);
+    allocated_lease = engine.allocateLease4(ctx2);
     ASSERT_FALSE(allocated_lease);
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx2.old_lease_);
 
     from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
     ASSERT_TRUE(from_mgr);
@@ -905,26 +889,24 @@ TEST_F(AllocEngine4Test, reservedAddressHijackedFakeAllocation) {
     // Query allocation engine for the lease to be allocated to the client B.
     // The allocation engine is not able to allocate the lease to the client
     // B, because the address is in use by client A.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                                      hwaddr_,
-                                                      IOAddress("192.0.2.123"),
-                                                      false, false, "",
-                                                      true, CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.123"), false, false,
+                                    "", true);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
+
     // The allocation engine should return no lease.
     ASSERT_FALSE(allocated_lease);
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx1.old_lease_);
 
     // Do the same test. But, this time do not specify any address to be
     // allocated.
-    allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                            hwaddr_,
-                                            IOAddress("0.0.0.0"),
-                                            false, false, "",
-                                            true, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", true);
+    allocated_lease = engine.allocateLease4(ctx2);
+
     EXPECT_FALSE(allocated_lease);
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx2.old_lease_);
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -956,23 +938,19 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseInvalidHint) {
 
     // Try to allocate a lease and specify a different address than reserved
     // and different from the one that client is currently using.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                                      hwaddr_,
-                                                      IOAddress("192.0.2.102"),
-                                                      false, false, "",
-                                                      false, CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.102"), false, false,
+                                    "", false);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
     ASSERT_FALSE(allocated_lease);
-    ASSERT_FALSE(old_lease_);
+    ASSERT_FALSE(ctx1.old_lease_);
 
     // Repeat the test, but this time ask for the address that the client
     // has allocated.
-    allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                            hwaddr_,
-                                            IOAddress("192.0.2.101"),
-                                            false, false, "",
-                                            false, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.101"), false, false,
+                                    "", false);
+    allocated_lease = engine.allocateLease4(ctx2);
     // The client has reservation so the server wants to allocate a
     // reserved address and doesn't want to renew the address that the
     // client is currently using. This is equivalent of the case when
@@ -981,7 +959,7 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseInvalidHint) {
     // responds with DHCPNAK to force the client to return to the
     // DHCP server discovery.
     EXPECT_FALSE(allocated_lease);
-    EXPECT_FALSE(old_lease_);
+    EXPECT_FALSE(ctx2.old_lease_);
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -1010,12 +988,11 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseFakeAllocation) {
 
     // Try to allocate a lease and use a completely different address
     // as a hint.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                                      hwaddr_,
-                                                      IOAddress("192.0.2.102"),
-                                                      false, false, "",
-                                                      true, CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx1(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.102"), false, false,
+                                    "", true);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
+
     // Server should offer a lease for a reserved address.
     ASSERT_TRUE(allocated_lease);
     EXPECT_EQ("192.0.2.123", allocated_lease->addr_.toText());
@@ -1024,25 +1001,24 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseFakeAllocation) {
     EXPECT_FALSE(LeaseMgrFactory::instance().getLease4(allocated_lease->addr_));
 
     // Old lease should contain the currently used lease.
-    ASSERT_TRUE(old_lease_);
-    EXPECT_EQ("192.0.2.101", old_lease_->addr_.toText());
+    ASSERT_TRUE(ctx1.old_lease_);
+    EXPECT_EQ("192.0.2.101", ctx1.old_lease_->addr_.toText());
 
     // Repeat the test but this time ask for the address for which the
     // client has a lease.
-    allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                            hwaddr_,
-                                            IOAddress("192.0.2.101"),
-                                            false, false, "",
-                                            true, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.101"), false, false,
+                                    "", true);
+    allocated_lease = engine.allocateLease4(ctx2);
+
     // The server should offer the lease, but not for the address that
     // the client requested. The server should offer a reserved address.
     ASSERT_TRUE(allocated_lease);
     EXPECT_EQ("192.0.2.123", allocated_lease->addr_.toText());
 
     // Old lease should contain the currently used lease.
-    ASSERT_TRUE(old_lease_);
-    EXPECT_EQ("192.0.2.101", old_lease_->addr_.toText());
+    ASSERT_TRUE(ctx2.old_lease_);
+    EXPECT_EQ("192.0.2.101", ctx2.old_lease_->addr_.toText());
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -1070,12 +1046,11 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseNoHint) {
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, false);
 
     // Try to allocate a lease with providing no hint.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                                      hwaddr_,
-                                                      IOAddress("0.0.0.0"),
-                                                      false, false, "",
-                                                      false, CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", false);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx);
+
     // The reserved address should be allocated.
     ASSERT_TRUE(allocated_lease);
     EXPECT_EQ("192.0.2.123", allocated_lease->addr_.toText());
@@ -1090,8 +1065,8 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseNoHint) {
     detailCompareLease(allocated_lease, from_mgr);
 
     // Old lease should be returned.
-    ASSERT_TRUE(old_lease_);
-    detailCompareLease(lease, old_lease_);
+    ASSERT_TRUE(ctx.old_lease_);
+    detailCompareLease(lease, ctx.old_lease_);
 }
 
 // This test checks that the behavior of the allocation engine in the following
@@ -1120,12 +1095,11 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseNoHintFakeAllocation) {
 
     // Query the allocation engine for the lease to be allocated for the
     // client.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                                      hwaddr_,
-                                                      IOAddress("0.0.0.0"),
-                                                      false, false, "",
-                                                      true, CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"), false, false,
+                                    "", true);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx);
+
     // The server should offer the reserved address.
     ASSERT_TRUE(allocated_lease);
     EXPECT_EQ("192.0.2.123", allocated_lease->addr_.toText());
@@ -1135,7 +1109,7 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseNoHintFakeAllocation) {
     EXPECT_FALSE(LeaseMgrFactory::instance().getLease4(allocated_lease->addr_));
 
     // The old lease should reflect what is in the database.
-    ASSERT_TRUE(old_lease_);
+    ASSERT_TRUE(ctx.old_lease_);
     Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
     ASSERT_TRUE(from_mgr);
     detailCompareLease(lease, from_mgr);
@@ -1149,7 +1123,7 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseNoHintFakeAllocation) {
 // - Server returns DHCPNAK to the client to indicate that the requested address
 // can't be allocated.
 // - Client A renews the lease.
-// - Server determines that the lease that the Client A is trying to renews
+// - Server determines that the lease that the Client A is trying to renew
 // is for the address reserved for Client B. Therefore, the server returns
 // DHCPNAK to force the client to return to the server discovery.
 // - The Client A sends DHCPDISCOVER.
@@ -1163,7 +1137,7 @@ TEST_F(AllocEngine4Test, reservedAddressExistingLeaseNoHintFakeAllocation) {
 // - The server allocates the reserved address to the Client B.
 TEST_F(AllocEngine4Test, reservedAddressConflictResolution) {
     // Create a reservation for client B.
-    HostPtr host(new Host(&hwaddr2_->hwaddr_[0], hwaddr_->hwaddr_.size(),
+    HostPtr host(new Host(&hwaddr2_->hwaddr_[0], hwaddr2_->hwaddr_.size(),
                           Host::IDENT_HWADDR, subnet_->getID(),
                           SubnetID(0), IOAddress("192.0.2.101")));
     CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
@@ -1181,63 +1155,59 @@ TEST_F(AllocEngine4Test, reservedAddressConflictResolution) {
     // Client B sends a DHCPREQUEST to allocate a reserved lease. The
     // allocation engine declines allocation of the address for the
     // client because Client A has a lease for it.
-    ASSERT_FALSE(engine.allocateLease4(subnet_, ClientIdPtr(), hwaddr2_,
-                                       IOAddress("192.0.2.101"), false,
-                                       false, "", false, CalloutHandlePtr(),
-                                       old_lease_));
+    AllocEngine::ClientContext4 ctx1(subnet_, ClientIdPtr(), hwaddr2_,
+                                    IOAddress("192.0.2.101"), false, false,
+                                    "", false);
+    ASSERT_FALSE(engine.allocateLease4(ctx1));
 
     // Client A tries to renew the lease. The renewal should fail because
     // server detects that Client A doesn't have reservation for this
     // address.
-    ASSERT_FALSE(engine.allocateLease4(subnet_, clientid_, hwaddr_,
-                                       IOAddress("192.0.2.101"), false, false,
-                                       "", false, CalloutHandlePtr(),
-                                       old_lease_));
-    ASSERT_TRUE(old_lease_);
-    EXPECT_EQ("192.0.2.101", old_lease_->addr_.toText());
+    AllocEngine::ClientContext4 ctx2(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.101"), false, false,
+                                    "", false);
+    ASSERT_FALSE(engine.allocateLease4(ctx2));
+
+    ASSERT_TRUE(ctx2.old_lease_);
+    EXPECT_EQ("192.0.2.101", ctx2.old_lease_->addr_.toText());
 
     // Client A returns to DHCPDISCOVER and should be offered a lease.
     // The offered lease address must be different than the one the
     // Client B has reservation for.
-    Lease4Ptr offered_lease = engine.allocateLease4(subnet_, clientid_,
-                                                    hwaddr_,
-                                                    IOAddress("192.0.2.101"),
-                                                    false, false, "", true,
-                                                    CalloutHandlePtr(),
-                                                    old_lease_);
+    AllocEngine::ClientContext4 ctx3(subnet_, clientid_, hwaddr_,
+                                    IOAddress("192.0.2.101"), false, false,
+                                    "", true);
+    Lease4Ptr offered_lease = engine.allocateLease4(ctx3);
     ASSERT_TRUE(offered_lease);
     EXPECT_NE(offered_lease->addr_.toText(), "192.0.2.101");
 
     // Client A tried to acquire the lease. It should succeed. At this point
     // the previous lease should be released and become available for the
     // Client B.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, clientid_,
-                                                      hwaddr_,
-                                                      offered_lease->addr_,
-                                                      false, false, "", false,
-                                                      CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx4(subnet_, clientid_, hwaddr_,
+                                    offered_lease->addr_, false, false,
+                                    "", false);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx4);
+
     ASSERT_TRUE(allocated_lease);
     EXPECT_NE(allocated_lease->addr_.toText(), "192.0.2.101");
 
     // Client B tries to get the lease again. It should be offered
     // a reserved lease.
-    offered_lease = engine.allocateLease4(subnet_, ClientIdPtr(),
-                                          hwaddr2_,
-                                          IOAddress("0.0.0.0"),
-                                          false, false, "", true,
-                                          CalloutHandlePtr(),
-                                          old_lease_);
+    AllocEngine::ClientContext4 ctx5(subnet_, ClientIdPtr(), hwaddr2_,
+                                     IOAddress("0.0.0.0"), false, false,
+                                    "", true);
+    offered_lease = engine.allocateLease4(ctx5);
+
     ASSERT_TRUE(offered_lease);
     EXPECT_EQ("192.0.2.101", offered_lease->addr_.toText());
 
     // Client B requests allocation of the lease and it should succeed.
-    allocated_lease = engine.allocateLease4(subnet_, ClientIdPtr(),
-                                            hwaddr2_,
-                                            offered_lease->addr_,
-                                            false, false, "", false,
-                                            CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx6(subnet_, ClientIdPtr(), hwaddr2_,
+                                     offered_lease->addr_, false, false,
+                                    "", false);
+    allocated_lease = engine.allocateLease4(ctx6);
+
     ASSERT_TRUE(allocated_lease);
     EXPECT_EQ("192.0.2.101", allocated_lease->addr_.toText());
 }
@@ -1258,12 +1228,11 @@ TEST_F(AllocEngine4Test, reservedAddressVsDynamicPool) {
     // an iterative allocator which would pick the first address from the
     // dynamic pool, i.e. 192.0.2.100. This address is reserved so we expect
     // that a different address will be allocated.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, ClientIdPtr(),
-                                                      hwaddr_,
-                                                      IOAddress("0.0.0.0"),
-                                                      false, false, "", false,
-                                                      CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, ClientIdPtr(), hwaddr_,
+                                     IOAddress("0.0.0.0"), false, false,
+                                    "", false);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx);
+
     ASSERT_TRUE(allocated_lease);
     EXPECT_NE(allocated_lease->addr_.toText(), "192.0.2.100");
 }
@@ -1282,23 +1251,21 @@ TEST_F(AllocEngine4Test, reservedAddressHintUsedByOtherClient) {
     AllocEngine engine(AllocEngine::ALLOC_ITERATIVE, 100, false);
 
     // Different client is requesting this address.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, ClientIdPtr(),
-                                                      hwaddr_,
-                                                      IOAddress("192.0.2.100"),
-                                                      false, false, "", false,
-                                                      CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx1(subnet_, ClientIdPtr(), hwaddr_,
+                                     IOAddress("192.0.2.100"), false, false,
+                                    "", false);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
+
     // The client should get no lease (DHCPNAK).
     ASSERT_FALSE(allocated_lease);
 
     // The same client should get a different lease than requested if
     // if is sending a DHCPDISCOVER (fake allocation is true).
-    allocated_lease = engine.allocateLease4(subnet_, ClientIdPtr(),
-                                            hwaddr_,
-                                            IOAddress("192.0.2.100"),
-                                            false, false, "", true,
-                                            CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, ClientIdPtr(), hwaddr_,
+                                     IOAddress("192.0.2.100"), false, false,
+                                    "", true);
+    allocated_lease = engine.allocateLease4(ctx2);
+
     ASSERT_TRUE(allocated_lease);
     // Make sure the lease obtained is for a different address.
     EXPECT_NE(allocated_lease->addr_.toText(), "192.0.2.100");
@@ -1321,12 +1288,11 @@ TEST_F(AllocEngine4Test, reservedAddressShortPool) {
 
     // Allocation engine should determine that the available address is
     // reserved for someone else and not allocate it.
-    Lease4Ptr allocated_lease = engine.allocateLease4(subnet_, ClientIdPtr(),
-                                                      hwaddr_,
-                                                      IOAddress("0.0.0.0"),
-                                                      false, false, "", false,
-                                                      CalloutHandlePtr(),
-                                                      old_lease_);
+    AllocEngine::ClientContext4 ctx1(subnet_, ClientIdPtr(), hwaddr_,
+                                     IOAddress("0.0.0.0"), false, false,
+                                     "", false);
+    Lease4Ptr allocated_lease = engine.allocateLease4(ctx1);
+
     EXPECT_FALSE(allocated_lease);
 
     // Now, let's remove the reservation.
@@ -1334,10 +1300,11 @@ TEST_F(AllocEngine4Test, reservedAddressShortPool) {
     CfgMgr::instance().commit();
 
     // Address should be successfully allocated.
-    allocated_lease = engine.allocateLease4(subnet_, ClientIdPtr(), hwaddr_,
-                                            IOAddress("0.0.0.0"), false, false,
-                                            "", false, CalloutHandlePtr(),
-                                            old_lease_);
+    AllocEngine::ClientContext4 ctx2(subnet_, ClientIdPtr(), hwaddr_,
+                                     IOAddress("0.0.0.0"), false, false,
+                                     "", false);
+    allocated_lease = engine.allocateLease4(ctx2);
+
     ASSERT_TRUE(allocated_lease);
     EXPECT_EQ("192.0.2.100", allocated_lease->addr_.toText());
 }

+ 14 - 10
src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc

@@ -383,11 +383,13 @@ TEST_F(HookAllocEngine4Test, lease4_select) {
 
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
 
-    Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                               IOAddress("0.0.0.0"),
-                                               false, false, "",
-                                               false, callout_handle,
-                                               old_lease_);
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
+                                    IOAddress("0.0.0.0"),
+                                    false, false, "", false);
+    ctx.callout_handle_ = callout_handle;
+
+    Lease4Ptr lease = engine->allocateLease4(ctx);
+
     // Check that we got a lease
     ASSERT_TRUE(lease);
 
@@ -449,12 +451,14 @@ TEST_F(HookAllocEngine4Test, change_lease4_select) {
     // but in tests we need to create it on our own.
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
 
+
+    AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
+                                    false, true, "somehost.example.com.", false);
+    ctx.callout_handle_ = callout_handle;
+
     // Call allocateLease4. Callouts should be triggered here.
-    Lease4Ptr lease = engine->allocateLease4(subnet_, clientid_, hwaddr_,
-                                             IOAddress("0.0.0.0"),
-                                             false, false, "",
-                                             false, callout_handle,
-                                             old_lease_);
+    Lease4Ptr lease = engine->allocateLease4(ctx);
+
     // Check that we got a lease
     ASSERT_TRUE(lease);
 

+ 0 - 1
src/lib/dhcpsrv/tests/alloc_engine_utils.h

@@ -379,7 +379,6 @@ public:
     Subnet4Ptr subnet_;         ///< Subnet4 (used in tests)
     Pool4Ptr pool_;             ///< Pool belonging to subnet_
     LeaseMgrFactory factory_;   ///< Pointer to LeaseMgr factory
-    Lease4Ptr old_lease_;       ///< Holds previous instance of the lease.
     AllocEngine::ClientContext4 ctx_; ///< Context information passed to various
                                      ///< allocation engine functions.
 };