blob: 902008de0bf98249b94978f9e4f595e7c08609fc [file] [log] [blame]
Lorenz Brunae0d90d2019-09-05 17:53:56 +02001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package main
18
19import (
Lorenz Brundd8c80e2019-10-07 16:19:49 +020020 "fmt"
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020021 "git.monogon.dev/source/nexantic.git/core/internal/network"
22 "git.monogon.dev/source/nexantic.git/core/internal/node"
23 "git.monogon.dev/source/nexantic.git/core/pkg/tpm"
Lorenz Brunae0d90d2019-09-05 17:53:56 +020024 "os"
Lorenz Brunae0d90d2019-09-05 17:53:56 +020025 "os/signal"
Lorenz Brunf95909d2019-09-11 19:48:26 +020026 "runtime/debug"
Lorenz Brunae0d90d2019-09-05 17:53:56 +020027
28 "go.uber.org/zap"
29 "golang.org/x/sys/unix"
30)
31
Leopold Schabela4516f92019-12-04 20:27:05 +000032const (
33 apiPort = 7833
34 consensusPort = 7834
35)
36
Lorenz Brunae0d90d2019-09-05 17:53:56 +020037func main() {
Lorenz Brunf95909d2019-09-11 19:48:26 +020038 defer func() {
39 if r := recover(); r != nil {
40 fmt.Println("Init panicked:", r)
41 debug.PrintStack()
42 }
43 unix.Sync()
Leopold Schabel68c58752019-11-14 21:00:59 +010044 // TODO(lorenz): Switch this to Reboot when init panics are less likely
45 // Best effort, nothing we can do if this fails except printing the error to the console.
46 if err := unix.Reboot(unix.LINUX_REBOOT_CMD_POWER_OFF); err != nil {
47 panic(fmt.Sprintf("failed to halt node: %v\n", err))
48 }
Lorenz Brunf95909d2019-09-11 19:48:26 +020049 }()
Lorenz Brunae0d90d2019-09-05 17:53:56 +020050 logger, err := zap.NewDevelopment()
51 if err != nil {
52 panic(err)
53 }
54 logger.Info("Starting Smalltown Init")
55
56 // Set up bare minimum mounts
57 if err := os.Mkdir("/sys", 0755); err != nil {
58 panic(err)
59 }
60 if err := unix.Mount("sysfs", "/sys", "sysfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, ""); err != nil {
61 panic(err)
62 }
63
64 if err := os.Mkdir("/proc", 0755); err != nil {
65 panic(err)
66 }
67 if err := unix.Mount("procfs", "/proc", "proc", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, ""); err != nil {
68 panic(err)
69 }
70
71 signalChannel := make(chan os.Signal, 2)
72 signal.Notify(signalChannel)
73
Lorenz Brunae0d90d2019-09-05 17:53:56 +020074 if err := tpm.Initialize(logger.With(zap.String("component", "tpm"))); err != nil {
75 logger.Panic("Failed to initialize TPM 2.0", zap.Error(err))
76 }
77
Lorenz Brunf95909d2019-09-11 19:48:26 +020078 networkSvc, err := network.NewNetworkService(network.Config{}, logger.With(zap.String("component", "network")))
79 if err != nil {
80 panic(err)
81 }
Leopold Schabel68c58752019-11-14 21:00:59 +010082
83 if err := networkSvc.Start(); err != nil {
84 logger.Panic("Failed to start network service", zap.Error(err))
85 }
Lorenz Brunf95909d2019-09-11 19:48:26 +020086
Leopold Schabela4516f92019-12-04 20:27:05 +000087 nodeInstance, err := node.NewSmalltownNode(logger, apiPort, consensusPort)
Lorenz Brunae0d90d2019-09-05 17:53:56 +020088 if err != nil {
89 panic(err)
90 }
91
Lorenz Brundd8c80e2019-10-07 16:19:49 +020092 err = nodeInstance.Start()
Lorenz Brunae0d90d2019-09-05 17:53:56 +020093 if err != nil {
94 panic(err)
95 }
96
97 // We're PID1, so orphaned processes get reparented to us to clean up
98 for {
99 sig := <-signalChannel
100 switch sig {
101 case unix.SIGCHLD:
102 var status unix.WaitStatus
103 var rusage unix.Rusage
104 for {
Lorenz Brunf95909d2019-09-11 19:48:26 +0200105 res, err := unix.Wait4(-1, &status, unix.WNOHANG, &rusage)
106 if err != nil && err != unix.ECHILD {
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200107 logger.Error("Failed to wait on orphaned child", zap.Error(err))
108 break
109 }
110 if res <= 0 {
111 break
112 }
113 }
114 // TODO(lorenz): We can probably get more than just SIGCHLD as init, but I can't think
115 // of any others right now, just log them in case we hit any of them.
116 default:
117 logger.Warn("Got unexpected signal", zap.String("signal", sig.String()))
118 }
119 }
120}