blob: f5b09f8bb57b04661d237cdf4cae3df1ed5e9e7c [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
Lorenz Brun70f65b22020-07-08 17:02:47 +020089 // This function initializes a headless Delve if this is a debug build or does nothing if it's not
90 initializeDebugger(networkSvc)
91
Serge Bazanskib1b742f2020-03-24 13:58:19 +010092 supervisor.New(context.Background(), logger, func(ctx context.Context) error {
93 if err := supervisor.Run(ctx, "network", networkSvc.Run); err != nil {
94 return err
95 }
Lorenz Brunf95909d2019-09-11 19:48:26 +020096
Serge Bazanskib1b742f2020-03-24 13:58:19 +010097 // TODO(q3k): convert node code to supervisor
98 nodeInstance, err := node.NewSmalltownNode(logger, networkSvc, storageManager)
99 if err != nil {
100 panic(err)
101 }
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200102
Serge Bazanskib1b742f2020-03-24 13:58:19 +0100103 err = nodeInstance.Start(ctx)
104 if err != nil {
105 panic(err)
106 }
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200107
Serge Bazanskib1b742f2020-03-24 13:58:19 +0100108 supervisor.Signal(ctx, supervisor.SignalHealthy)
109
110 // We're PID1, so orphaned processes get reparented to us to clean up
111 for {
112 select {
113 case <-ctx.Done():
114 return ctx.Err()
115 case sig := <-signalChannel:
116 switch sig {
117 case unix.SIGCHLD:
118 var status unix.WaitStatus
119 var rusage unix.Rusage
120 for {
121 res, err := unix.Wait4(-1, &status, unix.WNOHANG, &rusage)
122 if err != nil && err != unix.ECHILD {
123 logger.Error("Failed to wait on orphaned child", zap.Error(err))
124 break
125 }
126 if res <= 0 {
127 break
128 }
129 }
Leopold Schabel8da53772020-06-02 15:56:51 +0200130 case unix.SIGURG:
131 // Go 1.14 introduced asynchronous preemption, which uses SIGURG.
132 // In order not to break backwards compatibility in the unlikely case
133 // of an application actually using SIGURG on its own, they're not filtering them.
134 // (https://github.com/golang/go/issues/37942)
135 logger.Debug("Ignoring SIGURG")
Serge Bazanskib1b742f2020-03-24 13:58:19 +0100136 // TODO(lorenz): We can probably get more than just SIGCHLD as init, but I can't think
137 // of any others right now, just log them in case we hit any of them.
138 default:
139 logger.Warn("Got unexpected signal", zap.String("signal", sig.String()))
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200140 }
141 }
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200142 }
Serge Bazanskib1b742f2020-03-24 13:58:19 +0100143 })
144 select {}
Lorenz Brunae0d90d2019-09-05 17:53:56 +0200145}