libutil/systemd/hostnamectl: init
This is some code that is specific to systemd to fetch hostnamectl information via the JSON flag. This will be used for `nix doctor`. Errors will show up similar to this: ``` ❯ ./build/lix/nix/nix doctor [INFO] Nix system type: 'x86_64-linux' warning: could not get host information via hostnamectl: error: Expected JSON value to be of type 'string' but it is of type 'number' ``` and makes them non-fatal. Change-Id: Idd39f29626e770b1cd3896e8eb8545416c74b041 Signed-off-by: Raito Bezarius <raito@lix.systems>
This commit is contained in:
@@ -45,6 +45,7 @@ liblix_sources += files(
|
||||
'source-path.cc',
|
||||
'strings.cc',
|
||||
'suggestions.cc',
|
||||
'systemd.cc',
|
||||
'tarfile.cc',
|
||||
'terminal.cc',
|
||||
'thread-name.cc',
|
||||
@@ -139,6 +140,7 @@ libutil_headers = files(
|
||||
'strings.hh',
|
||||
'suggestions.hh',
|
||||
'sync.hh',
|
||||
'systemd.hh',
|
||||
'tarfile.hh',
|
||||
'terminal.hh',
|
||||
'thread-name.hh',
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#if __linux__
|
||||
|
||||
#include "libutil/systemd.hh"
|
||||
#include "libutil/json-fwd.hh"
|
||||
namespace nix {
|
||||
|
||||
namespace systemd {
|
||||
|
||||
void from_json(const JSON & j, SystemdHostname & h)
|
||||
{
|
||||
h = SystemdHostname::parse(j);
|
||||
}
|
||||
|
||||
kj::Promise<Result<std::optional<HostInformation>>> get_host_information()
|
||||
try {
|
||||
auto output = TRY_AWAIT(runProgram("hostnamectl", true, {"--json=short"}));
|
||||
SystemdHostname raw = json::parse(output);
|
||||
std::optional<std::string> buildId;
|
||||
|
||||
for (const auto & line : raw.OperatingSystemReleaseData) {
|
||||
if (line.starts_with("BUILD_ID=")) {
|
||||
buildId = line.substr(9);
|
||||
|
||||
// Clean up quotes if they are present.
|
||||
if (buildId->size() >= 2 && buildId->front() == '"' && buildId->back() == '"') {
|
||||
buildId = buildId->substr(1, buildId->length() - 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HostInformation host_info = {
|
||||
.hostname = raw.Hostname,
|
||||
.chassis = raw.Chassis,
|
||||
.kernel_release = raw.KernelRelease,
|
||||
.kernel_version = raw.KernelVersion,
|
||||
.os_pretty_name = raw.OperatingSystemPrettyName,
|
||||
.hardware_vendor = raw.HardwareVendor,
|
||||
.hardware_model = raw.HardwareModel,
|
||||
.hardware_version = raw.HardwareVersion,
|
||||
.firmware_vendor = raw.FirmwareVendor,
|
||||
.firmware_version = raw.FirmwareVersion,
|
||||
.firmware_date = raw.FirmwareDate,
|
||||
.build_id = buildId,
|
||||
};
|
||||
|
||||
co_return {host_info};
|
||||
} catch (Error & e) {
|
||||
printTaggedWarning("could not get host information via hostnamectl: %s", e.msg());
|
||||
co_return {{}};
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#if __linux__
|
||||
|
||||
#include "lix/libutil/types.hh"
|
||||
#include "lix/libutil/json.hh"
|
||||
#include "lix/libutil/processes.hh"
|
||||
#include "lix/libutil/logging.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
namespace systemd {
|
||||
|
||||
// Machine readable information returned by the hostname component from systemd (hostnamectl).
|
||||
struct HostInformation
|
||||
{
|
||||
std::string hostname;
|
||||
std::string chassis;
|
||||
std::string kernel_release;
|
||||
std::string kernel_version;
|
||||
std::string os_pretty_name;
|
||||
std::string hardware_vendor;
|
||||
std::string hardware_model;
|
||||
std::string hardware_version;
|
||||
std::string firmware_vendor;
|
||||
std::string firmware_version;
|
||||
std::string firmware_date;
|
||||
std::optional<std::string> build_id;
|
||||
};
|
||||
|
||||
// Internal data structure that systemd returns for hostnamectl.
|
||||
// This needs to be kept update with the range of supported versions of systemd for Lix.
|
||||
struct SystemdHostname
|
||||
{
|
||||
std::string Hostname;
|
||||
std::string Chassis;
|
||||
std::string KernelRelease;
|
||||
std::string KernelVersion;
|
||||
std::string OperatingSystemPrettyName;
|
||||
std::vector<std::string> OperatingSystemReleaseData;
|
||||
std::string HardwareVendor;
|
||||
std::string HardwareModel;
|
||||
std::string HardwareVersion;
|
||||
std::string FirmwareVersion;
|
||||
std::string FirmwareVendor;
|
||||
std::string FirmwareDate;
|
||||
|
||||
static SystemdHostname parse(const JSON & j)
|
||||
{
|
||||
using nlohmann::detail::value_t;
|
||||
|
||||
SystemdHostname raw;
|
||||
|
||||
ensureType(j, value_t::object);
|
||||
raw.Hostname = ensureType(valueAt(j, "Hostname"), value_t::string);
|
||||
raw.Chassis = ensureType(valueAt(j, "Chassis"), value_t::string);
|
||||
raw.KernelRelease = ensureType(valueAt(j, "KernelRelease"), value_t::string);
|
||||
raw.KernelVersion = ensureType(valueAt(j, "KernelVersion"), value_t::string);
|
||||
raw.OperatingSystemPrettyName = ensureType(valueAt(j, "OperatingSystemPrettyName"), value_t::string);
|
||||
raw.HardwareVendor = ensureType(valueAt(j, "HardwareVendor"), value_t::string);
|
||||
raw.HardwareModel = ensureType(valueAt(j, "HardwareModel"), value_t::string);
|
||||
raw.HardwareVersion = ensureType(valueAt(j, "HardwareVersion"), value_t::string);
|
||||
raw.FirmwareVersion = ensureType(valueAt(j, "FirmwareVersion"), value_t::string);
|
||||
raw.FirmwareVendor = ensureType(valueAt(j, "FirmwareVendor"), value_t::string);
|
||||
raw.FirmwareDate =
|
||||
std::to_string((uint64_t) ensureType(valueAt(j, "FirmwareDate"), value_t::number_unsigned));
|
||||
const JSON & osReleaseRaw = valueAt(j, "OperatingSystemReleaseData");
|
||||
ensureType(osReleaseRaw, value_t::array);
|
||||
std::vector<JSON> osRelease = (std::vector<JSON>) osReleaseRaw;
|
||||
for (const auto & item : osRelease) {
|
||||
raw.OperatingSystemReleaseData.push_back(ensureType(item, value_t::string));
|
||||
}
|
||||
|
||||
return raw;
|
||||
}
|
||||
};
|
||||
|
||||
void from_json(const JSON & j, SystemdHostname & h);
|
||||
|
||||
kj::Promise<Result<std::optional<HostInformation>>> get_host_information();
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user