blob: 42770a91a0c1117516e38fec84b82259614bd42b [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 (
Serge Bazanskicdb8c782020-02-17 12:34:02 +010020 "context"
Lorenz Brundd8c80e2019-10-07 16:19:49 +020021 "fmt"
Lorenz Brunae0d90d2019-09-05 17:53:56 +020022 "os"
Lorenz Brunae0d90d2019-09-05 17:53:56 +020023 "os/signal"
Lorenz Brunf95909d2019-09-11 19:48:26 +020024 "runtime/debug"
Lorenz Brunae0d90d2019-09-05 17:53:56 +020025
Serge Bazanskib1b742f2020-03-24 13:58:19 +010026 "git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
Lorenz Brunaa6b7342019-12-12 02:55:02 +010027 "git.monogon.dev/source/nexantic.git/core/internal/network"
28 "git.monogon.dev/source/nexantic.git/core/internal/node"
Serge Bazanskicdb8c782020-02-17 12:34:02 +010029 "git.monogon.dev/source/nexantic.git/core/internal/storage"
Lorenz Brunaa6b7342019-12-12 02:55:02 +010030 "git.monogon.dev/source/nexantic.git/core/pkg/tpm"
31
Lorenz Brunae0d90d2019-09-05 17:53:56 +020032 "go.uber.org/zap"
33 "golang.org/x/sys/unix"
34)
35
Leopold Schabela4516f92019-12-04 20:27:05 +000036const (
37 apiPort = 7833
38 consensusPort = 7834
39)
40
Lorenz Brunae0d90d2019-09-05 17:53:56 +020041func main() {
Lorenz Brunf95909d2019-09-11 19:48:26 +020042 defer func() {
43 if r := recover(); r != nil {
44 fmt.Println("Init panicked:", r)
45 debug.PrintStack()
46 }
47 unix.Sync()
Leopold Schabel68c58752019-11-14 21:00:59 +010048 // TODO(lorenz): Switch this to Reboot when init panics are less likely
49 // Best effort, nothing we can do if this fails except printing the error to the console.
50 if err := unix.Reboot(unix.LINUX_REBOOT_CMD_POWER_OFF); err != nil {
51 panic(fmt.Sprintf("failed to halt node: %v\n", err))
52 }
Lorenz Brunf95909d2019-09-11 19:48:26 +020053 }()
Lorenz Brunae0d90d2019-09-05 17:53:56 +020054 logger, err := zap.NewDevelopment()
55 if err != nil {
56 panic(err)
57 }
Serge Bazanski581b0bd2020-03-12 13:36:43 +010058
59 // Remount onto a tmpfs and re-exec if needed. Otherwise, keep running.
60 err = switchRoot(logger)
61 if err != nil {
62 panic(fmt.Errorf("could not remount root: %w", err))
63 }
64
Lorenz Brun878f5f92020-05-12 16:15:39 +020065 // Linux kernel default is 4096 which is far too low. Raise it to 1M which is what gVisor suggests.
66 if err := unix.Setrlimit(unix.RLIMIT_NOFILE, &unix.Rlimit{Cur: 1048576, Max: 1048576}); err != nil {
67 logger.Panic("Failed to raise rlimits", zap.Error(err))
68 }
69
Lorenz Brunae0d90d2019-09-05 17:53:56 +020070 logger.Info("Starting Smalltown Init")
71
Lorenz Brunae0d90d2019-09-05 17:53:56 +020072 signalChannel := make(chan os.Signal, 2)
73 signal.Notify(signalChannel)
74
Lorenz Brunae0d90d2019-09-05 17:53:56 +020075 if err := tpm.Initialize(logger.With(zap.String("component", "tpm"))); err != nil {
76 logger.Panic("Failed to initialize TPM 2.0", zap.Error(err))
77 }
78
Serge Bazanskicdb8c782020-02-17 12:34:02 +010079 storageManager, err := storage.Initialize(logger.With(zap.String("component", "storage")))
80 if err != nil {
Serge Bazanski581b0bd2020-03-12 13:36:43 +010081 panic(fmt.Errorf("could not initialize storage: %w", err))
Serge Bazanskicdb8c782020-02-17 12:34:02 +010082 }
83
Serge Bazanskib1b742f2020-03-24 13:58:19 +010084 networkSvc := network.New(network.Config{})
Lorenz Brunf95909d2019-09-11 19:48:26 +020085 if err != nil {
86 panic(err)
87 }
Leopold Schabel68c58752019-11-14 21:00:59 +010088
Serge Bazanskib1b742f2020-03-24 13:58:19 +010089 supervisor.New(context.Background(), logger, func(ctx context.Context) error {
90 if err := supervisor.Run(ctx, "network", networkSvc.Run); err != nil {
91 return err
92 }
Lorenz Brunf95909d2019-09-11 19:48:26 +020093
Serge Bazanskib1b742f2020-03-24 13:58:19 +010094 // TODO(q3k): convert node code to supervisor
95 nodeInstance, err := node.NewSmalltownNode(logger, networkSvc, storageManager)
96 if err != nil {
97 panic(err)
98 }
Lorenz Brunae0d90d2019-09-05 17:53:56 +020099
Serge Bazanskib1b742f2020-03-24 13:58:19 +0100100 err = nodeInstance.Start(ctx)
101 if err != nil {
102 panic(err)
103 }
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200104
Serge Bazanskib1b742f2020-03-24 13:58:19 +0100105 supervisor.Signal(ctx, supervisor.SignalHealthy)
106
107 // We're PID1, so orphaned processes get reparented to us to clean up
108 for {
109 select {
110 case <-ctx.Done():
111 return ctx.Err()
112 case sig := <-signalChannel:
113 switch sig {
114 case unix.SIGCHLD:
115 var status unix.WaitStatus
116 var rusage unix.Rusage
117 for {
118 res, err := unix.Wait4(-1, &status, unix.WNOHANG, &rusage)
119 if err != nil && err != unix.ECHILD {
120 logger.Error("Failed to wait on orphaned child", zap.Error(err))
121 break
122 }
123 if res <= 0 {
124 break
125 }
126 }
127 // TODO(lorenz): We can probably get more than just SIGCHLD as init, but I can't think
128 // of any others right now, just log them in case we hit any of them.
129 default:
130 logger.Warn("Got unexpected signal", zap.String("signal", sig.String()))
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200131 }
132 }
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200133 }
Serge Bazanskib1b742f2020-03-24 13:58:19 +0100134 })
135 select {}
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200136}