From be2b25a7c66aec4c2491435a18e1a2e339872592 Mon Sep 17 00:00:00 2001 From: Pierre Souchay Date: Tue, 6 Nov 2018 17:56:09 +0100 Subject: [PATCH] Have a real fixed HostID on Linux On Linux, most golang programs do not run as root (or at least, they should not), by default, the kernels uses strict permissions, so most userland programs cannot read `/sys/class/dmi/id/product_uuid`. However, programs such as Consul are relying on it to get fixed IDs, instead they have a different ID on each boot. We propose to use `/etc/machine-id` as fallback https://www.freedesktop.org/software/systemd/man/machine-id.html In order to fix this, this patch does the following: - if `/sys/class/dmi/id/product_uuid` can be read, use it for HostID - else if `/etc/machine-id` exists and has 32 chars, use it and add '-' to have the same format as product_uuid - finally, if notthing works, use the `kernel.random.boot_id` This will greatly increase the number of programs having correct behaviour when those rely on having a fixed HostID. This will fix the following issues: - https://github.com/shirou/gopsutil/issues/350 - https://github.com/hashicorp/consul/issues/4741 --- host/host_linux.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/host/host_linux.go b/host/host_linux.go index 7ca5089..2981675 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -73,7 +73,9 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { } sysProductUUID := common.HostSys("class/dmi/id/product_uuid") + machineID := common.HostEtc("machine-id") switch { + // When not running as root, lib cannot read the value case common.PathExists(sysProductUUID): lines, err := common.ReadLines(sysProductUUID) if err == nil && len(lines) > 0 && lines[0] != "" { @@ -81,6 +83,14 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { break } fallthrough + case common.PathExists(machineID): + lines, err := common.ReadLines(machineID) + if err == nil && len(lines) > 0 && len(lines[0]) == 32 { + st := lines[0] + ret.HostID = fmt.Sprintf("%s-%s-%s-%s-%s", st[0:8], st[8:12], st[12:16], st[16:20], st[20:32]) + break + } + fallthrough default: values, err := common.DoSysctrl("kernel.random.boot_id") if err == nil && len(values) == 1 && values[0] != "" {