-// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2021 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
return (0);
}
+/// @brief ha-reset command handler implementation.
+int ha_reset_command(CalloutHandle& handle) {
+ try {
+ impl->haResetHandler(handle);
+
+ } catch (const std::exception& ex) {
+ LOG_ERROR(ha_logger, HA_RESET_HANDLER_FAILED)
+ .arg(ex.what());
+ }
+}
+
/// @brief This function is called when the library is loaded.
///
/// @param handle library handle
handle.registerCommandCallout("ha-maintenance-notify", maintenance_notify_command);
handle.registerCommandCallout("ha-maintenance-start", maintenance_start_command);
handle.registerCommandCallout("ha-maintenance-cancel", maintenance_cancel_command);
+ handle.registerCommandCallout("ha-reset", ha_reset_command);
} catch (const std::exception& ex) {
LOG_ERROR(ha_logger, HA_CONFIGURATION_FAILED)
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2021 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
callout_handle.setArgument("response", response);
}
+void
+HAImpl::haResetHandler(hooks::CalloutHandle& callout_handle) {
+ ConstElementPtr response = service_->processHAReset();
+ callout_handle.setArgument("response", response);
+}
+
} // end of namespace isc::ha
} // end of namespace isc
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2021 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
/// @param callout_handle Callout handle provided to the callout.
void maintenanceCancelHandler(hooks::CalloutHandle& callout_handle);
+ /// @brief Implements handler for the ha-reset command.
+ ///
+ /// @param callout_handle Callout handle provided to the callout.
+ void haResetHandler(hooks::CalloutHandle& callout_handle);
+
protected:
/// @brief Holds parsed configuration.
extern const isc::log::MessageID HA_MAINTENANCE_STARTED_IN_PARTNER_DOWN = "HA_MAINTENANCE_STARTED_IN_PARTNER_DOWN";
extern const isc::log::MessageID HA_MAINTENANCE_START_HANDLER_FAILED = "HA_MAINTENANCE_START_HANDLER_FAILED";
extern const isc::log::MessageID HA_MISSING_CONFIGURATION = "HA_MISSING_CONFIGURATION";
+extern const isc::log::MessageID HA_RESET_HANDLER_FAILED = "HA_RESET_HANDLER_FAILED";
extern const isc::log::MessageID HA_SCOPES_HANDLER_FAILED = "HA_SCOPES_HANDLER_FAILED";
extern const isc::log::MessageID HA_SERVICE_STARTED = "HA_SERVICE_STARTED";
extern const isc::log::MessageID HA_STATE_MACHINE_CONTINUED = "HA_STATE_MACHINE_CONTINUED";
"HA_MAINTENANCE_STARTED_IN_PARTNER_DOWN", "the server is now in the partner-down mode as a result of requested maintenance",
"HA_MAINTENANCE_START_HANDLER_FAILED", "ha-maintenance-start command failed: %1",
"HA_MISSING_CONFIGURATION", "high-availability parameter not specified for High Availability hooks library",
+ "HA_RESET_HANDLER_FAILED", "ha-reset command failed: %1",
"HA_SCOPES_HANDLER_FAILED", "ha-scopes command failed: %1",
"HA_SERVICE_STARTED", "started high availability service in %1 mode as %2 server",
"HA_STATE_MACHINE_CONTINUED", "state machine is un-paused",
extern const isc::log::MessageID HA_MAINTENANCE_STARTED_IN_PARTNER_DOWN;
extern const isc::log::MessageID HA_MAINTENANCE_START_HANDLER_FAILED;
extern const isc::log::MessageID HA_MISSING_CONFIGURATION;
+extern const isc::log::MessageID HA_RESET_HANDLER_FAILED;
extern const isc::log::MessageID HA_SCOPES_HANDLER_FAILED;
extern const isc::log::MessageID HA_SERVICE_STARTED;
extern const isc::log::MessageID HA_STATE_MACHINE_CONTINUED;
High Availability hooks library hasn't been specified. The 'high-availability'
parameter must be specified for the hooks library to load properly.
+% HA_RESET_HANDLER_FAILED ha-reset command failed: %1
+This error message is issued to indicate that the ha-reset command handler
+failed while processing the command. The argument provides the reason for
+failure.
+
% HA_SCOPES_HANDLER_FAILED ha-scopes command failed: %1
This error message is issued to indicate that the ha-scopes command handler
failed while processing the command. The argument provides reason for
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2021 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
arguments));
}
+ConstElementPtr
+HAService::processHAReset() {
+ verboseTransition(HA_WAITING_ST);
+ runModel(NOP_EVT);
+ return (createAnswer(CONTROL_RESULT_SUCCESS, "HA state machine reset."));
+}
+
void
HAService::asyncSendHeartbeat() {
HAConfig::PeerConfigPtr partner_config = config_->getFailoverPeerConfig();
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2021 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
/// @brief Processes status-get command and returns a response.
///
- ///
- ///
/// @c HAImpl::commandProcessed calls this to add information about the
/// HA servers status into the status-get response.
data::ConstElementPtr processStatusGet() const;
+ /// @brief Processes ha-reset command and returns a response.
+ ///
+ /// This method processes ha-reset command which instructs the server to
+ /// transition to the waiting state. A partner may send this command when
+ /// the communication is re-established between the servers in the
+ /// communication-recovery state and full lease database synchronization is
+ /// required. This command may also be sent by an operator if the server's
+ /// state is invalid and the reset operation may help correct the situation.
+ ///
+ /// The ha-reset takes no arguments.
+ ///
+ /// @return Pointer to a response to the ha-reset command.
+ data::ConstElementPtr processHAReset();
+
protected:
/// @brief Starts asynchronous heartbeat to a peer.
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2021 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
checkAnswer(response, CONTROL_RESULT_SUCCESS, "Server is in-maintenance state.");
}
+// Test ha-reset command handler.
+TEST_F(HAImplTest, haReset) {
+ HAImpl ha_impl;
+ ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+
+ // Starting the service is required prior to running any callouts.
+ NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
+ ASSERT_NO_THROW(ha_impl.startService(io_service_, network_state,
+ HAServerType::DHCPv4));
+
+ ConstElementPtr command = Element::fromJSON(
+ "{"
+ " \"command\": \"ha-reset\""
+ "}"
+ );
+
+ CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
+ callout_handle->setArgument("command", command);
+
+ ASSERT_NO_THROW(ha_impl.haResetHandler(*callout_handle));
+
+ ConstElementPtr response;
+ callout_handle->getArgument("response", response);
+ ASSERT_TRUE(response);
+
+ checkAnswer(response, CONTROL_RESULT_SUCCESS, "HA state machine reset.");
+}
+
}
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2021 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
EXPECT_EQ(HA_PARTNER_IN_MAINTENANCE_ST, service.getCurrState());
}
+// This test verifies that the ha-reset command is processed successfully.
+TEST_F(HAServiceTest, processHAReset) {
+ HAConfigPtr config_storage = createValidConfiguration();
+ TestHAService service(io_service_, network_state_, config_storage);
+
+ // Transion the server to the load-balancing state.
+ EXPECT_NO_THROW(service.transition(HA_LOAD_BALANCING_ST, HAService::NOP_EVT));
+
+ // Process ha-reset command that should cause the server to transition
+ // to the waiting state.
+ ConstElementPtr rsp;
+ ASSERT_NO_THROW(rsp = service.processHAReset());
+
+ // The server should have responded.
+ ASSERT_TRUE(rsp);
+ checkAnswer(rsp, CONTROL_RESULT_SUCCESS, "HA state machine reset.");
+
+ // Response should include no arguments.
+ EXPECT_FALSE(rsp->get("arguments"));
+
+ // The server should be in the waiting state.
+ EXPECT_EQ(HA_WAITING_ST, service.getCurrState());
+}
/// @brief HA partner to the server under test.
///