blob: 9ad3d1a30698c7ad8246d3ccffbf26001ad0743b [file] [log] [blame]
Tomáš Pecka292bc9c2021-01-11 22:03:11 +01001/*
2 * Copyright (C) 2021 CESNET, https://photonics.cesnet.cz/
3 *
4 * Written by Tomáš Pecka <tomas.pecka@fit.cvut.cz>
5 *
6 */
7
8#include <boost/algorithm/string/predicate.hpp>
9#include <fstream>
Tomáš Peckaf976c5b2021-01-23 21:19:52 +010010#include "IETFSystem.h"
Tomáš Pecka292bc9c2021-01-11 22:03:11 +010011#include "utils/io.h"
12#include "utils/log.h"
13
14using namespace std::literals;
15
16namespace {
17
18const auto IETF_SYSTEM_MODULE_NAME = "ietf-system"s;
19const auto IETF_SYSTEM_STATE_MODULE_PREFIX = "/"s + IETF_SYSTEM_MODULE_NAME + ":system-state/"s;
20
21/** @brief Returns key=value pairs from (e.g. /etc/os-release) as a std::map */
22std::map<std::string, std::string> parseKeyValueFile(const std::filesystem::path& path)
23{
24 std::map<std::string, std::string> res;
25 std::ifstream ifs(path);
26 if (!ifs.is_open())
27 throw std::invalid_argument("File '" + std::string(path) + "' not found.");
28
29 std::string line;
30 while (std::getline(ifs, line)) {
31 // man os-release: Lines beginning with "#" shall be ignored as comments. Blank lines are permitted and ignored.
32 if (line.empty() || boost::algorithm::starts_with(line, "#")) {
33 continue;
34 }
35
36 size_t equalSignPos = line.find_first_of('=');
37 if (equalSignPos != std::string::npos) {
38 std::string key = line.substr(0, equalSignPos);
39 std::string val = line.substr(equalSignPos + 1);
40
41 // remove quotes from value
42 if (val.length() >= 2 && val.front() == '"' && val.front() == val.back()) {
43 val = val.substr(1, val.length() - 2);
44 }
45
46 res[key] = val;
47 } else { // when there is no = sign, treat the value as empty string
48 res[line] = "";
49 }
50 }
51
52 return res;
53}
54
55}
56
57namespace velia::system {
58
59/** @brief Reads some OS-identification data from osRelease file and publishes them via ietf-system model */
Tomáš Peckaf976c5b2021-01-23 21:19:52 +010060IETFSystem::IETFSystem(std::shared_ptr<::sysrepo::Session> srSession, const std::filesystem::path& osRelease)
Tomáš Pecka292bc9c2021-01-11 22:03:11 +010061 : m_srSession(std::move(srSession))
62 , m_log(spdlog::get("system"))
63{
64 std::map<std::string, std::string> osReleaseContents = parseKeyValueFile(osRelease);
65
66 std::map<std::string, std::string> opsSystemStateData {
67 {IETF_SYSTEM_STATE_MODULE_PREFIX + "platform/os-name", osReleaseContents.at("NAME")},
68 {IETF_SYSTEM_STATE_MODULE_PREFIX + "platform/os-release", osReleaseContents.at("VERSION")},
69 {IETF_SYSTEM_STATE_MODULE_PREFIX + "platform/os-version", osReleaseContents.at("VERSION")},
70 };
71
72 sr_datastore_t oldDatastore = m_srSession->session_get_ds();
73 m_srSession->session_switch_ds(SR_DS_OPERATIONAL);
74
75 for (const auto& [k, v] : opsSystemStateData) {
76 m_log->debug("Pushing to sysrepo: {} = {}", k, v);
77 m_srSession->set_item_str(k.c_str(), v.c_str());
78 }
79
80 m_srSession->apply_changes();
81 m_srSession->session_switch_ds(oldDatastore);
82}
83}