Implement hostname
Change-Id: I676d7cf5c821debf59c62ddad6a06264d57918ec
diff --git a/src/system/IETFSystem.cpp b/src/system/IETFSystem.cpp
index 98bbb3d..5a8a5c7 100644
--- a/src/system/IETFSystem.cpp
+++ b/src/system/IETFSystem.cpp
@@ -20,6 +20,7 @@
const auto IETF_SYSTEM_MODULE_NAME = "ietf-system"s;
const auto IETF_SYSTEM_STATE_MODULE_PREFIX = "/"s + IETF_SYSTEM_MODULE_NAME + ":system-state/"s;
+const auto IETF_SYSTEM_HOSTNAME_PATH = "/ietf-system:system/hostname";
/** @brief Returns key=value pairs from (e.g. /etc/os-release) as a std::map */
std::map<std::string, std::string> parseKeyValueFile(const std::filesystem::path& path)
@@ -55,12 +56,27 @@
return res;
}
+std::optional<std::string> getHostnameFromChange(const std::shared_ptr<sysrepo::Session> session)
+{
+ std::optional<std::string> res;
+
+ auto data = session->get_data(IETF_SYSTEM_HOSTNAME_PATH);
+ if (data) {
+ auto hostnameNode = data->find_path(IETF_SYSTEM_HOSTNAME_PATH)->data().front();
+ auto leaf = std::make_shared<libyang::Data_Node_Leaf_List>(hostnameNode);
+ res = leaf->value_str();
+ }
+
+ return res;
+}
}
namespace velia::system {
void IETFSystem::initStaticProperties(const std::filesystem::path& osRelease)
{
+ utils::ensureModuleImplemented(m_srSession, IETF_SYSTEM_MODULE_NAME, "2014-08-06");
+
std::map<std::string, std::string> osReleaseContents = parseKeyValueFile(osRelease);
std::map<std::string, std::string> opsSystemStateData {
@@ -90,9 +106,51 @@
SR_SUBSCR_CTX_REUSE);
}
+void IETFSystem::initHostname()
+{
+ sysrepo::ModuleChangeCb hostNameCbRunning = [this] (auto session, auto, auto, auto, auto) {
+ if (auto newHostname = getHostnameFromChange(session)) {
+ velia::utils::execAndWait(m_log, HOSTNAMECTL_EXECUTABLE, {"set-hostname", *newHostname}, "");
+ }
+ return SR_ERR_OK;
+ };
+
+ sysrepo::ModuleChangeCb hostNameCbStartup = [] (auto session, auto, auto, auto, auto) {
+ if (auto newHostname = getHostnameFromChange(session)) {
+ utils::safeWriteFile(BACKUP_ETC_HOSTNAME_FILE, *newHostname);
+ }
+ return SR_ERR_OK;
+ };
+
+ sysrepo::OperGetItemsCb hostNameCbOperational = [] (auto session, auto, auto, auto, auto, auto& parent) {
+ // + 1 for null-terminating byte, HOST_NAME_MAX doesn't count that
+ std::array<char, HOST_NAME_MAX + 1> buffer;
+
+ if (gethostname(buffer.data(), buffer.size()) != 0) {
+ throw std::system_error(errno, std::system_category(), "gethostname() failed");
+ }
+
+ parent->new_path(
+ session->get_context(),
+ IETF_SYSTEM_HOSTNAME_PATH,
+ buffer.data(),
+ LYD_ANYDATA_CONSTSTRING,
+ 0);
+
+ return SR_ERR_OK;
+ };
+
+ m_srSubscribe->module_change_subscribe(IETF_SYSTEM_MODULE_NAME.c_str(), hostNameCbRunning, IETF_SYSTEM_HOSTNAME_PATH, 0, SR_SUBSCR_DONE_ONLY);
+ m_srSession->session_switch_ds(SR_DS_STARTUP);
+ m_srSubscribe->module_change_subscribe(IETF_SYSTEM_MODULE_NAME.c_str(), hostNameCbStartup, IETF_SYSTEM_HOSTNAME_PATH, 0, SR_SUBSCR_DONE_ONLY);
+ m_srSession->session_switch_ds(SR_DS_OPERATIONAL);
+ m_srSubscribe->oper_get_items_subscribe(IETF_SYSTEM_MODULE_NAME.c_str(), hostNameCbOperational, IETF_SYSTEM_HOSTNAME_PATH);
+}
+
/** This class handles multiple system properties and publishes them via the ietf-system model:
* - OS-identification data from osRelease file
* - Rebooting
+ * - Hostname
*/
IETFSystem::IETFSystem(std::shared_ptr<::sysrepo::Session> srSession, const std::filesystem::path& osRelease)
: m_srSession(std::move(srSession))
@@ -101,5 +159,6 @@
{
initStaticProperties(osRelease);
initSystemRestart();
+ initHostname();
}
}