-
Notifications
You must be signed in to change notification settings - Fork 6
/
main.go
128 lines (108 loc) · 3.08 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package main
import (
"fmt"
"log/slog"
"os"
"syscall"
"time"
"github.com/metal-stack/v"
"github.com/metal-stack/go-hal/connect"
"github.com/metal-stack/go-hal/pkg/logger"
"github.com/metal-stack/metal-hammer/cmd"
"github.com/metal-stack/metal-hammer/cmd/event"
"github.com/metal-stack/metal-hammer/cmd/network"
"github.com/metal-stack/metal-hammer/pkg/kernel"
"github.com/moby/sys/mountinfo"
)
func main() {
jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
})
log := slog.New(jsonHandler)
fmt.Print(cmd.HammerBanner)
if len(os.Args) > 1 {
panic("cmd args are not supported")
}
mounted, err := mountinfo.Mounted("/etc")
if err != nil {
log.Error("unable to check if /etc is a mountpoint", "error", err)
os.Exit(1)
}
if mounted {
err := syscall.Unmount("/etc", syscall.MNT_FORCE)
if err != nil {
log.Error("unable to umount /etc, which is overmounted with tmpfs", "error", err)
os.Exit(1)
}
}
err = updateResolvConf()
if err != nil {
log.Error("error updating resolv.conf", "error", err)
os.Exit(1)
}
// Reboot if metal-hammer crashes after 60sec.
go kernel.Watchdog(log)
hal, err := connect.InBand(logger.NewSlog(log))
if err != nil {
log.Error("unable to detect hardware", "error", err)
os.Exit(1)
}
uuid, err := hal.UUID()
if err != nil {
log.Error("unable to get uuid hardware", "error", err)
os.Exit(1)
}
log = log.With("machineID", uuid.String())
ip := network.InternalIP()
err = cmd.StartSSHD(log, ip)
if err != nil {
log.Error("sshd error", "error", err)
os.Exit(1)
}
log.Info("starting", "version", v.V.String(), "hal", hal.Describe())
spec := cmd.NewSpec(log)
spec.MachineUUID = uuid.String()
spec.IP = ip
spec.Log()
withRemoteHandler, err := cmd.AddRemoteHandler(spec, jsonHandler)
if err != nil {
log.Error("unable to add remote logging", "error", err)
} else {
log = slog.New(withRemoteHandler).With("machineID", uuid.String())
log.Info("remote logging enabled")
}
// FIXME set loglevel from spec.Debug
emitter, err := cmd.Run(log, spec, hal)
if err != nil {
wait := 5 * time.Second
log.Error("metal-hammer failed", "rebooting in", wait, "error", err)
if emitter != nil {
emitter.Emit(event.ProvisioningEventCrashed, fmt.Sprintf("%s", err))
}
time.Sleep(wait)
err := kernel.Reboot()
if err != nil {
log.Error("metal-hammer reboot failed", "error", err)
if emitter != nil {
emitter.Emit(event.ProvisioningEventCrashed, fmt.Sprintf("%s", err))
}
}
}
}
func updateResolvConf() error {
// when starting the metal-hammer u-root sets a static resolv.conf file containing 8.8.8.8
// this can only be overwritten by running dhclient
// however, we can use the dhcp information that the kernel used during startup
// this information is contained in /proc/net/pnp
//
// https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt
symlink := "/etc/resolv.conf"
target := "/proc/net/pnp"
if _, err := os.Stat(symlink); !os.IsNotExist(err) {
err := os.Remove(symlink)
if err != nil {
return err
}
}
return os.Symlink(target, symlink)
}