system: Implement remote system reboot via Sysrepo
The ietf-system model [1] models an RPC (ietf-system:system-restart)
which causes system restart.
The restart is done simply by invoking `systemctl reboot` command.
Originally, I wanted just to call systemd's Reboot method over its D-Bus
API [2], however, it does not shutdown services and just goes straight
into the reboot process. The version from logind, that can do this, is
not available on our boxes.
[1] https://tools.ietf.org/html/rfc7317
[2] https://www.freedesktop.org/wiki/Software/systemd/dbus/
Change-Id: I7d690a11402eaf408d9dce04d3ac0ef9006bcdb8
diff --git a/src/system/IETFSystem.cpp b/src/system/IETFSystem.cpp
index fcfe6b5..e508d20 100644
--- a/src/system/IETFSystem.cpp
+++ b/src/system/IETFSystem.cpp
@@ -8,6 +8,8 @@
#include <boost/algorithm/string/predicate.hpp>
#include <fstream>
#include "IETFSystem.h"
+#include "system_vars.h"
+#include "utils/exec.h"
#include "utils/io.h"
#include "utils/log.h"
#include "utils/sysrepo.h"
@@ -60,6 +62,7 @@
/** @brief Reads some OS-identification data from osRelease file and publishes them via ietf-system model */
IETFSystem::IETFSystem(std::shared_ptr<::sysrepo::Session> srSession, const std::filesystem::path& osRelease)
: m_srSession(std::move(srSession))
+ , m_srSubscribe(std::make_shared<::sysrepo::Subscribe>(m_srSession))
, m_log(spdlog::get("system"))
{
std::map<std::string, std::string> osReleaseContents = parseKeyValueFile(osRelease);
@@ -71,5 +74,20 @@
};
utils::valuesPush(opsSystemStateData, m_srSession, SR_DS_OPERATIONAL);
+
+ m_srSubscribe->rpc_subscribe(
+ ("/" + IETF_SYSTEM_MODULE_NAME + ":system-restart").c_str(),
+ [this](::sysrepo::S_Session session, [[maybe_unused]] const char* op_path, [[maybe_unused]] const ::sysrepo::S_Vals input, [[maybe_unused]] sr_event_t event, [[maybe_unused]] uint32_t request_id, [[maybe_unused]] ::sysrepo::S_Vals_Holder output) {
+ try {
+ velia::utils::execAndWait(m_log, SYSTEMCTL_EXECUTABLE, {"reboot"}, "", {});
+ } catch(const std::runtime_error& e) {
+ session->set_error("Reboot procedure failed.", nullptr);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ return SR_ERR_OK;
+ },
+ 0,
+ SR_SUBSCR_CTX_REUSE);
}
}
diff --git a/src/system/IETFSystem.h b/src/system/IETFSystem.h
index 4367369..c9ec195 100644
--- a/src/system/IETFSystem.h
+++ b/src/system/IETFSystem.h
@@ -14,10 +14,11 @@
class IETFSystem {
public:
- explicit IETFSystem(std::shared_ptr<::sysrepo::Session> srSession, const std::filesystem::path& osRelease);
+ IETFSystem(std::shared_ptr<::sysrepo::Session> srSession, const std::filesystem::path& osRelease);
private:
std::shared_ptr<::sysrepo::Session> m_srSession;
+ std::shared_ptr<::sysrepo::Subscribe> m_srSubscribe;
velia::Log m_log;
};
}
diff --git a/src/system/system_vars.h.in b/src/system/system_vars.h.in
index 833951a..8098a2e 100644
--- a/src/system/system_vars.h.in
+++ b/src/system/system_vars.h.in
@@ -7,3 +7,4 @@
#define BACKUP_ETC_SHADOW_FILE "@VELIA_BACKUP_ETC_SHADOW@"
#define SSH_KEYGEN_EXECUTABLE "@SSH_KEYGEN_EXECUTABLE@"
#define CHPASSWD_EXECUTABLE "@CHPASSWD_EXECUTABLE@"
+#define SYSTEMCTL_EXECUTABLE "@SYSTEMCTL_EXECUTABLE@"