From: Marcin Siodelski Date: Mon, 8 Jan 2018 16:50:56 +0000 (+0100) Subject: [5472] Added 'force-create' parameter to leaseX-update commands. X-Git-Tag: trac5425a_base~9^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26910888d296951d9817430cc7acf0178492fd8d;p=thirdparty%2Fkea.git [5472] Added 'force-create' parameter to leaseX-update commands. --- diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.cc b/src/hooks/dhcp/lease_cmds/lease_cmds.cc index a5d3f25fb7..6267714855 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds.cc +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -222,9 +222,11 @@ LeaseCmdsImpl::leaseAddHandler(CalloutHandle& handle) { Lease4Ptr lease4; Lease6Ptr lease6; + // This parameter is ignored for the commands adding the lease. + bool force_create = false; if (v4) { Lease4Parser parser; - lease4 = parser.parse(config, cmd_args_); + lease4 = parser.parse(config, cmd_args_, force_create); // checkLeaseIntegrity(config, lease4); @@ -234,7 +236,7 @@ LeaseCmdsImpl::leaseAddHandler(CalloutHandle& handle) { } else { Lease6Parser parser; - lease6 = parser.parse(config, cmd_args_); + lease6 = parser.parse(config, cmd_args_, force_create); // checkLeaseIntegrity(config, lease6); @@ -599,12 +601,19 @@ LeaseCmdsImpl::lease4UpdateHandler(CalloutHandle& handle) { ConstSrvConfigPtr config = CfgMgr::instance().getCurrentCfg(); Lease4Ptr lease4; Lease4Parser parser; + bool force_create = false; + // The parser does sanity checks (if the address is in scope, if // subnet-id is valid, etc) - lease4 = parser.parse(config, cmd_args_); + lease4 = parser.parse(config, cmd_args_, force_create); + if (force_create && !LeaseMgrFactory::instance().getLease4(lease4->addr_)) { + LeaseMgrFactory::instance().addLease(lease4); + setSuccessResponse(handle, "IPv4 lease created."); - LeaseMgrFactory::instance().updateLease4(lease4); - setSuccessResponse(handle, "IPv4 lease updated."); + } else { + LeaseMgrFactory::instance().updateLease4(lease4); + setSuccessResponse(handle, "IPv4 lease updated."); + } } catch (const std::exception& ex) { setErrorResponse(handle, ex.what()); return (1); @@ -627,12 +636,19 @@ LeaseCmdsImpl::lease6UpdateHandler(CalloutHandle& handle) { ConstSrvConfigPtr config = CfgMgr::instance().getCurrentCfg(); Lease6Ptr lease6; Lease6Parser parser; + bool force_create = false; + // The parser does sanity checks (if the address is in scope, if // subnet-id is valid, etc) - lease6 = parser.parse(config, cmd_args_); - - LeaseMgrFactory::instance().updateLease6(lease6); - setSuccessResponse(handle, "IPv6 lease updated."); + lease6 = parser.parse(config, cmd_args_, force_create); + if (force_create && !LeaseMgrFactory::instance().getLease6(lease6->type_, + lease6->addr_)) { + LeaseMgrFactory::instance().addLease(lease6); + setSuccessResponse(handle, "IPv6 lease created."); + } else { + LeaseMgrFactory::instance().updateLease6(lease6); + setSuccessResponse(handle, "IPv6 lease updated."); + } } catch (const std::exception& ex) { setErrorResponse(handle, ex.what()); return (1); diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.h b/src/hooks/dhcp/lease_cmds/lease_cmds.h index 03e2cdcaf1..b31328fc07 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds.h +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.h @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -227,6 +227,10 @@ public: /// } /// }; /// + /// The optional 'force-create' boolean parameter may be specified to force + /// the lease to be created if it doesn't exist. By default, this parameter + /// is set to false, which means that the lease is not created. + /// /// @param handle Callout context - which is expected to contain the /// update command JSON text in the "command" argument /// @return result of the operation @@ -255,6 +259,10 @@ public: /// } /// }"; /// + /// The optional 'force-create' boolean parameter may be specified to force + /// the lease to be created if it doesn't exist. By default, this parameter + /// is set to false, which means that the lease is not created. + /// /// @param handle Callout context - which is expected to contain the /// update command JSON text in the "command" argument /// @return result of the operation diff --git a/src/hooks/dhcp/lease_cmds/lease_parser.cc b/src/hooks/dhcp/lease_cmds/lease_parser.cc index b0288002d2..4a457d8a77 100644 --- a/src/hooks/dhcp/lease_cmds/lease_parser.cc +++ b/src/hooks/dhcp/lease_cmds/lease_parser.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -22,7 +22,8 @@ namespace lease_cmds { Lease4Ptr Lease4Parser::parse(ConstSrvConfigPtr& cfg, - const ConstElementPtr& lease_info) { + const ConstElementPtr& lease_info, + bool& force_create) { if (!lease_info) { isc_throw(BadValue, "lease information missing"); } @@ -117,12 +118,21 @@ Lease4Parser::parse(ConstSrvConfigPtr& cfg, cltt, subnet_id, fqdn_fwd, fqdn_rev, hostname)); l->state_ = state; + + // Retrieve the optional flag indicating if the lease must be created when it + // doesn't exist during the update. + force_create = false; + if (lease_info->contains("force-create")) { + force_create = getBoolean(lease_info, "force-create"); + } + return (l); } Lease6Ptr Lease6Parser::parse(ConstSrvConfigPtr& cfg, - const ConstElementPtr& lease_info) { + const ConstElementPtr& lease_info, + bool& force_create) { if (!lease_info) { isc_throw(BadValue, "lease information missing"); } @@ -250,6 +260,14 @@ Lease6Parser::parse(ConstSrvConfigPtr& cfg, hwaddr_ptr, prefix_len)); l->cltt_ = cltt; l->state_ = state; + + // Retrieve the optional flag indicating if the lease must be created when it + // doesn't exist during the update. + force_create = false; + if (lease_info->contains("force-create")) { + force_create = getBoolean(lease_info, "force-create"); + } + return (l); } diff --git a/src/hooks/dhcp/lease_cmds/lease_parser.h b/src/hooks/dhcp/lease_cmds/lease_parser.h index 40400bd94a..8b72c0018a 100644 --- a/src/hooks/dhcp/lease_cmds/lease_parser.h +++ b/src/hooks/dhcp/lease_cmds/lease_parser.h @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -40,11 +40,14 @@ public: /// /// @param cfg Currently running config (used for sanity checks and defaults) /// @param lease_info structure to be parsed + /// @param [out] force_create indicates if the lease should be created when it + /// doesn't exist. /// @return A pointer to Lease4 /// @throw BadValue if any of the parameters is invalid /// @throw DhcpConfigError if mandatory parameter is missing virtual isc::dhcp::Lease4Ptr parse(isc::dhcp::ConstSrvConfigPtr& cfg, - const isc::data::ConstElementPtr& lease_info); + const isc::data::ConstElementPtr& lease_info, + bool& force_create); /// @brief virtual dtor (does nothing) virtual ~Lease4Parser() {} @@ -76,11 +79,14 @@ public: /// /// @param cfg Currently running config (used for sanity checks and defaults) /// @param lease_info structure to be parsed + /// @param [out] force_create indicates if the lease should be created when it + /// doesn't exist. /// @return A pointer to Lease4 /// @throw BadValue if any of the parameters is invalid /// @throw DhcpConfigError if mandatory parameter is missing virtual isc::dhcp::Lease6Ptr parse(isc::dhcp::ConstSrvConfigPtr& cfg, - const isc::data::ConstElementPtr& lease_info); + const isc::data::ConstElementPtr& lease_info, + bool& force_create); /// @brief virtual dtor (does nothing) virtual ~Lease6Parser() {} diff --git a/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc index ff0d3b9a44..9a41749efc 100644 --- a/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc +++ b/src/hooks/dhcp/lease_cmds/tests/lease_cmds_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -1498,6 +1498,67 @@ TEST_F(LeaseCmdsTest, Lease4Update) { EXPECT_EQ("newhostname.example.org", l->hostname_); } +// Check that a lease4 is created if it doesn't exist during the update. +// To trigger this behavior 'force-create' boolean parameter must be +// included in the command. +TEST_F(LeaseCmdsTest, Lease4UpdateForceCreate) { + // Initialize lease manager (false = v4, true = add a lease) + initLeaseMgr(false, false); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // Now send the command. + string txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"ip-address\": \"192.0.2.1\",\n" + " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n" + " \"hostname\": \"newhostname.example.org\"," + " \"force-create\": true" + " }\n" + "}"; + string exp_rsp = "IPv4 lease created."; + testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Now check that the lease is still there. + Lease4Ptr l = lmptr_->getLease4(IOAddress("192.0.2.1")); + ASSERT_TRUE(l); + + // Make sure it contains expected values.. + ASSERT_TRUE(l->hwaddr_); + EXPECT_EQ("1a:1b:1c:1d:1e:1f", l->hwaddr_->toText(false)); + EXPECT_EQ("newhostname.example.org", l->hostname_); +} + +// Check that lease4-update correctly handles case when the 'force-create' +// parameter is explicitly set to false. +TEST_F(LeaseCmdsTest, Lease4UpdateDoNotForceCreate) { + + // Initialize lease manager (false = v4, false = don't add any lease) + initLeaseMgr(false, false); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // Now send the command. + string txt = + "{\n" + " \"command\": \"lease4-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 44,\n" + " \"ip-address\": \"192.0.2.1\",\n" + " \"hw-address\": \"1a:1b:1c:1d:1e:1f\",\n" + " \"hostname\": \"newhostname.example.org\"," + " \"force-create\": false" + " }\n" + "}"; + string exp_rsp = "failed to update the lease with address 192.0.2.1 - no such lease"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); +} + // Test checks if lease6-update handler refuses calls with missing parameters. TEST_F(LeaseCmdsTest, Lease6UpdateMissingParams) { // Initialize lease manager (true = v6, true = add a lease) @@ -1666,6 +1727,71 @@ TEST_F(LeaseCmdsTest, Lease6UpdateNoLease) { testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); } +// Check that a lease6 is created if it doesn't exist during the update. +// To trigger this behavior 'force-create' boolean parameter must be +// included in the command. +TEST_F(LeaseCmdsTest, Lease6UpdateForceCreate) { + + // Initialize lease manager (true = v6, true = add a lease) + initLeaseMgr(true, false); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // Now send the command. + string txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 66,\n" + " \"ip-address\": \"2001:db8::1\",\n" + " \"iaid\": 7654321,\n" + " \"duid\": \"88:88:88:88:88:88:88:88\",\n" + " \"hostname\": \"newhostname.example.org\"," + " \"force-create\": true" + " }\n" + "}"; + string exp_rsp = "IPv6 lease created."; + testCommand(txt, CONTROL_RESULT_SUCCESS, exp_rsp); + + // Now check that the lease is really there. + Lease6Ptr l = lmptr_->getLease6(Lease::TYPE_NA, IOAddress("2001:db8::1")); + ASSERT_TRUE(l); + + // Make sure the lease is correct. + ASSERT_TRUE(l->duid_); + EXPECT_EQ("88:88:88:88:88:88:88:88", l->duid_->toText()); + EXPECT_EQ("newhostname.example.org", l->hostname_); + EXPECT_EQ(7654321, l->iaid_); +} + +// Check that lease6-update correctly handles case when the 'force-create' +// parameter is explicitly set to false. +TEST_F(LeaseCmdsTest, Lease6UpdateDoNotForceCreate) { + + // Initialize lease manager (true = v6, false = don't add any lease) + initLeaseMgr(true, false); + + // Check that the lease manager pointer is there. + ASSERT_TRUE(lmptr_); + + // Now send the command. + string txt = + "{\n" + " \"command\": \"lease6-update\",\n" + " \"arguments\": {" + " \"subnet-id\": 66,\n" + " \"ip-address\": \"2001:db8::1\",\n" + " \"iaid\": 7654321,\n" + " \"duid\": \"88:88:88:88:88:88:88:88\",\n" + " \"hostname\": \"newhostname.example.org\"," + " \"force-create\": false" + " }\n" + "}"; + string exp_rsp = "failed to update the lease with address 2001:db8::1 - no such lease"; + testCommand(txt, CONTROL_RESULT_ERROR, exp_rsp); +} + // Checks that lease6-del can handle a situation when the query is // broken (some required parameters are missing). TEST_F(LeaseCmdsTest, Lease4DelMissingParams) {