Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/pkg/osutil/machineid.go
2606 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package osutil
5
6
import (
7
"bytes"
8
"context"
9
"encoding/xml"
10
"fmt"
11
"io"
12
"os"
13
"os/exec"
14
"runtime"
15
"strings"
16
"sync"
17
18
"github.com/sirupsen/logrus"
19
)
20
21
var MachineID = sync.OnceValue(func() string {
22
x, err := machineID(context.Background())
23
if err == nil && x != "" {
24
return x
25
}
26
logrus.WithError(err).Debug("failed to get machine ID, falling back to use hostname instead")
27
hostname, err := os.Hostname()
28
if err != nil {
29
panic(fmt.Errorf("failed to get hostname: %w", err))
30
}
31
return hostname
32
})
33
34
func machineID(ctx context.Context) (string, error) {
35
if runtime.GOOS == "darwin" {
36
ioPlatformExpertDeviceCmd := exec.CommandContext(ctx, "/usr/sbin/ioreg", "-a", "-d2", "-c", "IOPlatformExpertDevice")
37
ioPlatformExpertDevice, err := ioPlatformExpertDeviceCmd.CombinedOutput()
38
if err != nil {
39
return "", err
40
}
41
return parseIOPlatformUUIDFromIOPlatformExpertDevice(bytes.NewReader(ioPlatformExpertDevice))
42
}
43
44
candidates := []string{
45
"/etc/machine-id",
46
"/var/lib/dbus/machine-id",
47
// We don't use "/sys/class/dmi/id/product_uuid"
48
}
49
for _, f := range candidates {
50
b, err := os.ReadFile(f)
51
if err == nil {
52
return strings.TrimSpace(string(b)), nil
53
}
54
}
55
return "", fmt.Errorf("no machine-id found, tried %v", candidates)
56
}
57
58
func parseIOPlatformUUIDFromIOPlatformExpertDevice(r io.Reader) (string, error) {
59
d := xml.NewDecoder(r)
60
var (
61
elem string
62
elemKeyCharData string
63
)
64
for {
65
tok, err := d.Token()
66
if err != nil {
67
return "", err
68
}
69
switch v := tok.(type) {
70
case xml.StartElement:
71
elem = v.Name.Local
72
case xml.EndElement:
73
elem = ""
74
if v.Name.Local != "key" {
75
elemKeyCharData = ""
76
}
77
case xml.CharData:
78
if elem == "string" && elemKeyCharData == "IOPlatformUUID" {
79
return string(v), nil
80
}
81
if elem == "key" {
82
elemKeyCharData = string(v)
83
}
84
}
85
}
86
}
87
88