refactor: improve machined
This is a rewrite of machined. It addresses some of the limitations and complexity in the implementation. This introduces the idea of a controller. A controller is responsible for managing the runtime, the sequencer, and a new state type introduced in this PR. A few highlights are: - no more event bus - functional approach to tasks (no more types defined for each task) - the task function definition now offers a lot more context, like access to raw API requests, the current sequence, a logger, the new state interface, and the runtime interface. - no more panics to handle reboots - additional initialize and reboot sequences - graceful gRPC server shutdown on critical errors - config is now stored at install time to avoid having to download it at install time and at boot time - upgrades now use the local config instead of downloading it - the upgrade API's preserve option takes precedence over the config's install force option Additionally, this pulls various packes in under machined to make the code easier to navigate. Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
This commit is contained in:
parent
55dcbbc8d0
commit
49307d554d
4
Makefile
4
Makefile
@ -17,7 +17,7 @@ KUBECTL_URL ?= https://storage.googleapis.com/kubernetes-release/release/v1.18.0
|
||||
SONOBUOY_VERSION ?= 0.18.0
|
||||
SONOBUOY_URL ?= https://github.com/heptio/sonobuoy/releases/download/v$(SONOBUOY_VERSION)/sonobuoy_$(SONOBUOY_VERSION)_$(OPERATING_SYSTEM)_amd64.tar.gz
|
||||
TESTPKGS ?= ./...
|
||||
RELEASES ?= v0.3.3 v0.4.0-beta.1
|
||||
RELEASES ?= v0.3.3 v0.4.1
|
||||
|
||||
BUILD := docker buildx build
|
||||
PLATFORM ?= linux/amd64
|
||||
@ -154,7 +154,7 @@ boot: ## Creates a compressed tarball that includes vmlinuz and initramfs.xz. No
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## Formats the source code.
|
||||
@docker run --rm -it -v $(PWD):/src -w /src golang:$(GO_VERSION) bash -c "export GO111MODULE=on; export GOPROXY=https://proxy.golang.org; cd /tmp && go mod init tmp && go get mvdan.cc/gofumpt/gofumports && cd - && gofumports -w -local github.com/talos-systems/talos ."
|
||||
@docker run --rm -it -v $(PWD):/src -w /src golang:$(GO_VERSION) bash -c "export GO111MODULE=on; export GOPROXY=https://proxy.golang.org; cd /tmp && go mod init tmp && go get mvdan.cc/gofumpt/gofumports@aaa7156f4122b1055c466e26e77812fa32bac1d9 && cd - && gofumports -w -local github.com/talos-systems/talos ."
|
||||
|
||||
lint-%: ## Runs the specified linter. Valid options are go, protobuf, and markdown (e.g. lint-go).
|
||||
@$(MAKE) target-lint-$*
|
||||
|
@ -2205,102 +2205,100 @@ func init() {
|
||||
func init() { proto.RegisterFile("machine/machine.proto", fileDescriptor_84b4f59d98cc997c) }
|
||||
|
||||
var fileDescriptor_84b4f59d98cc997c = []byte{
|
||||
// 1520 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xcd, 0x73, 0xdb, 0x44,
|
||||
0x14, 0x1f, 0x39, 0x8e, 0x63, 0x3f, 0x27, 0x4e, 0x50, 0x9b, 0x44, 0xa4, 0xe9, 0x97, 0xf8, 0x68,
|
||||
0x27, 0xb4, 0x4e, 0x9a, 0x42, 0xa7, 0x10, 0x0a, 0xd3, 0x26, 0xa5, 0xed, 0xb4, 0xa1, 0x41, 0x01,
|
||||
0x0e, 0x5c, 0xcc, 0xda, 0x5a, 0xcb, 0x3b, 0x95, 0xb4, 0x42, 0xbb, 0x4e, 0x27, 0x0c, 0x7f, 0x00,
|
||||
0xc3, 0x8d, 0xe1, 0xc6, 0x95, 0xff, 0x91, 0x33, 0xb3, 0x9f, 0x52, 0xac, 0xb8, 0xd4, 0x33, 0x3d,
|
||||
0x79, 0xf7, 0xed, 0xef, 0x7d, 0x3f, 0xbd, 0x7d, 0x6b, 0x58, 0x4d, 0xd0, 0x60, 0x44, 0x52, 0xbc,
|
||||
0xad, 0x7f, 0xbb, 0x59, 0x4e, 0x39, 0x75, 0x17, 0xf4, 0x76, 0xe3, 0x52, 0x44, 0x69, 0x14, 0xe3,
|
||||
0x6d, 0x49, 0xee, 0x8f, 0x87, 0xdb, 0x38, 0xc9, 0xf8, 0xa9, 0x42, 0x6d, 0x5c, 0x9d, 0x3c, 0xe4,
|
||||
0x24, 0xc1, 0x8c, 0xa3, 0x24, 0xd3, 0x80, 0x0b, 0x03, 0x9a, 0x24, 0x34, 0xdd, 0x56, 0x3f, 0x8a,
|
||||
0xe8, 0xdf, 0x83, 0x46, 0x80, 0xfb, 0x94, 0x72, 0xf7, 0x16, 0x34, 0x13, 0xcc, 0x51, 0x88, 0x38,
|
||||
0xf2, 0x9c, 0x6b, 0xce, 0xcd, 0xf6, 0xee, 0x4a, 0x57, 0x43, 0x0f, 0x35, 0x3d, 0xb0, 0x08, 0xff,
|
||||
0x01, 0x74, 0x14, 0x5f, 0x80, 0x59, 0x46, 0x53, 0x86, 0xdd, 0x4f, 0x04, 0x3f, 0x63, 0x28, 0xc2,
|
||||
0xcc, 0x73, 0xae, 0xcd, 0xdd, 0x6c, 0xef, 0x2e, 0x77, 0x8d, 0x1f, 0x1a, 0x6a, 0x01, 0xfe, 0x23,
|
||||
0x58, 0x0c, 0x30, 0xc3, 0x3c, 0xc0, 0xbf, 0x8c, 0x31, 0xe3, 0xee, 0x06, 0x34, 0xa3, 0x1c, 0x0d,
|
||||
0xf0, 0x70, 0x1c, 0x4b, 0xe5, 0xcd, 0xc0, 0xee, 0xdd, 0x35, 0x68, 0xe4, 0x92, 0xdf, 0xab, 0xc9,
|
||||
0x13, 0xbd, 0xf3, 0x3f, 0x83, 0x79, 0x29, 0x63, 0x46, 0xcb, 0xf7, 0x60, 0x49, 0xab, 0xd6, 0x86,
|
||||
0x6f, 0x55, 0x0c, 0xef, 0x94, 0x0c, 0x17, 0xc8, 0xc2, 0xee, 0xfb, 0xd0, 0x3c, 0x1e, 0x8d, 0x79,
|
||||
0x48, 0x5f, 0xa7, 0x33, 0xaa, 0x7d, 0x08, 0x2b, 0x86, 0xd3, 0x6a, 0xbe, 0x5d, 0xd1, 0xfc, 0x9e,
|
||||
0xd5, 0x6c, 0xc1, 0xe5, 0xa0, 0x75, 0x7e, 0xc8, 0xa2, 0x1c, 0x85, 0xd8, 0x84, 0xed, 0x22, 0xcc,
|
||||
0x93, 0x04, 0x45, 0x58, 0xea, 0x6f, 0x05, 0x6a, 0x23, 0x82, 0x99, 0xe5, 0x98, 0xe1, 0xfc, 0x04,
|
||||
0xeb, 0x90, 0xd9, 0xbd, 0xff, 0x0c, 0x16, 0xb4, 0x8c, 0xd9, 0xec, 0x77, 0x57, 0x60, 0x0e, 0x0d,
|
||||
0x5e, 0x49, 0x79, 0xad, 0x40, 0x2c, 0xfd, 0xaf, 0x61, 0xd9, 0x9a, 0xa3, 0x1d, 0xba, 0x55, 0x71,
|
||||
0x68, 0xc5, 0x3a, 0x64, 0xb0, 0x85, 0x3f, 0x09, 0xb4, 0x8f, 0x71, 0x7e, 0x42, 0x06, 0xf8, 0x05,
|
||||
0x61, 0x33, 0xa6, 0xd1, 0xdd, 0x81, 0x26, 0x53, 0xcc, 0xcc, 0xab, 0x49, 0x55, 0x17, 0x8b, 0xd8,
|
||||
0xa9, 0x83, 0x67, 0xe9, 0x90, 0x06, 0x16, 0xe5, 0x3f, 0x81, 0x0b, 0x25, 0x75, 0xd6, 0xe6, 0x9d,
|
||||
0x8a, 0xcd, 0x15, 0x41, 0x12, 0x5f, 0xd8, 0xfd, 0x97, 0x63, 0x0d, 0x17, 0x2a, 0xdc, 0x0e, 0xd4,
|
||||
0x48, 0xa8, 0x53, 0x50, 0x23, 0xa1, 0xc8, 0x0a, 0xe3, 0x88, 0x63, 0x1d, 0x2c, 0xb5, 0x71, 0xbb,
|
||||
0xd0, 0xc0, 0x27, 0x38, 0xe5, 0xcc, 0x9b, 0x93, 0xce, 0xad, 0x4d, 0x6a, 0x79, 0x2c, 0x4f, 0x03,
|
||||
0x8d, 0x12, 0xf8, 0x11, 0x46, 0x31, 0x1f, 0x79, 0xf5, 0xf3, 0xf1, 0x4f, 0xe5, 0x69, 0xa0, 0x51,
|
||||
0xfe, 0x57, 0xb0, 0x74, 0x46, 0x90, 0x7b, 0xdb, 0x2a, 0x54, 0x6e, 0xad, 0x9e, 0xab, 0xd0, 0xe8,
|
||||
0xf3, 0xfb, 0xb0, 0x58, 0xa6, 0x8b, 0x84, 0x27, 0x2c, 0xd2, 0x6e, 0x89, 0xe5, 0x14, 0xbf, 0xb6,
|
||||
0xa0, 0x66, 0x7d, 0xda, 0xe8, 0xaa, 0x26, 0xd4, 0x35, 0x4d, 0xa8, 0xfb, 0xbd, 0x69, 0x42, 0x41,
|
||||
0x8d, 0x33, 0xff, 0x1f, 0xc7, 0x1a, 0xa9, 0xac, 0x77, 0x3d, 0x58, 0x18, 0xa7, 0xaf, 0x52, 0xfa,
|
||||
0x3a, 0xd5, 0xdf, 0xbd, 0xd9, 0x8a, 0x13, 0xe5, 0xd9, 0xa9, 0x2e, 0x62, 0xb3, 0x75, 0xaf, 0xc3,
|
||||
0x62, 0x8c, 0x18, 0xef, 0xe9, 0x84, 0x48, 0xdd, 0xad, 0xa0, 0x2d, 0x68, 0x87, 0x8a, 0xe4, 0xee,
|
||||
0x81, 0xdc, 0xf6, 0x06, 0x23, 0x94, 0x46, 0x58, 0x47, 0xf0, 0x4d, 0xd6, 0x81, 0x80, 0xef, 0x4b,
|
||||
0xb4, 0xff, 0x91, 0x2d, 0x94, 0x63, 0x8e, 0x72, 0xdb, 0xa3, 0x26, 0xd2, 0xec, 0x1f, 0xd9, 0x80,
|
||||
0x49, 0xd8, 0x8c, 0xf5, 0xeb, 0x42, 0x3d, 0xc7, 0x2c, 0xd3, 0xb1, 0x94, 0x6b, 0xff, 0x19, 0x5c,
|
||||
0x3c, 0xab, 0x58, 0x97, 0xe8, 0x9d, 0x4a, 0x89, 0x56, 0x72, 0xa9, 0x18, 0x8a, 0x1a, 0xfd, 0x10,
|
||||
0x5c, 0x7b, 0x42, 0xb3, 0x69, 0x2e, 0xbc, 0xb4, 0x85, 0x2c, 0x50, 0xef, 0xc0, 0x83, 0x27, 0xa5,
|
||||
0xd0, 0x09, 0xb5, 0x6f, 0xff, 0x8d, 0x49, 0x7c, 0x61, 0xff, 0x0d, 0x58, 0xd5, 0x07, 0x81, 0xc8,
|
||||
0xd0, 0xf4, 0x2c, 0x04, 0xd0, 0x39, 0x0b, 0x7c, 0x07, 0x5e, 0x1c, 0xc2, 0xda, 0xa4, 0x72, 0xed,
|
||||
0xc8, 0xdd, 0x8a, 0x23, 0xeb, 0x93, 0x8e, 0x18, 0x96, 0xc2, 0x17, 0x1f, 0x16, 0xdf, 0x54, 0x48,
|
||||
0x5f, 0xd4, 0x3c, 0xc7, 0xbf, 0x01, 0x4b, 0x67, 0x73, 0x6e, 0xec, 0x72, 0x0a, 0xbb, 0x24, 0xf0,
|
||||
0x3a, 0xb4, 0xdf, 0x90, 0x51, 0x09, 0xf9, 0x58, 0xe8, 0x2b, 0x45, 0x7f, 0x9a, 0xa8, 0x2d, 0x68,
|
||||
0xef, 0xd3, 0xec, 0xd4, 0x88, 0xba, 0x04, 0xad, 0x9c, 0x52, 0xde, 0xcb, 0x10, 0x1f, 0x69, 0x6c,
|
||||
0x53, 0x10, 0x8e, 0x10, 0x1f, 0xf9, 0x21, 0xb4, 0x55, 0xd7, 0x54, 0x58, 0x21, 0x52, 0xdc, 0xc8,
|
||||
0x46, 0xa4, 0x18, 0x20, 0x3c, 0x58, 0xc8, 0xf1, 0x60, 0x9c, 0x33, 0x73, 0xeb, 0x98, 0xad, 0x7b,
|
||||
0x03, 0x96, 0xd5, 0x92, 0xd0, 0xb4, 0x17, 0xe2, 0x8c, 0x8f, 0xe4, 0x37, 0x3b, 0x1f, 0x74, 0x2c,
|
||||
0xf9, 0x40, 0x50, 0xfd, 0x7f, 0x1d, 0x68, 0x7e, 0x43, 0x62, 0xd5, 0x56, 0x67, 0xce, 0x63, 0x8a,
|
||||
0x12, 0xd3, 0x9b, 0xe4, 0x5a, 0xd0, 0x18, 0xf9, 0x55, 0x35, 0x88, 0xb9, 0x40, 0xae, 0x05, 0x2d,
|
||||
0xa1, 0xa1, 0x6a, 0x09, 0x4b, 0x81, 0x5c, 0x8b, 0x0b, 0x33, 0xa1, 0x21, 0x19, 0x12, 0x1c, 0x7a,
|
||||
0xf3, 0x12, 0x6b, 0xf7, 0xee, 0x2a, 0x34, 0x08, 0xeb, 0x85, 0x24, 0xf7, 0x1a, 0xd2, 0xa9, 0x79,
|
||||
0xc2, 0x0e, 0x48, 0x2e, 0x7a, 0x21, 0xce, 0x73, 0x9a, 0x7b, 0x0b, 0xaa, 0x17, 0xca, 0x8d, 0x10,
|
||||
0x1e, 0x93, 0xf4, 0x95, 0xd7, 0x54, 0x46, 0x88, 0xb5, 0xfb, 0x01, 0x2c, 0xe5, 0x38, 0x46, 0x9c,
|
||||
0x9c, 0xe0, 0x9e, 0xb4, 0xb0, 0x25, 0x0f, 0x17, 0x0d, 0xf1, 0x5b, 0x94, 0x60, 0xff, 0x67, 0x68,
|
||||
0x1c, 0xd2, 0xb1, 0xe8, 0xda, 0xb3, 0x79, 0x7d, 0x53, 0xb5, 0x64, 0x73, 0x05, 0xba, 0xb6, 0x18,
|
||||
0xa5, 0xb4, 0x63, 0x8e, 0xb8, 0x6a, 0xd3, 0x4c, 0x0c, 0x6c, 0x4a, 0xc3, 0x5b, 0x0d, 0x6c, 0x1a,
|
||||
0x5a, 0xd4, 0xf0, 0x6f, 0xd0, 0xb2, 0x22, 0xdd, 0x2b, 0x00, 0x43, 0x12, 0x63, 0x76, 0xca, 0x38,
|
||||
0x4e, 0x74, 0x0d, 0x94, 0x28, 0x36, 0xee, 0x22, 0x17, 0x75, 0x1d, 0xf7, 0x4d, 0x68, 0xa1, 0x13,
|
||||
0x44, 0x62, 0xd4, 0x8f, 0x55, 0x42, 0xea, 0x41, 0x41, 0x70, 0x2f, 0x03, 0x24, 0x42, 0x3c, 0x0e,
|
||||
0x7b, 0x34, 0x95, 0xb9, 0x69, 0x05, 0x2d, 0x4d, 0x79, 0x99, 0xfa, 0x7f, 0x3b, 0xb0, 0xf0, 0x23,
|
||||
0x96, 0x85, 0x32, 0x63, 0x80, 0xba, 0xb0, 0x70, 0xa2, 0x18, 0xa5, 0x35, 0xe5, 0xc6, 0xa3, 0x05,
|
||||
0xca, 0x29, 0xc1, 0x80, 0x44, 0xab, 0xcd, 0x62, 0xc4, 0x87, 0x34, 0x4f, 0xf4, 0x9d, 0x56, 0xb4,
|
||||
0xda, 0x23, 0x7d, 0xa0, 0xe6, 0x0a, 0x03, 0x13, 0x73, 0x90, 0x16, 0xf5, 0x56, 0x73, 0x90, 0xc1,
|
||||
0x16, 0xb1, 0xfd, 0xc3, 0x81, 0x76, 0xc9, 0x18, 0x71, 0xf3, 0x72, 0x64, 0x6f, 0x5e, 0x8e, 0x22,
|
||||
0x41, 0x61, 0x23, 0x64, 0x86, 0x2f, 0x36, 0x42, 0xa2, 0xfe, 0xfa, 0x63, 0x12, 0x73, 0x7d, 0xf9,
|
||||
0xa9, 0x8d, 0x08, 0x63, 0x44, 0x7b, 0xc6, 0x61, 0x1d, 0xc6, 0x88, 0x9a, 0xd0, 0x75, 0xa0, 0x46,
|
||||
0x99, 0xac, 0xf0, 0x56, 0x50, 0xa3, 0x4c, 0xe4, 0x09, 0xe5, 0x83, 0x91, 0xac, 0xec, 0x56, 0x20,
|
||||
0xd7, 0xfe, 0x3d, 0x58, 0x2c, 0xfb, 0x69, 0xbf, 0x2b, 0xe7, 0xec, 0x77, 0x25, 0xbf, 0x21, 0xfd,
|
||||
0xad, 0x89, 0xb5, 0xb8, 0xda, 0xdb, 0x2f, 0x68, 0xc4, 0x4c, 0x87, 0xd8, 0x84, 0x96, 0xc0, 0xb2,
|
||||
0x0c, 0x0d, 0x0c, 0x73, 0x41, 0xd0, 0x6d, 0xab, 0x66, 0x47, 0xa6, 0x6d, 0x68, 0x84, 0x39, 0x39,
|
||||
0xc1, 0xb9, 0xf4, 0xa7, 0xb3, 0xbb, 0x6e, 0x52, 0xba, 0x4f, 0x53, 0x8e, 0x48, 0x8a, 0xf3, 0x03,
|
||||
0x79, 0x1c, 0x68, 0x98, 0x78, 0x14, 0x0c, 0x69, 0x1c, 0xd3, 0xd7, 0xd2, 0xcb, 0x66, 0xa0, 0x77,
|
||||
0x22, 0x02, 0x1c, 0x91, 0xb8, 0x17, 0x93, 0x14, 0x2b, 0x57, 0xe7, 0x83, 0x96, 0xa0, 0xbc, 0x10,
|
||||
0x04, 0xd1, 0x3d, 0x03, 0x8c, 0xc2, 0x52, 0x1b, 0x2b, 0x75, 0x3b, 0xb9, 0xde, 0xfd, 0xb3, 0x09,
|
||||
0x9d, 0x43, 0x95, 0x2b, 0xdd, 0xd1, 0xdd, 0x5b, 0x50, 0x17, 0x8d, 0xd2, 0x2d, 0x6a, 0xa7, 0xd4,
|
||||
0x37, 0x37, 0x16, 0x8d, 0xad, 0x07, 0x88, 0xa3, 0x1d, 0xc7, 0xfd, 0x14, 0xe0, 0xf9, 0xb8, 0x8f,
|
||||
0x07, 0x34, 0x1d, 0x92, 0xc8, 0x5d, 0xab, 0x0c, 0x1d, 0x8f, 0xc5, 0xa3, 0xad, 0xc2, 0x75, 0x07,
|
||||
0xea, 0x72, 0x0a, 0x2e, 0x74, 0x94, 0xfa, 0xed, 0x46, 0xf1, 0x2e, 0x30, 0xed, 0x71, 0xc7, 0x11,
|
||||
0x66, 0x89, 0x88, 0x97, 0x59, 0x8a, 0x04, 0x54, 0x14, 0x7c, 0x6e, 0x5b, 0xcc, 0x34, 0x93, 0xd6,
|
||||
0x27, 0x3f, 0xff, 0xa2, 0x9c, 0xeb, 0x22, 0x6a, 0x25, 0x45, 0xa5, 0x20, 0x9e, 0xa7, 0x48, 0x3f,
|
||||
0x29, 0xff, 0x5f, 0xd1, 0xc4, 0x1b, 0xf2, 0x9e, 0x79, 0xd2, 0xad, 0x4e, 0xbc, 0xc0, 0xb4, 0xaa,
|
||||
0xb5, 0x49, 0xb2, 0xe6, 0xdb, 0x3f, 0xfb, 0x92, 0x98, 0xa6, 0x77, 0xf3, 0xdc, 0xc1, 0xde, 0x08,
|
||||
0xf9, 0xae, 0x32, 0x49, 0x5c, 0x99, 0x76, 0xb7, 0x6b, 0x73, 0xae, 0x4e, 0x3d, 0xd7, 0x22, 0x9f,
|
||||
0x4f, 0x8c, 0x88, 0x9b, 0xe7, 0x8f, 0x6d, 0x5a, 0xdc, 0xe5, 0x29, 0xa7, 0x5a, 0xd8, 0xd3, 0xb3,
|
||||
0xc3, 0xda, 0xa5, 0x73, 0x27, 0x28, 0x2d, 0x6a, 0xf3, 0xfc, 0x43, 0x2d, 0xe9, 0x41, 0xe9, 0x15,
|
||||
0x3b, 0x2d, 0x56, 0xef, 0x57, 0x5f, 0xa2, 0x86, 0xfd, 0xcb, 0xe2, 0x0d, 0xb9, 0x5e, 0x79, 0xde,
|
||||
0x69, 0x03, 0xbc, 0xea, 0x81, 0xe6, 0xde, 0x83, 0x79, 0x15, 0x8c, 0xd2, 0x0c, 0x5b, 0x8e, 0xc2,
|
||||
0xda, 0x24, 0x59, 0xf1, 0xf9, 0x73, 0xbf, 0xd7, 0x1c, 0xf7, 0x3e, 0xd4, 0xa5, 0xf3, 0xa5, 0xf1,
|
||||
0xb1, 0xe4, 0xf5, 0xea, 0x04, 0xb5, 0xcc, 0xb9, 0x57, 0xdc, 0x20, 0xd3, 0x5c, 0xf6, 0x2a, 0x3d,
|
||||
0x5a, 0x4b, 0x78, 0xf4, 0x1c, 0x96, 0x07, 0x34, 0xb1, 0xc7, 0x28, 0x23, 0x8f, 0x40, 0xf7, 0x88,
|
||||
0x87, 0x19, 0x39, 0x72, 0x7e, 0xda, 0x8a, 0x08, 0x1f, 0x8d, 0xfb, 0xe2, 0x4b, 0xd8, 0xe6, 0x28,
|
||||
0xa6, 0xec, 0xb6, 0xba, 0x0a, 0x99, 0xda, 0x6d, 0xa3, 0x8c, 0x98, 0x3f, 0x75, 0xfa, 0x0d, 0xa9,
|
||||
0xf6, 0xee, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc2, 0xaf, 0xdf, 0x04, 0xee, 0x11, 0x00, 0x00,
|
||||
// 1484 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x5b, 0x73, 0xdb, 0x44,
|
||||
0x14, 0x1e, 0x39, 0x89, 0x2f, 0xc7, 0x89, 0x13, 0xd4, 0x26, 0x11, 0x69, 0x7a, 0x13, 0x97, 0x76,
|
||||
0x42, 0xeb, 0xa4, 0x29, 0x74, 0x80, 0x52, 0x98, 0x36, 0x29, 0x6d, 0xa7, 0x0d, 0x0d, 0x0a, 0xf0,
|
||||
0xc0, 0x8b, 0x59, 0x5b, 0x6b, 0x79, 0xa7, 0x92, 0x56, 0x68, 0xd7, 0xe9, 0x84, 0xe1, 0x17, 0xf0,
|
||||
0xca, 0x5b, 0x5f, 0xf9, 0x8f, 0x3c, 0x33, 0x7b, 0x95, 0x62, 0xd9, 0xa5, 0x9e, 0xe9, 0x93, 0x77,
|
||||
0xcf, 0xf9, 0xf6, 0xdc, 0x75, 0xf6, 0xac, 0x61, 0x3d, 0x41, 0x83, 0x11, 0x49, 0xf1, 0xae, 0xfe,
|
||||
0xed, 0x66, 0x39, 0xe5, 0xd4, 0x6d, 0xe8, 0xed, 0xd6, 0xa5, 0x88, 0xd2, 0x28, 0xc6, 0xbb, 0x92,
|
||||
0xdc, 0x1f, 0x0f, 0x77, 0x71, 0x92, 0xf1, 0x33, 0x85, 0xda, 0xba, 0x3a, 0xc9, 0xe4, 0x24, 0xc1,
|
||||
0x8c, 0xa3, 0x24, 0xd3, 0x80, 0x0b, 0x03, 0x9a, 0x24, 0x34, 0xdd, 0x55, 0x3f, 0x8a, 0xe8, 0xdf,
|
||||
0x83, 0x7a, 0x80, 0xfb, 0x94, 0x72, 0xf7, 0x16, 0x34, 0x13, 0xcc, 0x51, 0x88, 0x38, 0xf2, 0x9c,
|
||||
0x6b, 0xce, 0xcd, 0xf6, 0xfe, 0x5a, 0x57, 0x43, 0x8f, 0x34, 0x3d, 0xb0, 0x08, 0xff, 0x01, 0x74,
|
||||
0xd4, 0xb9, 0x00, 0xb3, 0x8c, 0xa6, 0x0c, 0xbb, 0x9f, 0x89, 0xf3, 0x8c, 0xa1, 0x08, 0x33, 0xcf,
|
||||
0xb9, 0xb6, 0x70, 0xb3, 0xbd, 0xbf, 0xda, 0x35, 0x7e, 0x68, 0xa8, 0x05, 0xf8, 0x8f, 0x60, 0x39,
|
||||
0xc0, 0x0c, 0xf3, 0x00, 0xff, 0x3e, 0xc6, 0x8c, 0xbb, 0x5b, 0xd0, 0x8c, 0x72, 0x34, 0xc0, 0xc3,
|
||||
0x71, 0x2c, 0x95, 0x37, 0x03, 0xbb, 0x77, 0x37, 0xa0, 0x9e, 0xcb, 0xf3, 0x5e, 0x4d, 0x72, 0xf4,
|
||||
0xce, 0xff, 0x02, 0x96, 0xa4, 0x8c, 0x39, 0x2d, 0xbf, 0x0f, 0x2b, 0x5a, 0xb5, 0x36, 0x7c, 0xa7,
|
||||
0x62, 0x78, 0xa7, 0x64, 0xb8, 0x40, 0x16, 0x76, 0x7f, 0x09, 0xcd, 0x93, 0xd1, 0x98, 0x87, 0xf4,
|
||||
0x75, 0x3a, 0xa7, 0xda, 0x87, 0xb0, 0x66, 0x4e, 0x5a, 0xcd, 0xb7, 0x2b, 0x9a, 0x3f, 0xb0, 0x9a,
|
||||
0x2d, 0xb8, 0x1c, 0xb4, 0xce, 0xcf, 0x59, 0x94, 0xa3, 0x10, 0x9b, 0xb0, 0x5d, 0x84, 0x25, 0x92,
|
||||
0xa0, 0x08, 0x4b, 0xfd, 0xad, 0x40, 0x6d, 0x44, 0x30, 0xb3, 0x1c, 0x33, 0x9c, 0x9f, 0x62, 0x1d,
|
||||
0x32, 0xbb, 0xf7, 0x9f, 0x41, 0x43, 0xcb, 0x98, 0xcf, 0x7e, 0x77, 0x0d, 0x16, 0xd0, 0xe0, 0x95,
|
||||
0x94, 0xd7, 0x0a, 0xc4, 0xd2, 0xff, 0x0e, 0x56, 0xad, 0x39, 0xda, 0xa1, 0x5b, 0x15, 0x87, 0xd6,
|
||||
0xac, 0x43, 0x06, 0x5b, 0xf8, 0x93, 0x40, 0xfb, 0x04, 0xe7, 0xa7, 0x64, 0x80, 0x5f, 0x10, 0x36,
|
||||
0x67, 0x1a, 0xdd, 0x3d, 0x68, 0x32, 0x75, 0x98, 0x79, 0x35, 0xa9, 0xea, 0x62, 0x11, 0x3b, 0xc5,
|
||||
0x78, 0x96, 0x0e, 0x69, 0x60, 0x51, 0xfe, 0x13, 0xb8, 0x50, 0x52, 0x67, 0x6d, 0xde, 0xab, 0xd8,
|
||||
0x5c, 0x11, 0x24, 0xf1, 0x85, 0xdd, 0x7f, 0x3b, 0xd6, 0x70, 0xa1, 0xc2, 0xed, 0x40, 0x8d, 0x84,
|
||||
0x3a, 0x05, 0x35, 0x12, 0x8a, 0xac, 0x30, 0x8e, 0x38, 0xd6, 0xc1, 0x52, 0x1b, 0xb7, 0x0b, 0x75,
|
||||
0x7c, 0x8a, 0x53, 0xce, 0xbc, 0x05, 0xe9, 0xdc, 0xc6, 0xa4, 0x96, 0xc7, 0x92, 0x1b, 0x68, 0x94,
|
||||
0xc0, 0x8f, 0x30, 0x8a, 0xf9, 0xc8, 0x5b, 0x9c, 0x8e, 0x7f, 0x2a, 0xb9, 0x81, 0x46, 0xf9, 0xdf,
|
||||
0xc2, 0xca, 0x39, 0x41, 0xee, 0x6d, 0xab, 0x50, 0xb9, 0xb5, 0x3e, 0x55, 0xa1, 0xd1, 0xe7, 0xf7,
|
||||
0x61, 0xb9, 0x4c, 0x17, 0x09, 0x4f, 0x58, 0xa4, 0xdd, 0x12, 0xcb, 0x19, 0x7e, 0xed, 0x40, 0xcd,
|
||||
0xfa, 0xb4, 0xd5, 0x55, 0x4d, 0xa8, 0x6b, 0x9a, 0x50, 0xf7, 0x27, 0xd3, 0x84, 0x82, 0x1a, 0x67,
|
||||
0xfe, 0x3f, 0x8e, 0x35, 0x52, 0x59, 0xef, 0x7a, 0xd0, 0x18, 0xa7, 0xaf, 0x52, 0xfa, 0x3a, 0xd5,
|
||||
0xdf, 0xbd, 0xd9, 0x0a, 0x8e, 0xf2, 0xec, 0x4c, 0x17, 0xb1, 0xd9, 0xba, 0xd7, 0x61, 0x39, 0x46,
|
||||
0x8c, 0xf7, 0x74, 0x42, 0xa4, 0xee, 0x56, 0xd0, 0x16, 0xb4, 0x23, 0x45, 0x72, 0xef, 0x83, 0xdc,
|
||||
0xf6, 0x06, 0x23, 0x94, 0x46, 0x58, 0x47, 0xf0, 0x6d, 0xd6, 0x81, 0x80, 0x1f, 0x48, 0xb4, 0xff,
|
||||
0x89, 0x2d, 0x94, 0x13, 0x8e, 0x72, 0xdb, 0xa3, 0x26, 0xd2, 0xec, 0x1f, 0xdb, 0x80, 0x49, 0xd8,
|
||||
0x9c, 0xf5, 0xeb, 0xc2, 0x62, 0x8e, 0x59, 0xa6, 0x63, 0x29, 0xd7, 0xfe, 0x33, 0xb8, 0x78, 0x5e,
|
||||
0xb1, 0x2e, 0xd1, 0x3b, 0x95, 0x12, 0xad, 0xe4, 0x52, 0x1d, 0x28, 0x6a, 0xf4, 0x63, 0x70, 0x2d,
|
||||
0x87, 0x66, 0xb3, 0x5c, 0x78, 0x69, 0x0b, 0x59, 0xa0, 0xde, 0x83, 0x07, 0x4f, 0x4a, 0xa1, 0x13,
|
||||
0x6a, 0xdf, 0xfd, 0x1b, 0x93, 0xf8, 0xc2, 0xfe, 0x1b, 0xb0, 0xae, 0x19, 0x81, 0xc8, 0xd0, 0xec,
|
||||
0x2c, 0x04, 0xd0, 0x39, 0x0f, 0x7c, 0x0f, 0x5e, 0x1c, 0xc1, 0xc6, 0xa4, 0x72, 0xed, 0xc8, 0xdd,
|
||||
0x8a, 0x23, 0x9b, 0x93, 0x8e, 0x98, 0x23, 0x85, 0x2f, 0x3e, 0x2c, 0xbf, 0xad, 0x90, 0xbe, 0xae,
|
||||
0x79, 0x8e, 0x7f, 0x03, 0x56, 0xce, 0xe7, 0xdc, 0xd8, 0xe5, 0x14, 0x76, 0x49, 0xe0, 0x75, 0x68,
|
||||
0xbf, 0x25, 0xa3, 0x12, 0xf2, 0xa9, 0xd0, 0x57, 0x8a, 0xfe, 0x2c, 0x51, 0x3b, 0xd0, 0x3e, 0xa0,
|
||||
0xd9, 0x99, 0x11, 0x75, 0x09, 0x5a, 0x39, 0xa5, 0xbc, 0x97, 0x21, 0x3e, 0xd2, 0xd8, 0xa6, 0x20,
|
||||
0x1c, 0x23, 0x3e, 0xf2, 0x43, 0x68, 0xab, 0xae, 0xa9, 0xb0, 0x42, 0xa4, 0xb8, 0x91, 0x8d, 0x48,
|
||||
0x31, 0x40, 0x78, 0xd0, 0xc8, 0xf1, 0x60, 0x9c, 0x33, 0x73, 0xeb, 0x98, 0xad, 0x7b, 0x03, 0x56,
|
||||
0xd5, 0x92, 0xd0, 0xb4, 0x17, 0xe2, 0x8c, 0x8f, 0xe4, 0x37, 0xbb, 0x14, 0x74, 0x2c, 0xf9, 0x50,
|
||||
0x50, 0xfd, 0x7f, 0x1d, 0x68, 0x7e, 0x4f, 0x62, 0xd5, 0x56, 0xe7, 0xce, 0x63, 0x8a, 0x12, 0xd3,
|
||||
0x9b, 0xe4, 0x5a, 0xd0, 0x18, 0xf9, 0x43, 0x35, 0x88, 0x85, 0x40, 0xae, 0x05, 0x2d, 0xa1, 0xa1,
|
||||
0x6a, 0x09, 0x2b, 0x81, 0x5c, 0x8b, 0x0b, 0x33, 0xa1, 0x21, 0x19, 0x12, 0x1c, 0x7a, 0x4b, 0x12,
|
||||
0x6b, 0xf7, 0xee, 0x3a, 0xd4, 0x09, 0xeb, 0x85, 0x24, 0xf7, 0xea, 0xd2, 0xa9, 0x25, 0xc2, 0x0e,
|
||||
0x49, 0x2e, 0x7a, 0x21, 0xce, 0x73, 0x9a, 0x7b, 0x0d, 0xd5, 0x0b, 0xe5, 0x46, 0x08, 0x8f, 0x49,
|
||||
0xfa, 0xca, 0x6b, 0x2a, 0x23, 0xc4, 0xda, 0xfd, 0x08, 0x56, 0x72, 0x1c, 0x23, 0x4e, 0x4e, 0x71,
|
||||
0x4f, 0x5a, 0xd8, 0x92, 0xcc, 0x65, 0x43, 0xfc, 0x01, 0x25, 0xd8, 0xff, 0x0d, 0xea, 0x47, 0x74,
|
||||
0x2c, 0xba, 0xf6, 0x7c, 0x5e, 0xdf, 0x54, 0x2d, 0xd9, 0x5c, 0x81, 0xae, 0x2d, 0x46, 0x29, 0xed,
|
||||
0x84, 0x23, 0xae, 0xda, 0x34, 0x13, 0x03, 0x9b, 0xd2, 0xf0, 0x4e, 0x03, 0x9b, 0x86, 0x16, 0x35,
|
||||
0xfc, 0x27, 0xb4, 0xac, 0x48, 0xf7, 0x0a, 0xc0, 0x90, 0xc4, 0x98, 0x9d, 0x31, 0x8e, 0x13, 0x5d,
|
||||
0x03, 0x25, 0x8a, 0x8d, 0xbb, 0xc8, 0xc5, 0xa2, 0x8e, 0xfb, 0x36, 0xb4, 0xd0, 0x29, 0x22, 0x31,
|
||||
0xea, 0xc7, 0x2a, 0x21, 0x8b, 0x41, 0x41, 0x70, 0x2f, 0x03, 0x24, 0x42, 0x3c, 0x0e, 0x7b, 0x34,
|
||||
0x95, 0xb9, 0x69, 0x05, 0x2d, 0x4d, 0x79, 0x99, 0xfa, 0x6f, 0x1c, 0x68, 0xfc, 0x82, 0x65, 0xa1,
|
||||
0xcc, 0x19, 0xa0, 0x2e, 0x34, 0x4e, 0xd5, 0x41, 0x69, 0x4d, 0xb9, 0xf1, 0x68, 0x81, 0x72, 0x4a,
|
||||
0x30, 0x20, 0xd1, 0x6a, 0xb3, 0x18, 0xf1, 0x21, 0xcd, 0x13, 0x7d, 0xa7, 0x15, 0xad, 0xf6, 0x58,
|
||||
0x33, 0xd4, 0x5c, 0x61, 0x60, 0x62, 0x0e, 0xd2, 0xa2, 0xde, 0x69, 0x0e, 0x32, 0xd8, 0x22, 0xb6,
|
||||
0x7f, 0x39, 0xd0, 0x2e, 0x19, 0x23, 0x6e, 0x5e, 0x8e, 0xec, 0xcd, 0xcb, 0x51, 0x24, 0x28, 0x6c,
|
||||
0x84, 0xcc, 0xf0, 0xc5, 0x46, 0x48, 0xd4, 0x5f, 0x7f, 0x4c, 0x62, 0xae, 0x2f, 0x3f, 0xb5, 0x11,
|
||||
0x61, 0x8c, 0x68, 0xcf, 0x38, 0xac, 0xc3, 0x18, 0x51, 0x13, 0xba, 0x0e, 0xd4, 0x28, 0x93, 0x15,
|
||||
0xde, 0x0a, 0x6a, 0x94, 0x89, 0x3c, 0xa1, 0x7c, 0x30, 0x92, 0x95, 0xdd, 0x0a, 0xe4, 0xda, 0xbf,
|
||||
0x07, 0xcb, 0x65, 0x3f, 0xed, 0x77, 0xe5, 0x9c, 0xff, 0xae, 0xe4, 0x37, 0xa4, 0xbf, 0x35, 0xb1,
|
||||
0x16, 0x57, 0x7b, 0xfb, 0x05, 0x8d, 0x98, 0xe9, 0x10, 0xdb, 0xd0, 0x12, 0x58, 0x96, 0xa1, 0x81,
|
||||
0x39, 0x5c, 0x10, 0x74, 0xdb, 0xaa, 0xd9, 0x91, 0x69, 0x17, 0xea, 0x61, 0x4e, 0x4e, 0x71, 0x2e,
|
||||
0xfd, 0xe9, 0xec, 0x6f, 0x9a, 0x94, 0x1e, 0xd0, 0x94, 0x23, 0x92, 0xe2, 0xfc, 0x50, 0xb2, 0x03,
|
||||
0x0d, 0x13, 0x8f, 0x82, 0x21, 0x8d, 0x63, 0xfa, 0x5a, 0x7a, 0xd9, 0x0c, 0xf4, 0x4e, 0x44, 0x80,
|
||||
0x23, 0x12, 0xf7, 0x62, 0x92, 0x62, 0xe5, 0xea, 0x52, 0xd0, 0x12, 0x94, 0x17, 0x82, 0x20, 0xba,
|
||||
0x67, 0x80, 0x51, 0x58, 0x6a, 0x63, 0xa5, 0x6e, 0x27, 0xd7, 0xfb, 0x6f, 0x1a, 0xd0, 0x39, 0x52,
|
||||
0xb9, 0xd2, 0x1d, 0xdd, 0xbd, 0x05, 0x8b, 0xa2, 0x51, 0xba, 0x45, 0xed, 0x94, 0xfa, 0xe6, 0xd6,
|
||||
0xb2, 0xb1, 0xf5, 0x10, 0x71, 0xb4, 0xe7, 0xb8, 0x9f, 0x03, 0x3c, 0x1f, 0xf7, 0xf1, 0x80, 0xa6,
|
||||
0x43, 0x12, 0xb9, 0x1b, 0x95, 0xa1, 0xe3, 0xb1, 0x78, 0xb4, 0x55, 0x4e, 0xdd, 0x81, 0x45, 0x39,
|
||||
0x05, 0x17, 0x3a, 0x4a, 0xfd, 0x76, 0xab, 0x78, 0x17, 0x98, 0xf6, 0xb8, 0xe7, 0x08, 0xb3, 0x44,
|
||||
0xc4, 0xcb, 0x47, 0x8a, 0x04, 0x54, 0x14, 0x7c, 0x65, 0x5b, 0xcc, 0x2c, 0x93, 0x36, 0x27, 0x3f,
|
||||
0xff, 0xa2, 0x9c, 0x17, 0x45, 0xd4, 0x4a, 0x8a, 0x4a, 0x41, 0x9c, 0xa6, 0x48, 0x3f, 0x29, 0xff,
|
||||
0x5f, 0xd1, 0xc4, 0x1b, 0xf2, 0x9e, 0x79, 0xd2, 0xad, 0x4f, 0xbc, 0xc0, 0xb4, 0xaa, 0x8d, 0x49,
|
||||
0xb2, 0x3e, 0x77, 0x70, 0xfe, 0x25, 0x31, 0x4b, 0xef, 0xf6, 0xd4, 0xc1, 0xde, 0x08, 0xf9, 0xb1,
|
||||
0x32, 0x49, 0x5c, 0x99, 0x75, 0xb7, 0x6b, 0x73, 0xae, 0xce, 0xe4, 0x6b, 0x91, 0xcf, 0x27, 0x46,
|
||||
0xc4, 0xed, 0xe9, 0x63, 0x9b, 0x16, 0x77, 0x79, 0x06, 0x57, 0x0b, 0x7b, 0x7a, 0x7e, 0x58, 0xbb,
|
||||
0x34, 0x75, 0x82, 0xd2, 0xa2, 0xb6, 0xa7, 0x33, 0xb5, 0xa4, 0x07, 0xa5, 0x57, 0xec, 0xac, 0x58,
|
||||
0x7d, 0x58, 0x7d, 0x89, 0x9a, 0xe3, 0xdf, 0x14, 0x6f, 0xc8, 0xcd, 0xca, 0xf3, 0x4e, 0x1b, 0xe0,
|
||||
0x55, 0x19, 0xfa, 0xf4, 0xfd, 0xa2, 0x95, 0xcf, 0xd2, 0xed, 0x55, 0x9a, 0xa5, 0x3e, 0xfc, 0xe8,
|
||||
0x39, 0xac, 0x0e, 0x68, 0x62, 0xd9, 0x28, 0x23, 0x8f, 0x40, 0x7f, 0xac, 0x0f, 0x33, 0x72, 0xec,
|
||||
0xfc, 0xba, 0x13, 0x11, 0x3e, 0x1a, 0xf7, 0x45, 0x49, 0xee, 0x72, 0x14, 0x53, 0x76, 0x5b, 0xdd,
|
||||
0x49, 0x4c, 0xed, 0x76, 0x51, 0x46, 0xcc, 0xbf, 0x2b, 0xfd, 0xba, 0x54, 0x7b, 0xf7, 0xbf, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xe9, 0x7e, 0xca, 0xfb, 0x77, 0x11, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@ -2331,8 +2329,6 @@ type MachineServiceClient interface {
|
||||
ServiceStop(ctx context.Context, in *ServiceStopRequest, opts ...grpc.CallOption) (*ServiceStopResponse, error)
|
||||
Shutdown(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ShutdownResponse, error)
|
||||
Upgrade(ctx context.Context, in *UpgradeRequest, opts ...grpc.CallOption) (*UpgradeResponse, error)
|
||||
Start(ctx context.Context, in *StartRequest, opts ...grpc.CallOption) (*StartResponse, error)
|
||||
Stop(ctx context.Context, in *StopRequest, opts ...grpc.CallOption) (*StopResponse, error)
|
||||
Version(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*VersionResponse, error)
|
||||
}
|
||||
|
||||
@ -2585,26 +2581,6 @@ func (c *machineServiceClient) Upgrade(ctx context.Context, in *UpgradeRequest,
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func (c *machineServiceClient) Start(ctx context.Context, in *StartRequest, opts ...grpc.CallOption) (*StartResponse, error) {
|
||||
out := new(StartResponse)
|
||||
err := c.cc.Invoke(ctx, "/machine.MachineService/Start", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func (c *machineServiceClient) Stop(ctx context.Context, in *StopRequest, opts ...grpc.CallOption) (*StopResponse, error) {
|
||||
out := new(StopResponse)
|
||||
err := c.cc.Invoke(ctx, "/machine.MachineService/Stop", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *machineServiceClient) Version(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*VersionResponse, error) {
|
||||
out := new(VersionResponse)
|
||||
err := c.cc.Invoke(ctx, "/machine.MachineService/Version", in, out, opts...)
|
||||
@ -2630,8 +2606,6 @@ type MachineServiceServer interface {
|
||||
ServiceStop(context.Context, *ServiceStopRequest) (*ServiceStopResponse, error)
|
||||
Shutdown(context.Context, *empty.Empty) (*ShutdownResponse, error)
|
||||
Upgrade(context.Context, *UpgradeRequest) (*UpgradeResponse, error)
|
||||
Start(context.Context, *StartRequest) (*StartResponse, error)
|
||||
Stop(context.Context, *StopRequest) (*StopResponse, error)
|
||||
Version(context.Context, *empty.Empty) (*VersionResponse, error)
|
||||
}
|
||||
|
||||
@ -2906,42 +2880,6 @@ func _MachineService_Upgrade_Handler(srv interface{}, ctx context.Context, dec f
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MachineService_Start_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(StartRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MachineServiceServer).Start(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/machine.MachineService/Start",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MachineServiceServer).Start(ctx, req.(*StartRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MachineService_Stop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(StopRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MachineServiceServer).Stop(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/machine.MachineService/Stop",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MachineServiceServer).Stop(ctx, req.(*StopRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MachineService_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(empty.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
@ -3000,14 +2938,6 @@ var _MachineService_serviceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Upgrade",
|
||||
Handler: _MachineService_Upgrade_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Start",
|
||||
Handler: _MachineService_Start_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Stop",
|
||||
Handler: _MachineService_Stop_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Version",
|
||||
Handler: _MachineService_Version_Handler,
|
||||
|
@ -27,14 +27,6 @@ service MachineService {
|
||||
rpc ServiceStop(ServiceStopRequest) returns (ServiceStopResponse);
|
||||
rpc Shutdown(google.protobuf.Empty) returns (ShutdownResponse);
|
||||
rpc Upgrade(UpgradeRequest) returns (UpgradeResponse);
|
||||
|
||||
rpc Start(StartRequest) returns (StartResponse) {
|
||||
option deprecated = true;
|
||||
};
|
||||
rpc Stop(StopRequest) returns (StopResponse) {
|
||||
option deprecated = true;
|
||||
};
|
||||
|
||||
rpc Version(google.protobuf.Empty) returns (VersionResponse);
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,12 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg"
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/install"
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/ova"
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/qemuimg"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime/platform"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform"
|
||||
"github.com/talos-systems/talos/pkg/cmd"
|
||||
"github.com/talos-systems/talos/pkg/config/types/v1alpha1"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
@ -71,20 +71,6 @@ func runImageCmd() (err error) {
|
||||
}
|
||||
}()
|
||||
|
||||
config := &v1alpha1.Config{
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{},
|
||||
},
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineInstall: &v1alpha1.InstallConfig{
|
||||
InstallForce: true,
|
||||
InstallBootloader: options.Bootloader,
|
||||
InstallDisk: options.Disk,
|
||||
InstallExtraKernelArgs: options.ExtraKernelArgs,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if options.ConfigSource == "" {
|
||||
switch p.Name() {
|
||||
case "aws", "azure", "digital-ocean", "gcp":
|
||||
@ -95,7 +81,7 @@ func runImageCmd() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = pkg.Install(p, config, runtime.None, options); err != nil {
|
||||
if err = install.Install(p, runtime.SequenceNoop, options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -5,17 +5,11 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime/platform"
|
||||
machineconfig "github.com/talos-systems/talos/pkg/config"
|
||||
"github.com/talos-systems/talos/pkg/config/types/v1alpha1"
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/install"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform"
|
||||
)
|
||||
|
||||
// installCmd represents the install command
|
||||
@ -39,51 +33,18 @@ func init() {
|
||||
}
|
||||
|
||||
func runInstallCmd() (err error) {
|
||||
var config runtime.Configurator
|
||||
seq := runtime.SequenceInstall
|
||||
|
||||
p, err := platform.CurrentPlatform()
|
||||
if err == nil {
|
||||
if !strings.EqualFold(p.Name(), options.Platform) {
|
||||
return fmt.Errorf("platform mismatch (%s != %s)", p.Name(), options.Platform)
|
||||
}
|
||||
|
||||
var b []byte
|
||||
|
||||
b, err = p.Configuration()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config, err = machineconfig.NewFromBytes(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
log.Printf("failed to source config from platform; falling back to defaults")
|
||||
|
||||
config = &v1alpha1.Config{
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{},
|
||||
},
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineInstall: &v1alpha1.InstallConfig{
|
||||
InstallForce: options.Force,
|
||||
InstallBootloader: options.Bootloader,
|
||||
InstallDisk: options.Disk,
|
||||
InstallExtraKernelArgs: options.ExtraKernelArgs,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
sequence := runtime.None
|
||||
if options.Upgrade {
|
||||
sequence = runtime.Upgrade
|
||||
seq = runtime.SequenceUpgrade
|
||||
}
|
||||
|
||||
if err = pkg.Install(p, config, sequence, options); err != nil {
|
||||
p, err := platform.NewPlatform(options.Platform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = install.Install(p, seq, options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg"
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/install"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
@ -30,15 +30,15 @@ func Execute() {
|
||||
}
|
||||
}
|
||||
|
||||
var options = &pkg.InstallOptions{}
|
||||
var options = &install.Options{}
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().StringVar(&options.ConfigSource, "config", "", "The value of "+constants.KernelParamConfig)
|
||||
rootCmd.PersistentFlags().MarkHidden("config") //nolint: errcheck
|
||||
rootCmd.PersistentFlags().StringVar(&options.Disk, "disk", "", "The path to the disk to install to")
|
||||
rootCmd.PersistentFlags().StringVar(&options.Platform, "platform", "", "The value of "+constants.KernelParamPlatform)
|
||||
rootCmd.PersistentFlags().StringArrayVar(&options.ExtraKernelArgs, "extra-kernel-arg", []string{}, "Extra argument to pass to the kernel")
|
||||
rootCmd.PersistentFlags().BoolVar(&options.Bootloader, "bootloader", true, "Install a booloader to the specified disk")
|
||||
rootCmd.PersistentFlags().BoolVar(&options.Upgrade, "upgrade", false, "Indicates that the install is being performed by an upgrade")
|
||||
rootCmd.PersistentFlags().BoolVar(&options.Force, "force", false, "Indicates that the install should forcefully format the partition")
|
||||
rootCmd.PersistentFlags().BoolVar(&options.Zero, "zero", false, "Indicates that the install should write zeros to the disk before installing")
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/version"
|
||||
)
|
||||
|
||||
// InstallOptions represents the set of options available for an install.
|
||||
type InstallOptions struct {
|
||||
ConfigSource string
|
||||
Disk string
|
||||
Platform string
|
||||
ExtraKernelArgs []string
|
||||
Bootloader bool
|
||||
Upgrade bool
|
||||
Force bool
|
||||
}
|
||||
|
||||
// Install installs Talos.
|
||||
func Install(p runtime.Platform, config runtime.Configurator, sequence runtime.Sequence, opts *InstallOptions) (err error) {
|
||||
cmdline := procfs.NewCmdline("")
|
||||
cmdline.Append(constants.KernelParamPlatform, p.Name())
|
||||
cmdline.Append(constants.KernelParamConfig, opts.ConfigSource)
|
||||
|
||||
if err = cmdline.AppendAll(p.KernelArgs().Strings()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = cmdline.AppendAll(config.Machine().Install().ExtraKernelArgs()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmdline.AppendDefaults()
|
||||
|
||||
i, err := NewInstaller(cmdline, sequence, config.Machine().Install())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = i.Install(sequence); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("installation of %s complete", version.Tag)
|
||||
|
||||
return nil
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package pkg
|
||||
package install
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -12,30 +12,68 @@ import (
|
||||
"path/filepath"
|
||||
"unsafe"
|
||||
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/bootloader/syslinux"
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/manifest"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/syslinux"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/owned"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/probe"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/table"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/util"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/version"
|
||||
)
|
||||
|
||||
// Options represents the set of options available for an install.
|
||||
type Options struct {
|
||||
ConfigSource string
|
||||
Disk string
|
||||
Platform string
|
||||
ExtraKernelArgs []string
|
||||
Bootloader bool
|
||||
Upgrade bool
|
||||
Force bool
|
||||
Zero bool
|
||||
}
|
||||
|
||||
// Install installs Talos.
|
||||
func Install(p runtime.Platform, seq runtime.Sequence, opts *Options) (err error) {
|
||||
cmdline := procfs.NewCmdline("")
|
||||
cmdline.Append(constants.KernelParamPlatform, p.Name())
|
||||
cmdline.Append(constants.KernelParamConfig, opts.ConfigSource)
|
||||
|
||||
if err = cmdline.AppendAll(p.KernelArgs().Strings()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = cmdline.AppendAll(opts.ExtraKernelArgs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmdline.AppendDefaults()
|
||||
|
||||
i, err := NewInstaller(cmdline, seq, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = i.Install(seq); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("installation of %s complete", version.Tag)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Installer represents the installer logic. It serves as the entrypoint to all
|
||||
// installation methods.
|
||||
type Installer struct {
|
||||
cmdline *procfs.Cmdline
|
||||
install machine.Install
|
||||
manifest *manifest.Manifest
|
||||
options *Options
|
||||
manifest *Manifest
|
||||
Current string
|
||||
Next string
|
||||
|
||||
@ -45,10 +83,10 @@ type Installer struct {
|
||||
// NewInstaller initializes and returns an Installer.
|
||||
//
|
||||
// nolint: gocyclo
|
||||
func NewInstaller(cmdline *procfs.Cmdline, sequence runtime.Sequence, install machine.Install) (i *Installer, err error) {
|
||||
func NewInstaller(cmdline *procfs.Cmdline, seq runtime.Sequence, opts *Options) (i *Installer, err error) {
|
||||
i = &Installer{
|
||||
cmdline: cmdline,
|
||||
install: install,
|
||||
options: opts,
|
||||
}
|
||||
|
||||
var dev *probe.ProbedBlockDevice
|
||||
@ -61,7 +99,7 @@ func NewInstaller(cmdline *procfs.Cmdline, sequence runtime.Sequence, install ma
|
||||
i.bootPartitionFound = true
|
||||
}
|
||||
|
||||
if sequence == runtime.Upgrade && i.bootPartitionFound {
|
||||
if seq == runtime.SequenceUpgrade && i.bootPartitionFound {
|
||||
if err = os.MkdirAll("/boot", 0777); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -78,11 +116,11 @@ func NewInstaller(cmdline *procfs.Cmdline, sequence runtime.Sequence, install ma
|
||||
|
||||
label := i.Current
|
||||
|
||||
if sequence == runtime.Upgrade && i.bootPartitionFound {
|
||||
if seq == runtime.SequenceUpgrade && i.bootPartitionFound {
|
||||
label = i.Next
|
||||
}
|
||||
|
||||
i.manifest, err = manifest.NewManifest(label, sequence, install)
|
||||
i.manifest, err = NewManifest(label, seq, i.options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create installation manifest: %w", err)
|
||||
}
|
||||
@ -94,9 +132,9 @@ func NewInstaller(cmdline *procfs.Cmdline, sequence runtime.Sequence, install ma
|
||||
// to the target locations.
|
||||
//
|
||||
// nolint: gocyclo
|
||||
func (i *Installer) Install(sequence runtime.Sequence) (err error) {
|
||||
if sequence != runtime.Upgrade || !i.bootPartitionFound {
|
||||
if i.install.Zero() {
|
||||
func (i *Installer) Install(seq runtime.Sequence) (err error) {
|
||||
if seq != runtime.SequenceUpgrade || !i.bootPartitionFound {
|
||||
if i.options.Zero {
|
||||
if err = zero(i.manifest); err != nil {
|
||||
return fmt.Errorf("failed to wipe device(s): %w", err)
|
||||
}
|
||||
@ -114,7 +152,7 @@ func (i *Installer) Install(sequence runtime.Sequence) (err error) {
|
||||
for dev := range i.manifest.Targets {
|
||||
var mp *mount.Points
|
||||
|
||||
mp, err = owned.MountPointsForDevice(dev)
|
||||
mp, err = mount.SystemMountPointsForDevice(dev)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -125,16 +163,15 @@ func (i *Installer) Install(sequence runtime.Sequence) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
m := manager.NewManager(mountpoints)
|
||||
if err = m.MountAll(); err != nil {
|
||||
if err = mount.Mount(mountpoints); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
defer m.UnmountAll()
|
||||
defer mount.Unmount(mountpoints)
|
||||
}
|
||||
|
||||
if sequence == runtime.Upgrade && i.bootPartitionFound && i.install.Force() {
|
||||
if seq == runtime.SequenceUpgrade && i.bootPartitionFound && i.options.Force {
|
||||
for dev, targets := range i.manifest.Targets {
|
||||
var bd *blockdevice.BlockDevice
|
||||
|
||||
@ -193,11 +230,11 @@ func (i *Installer) Install(sequence runtime.Sequence) (err error) {
|
||||
|
||||
// Install the bootloader.
|
||||
|
||||
if !i.install.WithBootloader() {
|
||||
if !i.options.Bootloader {
|
||||
return nil
|
||||
}
|
||||
|
||||
if sequence != runtime.Upgrade || !i.bootPartitionFound {
|
||||
if seq != runtime.SequenceUpgrade || !i.bootPartitionFound {
|
||||
i.cmdline.Append("initrd", filepath.Join("/", i.Current, constants.InitramfsAsset))
|
||||
|
||||
syslinuxcfg := &syslinux.Cfg{
|
||||
@ -212,7 +249,7 @@ func (i *Installer) Install(sequence runtime.Sequence) (err error) {
|
||||
},
|
||||
}
|
||||
|
||||
if err = syslinux.Install("", syslinuxcfg, sequence, i.bootPartitionFound); err != nil {
|
||||
if err = syslinux.Install("", syslinuxcfg, seq, i.bootPartitionFound); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@ -236,7 +273,7 @@ func (i *Installer) Install(sequence runtime.Sequence) (err error) {
|
||||
},
|
||||
}
|
||||
|
||||
if err = syslinux.Install(i.Current, syslinuxcfg, sequence, i.bootPartitionFound); err != nil {
|
||||
if err = syslinux.Install(i.Current, syslinuxcfg, seq, i.bootPartitionFound); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -244,7 +281,7 @@ func (i *Installer) Install(sequence runtime.Sequence) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func zero(manifest *manifest.Manifest) (err error) {
|
||||
func zero(manifest *Manifest) (err error) {
|
||||
var zero *os.File
|
||||
|
||||
if zero, err = os.Open("/dev/zero"); err != nil {
|
@ -2,7 +2,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package manifest
|
||||
package install
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -11,14 +11,13 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/filesystem/vfat"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/filesystem/xfs"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/table"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/table/gpt/partition"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/util"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
@ -48,19 +47,19 @@ type Asset struct {
|
||||
}
|
||||
|
||||
// NewManifest initializes and returns a Manifest.
|
||||
func NewManifest(label string, sequence runtime.Sequence, install machine.Install) (manifest *Manifest, err error) {
|
||||
func NewManifest(label string, sequence runtime.Sequence, opts *Options) (manifest *Manifest, err error) {
|
||||
manifest = &Manifest{
|
||||
Targets: map[string][]*Target{},
|
||||
}
|
||||
|
||||
// Verify that the target device(s) can satisify the requested options.
|
||||
|
||||
if sequence != runtime.Upgrade {
|
||||
if err = VerifyDataDevice(install); err != nil {
|
||||
if sequence != runtime.SequenceUpgrade {
|
||||
if err = VerifyEphemeralPartition(opts); err != nil {
|
||||
return nil, fmt.Errorf("failed to prepare ephemeral partition: %w", err)
|
||||
}
|
||||
|
||||
if err = VerifyBootDevice(install); err != nil {
|
||||
if err = VerifyBootPartition(opts); err != nil {
|
||||
return nil, fmt.Errorf("failed to prepare boot partition: %w", err)
|
||||
}
|
||||
}
|
||||
@ -68,14 +67,15 @@ func NewManifest(label string, sequence runtime.Sequence, install machine.Instal
|
||||
// Initialize any slices we need. Note that a boot paritition is not
|
||||
// required.
|
||||
|
||||
if manifest.Targets[install.Disk()] == nil {
|
||||
manifest.Targets[install.Disk()] = []*Target{}
|
||||
if manifest.Targets[opts.Disk] == nil {
|
||||
manifest.Targets[opts.Disk] = []*Target{}
|
||||
}
|
||||
|
||||
var bootTarget *Target
|
||||
if install.WithBootloader() {
|
||||
|
||||
if opts.Bootloader {
|
||||
bootTarget = &Target{
|
||||
Device: install.Disk(),
|
||||
Device: opts.Disk,
|
||||
Label: constants.BootPartitionLabel,
|
||||
Size: 512 * 1024 * 1024,
|
||||
Force: true,
|
||||
@ -94,7 +94,7 @@ func NewManifest(label string, sequence runtime.Sequence, install machine.Instal
|
||||
}
|
||||
|
||||
ephemeralTarget := &Target{
|
||||
Device: install.Disk(),
|
||||
Device: opts.Disk,
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
Size: 0,
|
||||
Force: true,
|
@ -2,7 +2,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package manifest
|
||||
package install
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
@ -2,45 +2,44 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package manifest
|
||||
package install
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/probe"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// VerifyDataDevice verifies the supplied data device options.
|
||||
func VerifyDataDevice(install machine.Install) (err error) {
|
||||
if install.Disk() == "" {
|
||||
// VerifyEphemeralPartition verifies the supplied data device options.
|
||||
func VerifyEphemeralPartition(opts *Options) (err error) {
|
||||
if opts.Disk == "" {
|
||||
return errors.New("missing disk")
|
||||
}
|
||||
|
||||
if install.Force() {
|
||||
if opts.Force {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = VerifyDiskAvailability(install.Disk(), constants.EphemeralPartitionLabel); err != nil {
|
||||
if err = VerifyDiskAvailability(opts.Disk, constants.EphemeralPartitionLabel); err != nil {
|
||||
return fmt.Errorf("failed to verify disk availability: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyBootDevice verifies the supplied boot device options.
|
||||
func VerifyBootDevice(install machine.Install) (err error) {
|
||||
if !install.WithBootloader() {
|
||||
// VerifyBootPartition verifies the supplied boot device options.
|
||||
func VerifyBootPartition(opts *Options) (err error) {
|
||||
if opts.Bootloader {
|
||||
return nil
|
||||
}
|
||||
|
||||
if install.Force() {
|
||||
if opts.Force {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = VerifyDiskAvailability(install.Disk(), constants.BootPartitionLabel); err != nil {
|
||||
if err = VerifyDiskAvailability(opts.Disk, constants.BootPartitionLabel); err != nil {
|
||||
return fmt.Errorf("failed to verify disk availability: %w", err)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package manifest
|
||||
package install
|
||||
|
||||
import (
|
||||
"testing"
|
@ -17,11 +17,11 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/talosctl/pkg/mgmt/helpers"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/cluster/check"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision/access"
|
||||
"github.com/talos-systems/talos/internal/pkg/provision/providers"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
clientconfig "github.com/talos-systems/talos/pkg/client/config"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
|
@ -16,8 +16,8 @@ import (
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/talosctl/pkg/mgmt/helpers"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/config/types/v1alpha1/generate"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
@ -107,24 +107,24 @@ func genV1Alpha1Config(args []string) error {
|
||||
return fmt.Errorf("failed to generate config bundle: %w", err)
|
||||
}
|
||||
|
||||
for _, t := range []machine.Type{machine.TypeInit, machine.TypeControlPlane, machine.TypeWorker} {
|
||||
for _, t := range []runtime.MachineType{runtime.MachineTypeInit, runtime.MachineTypeControlPlane, runtime.MachineTypeJoin} {
|
||||
name := strings.ToLower(t.String()) + ".yaml"
|
||||
fullFilePath := filepath.Join(outputDir, name)
|
||||
|
||||
var configString string
|
||||
|
||||
switch t {
|
||||
case machine.TypeInit:
|
||||
case runtime.MachineTypeInit:
|
||||
configString, err = configBundle.Init().String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case machine.TypeControlPlane:
|
||||
case runtime.MachineTypeControlPlane:
|
||||
configString, err = configBundle.ControlPlane().String()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case machine.TypeWorker:
|
||||
case runtime.MachineTypeJoin:
|
||||
configString, err = configBundle.Join().String()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
)
|
||||
@ -31,7 +31,7 @@ var validateCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
mode, err := runtime.ModeFromString(validateModeArg)
|
||||
mode, err := runtime.ParseMode(validateModeArg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -10,10 +10,10 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/cluster"
|
||||
"github.com/talos-systems/talos/internal/pkg/cluster/check"
|
||||
"github.com/talos-systems/talos/pkg/client"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
)
|
||||
|
||||
type clusterNodes struct {
|
||||
@ -26,13 +26,13 @@ func (cluster *clusterNodes) Nodes() []string {
|
||||
return append([]string{cluster.InitNode}, append(cluster.ControlPlaneNodes, cluster.WorkerNodes...)...)
|
||||
}
|
||||
|
||||
func (cluster *clusterNodes) NodesByType(t machine.Type) []string {
|
||||
func (cluster *clusterNodes) NodesByType(t runtime.MachineType) []string {
|
||||
switch t {
|
||||
case machine.TypeInit:
|
||||
case runtime.MachineTypeInit:
|
||||
return []string{cluster.InitNode}
|
||||
case machine.TypeControlPlane:
|
||||
case runtime.MachineTypeControlPlane:
|
||||
return cluster.ControlPlaneNodes
|
||||
case machine.TypeWorker:
|
||||
case runtime.MachineTypeJoin:
|
||||
return cluster.WorkerNodes
|
||||
default:
|
||||
panic("unsupported machine type")
|
||||
|
4
go.mod
4
go.mod
@ -45,8 +45,8 @@ require (
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/kubernetes-sigs/bootkube v0.14.1-0.20200421144856-831deff0541a
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 // indirect
|
||||
github.com/mdlayher/genetlink v0.0.0-20190313224034-60417448a851
|
||||
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b
|
||||
github.com/mdlayher/genetlink v1.0.0
|
||||
github.com/mdlayher/netlink v1.0.0
|
||||
github.com/mdlayher/raw v0.0.0-20190606144222-a54781e5f38f // indirect
|
||||
github.com/onsi/gomega v1.8.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
|
||||
|
10
go.sum
10
go.sum
@ -434,13 +434,12 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
||||
github.com/mdlayher/genetlink v0.0.0-20190313224034-60417448a851 h1:QYJTEbSDJvDBQenHYMxoiBQPgZ4QUcm75vACe3dkW7o=
|
||||
github.com/mdlayher/genetlink v0.0.0-20190313224034-60417448a851/go.mod h1:EsbsAEUEs15qC1cosAwxgCWV0Qhd8TmkxnA9Kw1Vhl4=
|
||||
github.com/mdlayher/netlink v0.0.0-20190313131330-258ea9dff42c/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
|
||||
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
|
||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
github.com/mdlayher/netlink v0.0.0-20191008140946-2a17fd90af51/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b h1:W3er9pI7mt2gOqOWzwvx20iJ8Akiqz1mUMTxU6wdvl8=
|
||||
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mdlayher/netlink v1.0.0 h1:vySPY5Oxnn/8lxAPn2cK6kAzcZzYJl3KriSLO46OT18=
|
||||
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.0.0-20190606144222-a54781e5f38f h1:Xjvm7UTnKTwrlhbs+8qA6I0v1iX77rY3QxftSgvOVRk=
|
||||
github.com/mdlayher/raw v0.0.0-20190606144222-a54781e5f38f/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
@ -701,7 +700,6 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
apidbackend "github.com/talos-systems/talos/internal/app/apid/pkg/backend"
|
||||
"github.com/talos-systems/talos/internal/app/apid/pkg/director"
|
||||
"github.com/talos-systems/talos/internal/app/apid/pkg/provider"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/grpc/factory"
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
stdlibtls "crypto/tls"
|
||||
stdlibnet "net"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/grpc/tls"
|
||||
"github.com/talos-systems/talos/pkg/net"
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"github.com/kubernetes-sigs/bootkube/pkg/tlsutil"
|
||||
"github.com/talos-systems/bootkube-plugin/pkg/asset"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
tnet "github.com/talos-systems/talos/pkg/net"
|
||||
)
|
||||
|
@ -18,9 +18,7 @@ import (
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/kmsg"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/pseudo"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/squashfs"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/switchroot"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/version"
|
||||
@ -29,13 +27,12 @@ import (
|
||||
// nolint: gocyclo
|
||||
func run() (err error) {
|
||||
// Mount the pseudo devices.
|
||||
mountpoints, err := pseudo.MountPoints()
|
||||
pseudo, err := mount.PseudoMountPoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pseudo := manager.NewManager(mountpoints)
|
||||
if err = pseudo.MountAll(); err != nil {
|
||||
if err = mount.Mount(pseudo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -50,13 +47,12 @@ func run() (err error) {
|
||||
// Mount the rootfs.
|
||||
log.Println("mounting the rootfs")
|
||||
|
||||
mountpoints, err = squashfs.MountPoints(constants.NewRoot)
|
||||
squashfs, err := mount.SquashfsMountPoints(constants.NewRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
squashfs := manager.NewManager(mountpoints)
|
||||
if err = squashfs.MountAll(); err != nil {
|
||||
if err = mount.Mount(squashfs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/api/reg"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/grpc/factory"
|
||||
)
|
||||
|
||||
// Service wraps machined API server
|
||||
type Service struct{}
|
||||
|
||||
// NewService creates new Service
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
}
|
||||
|
||||
// Main is an entrypoint the the API service
|
||||
func (s *Service) Main(ctx context.Context, config runtime.Configurator, logWriter io.Writer) error {
|
||||
api := reg.NewRegistrator(config)
|
||||
server := factory.NewServer(api, factory.WithLog("machined ", logWriter))
|
||||
|
||||
listener, err := factory.NewListener(factory.Network("unix"), factory.SocketPath(constants.MachineSocketPath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer server.Stop()
|
||||
|
||||
go func() {
|
||||
// nolint: errcheck
|
||||
server.Serve(listener)
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
|
||||
return nil
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package cni
|
||||
|
||||
import (
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// Mounts returns the set of mounts required by the requested CNI plugin. All
|
||||
// paths are relative to the root file system after switching the root.
|
||||
func Mounts(config runtime.Configurator) ([]specs.Mount, error) {
|
||||
mounts := []specs.Mount{
|
||||
{Type: "bind", Destination: "/etc/cni", Source: "/etc/cni", Options: []string{"rbind", "rshared", "rw"}},
|
||||
}
|
||||
|
||||
return mounts, nil
|
||||
}
|
@ -20,15 +20,16 @@ import (
|
||||
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/containers/image"
|
||||
"github.com/talos-systems/talos/internal/pkg/kmsg"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// RunInstallerContainer performs an installation via the installer container.
|
||||
//
|
||||
//nolint: gocyclo
|
||||
func RunInstallerContainer(r runtime.Runtime, opts ...Option) error {
|
||||
func RunInstallerContainer(disk, platform, ref string, reg runtime.Registries, opts ...Option) error {
|
||||
options := DefaultInstallOptions()
|
||||
|
||||
for _, opt := range opts {
|
||||
@ -44,17 +45,17 @@ func RunInstallerContainer(r runtime.Runtime, opts ...Option) error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("pulling installer container image: %q", r.Config().Machine().Install().Image())
|
||||
|
||||
var img containerd.Image
|
||||
|
||||
if options.ImagePull {
|
||||
img, err = image.Pull(ctx, r.Config().Machine().Registries(), client, r.Config().Machine().Install().Image())
|
||||
if options.Pull {
|
||||
log.Printf("pulling %q", ref)
|
||||
|
||||
img, err = image.Pull(ctx, reg, client, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
img, err = client.GetImage(ctx, r.Config().Machine().Install().Image())
|
||||
img, err = client.GetImage(ctx, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -71,22 +72,22 @@ func RunInstallerContainer(r runtime.Runtime, opts ...Option) error {
|
||||
return fmt.Errorf("no config option was found")
|
||||
}
|
||||
|
||||
upgrade := "false"
|
||||
if r.Sequence() == runtime.Upgrade {
|
||||
upgrade = "true"
|
||||
}
|
||||
upgrade := strconv.FormatBool(options.Upgrade)
|
||||
force := strconv.FormatBool(options.Force)
|
||||
zero := strconv.FormatBool(options.Zero)
|
||||
|
||||
args := []string{
|
||||
"/bin/installer",
|
||||
"install",
|
||||
"--disk=" + r.Config().Machine().Install().Disk(),
|
||||
"--platform=" + r.Platform().Name(),
|
||||
"--disk=" + disk,
|
||||
"--platform=" + platform,
|
||||
"--config=" + *config,
|
||||
"--upgrade=" + upgrade,
|
||||
"--force=" + strconv.FormatBool(!options.Preserve),
|
||||
"--force=" + force,
|
||||
"--zero=" + zero,
|
||||
}
|
||||
|
||||
for _, arg := range r.Config().Machine().Install().ExtraKernelArgs() {
|
||||
for _, arg := range options.ExtraKernelArgs {
|
||||
args = append(args, []string{"--extra-kernel-arg", arg}...)
|
||||
}
|
||||
|
||||
@ -101,6 +102,7 @@ func RunInstallerContainer(r runtime.Runtime, opts ...Option) error {
|
||||
oci.WithParentCgroupDevices,
|
||||
oci.WithPrivileged,
|
||||
}
|
||||
|
||||
containerOpts := []containerd.NewContainerOpts{
|
||||
containerd.WithImage(img),
|
||||
containerd.WithNewSnapshot("upgrade", img),
|
69
internal/app/machined/internal/install/options.go
Normal file
69
internal/app/machined/internal/install/options.go
Normal file
@ -0,0 +1,69 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package install
|
||||
|
||||
// Option is a functional option.
|
||||
type Option func(o *Options) error
|
||||
|
||||
// Options describes the install options.
|
||||
type Options struct {
|
||||
Pull bool
|
||||
Force bool
|
||||
Upgrade bool
|
||||
Zero bool
|
||||
ExtraKernelArgs []string
|
||||
}
|
||||
|
||||
// DefaultInstallOptions returns default options.
|
||||
func DefaultInstallOptions() Options {
|
||||
return Options{
|
||||
Pull: true,
|
||||
}
|
||||
}
|
||||
|
||||
// WithPull sets the pull option.
|
||||
func WithPull(b bool) Option {
|
||||
return func(o *Options) error {
|
||||
o.Pull = b
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithForce sets the force option.
|
||||
func WithForce(b bool) Option {
|
||||
return func(o *Options) error {
|
||||
o.Force = b
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithUpgrade sets the upgrade option.
|
||||
func WithUpgrade(b bool) Option {
|
||||
return func(o *Options) error {
|
||||
o.Upgrade = b
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithZero sets the zero option.
|
||||
func WithZero(b bool) Option {
|
||||
return func(o *Options) error {
|
||||
o.Zero = b
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithExtraKernelArgs sets the extra args.
|
||||
func WithExtraKernelArgs(s []string) Option {
|
||||
return func(o *Options) error {
|
||||
o.ExtraKernelArgs = s
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// Task represents the Task task.
|
||||
type Task struct {
|
||||
cfgBytes *[]byte
|
||||
}
|
||||
|
||||
// NewConfigTask initializes and returns a Task task.
|
||||
func NewConfigTask(cfgBytes *[]byte) phase.Task {
|
||||
return &Task{
|
||||
cfgBytes: cfgBytes,
|
||||
}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Task) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.standard
|
||||
}
|
||||
|
||||
func (task *Task) standard(r runtime.Runtime) (err error) {
|
||||
cfg, err := config.NewFromFile(constants.ConfigPath)
|
||||
if err != nil || !cfg.Persist() {
|
||||
log.Printf("failed to read config from file or persistence disabled. re-pulling config")
|
||||
|
||||
var cfgBytes []byte
|
||||
|
||||
cfgBytes, err = fetchConfig(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*task.cfgBytes = cfgBytes
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf("using existing config on disk")
|
||||
|
||||
cfgBytes, err := cfg.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*task.cfgBytes = cfgBytes
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchConfig(r runtime.Runtime) (out []byte, err error) {
|
||||
var b []byte
|
||||
|
||||
if b, err = r.Platform().Configuration(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Detect if config is a gzip archive and unzip it if so
|
||||
contentType := http.DetectContentType(b)
|
||||
if contentType == "application/x-gzip" {
|
||||
var gzipReader *gzip.Reader
|
||||
|
||||
gzipReader, err = gzip.NewReader(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating gzip reader: %w", err)
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
defer gzipReader.Close()
|
||||
|
||||
var unzippedData []byte
|
||||
|
||||
unzippedData, err = ioutil.ReadAll(gzipReader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error unzipping machine config: %w", err)
|
||||
}
|
||||
|
||||
b = unzippedData
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/manifest"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/probe"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/util"
|
||||
)
|
||||
|
||||
// ExtraDisks represents the ExtraDisks task.
|
||||
type ExtraDisks struct{}
|
||||
|
||||
// NewExtraDisksTask initializes and returns an ExtraDisks task.
|
||||
func NewExtraDisksTask() phase.Task {
|
||||
return &ExtraDisks{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *ExtraDisks) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
func (task *ExtraDisks) runtime(r runtime.Runtime) (err error) {
|
||||
if err = partitionAndFormatDisks(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return mountDisks(r)
|
||||
}
|
||||
|
||||
func partitionAndFormatDisks(r runtime.Runtime) (err error) {
|
||||
m := &manifest.Manifest{
|
||||
Targets: map[string][]*manifest.Target{},
|
||||
}
|
||||
|
||||
for _, disk := range r.Config().Machine().Disks() {
|
||||
if m.Targets[disk.Device] == nil {
|
||||
m.Targets[disk.Device] = []*manifest.Target{}
|
||||
}
|
||||
|
||||
for _, part := range disk.Partitions {
|
||||
extraTarget := &manifest.Target{
|
||||
Device: disk.Device,
|
||||
Size: part.Size,
|
||||
Force: true,
|
||||
Test: false,
|
||||
}
|
||||
|
||||
m.Targets[disk.Device] = append(m.Targets[disk.Device], extraTarget)
|
||||
}
|
||||
}
|
||||
|
||||
probed, err := probe.All()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(andrewrynhard): This is disgusting, but it works. We should revisit
|
||||
// this at a later time.
|
||||
for _, p := range probed {
|
||||
for _, disk := range r.Config().Machine().Disks() {
|
||||
for i := range disk.Partitions {
|
||||
partname := util.PartPath(disk.Device, i+1)
|
||||
if p.Path == partname {
|
||||
log.Printf(("found existing partitions for %q"), disk.Device)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err = m.ExecuteManifest(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mountDisks(r runtime.Runtime) (err error) {
|
||||
mountpoints := mount.NewMountPoints()
|
||||
|
||||
for _, extra := range r.Config().Machine().Disks() {
|
||||
for i, part := range extra.Partitions {
|
||||
partname := util.PartPath(extra.Device, i+1)
|
||||
mountpoints.Set(partname, mount.NewMountPoint(partname, part.MountPoint, "xfs", unix.MS_NOATIME, ""))
|
||||
}
|
||||
}
|
||||
|
||||
extras := manager.NewManager(mountpoints)
|
||||
if err = extras.MountAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// ExtraEnvVars represents the ExtraEnvVars task.
|
||||
type ExtraEnvVars struct{}
|
||||
|
||||
// NewExtraEnvVarsTask initializes and returns an ExtraEnvVars task.
|
||||
func NewExtraEnvVarsTask() phase.Task {
|
||||
return &ExtraEnvVars{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *ExtraEnvVars) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
func (task *ExtraEnvVars) runtime(r runtime.Runtime) (err error) {
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
if err = os.Setenv(key, val); err != nil {
|
||||
log.Printf("WARNING failed to set enivronment variable: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// ExtraFiles represents the ExtraFiles task.
|
||||
type ExtraFiles struct{}
|
||||
|
||||
// NewExtraFilesTask initializes and returns an ExtraFiles task.
|
||||
func NewExtraFilesTask() phase.Task {
|
||||
return &ExtraFiles{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *ExtraFiles) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func (task *ExtraFiles) runtime(r runtime.Runtime) (err error) {
|
||||
var result *multierror.Error
|
||||
|
||||
files, err := r.Config().Machine().Files()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating extra files: %w", err)
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
content := f.Content
|
||||
|
||||
switch f.Op {
|
||||
case "create":
|
||||
if err = doesNotExists(f.Path); err != nil {
|
||||
result = multierror.Append(result, fmt.Errorf("file must not exist: %q", f.Path))
|
||||
continue
|
||||
}
|
||||
case "overwrite":
|
||||
if err = existsAndIsFile(f.Path); err != nil {
|
||||
result = multierror.Append(result, err)
|
||||
continue
|
||||
}
|
||||
case "append":
|
||||
if err = existsAndIsFile(f.Path); err != nil {
|
||||
result = multierror.Append(result, err)
|
||||
continue
|
||||
}
|
||||
|
||||
var existingFileContents []byte
|
||||
|
||||
existingFileContents, err = ioutil.ReadFile(f.Path)
|
||||
if err != nil {
|
||||
result = multierror.Append(result, err)
|
||||
continue
|
||||
}
|
||||
|
||||
content = string(existingFileContents) + "\n" + f.Content
|
||||
default:
|
||||
result = multierror.Append(result, fmt.Errorf("unknown operation for file %q: %q", f.Path, f.Op))
|
||||
continue
|
||||
}
|
||||
|
||||
// Determine if supplied path is in /var or not.
|
||||
// If not, we'll write it to /var anyways and bind mount below
|
||||
p := f.Path
|
||||
inVar := true
|
||||
explodedPath := strings.Split(
|
||||
strings.TrimLeft(f.Path, "/"),
|
||||
string(os.PathSeparator),
|
||||
)
|
||||
|
||||
if explodedPath[0] != "var" {
|
||||
p = filepath.Join("/var", f.Path)
|
||||
inVar = false
|
||||
}
|
||||
|
||||
// We do not want to support creating new files anywhere outside of
|
||||
// /var. If a valid use case comes up, we can reconsider then.
|
||||
if !inVar && f.Op == "create" {
|
||||
return fmt.Errorf("create operation not allowed outside of /var: %q", f.Path)
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(filepath.Dir(p), os.ModeDir); err != nil {
|
||||
result = multierror.Append(result, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(p, []byte(content), f.Permissions); err != nil {
|
||||
result = multierror.Append(result, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// File path was not /var/... so we assume a bind mount is wanted
|
||||
if !inVar {
|
||||
if err = unix.Mount(p, f.Path, "", unix.MS_BIND|unix.MS_RDONLY, ""); err != nil {
|
||||
result = multierror.Append(result, fmt.Errorf("failed to create bind mount for %s: %w", p, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.ErrorOrNil()
|
||||
}
|
||||
|
||||
func doesNotExists(p string) (err error) {
|
||||
_, err = os.Stat(p)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("file exists")
|
||||
}
|
||||
|
||||
func existsAndIsFile(p string) (err error) {
|
||||
var info os.FileInfo
|
||||
|
||||
info, err = os.Stat(p)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("file must exist: %q", p)
|
||||
}
|
||||
|
||||
if !info.Mode().IsRegular() {
|
||||
return fmt.Errorf("invalid mode: %q", info.Mode().String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// SaveConfig represents the SaveConfig task.
|
||||
type SaveConfig struct{}
|
||||
|
||||
// NewSaveConfigTask initializes and returns an Config task.
|
||||
func NewSaveConfigTask() phase.Task {
|
||||
return &SaveConfig{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *SaveConfig) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
func (task *SaveConfig) runtime(r runtime.Runtime) (err error) {
|
||||
log.Printf("saving config %s to disk\n", r.Config().Version())
|
||||
|
||||
b, err := r.Config().Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(constants.ConfigPath, b, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/sysctl"
|
||||
)
|
||||
|
||||
// Sysctls represents the Sysctls task.
|
||||
type Sysctls struct{}
|
||||
|
||||
// NewSysctlsTask initializes and returns a Sysctls task.
|
||||
func NewSysctlsTask() phase.Task {
|
||||
return &Sysctls{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Sysctls) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
func (task *Sysctls) runtime(r runtime.Runtime) (err error) {
|
||||
var result *multierror.Error
|
||||
|
||||
for k, v := range r.Config().Machine().Sysctls() {
|
||||
if err = sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: k, Value: v}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return result.ErrorOrNil()
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package config_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice"
|
||||
)
|
||||
|
||||
// ResetSystemDisk represents the task for stop all containerd tasks in the
|
||||
// k8s.io namespace.
|
||||
type ResetSystemDisk struct {
|
||||
devname string
|
||||
}
|
||||
|
||||
// NewResetSystemDiskTask initializes and returns an Services task.
|
||||
func NewResetSystemDiskTask(devname string) phase.Task {
|
||||
return &ResetSystemDisk{
|
||||
devname: devname,
|
||||
}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *ResetSystemDisk) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return func(r runtime.Runtime) error {
|
||||
return task.standard()
|
||||
}
|
||||
}
|
||||
|
||||
func (task *ResetSystemDisk) standard() (err error) {
|
||||
return blockdevice.ResetDevice(task.devname)
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/retry"
|
||||
)
|
||||
|
||||
// VerifyDiskAvailability represents the task for verifying that the system
|
||||
// disk is not in use.
|
||||
type VerifyDiskAvailability struct {
|
||||
devname string
|
||||
}
|
||||
|
||||
// NewVerifyDiskAvailabilityTask initializes and returns a
|
||||
// VerifyDiskAvailability task.
|
||||
func NewVerifyDiskAvailabilityTask(devname string) phase.Task {
|
||||
return &VerifyDiskAvailability{
|
||||
devname: devname,
|
||||
}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *VerifyDiskAvailability) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return func(r runtime.Runtime) error {
|
||||
// We only need to verify system disk availability if we are going to
|
||||
// reformat the ephemeral partition.
|
||||
if r.Config().Machine().Install().Force() {
|
||||
return task.standard()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (task *VerifyDiskAvailability) standard() (err error) {
|
||||
if _, err = os.Stat(task.devname); errors.Is(err, os.ErrNotExist) {
|
||||
return fmt.Errorf("system disk not found: %w", err)
|
||||
}
|
||||
|
||||
mountsReported := false
|
||||
|
||||
return retry.Constant(3*time.Minute, retry.WithUnits(500*time.Millisecond)).Retry(func() error {
|
||||
if err = tryLock(task.devname); err != nil {
|
||||
if err == unix.EBUSY {
|
||||
if !mountsReported {
|
||||
// if disk is busy, report mounts for debugging purposes but just once
|
||||
// otherwise console might be flooded with messages
|
||||
dumpMounts()
|
||||
mountsReported = true
|
||||
}
|
||||
|
||||
return retry.ExpectedError(errors.New("system disk in use"))
|
||||
}
|
||||
|
||||
return retry.UnexpectedError(fmt.Errorf("failed to verify system disk not in use: %w", err))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func tryLock(devname string) error {
|
||||
fd, errno := unix.Open(devname, unix.O_RDONLY|unix.O_EXCL|unix.O_CLOEXEC, 0)
|
||||
|
||||
// nolint: errcheck
|
||||
defer unix.Close(fd)
|
||||
|
||||
return errno
|
||||
}
|
||||
|
||||
func dumpMounts() {
|
||||
mounts, err := os.Open("/proc/mounts")
|
||||
if err != nil {
|
||||
log.Printf("failed to read mounts: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer mounts.Close() //nolint: errcheck
|
||||
|
||||
log.Printf("contents of /proc/mounts:")
|
||||
|
||||
_, _ = io.Copy(log.Writer(), mounts) //nolint: errcheck
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/kubernetes"
|
||||
)
|
||||
|
||||
// CordonAndDrain represents the task for stop all containerd tasks in the
|
||||
// k8s.io namespace.
|
||||
type CordonAndDrain struct{}
|
||||
|
||||
// NewCordonAndDrainTask initializes and returns an Services task.
|
||||
func NewCordonAndDrainTask() phase.Task {
|
||||
return &CordonAndDrain{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *CordonAndDrain) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return func(r runtime.Runtime) error {
|
||||
return task.standard()
|
||||
}
|
||||
}
|
||||
|
||||
func (task *CordonAndDrain) standard() (err error) {
|
||||
var hostname string
|
||||
|
||||
if hostname, err = os.Hostname(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var kubeHelper *kubernetes.Client
|
||||
|
||||
if kubeHelper, err = kubernetes.NewClientFromKubeletKubeconfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = kubeHelper.CordonAndDrain(hostname); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
|
||||
"github.com/talos-systems/talos/internal/pkg/cri"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// RemoveAllPods represents the task for stopping all pods.
|
||||
type RemoveAllPods struct{}
|
||||
|
||||
// NewRemoveAllPodsTask initializes and returns an Services task.
|
||||
func NewRemoveAllPodsTask() phase.Task {
|
||||
return &RemoveAllPods{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *RemoveAllPods) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return func(r runtime.Runtime) error {
|
||||
return task.standard()
|
||||
}
|
||||
}
|
||||
|
||||
func (task *RemoveAllPods) standard() (err error) {
|
||||
if err = system.Services(nil).Stop(context.Background(), "kubelet"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := cri.NewClient("unix://"+constants.ContainerdAddress, 10*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
defer client.Close()
|
||||
|
||||
// We remove pods with POD network mode first so that the CNI can perform
|
||||
// any cleanup tasks. If we don't do this, we run the risk of killing the
|
||||
// CNI, preventing the CRI from cleaning up the pod's netwokring.
|
||||
|
||||
if err = client.RemovePodSandboxes(runtimeapi.NamespaceMode_POD, runtimeapi.NamespaceMode_CONTAINER); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// With the POD network mode pods out of the way, we kill the remaining
|
||||
// pods.
|
||||
|
||||
if err = client.RemovePodSandboxes(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package limits
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// FileLimitTask represents the FileLimitTask task.
|
||||
type FileLimitTask struct{}
|
||||
|
||||
// NewFileLimitTask initializes and returns a FileLimitTask task.
|
||||
func NewFileLimitTask() phase.Task {
|
||||
return &FileLimitTask{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *FileLimitTask) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *FileLimitTask) standard(r runtime.Runtime) (err error) {
|
||||
// TODO(andrewrynhard): Should we read limit from /proc/sys/fs/nr_open?
|
||||
if err = unix.Setrlimit(unix.RLIMIT_NOFILE, &unix.Rlimit{Cur: 1048576, Max: 1048576}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package limits_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/networkd/pkg/networkd"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// InitialNetworkSetup represents the task for setting up the initial network.
|
||||
type InitialNetworkSetup struct{}
|
||||
|
||||
// NewInitialNetworkSetupTask initializes and returns an InitialNetworkSetup task.
|
||||
func NewInitialNetworkSetupTask() phase.Task {
|
||||
return &InitialNetworkSetup{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *InitialNetworkSetup) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
func (task *InitialNetworkSetup) runtime(r runtime.Runtime) (err error) {
|
||||
nwd, err := networkd.New(r.Config())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = nwd.Configure(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/networkd/pkg/networkd"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// ResetNetworkNetwork represents the ResetNetworkNetwork task.
|
||||
type ResetNetworkNetwork struct{}
|
||||
|
||||
// NewResetNetworkTask initializes and returns an ResetNetworkNetwork task.
|
||||
func NewResetNetworkTask() phase.Task {
|
||||
return &ResetNetworkNetwork{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *ResetNetworkNetwork) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func (task *ResetNetworkNetwork) runtime(r runtime.Runtime) (err error) {
|
||||
nwd, err := networkd.New(r.Config())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nwd.Reset()
|
||||
|
||||
return nil
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package phase
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
goruntime "runtime"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/talos-systems/talos/internal/pkg/kmsg"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime/platform"
|
||||
)
|
||||
|
||||
// RuntimeArgs represents the set of arguments passed into a TaskFunc.
|
||||
type RuntimeArgs struct {
|
||||
platform runtime.Platform
|
||||
config runtime.Configurator
|
||||
}
|
||||
|
||||
// TaskFunc defines the function that a task must return. The function
|
||||
// envelopes the task logic for a given runtime mode.
|
||||
type TaskFunc func(runtime.Runtime) error
|
||||
|
||||
// Task represents a task within a Phase.
|
||||
type Task interface {
|
||||
TaskFunc(runtime.Mode) TaskFunc
|
||||
}
|
||||
|
||||
// Phase represents a phase in the boot process.
|
||||
type Phase struct {
|
||||
description string
|
||||
tasks []Task
|
||||
}
|
||||
|
||||
// Runner represents a management layer for phases.
|
||||
type Runner struct {
|
||||
phases []*Phase
|
||||
runtime runtime.Runtime
|
||||
}
|
||||
|
||||
// NewRunner initializes and returns a Runner.
|
||||
func NewRunner(config runtime.Configurator, sequence runtime.Sequence) (*Runner, error) {
|
||||
platform, err := platform.CurrentPlatform()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch platform.Mode() {
|
||||
case runtime.Metal:
|
||||
fallthrough
|
||||
case runtime.Cloud:
|
||||
// Setup logging to /dev/kmsg.
|
||||
if err = kmsg.Setup("[talos]", true); err != nil {
|
||||
return nil, fmt.Errorf("failed to setup logging: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
runner := &Runner{
|
||||
runtime: runtime.NewRuntime(platform, config, sequence),
|
||||
}
|
||||
|
||||
return runner, nil
|
||||
}
|
||||
|
||||
// Platform returns the platform.
|
||||
func (r *RuntimeArgs) Platform() runtime.Platform {
|
||||
return r.platform
|
||||
}
|
||||
|
||||
// Config returns the config.
|
||||
func (r *RuntimeArgs) Config() runtime.Configurator {
|
||||
return r.config
|
||||
}
|
||||
|
||||
// Run executes sequentially all phases known to a Runner.
|
||||
//
|
||||
// If any phase fails, Runner aborts immediately.
|
||||
func (r *Runner) Run() error {
|
||||
for _, phase := range r.phases {
|
||||
if err := r.runPhase(phase); err != nil {
|
||||
return fmt.Errorf("error running phase %q: %w", phase.description, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// runPhase runs a phase by running all phase tasks concurrently.
|
||||
func (r *Runner) runPhase(phase *Phase) error {
|
||||
errCh := make(chan error)
|
||||
|
||||
start := time.Now()
|
||||
|
||||
log.Printf("[phase]: %s", phase.description)
|
||||
|
||||
for _, task := range phase.tasks {
|
||||
go r.runTask(task, errCh)
|
||||
}
|
||||
|
||||
var (
|
||||
result *multierror.Error
|
||||
reboot bool
|
||||
)
|
||||
|
||||
for range phase.tasks {
|
||||
err := <-errCh
|
||||
if err != nil {
|
||||
if errors.Is(err, runtime.ErrReboot) {
|
||||
reboot = true
|
||||
} else {
|
||||
log.Printf("[phase]: %s error running task: %s", phase.description, err)
|
||||
}
|
||||
}
|
||||
|
||||
result = multierror.Append(result, err)
|
||||
}
|
||||
|
||||
log.Printf("[phase]: %s done, %s", phase.description, time.Since(start))
|
||||
|
||||
if reboot {
|
||||
return runtime.ErrReboot
|
||||
}
|
||||
|
||||
return result.ErrorOrNil()
|
||||
}
|
||||
|
||||
func (r *Runner) runTask(task Task, errCh chan<- error) {
|
||||
var err error
|
||||
|
||||
defer func() {
|
||||
errCh <- err
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// don't generate traceback for reboot error
|
||||
if r == runtime.ErrReboot {
|
||||
err = r.(error) //nolint: errcheck
|
||||
return
|
||||
}
|
||||
|
||||
buf := make([]byte, 8192)
|
||||
n := goruntime.Stack(buf, false)
|
||||
err = fmt.Errorf("panic recovered: %v\n%s", r, string(buf[:n]))
|
||||
}
|
||||
}()
|
||||
|
||||
var f TaskFunc
|
||||
if f = task.TaskFunc(r.runtime.Platform().Mode()); f == nil {
|
||||
// A task is not defined for this runtime mode.
|
||||
return
|
||||
}
|
||||
|
||||
err = f(r.runtime)
|
||||
}
|
||||
|
||||
// Add adds a phase to a Runner.
|
||||
func (r *Runner) Add(phase ...*Phase) {
|
||||
r.phases = append(r.phases, phase...)
|
||||
}
|
||||
|
||||
// NewPhase initializes and returns a Phase.
|
||||
func NewPhase(description string, tasks ...Task) *Phase {
|
||||
tasks = append([]Task{}, tasks...)
|
||||
|
||||
return &Phase{
|
||||
description: description,
|
||||
tasks: tasks,
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package phase_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
type PhaseSuite struct {
|
||||
suite.Suite
|
||||
|
||||
platformExists bool
|
||||
platformValue string
|
||||
}
|
||||
|
||||
type regularTask struct {
|
||||
errCh <-chan error
|
||||
}
|
||||
|
||||
func (t *regularTask) TaskFunc(runtime.Mode) phase.TaskFunc {
|
||||
return func(runtime.Runtime) error {
|
||||
return <-t.errCh
|
||||
}
|
||||
}
|
||||
|
||||
type nilTask struct{}
|
||||
|
||||
func (t *nilTask) TaskFunc(runtime.Mode) phase.TaskFunc {
|
||||
return nil
|
||||
}
|
||||
|
||||
type panicTask struct{}
|
||||
|
||||
func (t *panicTask) TaskFunc(runtime.Mode) phase.TaskFunc {
|
||||
return func(runtime.Runtime) error {
|
||||
panic("in task")
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *PhaseSuite) SetupSuite() {
|
||||
suite.platformValue, suite.platformExists = os.LookupEnv("PLATFORM")
|
||||
suite.Require().NoError(os.Setenv("PLATFORM", "container"))
|
||||
}
|
||||
|
||||
func (suite *PhaseSuite) TearDownSuite() {
|
||||
if !suite.platformExists {
|
||||
suite.Require().NoError(os.Unsetenv("PLATFORM"))
|
||||
} else {
|
||||
suite.Require().NoError(os.Setenv("PLATFORM", suite.platformValue))
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *PhaseSuite) TestRunSuccess() {
|
||||
r, err := phase.NewRunner(nil, runtime.None)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
taskErr := make(chan error)
|
||||
|
||||
r.Add(phase.NewPhase("empty"))
|
||||
r.Add(phase.NewPhase("phase1", ®ularTask{errCh: taskErr}, ®ularTask{errCh: taskErr}))
|
||||
r.Add(phase.NewPhase("phase2", ®ularTask{errCh: taskErr}, &nilTask{}))
|
||||
|
||||
errCh := make(chan error)
|
||||
|
||||
go func() {
|
||||
errCh <- r.Run()
|
||||
}()
|
||||
|
||||
taskErr <- nil
|
||||
taskErr <- nil
|
||||
|
||||
select {
|
||||
case <-errCh:
|
||||
suite.Require().Fail("should be still running")
|
||||
default:
|
||||
}
|
||||
|
||||
taskErr <- nil
|
||||
|
||||
suite.Require().NoError(<-errCh)
|
||||
}
|
||||
|
||||
func (suite *PhaseSuite) TestRunFailures() {
|
||||
r, err := phase.NewRunner(nil, runtime.None)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
taskErr := make(chan error, 1)
|
||||
|
||||
r.Add(phase.NewPhase("empty"))
|
||||
r.Add(phase.NewPhase("failphase", &panicTask{}, ®ularTask{errCh: taskErr}, &nilTask{}))
|
||||
r.Add(phase.NewPhase("neverreached",
|
||||
®ularTask{}, // should never be reached
|
||||
))
|
||||
|
||||
taskErr <- errors.New("test error")
|
||||
|
||||
err = r.Run()
|
||||
suite.Require().Error(err)
|
||||
suite.Assert().Contains(err.Error(), "2 errors occurred")
|
||||
suite.Assert().Contains(err.Error(), "test error")
|
||||
suite.Assert().Contains(err.Error(), "panic recovered: in task")
|
||||
}
|
||||
|
||||
func TestPhaseSuite(t *testing.T) {
|
||||
suite.Run(t, new(PhaseSuite))
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package platform
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime/initializer"
|
||||
)
|
||||
|
||||
// Platform represents the Platform task.
|
||||
type Platform struct{}
|
||||
|
||||
// NewPlatformTask initializes and returns an Platform task.
|
||||
func NewPlatformTask() phase.Task {
|
||||
return &Platform{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Platform) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
func (task *Platform) runtime(r runtime.Runtime) (err error) {
|
||||
i, err := initializer.New(r.Platform().Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = i.Initialize(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hostname, err := r.Platform().Hostname()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if hostname != nil {
|
||||
r.Config().Machine().Network().SetHostname(string(hostname))
|
||||
}
|
||||
|
||||
addrs, err := r.Platform().ExternalIPs()
|
||||
if err != nil {
|
||||
log.Printf("certificates will be created without external IPs: %v\n", err)
|
||||
}
|
||||
|
||||
sans := make([]string, 0, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
sans = append(sans, addr.String())
|
||||
}
|
||||
|
||||
r.Config().Machine().Security().SetCertSANs(sans)
|
||||
r.Config().Cluster().SetCertSANs(sans)
|
||||
|
||||
return nil
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package platform_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/bootloader/syslinux"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// CheckInstall represents the CheckInstall task.
|
||||
type CheckInstall struct{}
|
||||
|
||||
// NewCheckInstallTask initializes and returns a CheckInstall task.
|
||||
func NewCheckInstallTask() phase.Task {
|
||||
return &CheckInstall{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *CheckInstall) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *CheckInstall) standard(r runtime.Runtime) (err error) {
|
||||
var (
|
||||
current string
|
||||
next string
|
||||
)
|
||||
|
||||
current, next, err = syslinux.Labels()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if current == "" && next == "" {
|
||||
return fmt.Errorf("syslinux.cfg is not configured")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package etc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/talos-systems/talos/pkg/version"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const osReleaseTemplate = `
|
||||
NAME="{{ .Name }}"
|
||||
ID={{ .ID }}
|
||||
VERSION_ID={{ .Version }}
|
||||
PRETTY_NAME="{{ .Name }} ({{ .Version }})"
|
||||
HOME_URL="https://docs.talos-systems.com/"
|
||||
BUG_REPORT_URL="https://github.com/talos-systems/talos/issues"
|
||||
`
|
||||
|
||||
// Hosts creates a persistent and writable /etc/hosts file.
|
||||
func Hosts() (err error) {
|
||||
return createBindMount("/run/system/etc/hosts", "/etc/hosts")
|
||||
}
|
||||
|
||||
// ResolvConf creates a persistent and writable /etc/resolv.conf file.
|
||||
func ResolvConf() (err error) {
|
||||
return createBindMount("/run/system/etc/resolv.conf", "/etc/resolv.conf")
|
||||
}
|
||||
|
||||
// OSRelease renders a valid /etc/os-release file and writes it to disk. The
|
||||
// node's OS Image field is reported by the node from /etc/os-release.
|
||||
func OSRelease() (err error) {
|
||||
if err = createBindMount("/run/system/etc/os-release", "/etc/os-release"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
v string
|
||||
tmpl *template.Template
|
||||
)
|
||||
|
||||
switch version.Tag {
|
||||
case "none":
|
||||
v = version.SHA
|
||||
default:
|
||||
v = version.Tag
|
||||
}
|
||||
|
||||
data := struct {
|
||||
Name string
|
||||
ID string
|
||||
Version string
|
||||
}{
|
||||
Name: version.Name,
|
||||
ID: strings.ToLower(version.Name),
|
||||
Version: v,
|
||||
}
|
||||
|
||||
tmpl, err = template.New("").Parse(osReleaseTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var buf []byte
|
||||
|
||||
writer := bytes.NewBuffer(buf)
|
||||
|
||||
err = tmpl.Execute(writer, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile("/run/system/etc/os-release", writer.Bytes(), 0644)
|
||||
}
|
||||
|
||||
// createBindMount creates a common way to create a writable source file with a
|
||||
// bind mounted destination. This is most commonly used for well known files
|
||||
// under /etc that need to be adjusted during startup.
|
||||
func createBindMount(src, dst string) (err error) {
|
||||
var f *os.File
|
||||
|
||||
if f, err = os.OpenFile(src, os.O_WRONLY|os.O_CREATE, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
if err = f.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = unix.Mount(src, dst, "", unix.MS_BIND, ""); err != nil {
|
||||
return fmt.Errorf("failed to create bind mount for %s: %w", dst, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/bpffs"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// MountBPFFS represents the MountBPFFS task.
|
||||
type MountBPFFS struct{}
|
||||
|
||||
// NewMountBPFFSTask initializes and returns an MountBPFFS task.
|
||||
func NewMountBPFFSTask() phase.Task {
|
||||
return &MountBPFFS{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *MountBPFFS) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
func (task *MountBPFFS) runtime(r runtime.Runtime) (err error) {
|
||||
var mountpoints *mount.Points
|
||||
|
||||
mountpoints, err = bpffs.MountPoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := manager.NewManager(mountpoints)
|
||||
if err = m.MountAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/cgroups"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
memoryCgroup = "memory"
|
||||
memoryUseHierarchy = "memory.use_hierarchy"
|
||||
memoryUseHierarchyPermissions = os.FileMode(400)
|
||||
)
|
||||
|
||||
var memoryUseHierarchyContents = []byte(strconv.Itoa(1))
|
||||
|
||||
// MountCgroups represents the MountCgroups task.
|
||||
type MountCgroups struct{}
|
||||
|
||||
// NewMountCgroupsTask initializes and returns an MountCgroups task.
|
||||
func NewMountCgroupsTask() phase.Task {
|
||||
return &MountCgroups{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *MountCgroups) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
func (task *MountCgroups) runtime(r runtime.Runtime) (err error) {
|
||||
var mountpoints *mount.Points
|
||||
|
||||
mountpoints, err = cgroups.MountPoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := manager.NewManager(mountpoints)
|
||||
if err = m.MountAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// See https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
|
||||
target := path.Join("/sys/fs/cgroup", memoryCgroup, memoryUseHierarchy)
|
||||
if err = ioutil.WriteFile(target, memoryUseHierarchyContents, memoryUseHierarchyPermissions); err != nil {
|
||||
return fmt.Errorf("failed to enable memory hierarchy support: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/overlay"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// MountOverlay represents the MountOverlay task.
|
||||
type MountOverlay struct{}
|
||||
|
||||
// NewMountOverlayTask initializes and returns an MountOverlay task.
|
||||
func NewMountOverlayTask() phase.Task {
|
||||
return &MountOverlay{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *MountOverlay) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *MountOverlay) standard(r runtime.Runtime) (err error) {
|
||||
var mountpoints *mount.Points
|
||||
|
||||
mountpoints, err = overlay.MountPoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := manager.NewManager(mountpoints)
|
||||
if err = m.MountAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// MountShared represents the MountShared task.
|
||||
type MountShared struct{}
|
||||
|
||||
// NewMountSharedTask initializes and returns an MountShared task.
|
||||
func NewMountSharedTask() phase.Task {
|
||||
return &MountShared{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *MountShared) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return task.container
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (task *MountShared) container(r runtime.Runtime) (err error) {
|
||||
targets := []string{"/", "/var/lib/kubelet", "/etc/cni", "/run"}
|
||||
for _, t := range targets {
|
||||
if err = unix.Mount("", t, "", unix.MS_SHARED|unix.MS_REC, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/pseudo"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// MountSubDevices represents the MountSubDevices task.
|
||||
type MountSubDevices struct{}
|
||||
|
||||
// NewMountSubDevicesTask initializes and returns an MountSubDevices task.
|
||||
func NewMountSubDevicesTask() phase.Task {
|
||||
return &MountSubDevices{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *MountSubDevices) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
func (task *MountSubDevices) runtime(r runtime.Runtime) (err error) {
|
||||
var mountpoints *mount.Points
|
||||
|
||||
mountpoints, err = pseudo.SubMountPoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := manager.NewManager(mountpoints)
|
||||
if err = m.MountAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/owned"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// MountSystemDisks represents the MountSystemDisks task.
|
||||
type MountSystemDisks struct {
|
||||
devlabel string
|
||||
opts []mount.Option
|
||||
}
|
||||
|
||||
// NewMountSystemDisksTask initializes and returns an MountSystemDisks task.
|
||||
func NewMountSystemDisksTask(devlabel string, opts ...mount.Option) phase.Task {
|
||||
return &MountSystemDisks{
|
||||
devlabel: devlabel,
|
||||
opts: opts,
|
||||
}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *MountSystemDisks) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
func (task *MountSystemDisks) runtime(r runtime.Runtime) (err error) {
|
||||
mountpoints := mount.NewMountPoints()
|
||||
|
||||
log.Printf("fetching mountpoint for label %q\n", task.devlabel)
|
||||
|
||||
mountpoint, err := owned.MountPointForLabel(task.devlabel, task.opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if mountpoint == nil {
|
||||
log.Printf("could not find boot partition with label %q\n", task.devlabel)
|
||||
return nil
|
||||
}
|
||||
|
||||
mountpoints.Set(task.devlabel, mountpoint)
|
||||
|
||||
m := manager.NewManager(mountpoints)
|
||||
if err = m.MountAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/rootfs/etc"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// NetworkConfiguration represents the NetworkConfiguration task.
|
||||
type NetworkConfiguration struct{}
|
||||
|
||||
// NewNetworkConfigurationTask initializes and returns an NetworkConfiguration task.
|
||||
func NewNetworkConfigurationTask() phase.Task {
|
||||
return &NetworkConfiguration{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *NetworkConfiguration) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
func (task *NetworkConfiguration) runtime(r runtime.Runtime) (err error) {
|
||||
// Create /etc/resolv.conf.
|
||||
if err = etc.ResolvConf(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create /etc/hosts
|
||||
if err = etc.Hosts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/rootfs/etc"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// OSRelease represents the OSRelease task.
|
||||
type OSRelease struct{}
|
||||
|
||||
// NewOSReleaseTask initializes and returns an OSRelease task.
|
||||
func NewOSReleaseTask() phase.Task {
|
||||
return &OSRelease{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *OSRelease) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
func (task *OSRelease) runtime(r runtime.Runtime) (err error) {
|
||||
// Create /etc/os-release.
|
||||
return etc.OSRelease()
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/bootloader/syslinux"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// Syslinux represents the Syslinux task.
|
||||
type Syslinux struct{}
|
||||
|
||||
// NewSyslinuxTask initializes and returns a ClearOnce task.
|
||||
func NewSyslinuxTask() phase.Task {
|
||||
return &Syslinux{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Syslinux) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *Syslinux) standard(r runtime.Runtime) (err error) {
|
||||
f, err := os.OpenFile(syslinux.SyslinuxLdlinux, os.O_RDWR, 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
defer f.Close()
|
||||
|
||||
adv, err := syslinux.NewADV(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ok := adv.DeleteTag(syslinux.AdvUpgrade); ok {
|
||||
log.Println("removing fallback")
|
||||
}
|
||||
|
||||
if _, err = f.Write(adv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// SystemDirectory represents the SystemDirectory task.
|
||||
type SystemDirectory struct{}
|
||||
|
||||
// NewSystemDirectoryTask initializes and returns an SystemDirectory task.
|
||||
func NewSystemDirectoryTask() phase.Task {
|
||||
return &SystemDirectory{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *SystemDirectory) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
func (task *SystemDirectory) runtime(r runtime.Runtime) (err error) {
|
||||
for _, p := range []string{"etc", "log"} {
|
||||
if err = os.MkdirAll(filepath.Join(constants.SystemRunPath, p), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/overlay"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// UnmountOverlay represents the UnmountOverlay task.
|
||||
type UnmountOverlay struct{}
|
||||
|
||||
// NewUnmountOverlayTask initializes and returns an UnmountOverlay task.
|
||||
func NewUnmountOverlayTask() phase.Task {
|
||||
return &UnmountOverlay{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *UnmountOverlay) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *UnmountOverlay) standard(r runtime.Runtime) (err error) {
|
||||
var mountpoints *mount.Points
|
||||
|
||||
mountpoints, err = overlay.MountPoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := manager.NewManager(mountpoints)
|
||||
if err = m.UnmountAll(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// UnmountPodMounts represents the UnmountPodMounts task.
|
||||
type UnmountPodMounts struct{}
|
||||
|
||||
// NewUnmountPodMountsTask initializes and returns an UnmountPodMounts task.
|
||||
func NewUnmountPodMountsTask() phase.Task {
|
||||
return &UnmountPodMounts{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *UnmountPodMounts) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *UnmountPodMounts) standard(r runtime.Runtime) (err error) {
|
||||
var b []byte
|
||||
|
||||
if b, err = ioutil.ReadFile("/proc/self/mounts"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rdr := bytes.NewReader(b)
|
||||
|
||||
scanner := bufio.NewScanner(rdr)
|
||||
for scanner.Scan() {
|
||||
fields := strings.Fields(scanner.Text())
|
||||
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
mountpoint := fields[1]
|
||||
if strings.HasPrefix(mountpoint, constants.EphemeralMountPoint+"/") {
|
||||
log.Printf("unmounting %s\n", mountpoint)
|
||||
|
||||
if err = unix.Unmount(mountpoint, 0); err != nil {
|
||||
return fmt.Errorf("error unmounting %s: %w", mountpoint, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err = scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// UnmountSystemDiskBindMounts represents the UnmountSystemDiskBindMounts task.
|
||||
type UnmountSystemDiskBindMounts struct {
|
||||
devname string
|
||||
}
|
||||
|
||||
// NewUnmountSystemDiskBindMountsTask initializes and returns an UnmountSystemDiskBindMounts task.
|
||||
func NewUnmountSystemDiskBindMountsTask(devname string) phase.Task {
|
||||
return &UnmountSystemDiskBindMounts{
|
||||
devname: devname,
|
||||
}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *UnmountSystemDiskBindMounts) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *UnmountSystemDiskBindMounts) standard(r runtime.Runtime) (err error) {
|
||||
f, err := os.Open("/proc/mounts")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close() //nolint: errcheck
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
fields := strings.Fields(scanner.Text())
|
||||
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
device := fields[0]
|
||||
mountpoint := fields[1]
|
||||
|
||||
if strings.HasPrefix(device, task.devname) {
|
||||
log.Printf("unmounting %s\n", mountpoint)
|
||||
|
||||
if err = unix.Unmount(mountpoint, 0); err != nil {
|
||||
return fmt.Errorf("error unmounting %s: %w", mountpoint, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scanner.Err()
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager"
|
||||
"github.com/talos-systems/talos/internal/pkg/mount/manager/owned"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// UnmountSystemDisks represents the UnmountSystemDisks task.
|
||||
type UnmountSystemDisks struct {
|
||||
devlabel string
|
||||
}
|
||||
|
||||
// NewUnmountSystemDisksTask initializes and returns an UnmountSystemDisks task.
|
||||
func NewUnmountSystemDisksTask(devlabel string) phase.Task {
|
||||
return &UnmountSystemDisks{
|
||||
devlabel: devlabel,
|
||||
}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *UnmountSystemDisks) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *UnmountSystemDisks) standard(r runtime.Runtime) (err error) {
|
||||
mountpoints := mount.NewMountPoints()
|
||||
|
||||
mountpoint, err := owned.MountPointForLabel(task.devlabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mountpoints.Set(task.devlabel, mountpoint)
|
||||
|
||||
unix.Sync()
|
||||
|
||||
m := manager.NewManager(mountpoints)
|
||||
if err = m.UnmountAll(); err != nil {
|
||||
return fmt.Errorf("error unmounting %q partition: %w", task.devlabel, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// ValidateConfig represents the ValidateConfig task.
|
||||
type ValidateConfig struct{}
|
||||
|
||||
// NewValidateConfigTask initializes and returns a ValidateConfig task.
|
||||
func NewValidateConfigTask() phase.Task {
|
||||
return &ValidateConfig{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *ValidateConfig) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.standard
|
||||
}
|
||||
|
||||
func (task *ValidateConfig) standard(r runtime.Runtime) (err error) {
|
||||
file := "/sys/module/usb_storage/parameters/delay_use"
|
||||
|
||||
_, err = os.Stat(file)
|
||||
if os.IsNotExist(err) {
|
||||
return r.Config().Validate(r.Platform().Mode())
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
val := strings.TrimSuffix(string(b), "\n")
|
||||
|
||||
i, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(i) * time.Second)
|
||||
|
||||
return r.Config().Validate(r.Platform().Mode())
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package rootfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// VarDirectories represents the VarDirectories task.
|
||||
type VarDirectories struct{}
|
||||
|
||||
// NewVarDirectoriesTask initializes and returns an VarDirectories task.
|
||||
func NewVarDirectoriesTask() phase.Task {
|
||||
return &VarDirectories{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *VarDirectories) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.runtime
|
||||
}
|
||||
|
||||
func (task *VarDirectories) runtime(r runtime.Runtime) (err error) {
|
||||
for _, p := range []string{"/var/log/pods", "/var/lib/kubelet", "/var/run/lock"} {
|
||||
if err = os.MkdirAll(p, 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// See https://www.kernel.org/doc/Documentation/ABI/testing/ima_policy
|
||||
var rules = []string{
|
||||
"dont_measure fsmagic=0x9fa0", // PROC_SUPER_MAGIC
|
||||
"dont_measure fsmagic=0x62656572", // SYSFS_MAGIC
|
||||
"dont_measure fsmagic=0x64626720", // DEBUGFS_MAGIC
|
||||
"dont_measure fsmagic=0x1021994", // TMPFS_MAGIC
|
||||
"dont_measure fsmagic=0x1cd1", // DEVPTS_SUPER_MAGIC
|
||||
"dont_measure fsmagic=0x42494e4d", // BINFMTFS_MAGIC
|
||||
"dont_measure fsmagic=0x73636673", // SECURITYFS_MAGIC
|
||||
"dont_measure fsmagic=0xf97cff8c", // SELINUX_MAGIC
|
||||
"dont_measure fsmagic=0x43415d53", // SMACK_MAGIC
|
||||
"dont_measure fsmagic=0x27e0eb", // CGROUP_SUPER_MAGIC
|
||||
"dont_measure fsmagic=0x63677270", // CGROUP2_SUPER_MAGIC
|
||||
"dont_measure fsmagic=0x6e736673", // NSFS_MAGIC
|
||||
"dont_measure fsmagic=0xde5e81e4", // EFIVARFS_MAGIC
|
||||
"dont_measure fsmagic=0x58465342", // XFS_MAGIC
|
||||
"dont_measure fsmagic=0x794c7630", // OVERLAYFS_SUPER_MAGIC
|
||||
"measure func=MMAP_CHECK mask=MAY_EXEC",
|
||||
"measure func=BPRM_CHECK mask=MAY_EXEC",
|
||||
"measure func=FILE_CHECK mask=^MAY_READ euid=0",
|
||||
"measure func=FILE_CHECK mask=^MAY_READ uid=0",
|
||||
"measure func=MODULE_CHECK",
|
||||
"measure func=FIRMWARE_CHECK",
|
||||
"measure func=POLICY_CHECK",
|
||||
}
|
||||
|
||||
// IMA represents the IMA task.
|
||||
type IMA struct{}
|
||||
|
||||
// NewIMATask initializes and returns an IMA task.
|
||||
func NewIMATask() phase.Task {
|
||||
return &IMA{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *IMA) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
func (task *IMA) runtime(r runtime.Runtime) (err error) {
|
||||
if _, err = os.Stat("/sys/kernel/security/ima/policy"); os.IsNotExist(err) {
|
||||
return fmt.Errorf("policy file does not exist: %w", err)
|
||||
}
|
||||
|
||||
f, err := os.OpenFile("/sys/kernel/security/ima/policy", os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close() //nolint: errcheck
|
||||
|
||||
for _, line := range rules {
|
||||
if _, err = f.WriteString(line + "\n"); err != nil {
|
||||
return fmt.Errorf("rule %q is invalid", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/kernel/kspp"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// Security represents the Security task.
|
||||
type Security struct{}
|
||||
|
||||
// NewSecurityTask initializes and returns an Security task.
|
||||
func NewSecurityTask() phase.Task {
|
||||
return &Security{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Security) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.runtime
|
||||
}
|
||||
}
|
||||
|
||||
func (task *Security) runtime(r runtime.Runtime) (err error) {
|
||||
if err = kspp.EnforceKSPPKernelParameters(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = kspp.EnforceKSPPSysctls(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package security_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/kubernetes"
|
||||
"github.com/talos-systems/talos/pkg/retry"
|
||||
)
|
||||
|
||||
// LabelNodeAsMaster represents the LabelNodeAsMaster task.
|
||||
type LabelNodeAsMaster struct{}
|
||||
|
||||
// NewLabelNodeAsMasterTask initializes and returns an Services task.
|
||||
func NewLabelNodeAsMasterTask() phase.Task {
|
||||
return &LabelNodeAsMaster{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *LabelNodeAsMaster) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.standard
|
||||
}
|
||||
|
||||
func (task *LabelNodeAsMaster) standard(r runtime.Runtime) (err error) {
|
||||
if r.Config().Machine().Type() == machine.TypeWorker {
|
||||
return nil
|
||||
}
|
||||
|
||||
h, err := kubernetes.NewTemporaryClientFromPKI(r.Config().Cluster().CA(), r.Config().Cluster().Endpoint())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = retry.Constant(10*time.Minute, retry.WithUnits(3*time.Second)).Retry(func() error {
|
||||
if err = h.LabelNodeAsMaster(hostname); err != nil {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to label node as master: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package services_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system/services"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// StartContainerd represents the task to start system containerd.
|
||||
type StartContainerd struct{}
|
||||
|
||||
// NewStartContainerdTask initializes and returns an Services task.
|
||||
func NewStartContainerdTask() phase.Task {
|
||||
return &StartContainerd{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *StartContainerd) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.standard
|
||||
}
|
||||
|
||||
func (task *StartContainerd) standard(r runtime.Runtime) (err error) {
|
||||
svc := &services.Containerd{}
|
||||
|
||||
system.Services(r.Config()).LoadAndStart(svc)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
return system.WaitForService(system.StateEventUp, svc.ID(r.Config())).Wait(ctx)
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system/services"
|
||||
"github.com/talos-systems/talos/internal/pkg/conditions"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
)
|
||||
|
||||
// StartServices represents the StartServices task.
|
||||
type StartServices struct{}
|
||||
|
||||
// NewStartServicesTask initializes and returns an Services task.
|
||||
func NewStartServicesTask() phase.Task {
|
||||
return &StartServices{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *StartServices) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.standard
|
||||
}
|
||||
|
||||
func (task *StartServices) standard(r runtime.Runtime) (err error) {
|
||||
task.loadSystemServices(r)
|
||||
task.loadKubernetesServices(r)
|
||||
|
||||
system.Services(r.Config()).StartAll()
|
||||
|
||||
return task.wait(r)
|
||||
}
|
||||
|
||||
func (task *StartServices) loadSystemServices(r runtime.Runtime) {
|
||||
svcs := system.Services(r.Config())
|
||||
// Start the services common to all nodes.
|
||||
svcs.Load(
|
||||
&services.MachinedAPI{},
|
||||
&services.CRI{},
|
||||
&services.APID{},
|
||||
&services.OSD{},
|
||||
&services.Networkd{},
|
||||
&services.Routerd{},
|
||||
)
|
||||
|
||||
if r.Platform().Mode() != runtime.Container {
|
||||
// udevd-trigger is causing stalls/unresponsive stuff when running in local mode
|
||||
// TODO: investigate root cause, but workaround for now is to skip it in container mode
|
||||
svcs.Load(
|
||||
&services.Timed{},
|
||||
&services.Udevd{},
|
||||
&services.UdevdTrigger{},
|
||||
)
|
||||
}
|
||||
|
||||
// Start the services common to all control plane nodes.
|
||||
|
||||
switch r.Config().Machine().Type() {
|
||||
case machine.TypeInit:
|
||||
fallthrough
|
||||
case machine.TypeControlPlane:
|
||||
svcs.Load(
|
||||
&services.Etcd{},
|
||||
&services.Trustd{},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (task *StartServices) loadKubernetesServices(r runtime.Runtime) {
|
||||
svcs := system.Services(r.Config())
|
||||
svcs.Load(
|
||||
&services.Kubelet{},
|
||||
)
|
||||
|
||||
if r.Config().Machine().Type() == machine.TypeInit {
|
||||
svcs.Load(
|
||||
&services.Bootkube{},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (task *StartServices) wait(r runtime.Runtime) (err error) {
|
||||
svcs := system.Services(r.Config()).List()
|
||||
|
||||
all := []conditions.Condition{}
|
||||
|
||||
for _, svc := range svcs {
|
||||
cond := system.WaitForService(system.StateEventUp, svc.AsProto().GetId())
|
||||
all = append(all, cond)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
|
||||
defer cancel()
|
||||
|
||||
return conditions.WaitForAll(all...).Wait(ctx)
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// StopServices represents the StopServices task.
|
||||
type StopServices struct {
|
||||
services []string
|
||||
}
|
||||
|
||||
// NewStopServicesTask initializes and returns an Services task.
|
||||
func NewStopServicesTask(services ...string) phase.Task {
|
||||
return &StopServices{
|
||||
services: services,
|
||||
}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *StopServices) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.standard
|
||||
}
|
||||
|
||||
func (task *StopServices) standard(r runtime.Runtime) (err error) {
|
||||
if len(task.services) > 0 {
|
||||
for _, service := range task.services {
|
||||
if err = system.Services(nil).Stop(context.Background(), service); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
system.Services(nil).Shutdown()
|
||||
|
||||
return nil
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package signal
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/event"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
// Handler represents the signal handler task.
|
||||
type Handler struct{}
|
||||
|
||||
// NewHandlerTask initializes and returns a signal handler task.
|
||||
func NewHandlerTask() phase.Task {
|
||||
return &Handler{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Handler) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return task.container
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (task *Handler) container(r runtime.Runtime) (err error) {
|
||||
termCh := make(chan os.Signal, 1)
|
||||
signal.Notify(termCh, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
<-termCh
|
||||
signal.Stop(termCh)
|
||||
|
||||
log.Printf("shutdown via SIGTERM received")
|
||||
event.Bus().Notify(event.Event{Type: event.Shutdown})
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package signal_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package sysctls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/sysctl"
|
||||
)
|
||||
|
||||
// Task represents the Task task.
|
||||
type Task struct{}
|
||||
|
||||
// NewSysctlsTask initializes and returns a Task task.
|
||||
func NewSysctlsTask() phase.Task {
|
||||
return &Task{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Task) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return task.container
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *Task) standard(r runtime.Runtime) error {
|
||||
var multiErr *multierror.Error
|
||||
|
||||
if err := sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: "net.ipv4.ip_forward", Value: "1"}); err != nil {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("failed to set net.ipv4.ip_forward: %w", err))
|
||||
}
|
||||
|
||||
if err := sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: "net.bridge.bridge-nf-call-iptables", Value: "1"}); err != nil {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("failed to set net.bridge.bridge-nf-call-iptables: %w", err))
|
||||
}
|
||||
|
||||
if err := sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: "net.bridge.bridge-nf-call-ip6tables", Value: "1"}); err != nil {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("failed to set net.bridge.bridge-nf-call-ip6tables: %w", err))
|
||||
}
|
||||
|
||||
if err := sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: "net.ipv6.conf.default.forwarding", Value: "1"}); err != nil {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("failed to set net.ipv6.conf.default.forwarding: %w", err))
|
||||
}
|
||||
|
||||
if err := sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: "kernel.pid_max", Value: "262144"}); err != nil {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("failed to set kernel.pid_max: %w", err))
|
||||
}
|
||||
|
||||
return multiErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
func (task *Task) container(r runtime.Runtime) error {
|
||||
var multiErr *multierror.Error
|
||||
|
||||
if err := sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: "net.ipv4.ip_forward", Value: "1"}); err != nil {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("failed to set net.ipv4.ip_forward: %w", err))
|
||||
}
|
||||
|
||||
if err := sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: "net.ipv6.conf.default.forwarding", Value: "1"}); err != nil {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("failed to set net.ipv6.conf.default.forwarding: %w", err))
|
||||
}
|
||||
|
||||
if err := sysctl.WriteSystemProperty(&sysctl.SystemProperty{Key: "kernel.pid_max", Value: "262144"}); err != nil {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("failed to set kernel.pid_max: %w", err))
|
||||
}
|
||||
|
||||
return multiErr.ErrorOrNil()
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package sysctls_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
|
||||
"github.com/talos-systems/talos/internal/pkg/etcd"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// LeaveEtcd represents the task for removing a control plane node from etcd.
|
||||
type LeaveEtcd struct {
|
||||
preserve bool
|
||||
}
|
||||
|
||||
// NewLeaveEtcdTask initializes and returns a LeaveEtcd task.
|
||||
func NewLeaveEtcdTask(preserve bool) phase.Task {
|
||||
return &LeaveEtcd{preserve: preserve}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *LeaveEtcd) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.standard
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func (task *LeaveEtcd) standard(r runtime.Runtime) (err error) {
|
||||
if r.Config().Machine().Type() == machine.TypeWorker {
|
||||
return nil
|
||||
}
|
||||
|
||||
if task.preserve {
|
||||
return nil
|
||||
}
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := etcd.NewClientFromControlPlaneIPs(r.Config().Cluster().CA(), r.Config().Cluster().Endpoint())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
defer client.Close()
|
||||
|
||||
resp, err := client.MemberList(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var id *uint64
|
||||
|
||||
for _, member := range resp.Members {
|
||||
if member.Name == hostname {
|
||||
id = &member.ID
|
||||
}
|
||||
}
|
||||
|
||||
if id == nil {
|
||||
return fmt.Errorf("failed to find %q in list of etcd members", hostname)
|
||||
}
|
||||
|
||||
log.Println("leaving etcd cluster")
|
||||
|
||||
_, err = client.MemberRemove(context.Background(), *id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = system.Services(nil).Stop(context.Background(), "etcd"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Once the member is removed, the data is no longer valid.
|
||||
if err = os.RemoveAll(constants.EtcdDataPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/install"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
// Upgrade represents the task for stop all containerd tasks in the
|
||||
// k8s.io namespace.
|
||||
type Upgrade struct {
|
||||
disk string
|
||||
image string
|
||||
preserve bool
|
||||
}
|
||||
|
||||
// NewUpgradeTask initializes and returns an Services task.
|
||||
func NewUpgradeTask(devname string, req *machineapi.UpgradeRequest) phase.Task {
|
||||
return &Upgrade{
|
||||
disk: devname,
|
||||
image: req.Image,
|
||||
preserve: req.Preserve,
|
||||
}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Upgrade) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
return task.standard
|
||||
}
|
||||
|
||||
func (task *Upgrade) standard(r runtime.Runtime) (err error) {
|
||||
log.Printf("performing upgrade via %q", task.image)
|
||||
|
||||
c := r.Config()
|
||||
if cfg, ok := c.(*v1alpha1.Config); ok {
|
||||
cfg.MachineConfig.MachineInstall.InstallDisk = task.disk
|
||||
cfg.MachineConfig.MachineInstall.InstallImage = task.image
|
||||
|
||||
r = runtime.NewRuntime(r.Platform(), runtime.Configurator(cfg), runtime.Upgrade)
|
||||
}
|
||||
|
||||
// We pull the installer image when we receive an upgrade request. No need to re-pull inside of installer container
|
||||
if err = install.RunInstallerContainer(r, install.WithImagePull(false), install.WithPreserve(task.preserve)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package sequencer
|
||||
|
||||
import (
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/sequencer/v1alpha1"
|
||||
)
|
||||
|
||||
// Sequencer describes the boot, shutdown, and upgrade events.
|
||||
type Sequencer interface {
|
||||
Boot() error
|
||||
Shutdown() error
|
||||
Upgrade(*machineapi.UpgradeRequest) error
|
||||
Reset(*machineapi.ResetRequest) error
|
||||
}
|
||||
|
||||
// Version represents the sequencer version.
|
||||
type Version int
|
||||
|
||||
const (
|
||||
// V1Alpha1 is the v1alpha1 sequencer.
|
||||
V1Alpha1 = iota
|
||||
)
|
||||
|
||||
// New initializes and returns a sequencer based on the specified version.
|
||||
func New(v Version) Sequencer {
|
||||
switch v {
|
||||
case V1Alpha1:
|
||||
return &v1alpha1.Sequencer{}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
@ -1,344 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/acpi"
|
||||
configtask "github.com/talos-systems/talos/internal/app/machined/internal/phase/config"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/disk"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/kubernetes"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/limits"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/network"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/platform"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/rootfs"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/security"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/services"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/signal"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/sysctls"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase/upgrade"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/probe"
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/util"
|
||||
"github.com/talos-systems/talos/pkg/config"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
)
|
||||
|
||||
// Sequencer represents the v1alpha1 sequencer.
|
||||
type Sequencer struct{}
|
||||
|
||||
// Boot implements the Sequencer interface.
|
||||
func (d *Sequencer) Boot() error {
|
||||
phaserunner, err := phase.NewRunner(nil, runtime.Boot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfgBytes := []byte{}
|
||||
|
||||
phaserunner.Add(
|
||||
phase.NewPhase(
|
||||
"system requirements",
|
||||
security.NewSecurityTask(),
|
||||
rootfs.NewSystemDirectoryTask(),
|
||||
rootfs.NewMountBPFFSTask(),
|
||||
rootfs.NewMountCgroupsTask(),
|
||||
rootfs.NewMountSubDevicesTask(),
|
||||
sysctls.NewSysctlsTask(),
|
||||
limits.NewFileLimitTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"configure Integrity Measurement Architecture",
|
||||
security.NewIMATask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"basic system configuration",
|
||||
rootfs.NewNetworkConfigurationTask(),
|
||||
rootfs.NewOSReleaseTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"discover network",
|
||||
network.NewInitialNetworkSetupTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"mount /boot",
|
||||
rootfs.NewMountSystemDisksTask(constants.BootPartitionLabel),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"config",
|
||||
configtask.NewConfigTask(&cfgBytes),
|
||||
),
|
||||
)
|
||||
|
||||
if err = phaserunner.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, err := config.NewFromBytes(cfgBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse config: %w", err)
|
||||
}
|
||||
|
||||
phaserunner, err = phase.NewRunner(cfg, runtime.Boot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
phaserunner.Add(
|
||||
phase.NewPhase(
|
||||
"config validation",
|
||||
rootfs.NewValidateConfigTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"network reset",
|
||||
network.NewResetNetworkTask(),
|
||||
configtask.NewExtraEnvVarsTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"initial network",
|
||||
network.NewInitialNetworkSetupTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"start containerd",
|
||||
services.NewStartContainerdTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"platform tasks",
|
||||
platform.NewPlatformTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"installation verification",
|
||||
rootfs.NewCheckInstallTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"overlay mounts",
|
||||
rootfs.NewMountOverlayTask(),
|
||||
rootfs.NewMountSharedTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"setup /var",
|
||||
rootfs.NewVarDirectoriesTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"save config",
|
||||
configtask.NewSaveConfigTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"mount extra disks",
|
||||
configtask.NewExtraDisksTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"user requests",
|
||||
configtask.NewExtraFilesTask(),
|
||||
configtask.NewSysctlsTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"start services",
|
||||
acpi.NewHandlerTask(),
|
||||
services.NewStartServicesTask(),
|
||||
signal.NewHandlerTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"post startup tasks",
|
||||
services.NewLabelNodeAsMasterTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"update bootloader",
|
||||
rootfs.NewSyslinuxTask(),
|
||||
),
|
||||
)
|
||||
|
||||
return phaserunner.Run()
|
||||
}
|
||||
|
||||
// Shutdown implements the Sequencer interface.
|
||||
func (d *Sequencer) Shutdown() (err error) {
|
||||
var dev *probe.ProbedBlockDevice
|
||||
|
||||
dev, err = probe.GetDevWithFileSystemLabel(constants.EphemeralPartitionLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
devname := dev.Device().Name()
|
||||
|
||||
if err = dev.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
phaserunner, err := phase.NewRunner(nil, runtime.Shutdown)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
phaserunner.Add(
|
||||
phase.NewPhase(
|
||||
"stop services",
|
||||
services.NewStopServicesTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"unmount system disk submounts",
|
||||
rootfs.NewUnmountOverlayTask(),
|
||||
rootfs.NewUnmountPodMountsTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"unmount system disks",
|
||||
rootfs.NewUnmountSystemDisksTask(constants.BootPartitionLabel),
|
||||
rootfs.NewUnmountSystemDisksTask(constants.EphemeralPartitionLabel),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"unmount system disk bind mounts",
|
||||
rootfs.NewUnmountSystemDiskBindMountsTask(devname),
|
||||
),
|
||||
)
|
||||
|
||||
return phaserunner.Run()
|
||||
}
|
||||
|
||||
// Upgrade implements the Sequencer interface.
|
||||
func (d *Sequencer) Upgrade(req *machineapi.UpgradeRequest) error {
|
||||
config, err := config.NewFromFile(constants.ConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
phaserunner, err := phase.NewRunner(config, runtime.Upgrade)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var dev *probe.ProbedBlockDevice
|
||||
|
||||
dev, err = probe.GetDevWithFileSystemLabel(constants.EphemeralPartitionLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
devname := dev.Device().Name()
|
||||
|
||||
// TODO(andrewrynhard): This should be more dynamic. If we ever change the
|
||||
// partition scheme there is the chance that 2 is not the correct parition to
|
||||
// check.
|
||||
partname := util.PartPath(dev.Device().Name(), 2)
|
||||
|
||||
if err := dev.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
phaserunner.Add(
|
||||
phase.NewPhase(
|
||||
"cordon and drain node",
|
||||
kubernetes.NewCordonAndDrainTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"handle control plane requirements",
|
||||
upgrade.NewLeaveEtcdTask(req.GetPreserve()),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"remove all pods",
|
||||
kubernetes.NewRemoveAllPodsTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"stop services",
|
||||
services.NewStopServicesTask("cri", "udevd"),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"unmount system disk submounts",
|
||||
rootfs.NewUnmountOverlayTask(),
|
||||
rootfs.NewUnmountPodMountsTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"unmount system disks",
|
||||
rootfs.NewUnmountSystemDisksTask(constants.BootPartitionLabel),
|
||||
rootfs.NewUnmountSystemDisksTask(constants.EphemeralPartitionLabel),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"unmount system disk bind mounts",
|
||||
rootfs.NewUnmountSystemDiskBindMountsTask(devname),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"verify system disk not in use",
|
||||
disk.NewVerifyDiskAvailabilityTask(partname),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"upgrade",
|
||||
upgrade.NewUpgradeTask(devname, req),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"stop all services",
|
||||
services.NewStopServicesTask(),
|
||||
),
|
||||
)
|
||||
|
||||
return phaserunner.Run()
|
||||
}
|
||||
|
||||
// Reset implements the Sequencer interface.
|
||||
func (d *Sequencer) Reset(req *machineapi.ResetRequest) error {
|
||||
config, err := config.NewFromFile(constants.ConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
phaserunner, err := phase.NewRunner(config, runtime.Reset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var dev *probe.ProbedBlockDevice
|
||||
|
||||
dev, err = probe.GetDevWithFileSystemLabel(constants.EphemeralPartitionLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
devname := dev.Device().Name()
|
||||
|
||||
if err := dev.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if req.GetGraceful() {
|
||||
phaserunner.Add(
|
||||
phase.NewPhase(
|
||||
"cordon and drain node",
|
||||
kubernetes.NewCordonAndDrainTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"handle control plane requirements",
|
||||
upgrade.NewLeaveEtcdTask(false),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"remove all pods",
|
||||
kubernetes.NewRemoveAllPodsTask(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
phaserunner.Add(
|
||||
phase.NewPhase(
|
||||
"stop all services",
|
||||
services.NewStopServicesTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"unmount system disk submounts",
|
||||
rootfs.NewUnmountOverlayTask(),
|
||||
rootfs.NewUnmountPodMountsTask(),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"unmount system disk",
|
||||
rootfs.NewUnmountSystemDisksTask(constants.EphemeralPartitionLabel),
|
||||
),
|
||||
phase.NewPhase(
|
||||
"reset system disk",
|
||||
disk.NewResetSystemDiskTask(devname),
|
||||
),
|
||||
)
|
||||
|
||||
return phaserunner.Run()
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package reg
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
@ -30,23 +30,20 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/talos-systems/talos/api/common"
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
|
||||
"github.com/talos-systems/talos/internal/pkg/containers"
|
||||
taloscontainerd "github.com/talos-systems/talos/internal/pkg/containers/containerd"
|
||||
"github.com/talos-systems/talos/internal/pkg/containers/cri"
|
||||
"github.com/talos-systems/talos/internal/pkg/containers/image"
|
||||
"github.com/talos-systems/talos/internal/pkg/etcd"
|
||||
"github.com/talos-systems/talos/internal/pkg/event"
|
||||
"github.com/talos-systems/talos/internal/pkg/kubeconfig"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime/platform"
|
||||
"github.com/talos-systems/talos/internal/pkg/tail"
|
||||
"github.com/talos-systems/talos/pkg/archiver"
|
||||
"github.com/talos-systems/talos/pkg/chunker"
|
||||
filechunker "github.com/talos-systems/talos/pkg/chunker/file"
|
||||
"github.com/talos-systems/talos/pkg/chunker/stream"
|
||||
machinecfg "github.com/talos-systems/talos/pkg/config/machine"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/version"
|
||||
)
|
||||
@ -54,65 +51,81 @@ import (
|
||||
// OSPathSeparator is the string version of the os.PathSeparator
|
||||
const OSPathSeparator = string(os.PathSeparator)
|
||||
|
||||
// Registrator is the concrete type that implements the factory.Registrator and
|
||||
// machineapi.Machine interfaces.
|
||||
type Registrator struct {
|
||||
config runtime.Configurator
|
||||
platform runtime.Platform
|
||||
}
|
||||
// Server implements the gRPC service server.
|
||||
type Server struct {
|
||||
Controller runtime.Controller
|
||||
|
||||
// NewRegistrator builds new Registrator instance
|
||||
func NewRegistrator(config runtime.Configurator) *Registrator {
|
||||
platform, err := platform.CurrentPlatform()
|
||||
if err != nil {
|
||||
// should never happen
|
||||
log.Printf("failed discovering platform: %v", err)
|
||||
}
|
||||
|
||||
return &Registrator{
|
||||
config: config,
|
||||
platform: platform,
|
||||
}
|
||||
server *grpc.Server
|
||||
}
|
||||
|
||||
// Register implements the factory.Registrator interface.
|
||||
func (r *Registrator) Register(s *grpc.Server) {
|
||||
machineapi.RegisterMachineServiceServer(s, r)
|
||||
func (s *Server) Register(obj *grpc.Server) {
|
||||
s.server = obj
|
||||
|
||||
machine.RegisterMachineServiceServer(obj, s)
|
||||
}
|
||||
|
||||
// Reboot implements the machineapi.MachineServer interface.
|
||||
func (r *Registrator) Reboot(ctx context.Context, in *empty.Empty) (reply *machineapi.RebootResponse, err error) {
|
||||
reply = &machineapi.RebootResponse{
|
||||
Messages: []*machineapi.Reboot{
|
||||
{},
|
||||
},
|
||||
}
|
||||
|
||||
// Reboot implements the machine.MachineServer interface.
|
||||
//
|
||||
// nolint: dupl
|
||||
func (s *Server) Reboot(ctx context.Context, in *empty.Empty) (reply *machine.RebootResponse, err error) {
|
||||
log.Printf("reboot via API received")
|
||||
event.Bus().Notify(event.Event{Type: event.Reboot})
|
||||
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
if err := s.Controller.Run(runtime.SequenceReboot, in); err != nil {
|
||||
log.Println("reboot failed:", err)
|
||||
|
||||
// Shutdown implements the machineapi.MachineServer interface.
|
||||
func (r *Registrator) Shutdown(ctx context.Context, in *empty.Empty) (reply *machineapi.ShutdownResponse, err error) {
|
||||
reply = &machineapi.ShutdownResponse{
|
||||
Messages: []*machineapi.Shutdown{
|
||||
if err != runtime.ErrLocked {
|
||||
// NB: Stopping the gRPC server will trigger machined's reboot mechanism.
|
||||
s.server.GracefulStop()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
reply = &machine.RebootResponse{
|
||||
Messages: []*machine.Reboot{
|
||||
{},
|
||||
},
|
||||
}
|
||||
|
||||
log.Printf("shutdown via API received")
|
||||
event.Bus().Notify(event.Event{Type: event.Shutdown})
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
return
|
||||
// Shutdown implements the machine.MachineServer interface.
|
||||
//
|
||||
// nolint: dupl
|
||||
func (s *Server) Shutdown(ctx context.Context, in *empty.Empty) (reply *machine.ShutdownResponse, err error) {
|
||||
log.Printf("shutdown via API received")
|
||||
|
||||
go func() {
|
||||
if err := s.Controller.Run(runtime.SequenceShutdown, in); err != nil {
|
||||
log.Println("shutdown failed:", err)
|
||||
|
||||
if err != runtime.ErrLocked {
|
||||
// NB: Stopping the gRPC server will trigger machined's reboot mechanism.
|
||||
s.server.GracefulStop()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
reply = &machine.ShutdownResponse{
|
||||
Messages: []*machine.Shutdown{
|
||||
{},
|
||||
},
|
||||
}
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
// Upgrade initiates an upgrade.
|
||||
func (r *Registrator) Upgrade(ctx context.Context, in *machineapi.UpgradeRequest) (data *machineapi.UpgradeResponse, err error) {
|
||||
//
|
||||
// nolint: dupl
|
||||
func (s *Server) Upgrade(ctx context.Context, in *machine.UpgradeRequest) (reply *machine.UpgradeResponse, err error) {
|
||||
log.Printf("upgrade request received")
|
||||
|
||||
log.Printf("validating %q", in.GetImage())
|
||||
|
||||
if err = pullAndValidateInstallerImage(ctx, r.config.Machine().Registries(), in.GetImage()); err != nil {
|
||||
if err = pullAndValidateInstallerImage(ctx, s.Controller.Runtime().Config().Machine().Registries(), in.GetImage()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -120,38 +133,62 @@ func (r *Registrator) Upgrade(ctx context.Context, in *machineapi.UpgradeRequest
|
||||
return nil, err
|
||||
}
|
||||
|
||||
event.Bus().Notify(event.Event{Type: event.Upgrade, Data: in})
|
||||
go func() {
|
||||
if err := s.Controller.Run(runtime.SequenceUpgrade, in); err != nil {
|
||||
log.Println("upgrade failed:", err)
|
||||
|
||||
data = &machineapi.UpgradeResponse{
|
||||
Messages: []*machineapi.Upgrade{
|
||||
if err != runtime.ErrLocked {
|
||||
// NB: Stopping the gRPC server will trigger machined's reboot mechanism.
|
||||
s.server.GracefulStop()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
reply = &machine.UpgradeResponse{
|
||||
Messages: []*machine.Upgrade{
|
||||
{
|
||||
Ack: "Upgrade request received",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return data, err
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
// Reset resets the node.
|
||||
func (r *Registrator) Reset(ctx context.Context, in *machineapi.ResetRequest) (data *machineapi.ResetResponse, err error) {
|
||||
event.Bus().Notify(event.Event{Type: event.Reset, Data: in})
|
||||
//
|
||||
// nolint: dupl
|
||||
func (s *Server) Reset(ctx context.Context, in *machine.ResetRequest) (reply *machine.ResetResponse, err error) {
|
||||
log.Printf("reset request received")
|
||||
|
||||
return &machineapi.ResetResponse{
|
||||
Messages: []*machineapi.Reset{
|
||||
go func() {
|
||||
if err := s.Controller.Run(runtime.SequenceReset, in); err != nil {
|
||||
log.Println("reset failed:", err)
|
||||
|
||||
if err != runtime.ErrLocked {
|
||||
// NB: Stopping the gRPC server will trigger machined's reboot mechanism.
|
||||
s.server.GracefulStop()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
reply = &machine.ResetResponse{
|
||||
Messages: []*machine.Reset{
|
||||
{},
|
||||
},
|
||||
}, err
|
||||
}
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
// ServiceList returns list of the registered services and their status
|
||||
func (r *Registrator) ServiceList(ctx context.Context, in *empty.Empty) (result *machineapi.ServiceListResponse, err error) {
|
||||
services := system.Services(r.config).List()
|
||||
func (s *Server) ServiceList(ctx context.Context, in *empty.Empty) (result *machine.ServiceListResponse, err error) {
|
||||
services := system.Services(s.Controller.Runtime()).List()
|
||||
|
||||
result = &machineapi.ServiceListResponse{
|
||||
Messages: []*machineapi.ServiceList{
|
||||
result = &machine.ServiceListResponse{
|
||||
Messages: []*machine.ServiceList{
|
||||
{
|
||||
Services: make([]*machineapi.ServiceInfo, len(services)),
|
||||
Services: make([]*machine.ServiceInfo, len(services)),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -163,15 +200,15 @@ func (r *Registrator) ServiceList(ctx context.Context, in *empty.Empty) (result
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ServiceStart implements the machineapi.MachineServer interface and starts a
|
||||
// ServiceStart implements the machine.MachineServer interface and starts a
|
||||
// service running on Talos.
|
||||
func (r *Registrator) ServiceStart(ctx context.Context, in *machineapi.ServiceStartRequest) (reply *machineapi.ServiceStartResponse, err error) {
|
||||
if err = system.Services(r.config).APIStart(ctx, in.Id); err != nil {
|
||||
return &machineapi.ServiceStartResponse{}, err
|
||||
func (s *Server) ServiceStart(ctx context.Context, in *machine.ServiceStartRequest) (reply *machine.ServiceStartResponse, err error) {
|
||||
if err = system.Services(s.Controller.Runtime()).APIStart(ctx, in.Id); err != nil {
|
||||
return &machine.ServiceStartResponse{}, err
|
||||
}
|
||||
|
||||
reply = &machineapi.ServiceStartResponse{
|
||||
Messages: []*machineapi.ServiceStart{
|
||||
reply = &machine.ServiceStartResponse{
|
||||
Messages: []*machine.ServiceStart{
|
||||
{
|
||||
Resp: fmt.Sprintf("Service %q started", in.Id),
|
||||
},
|
||||
@ -181,45 +218,15 @@ func (r *Registrator) ServiceStart(ctx context.Context, in *machineapi.ServiceSt
|
||||
return reply, err
|
||||
}
|
||||
|
||||
// Start implements deprecated Start method which forwards to 'ServiceStart'.
|
||||
//nolint: staticcheck
|
||||
func (r *Registrator) Start(ctx context.Context, in *machineapi.StartRequest) (reply *machineapi.StartResponse, err error) {
|
||||
var rep *machineapi.ServiceStartResponse
|
||||
|
||||
rep, err = r.ServiceStart(ctx, &machineapi.ServiceStartRequest{Id: in.Id})
|
||||
if rep != nil {
|
||||
reply = &machineapi.StartResponse{
|
||||
Resp: rep.Messages[0].Resp,
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Stop implements deprecated Stop method which forwards to 'ServiceStop'.
|
||||
//nolint: staticcheck
|
||||
func (r *Registrator) Stop(ctx context.Context, in *machineapi.StopRequest) (reply *machineapi.StopResponse, err error) {
|
||||
var rep *machineapi.ServiceStopResponse
|
||||
|
||||
rep, err = r.ServiceStop(ctx, &machineapi.ServiceStopRequest{Id: in.Id})
|
||||
if rep != nil {
|
||||
reply = &machineapi.StopResponse{
|
||||
Resp: rep.Messages[0].Resp,
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ServiceStop implements the machineapi.MachineServer interface and stops a
|
||||
// ServiceStop implements the machine.MachineServer interface and stops a
|
||||
// service running on Talos.
|
||||
func (r *Registrator) ServiceStop(ctx context.Context, in *machineapi.ServiceStopRequest) (reply *machineapi.ServiceStopResponse, err error) {
|
||||
if err = system.Services(r.config).APIStop(ctx, in.Id); err != nil {
|
||||
return &machineapi.ServiceStopResponse{}, err
|
||||
func (s *Server) ServiceStop(ctx context.Context, in *machine.ServiceStopRequest) (reply *machine.ServiceStopResponse, err error) {
|
||||
if err = system.Services(s.Controller.Runtime()).APIStop(ctx, in.Id); err != nil {
|
||||
return &machine.ServiceStopResponse{}, err
|
||||
}
|
||||
|
||||
reply = &machineapi.ServiceStopResponse{
|
||||
Messages: []*machineapi.ServiceStop{
|
||||
reply = &machine.ServiceStopResponse{
|
||||
Messages: []*machine.ServiceStop{
|
||||
{
|
||||
Resp: fmt.Sprintf("Service %q stopped", in.Id),
|
||||
},
|
||||
@ -229,15 +236,15 @@ func (r *Registrator) ServiceStop(ctx context.Context, in *machineapi.ServiceSto
|
||||
return reply, err
|
||||
}
|
||||
|
||||
// ServiceRestart implements the machineapi.MachineServer interface and stops a
|
||||
// ServiceRestart implements the machine.MachineServer interface and stops a
|
||||
// service running on Talos.
|
||||
func (r *Registrator) ServiceRestart(ctx context.Context, in *machineapi.ServiceRestartRequest) (reply *machineapi.ServiceRestartResponse, err error) {
|
||||
if err = system.Services(r.config).APIRestart(ctx, in.Id); err != nil {
|
||||
return &machineapi.ServiceRestartResponse{}, err
|
||||
func (s *Server) ServiceRestart(ctx context.Context, in *machine.ServiceRestartRequest) (reply *machine.ServiceRestartResponse, err error) {
|
||||
if err = system.Services(s.Controller.Runtime()).APIRestart(ctx, in.Id); err != nil {
|
||||
return &machine.ServiceRestartResponse{}, err
|
||||
}
|
||||
|
||||
reply = &machineapi.ServiceRestartResponse{
|
||||
Messages: []*machineapi.ServiceRestart{
|
||||
reply = &machine.ServiceRestartResponse{
|
||||
Messages: []*machine.ServiceRestart{
|
||||
{
|
||||
Resp: fmt.Sprintf("Service %q restarted", in.Id),
|
||||
},
|
||||
@ -247,8 +254,8 @@ func (r *Registrator) ServiceRestart(ctx context.Context, in *machineapi.Service
|
||||
return reply, err
|
||||
}
|
||||
|
||||
// Copy implements the machineapi.MachineServer interface and copies data out of Talos node
|
||||
func (r *Registrator) Copy(req *machineapi.CopyRequest, s machineapi.MachineService_CopyServer) error {
|
||||
// Copy implements the machine.MachineServer interface and copies data out of Talos node
|
||||
func (s *Server) Copy(req *machine.CopyRequest, obj machine.MachineService_CopyServer) error {
|
||||
path := req.RootPath
|
||||
path = filepath.Clean(path)
|
||||
|
||||
@ -260,7 +267,7 @@ func (r *Registrator) Copy(req *machineapi.CopyRequest, s machineapi.MachineServ
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
|
||||
ctx, ctxCancel := context.WithCancel(s.Context())
|
||||
ctx, ctxCancel := context.WithCancel(obj.Context())
|
||||
defer ctxCancel()
|
||||
|
||||
go func() {
|
||||
@ -273,7 +280,7 @@ func (r *Registrator) Copy(req *machineapi.CopyRequest, s machineapi.MachineServ
|
||||
chunkCh := chunker.Read(ctx)
|
||||
|
||||
for data := range chunkCh {
|
||||
err := s.SendMsg(&common.Data{Bytes: data})
|
||||
err := obj.SendMsg(&common.Data{Bytes: data})
|
||||
if err != nil {
|
||||
ctxCancel()
|
||||
}
|
||||
@ -281,7 +288,7 @@ func (r *Registrator) Copy(req *machineapi.CopyRequest, s machineapi.MachineServ
|
||||
|
||||
archiveErr := <-errCh
|
||||
if archiveErr != nil {
|
||||
return s.SendMsg(&common.Data{
|
||||
return obj.SendMsg(&common.Data{
|
||||
Metadata: &common.Metadata{
|
||||
Error: archiveErr.Error(),
|
||||
},
|
||||
@ -291,10 +298,10 @@ func (r *Registrator) Copy(req *machineapi.CopyRequest, s machineapi.MachineServ
|
||||
return nil
|
||||
}
|
||||
|
||||
// List implements the machineapi.MachineServer interface.
|
||||
func (r *Registrator) List(req *machineapi.ListRequest, s machineapi.MachineService_ListServer) error {
|
||||
// List implements the machine.MachineServer interface.
|
||||
func (s *Server) List(req *machine.ListRequest, obj machine.MachineService_ListServer) error {
|
||||
if req == nil {
|
||||
req = new(machineapi.ListRequest)
|
||||
req = new(machine.ListRequest)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(req.Root, OSPathSeparator) {
|
||||
@ -317,20 +324,20 @@ func (r *Registrator) List(req *machineapi.ListRequest, s machineapi.MachineServ
|
||||
}
|
||||
}
|
||||
|
||||
files, err := archiver.Walker(s.Context(), req.Root, archiver.WithMaxRecurseDepth(maxDepth))
|
||||
files, err := archiver.Walker(obj.Context(), req.Root, archiver.WithMaxRecurseDepth(maxDepth))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for fi := range files {
|
||||
if fi.Error != nil {
|
||||
err = s.Send(&machineapi.FileInfo{
|
||||
err = obj.Send(&machine.FileInfo{
|
||||
Name: fi.FullPath,
|
||||
RelativeName: fi.RelPath,
|
||||
Error: fi.Error.Error(),
|
||||
})
|
||||
} else {
|
||||
err = s.Send(&machineapi.FileInfo{
|
||||
err = obj.Send(&machine.FileInfo{
|
||||
Name: fi.FullPath,
|
||||
RelativeName: fi.RelPath,
|
||||
Size: fi.FileInfo.Size(),
|
||||
@ -349,8 +356,8 @@ func (r *Registrator) List(req *machineapi.ListRequest, s machineapi.MachineServ
|
||||
return nil
|
||||
}
|
||||
|
||||
// Mounts implements the machineapi.OSDServer interface.
|
||||
func (r *Registrator) Mounts(ctx context.Context, in *empty.Empty) (reply *machineapi.MountsResponse, err error) {
|
||||
// Mounts implements the machine.OSDServer interface.
|
||||
func (s *Server) Mounts(ctx context.Context, in *empty.Empty) (reply *machine.MountsResponse, err error) {
|
||||
file, err := os.Open("/proc/mounts")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -363,7 +370,7 @@ func (r *Registrator) Mounts(ctx context.Context, in *empty.Empty) (reply *machi
|
||||
multiErr *multierror.Error
|
||||
)
|
||||
|
||||
stats := []*machineapi.MountStat{}
|
||||
stats := []*machine.MountStat{}
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
for scanner.Scan() {
|
||||
@ -394,7 +401,7 @@ func (r *Registrator) Mounts(ctx context.Context, in *empty.Empty) (reply *machi
|
||||
totalSize := uint64(stat.Bsize) * stat.Blocks
|
||||
totalAvail := uint64(stat.Bsize) * stat.Bavail
|
||||
|
||||
stat := &machineapi.MountStat{
|
||||
stat := &machine.MountStat{
|
||||
Filesystem: filesystem,
|
||||
Size: totalSize,
|
||||
Available: totalAvail,
|
||||
@ -408,8 +415,8 @@ func (r *Registrator) Mounts(ctx context.Context, in *empty.Empty) (reply *machi
|
||||
multiErr = multierror.Append(multiErr, err)
|
||||
}
|
||||
|
||||
reply = &machineapi.MountsResponse{
|
||||
Messages: []*machineapi.Mounts{
|
||||
reply = &machine.MountsResponse{
|
||||
Messages: []*machine.Mounts{
|
||||
{
|
||||
Stats: stats,
|
||||
},
|
||||
@ -419,19 +426,19 @@ func (r *Registrator) Mounts(ctx context.Context, in *empty.Empty) (reply *machi
|
||||
return reply, multiErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
// Version implements the machineapi.MachineServer interface.
|
||||
func (r *Registrator) Version(ctx context.Context, in *empty.Empty) (reply *machineapi.VersionResponse, err error) {
|
||||
var platform *machineapi.PlatformInfo
|
||||
// Version implements the machine.MachineServer interface.
|
||||
func (s *Server) Version(ctx context.Context, in *empty.Empty) (reply *machine.VersionResponse, err error) {
|
||||
var platform *machine.PlatformInfo
|
||||
|
||||
if r.platform != nil {
|
||||
platform = &machineapi.PlatformInfo{
|
||||
Name: r.platform.Name(),
|
||||
Mode: r.platform.Mode().String(),
|
||||
if s.Controller.Runtime().State().Platform() != nil {
|
||||
platform = &machine.PlatformInfo{
|
||||
Name: s.Controller.Runtime().State().Platform().Name(),
|
||||
Mode: s.Controller.Runtime().State().Platform().Mode().String(),
|
||||
}
|
||||
}
|
||||
|
||||
return &machineapi.VersionResponse{
|
||||
Messages: []*machineapi.Version{
|
||||
return &machine.VersionResponse{
|
||||
Messages: []*machine.Version{
|
||||
{
|
||||
Version: version.NewVersion(),
|
||||
Platform: platform,
|
||||
@ -441,10 +448,10 @@ func (r *Registrator) Version(ctx context.Context, in *empty.Empty) (reply *mach
|
||||
}
|
||||
|
||||
// Kubeconfig implements the osapi.OSDServer interface.
|
||||
func (r *Registrator) Kubeconfig(empty *empty.Empty, s machineapi.MachineService_KubeconfigServer) error {
|
||||
var kubeconfigBuf bytes.Buffer
|
||||
func (s *Server) Kubeconfig(empty *empty.Empty, obj machine.MachineService_KubeconfigServer) error {
|
||||
var b bytes.Buffer
|
||||
|
||||
if err := kubeconfig.GenerateAdmin(r.config.Cluster(), &kubeconfigBuf); err != nil {
|
||||
if err := kubeconfig.GenerateAdmin(s.Controller.Runtime().Config().Cluster(), &b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -458,7 +465,7 @@ func (r *Registrator) Kubeconfig(empty *empty.Empty, s machineapi.MachineService
|
||||
err := tarW.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeReg,
|
||||
Name: "kubeconfig",
|
||||
Size: int64(kubeconfigBuf.Len()),
|
||||
Size: int64(b.Len()),
|
||||
ModTime: time.Now(),
|
||||
Mode: 0600,
|
||||
})
|
||||
@ -466,7 +473,7 @@ func (r *Registrator) Kubeconfig(empty *empty.Empty, s machineapi.MachineService
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(tarW, &kubeconfigBuf)
|
||||
_, err = io.Copy(tarW, &b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -475,7 +482,7 @@ func (r *Registrator) Kubeconfig(empty *empty.Empty, s machineapi.MachineService
|
||||
return err
|
||||
}
|
||||
|
||||
return s.Send(&common.Data{
|
||||
return obj.Send(&common.Data{
|
||||
Bytes: buf.Bytes(),
|
||||
})
|
||||
}
|
||||
@ -483,7 +490,7 @@ func (r *Registrator) Kubeconfig(empty *empty.Empty, s machineapi.MachineService
|
||||
// Logs provides a service or container logs can be requested and the contents of the
|
||||
// log file are streamed in chunks.
|
||||
// nolint: gocyclo
|
||||
func (r *Registrator) Logs(req *machineapi.LogsRequest, l machineapi.MachineService_LogsServer) (err error) {
|
||||
func (s *Server) Logs(req *machine.LogsRequest, l machine.MachineService_LogsServer) (err error) {
|
||||
var chunk chunker.Chunker
|
||||
|
||||
switch {
|
||||
@ -531,7 +538,7 @@ func (r *Registrator) Logs(req *machineapi.LogsRequest, l machineapi.MachineServ
|
||||
return nil
|
||||
}
|
||||
|
||||
func k8slogs(ctx context.Context, req *machineapi.LogsRequest) (chunker.Chunker, io.Closer, error) {
|
||||
func k8slogs(ctx context.Context, req *machine.LogsRequest) (chunker.Chunker, io.Closer, error) {
|
||||
inspector, err := getContainerInspector(ctx, req.Namespace, req.Driver)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -572,7 +579,7 @@ func getContainerInspector(ctx context.Context, namespace string, driver common.
|
||||
}
|
||||
|
||||
// Read implements the read API.
|
||||
func (r *Registrator) Read(in *machineapi.ReadRequest, srv machineapi.MachineService_ReadServer) (err error) {
|
||||
func (s *Server) Read(in *machine.ReadRequest, srv machine.MachineService_ReadServer) (err error) {
|
||||
stat, err := os.Stat(in.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -606,7 +613,7 @@ func (r *Registrator) Read(in *machineapi.ReadRequest, srv machineapi.MachineSer
|
||||
}
|
||||
}
|
||||
|
||||
func pullAndValidateInstallerImage(ctx context.Context, config machinecfg.Registries, ref string) error {
|
||||
func pullAndValidateInstallerImage(ctx context.Context, reg runtime.Registries, ref string) error {
|
||||
// Pull down specified installer image early so we can bail if it doesn't exist in the upstream registry
|
||||
containerdctx := namespaces.WithNamespace(ctx, constants.SystemContainerdNamespace)
|
||||
|
||||
@ -615,7 +622,7 @@ func pullAndValidateInstallerImage(ctx context.Context, config machinecfg.Regist
|
||||
return err
|
||||
}
|
||||
|
||||
img, err := image.Pull(containerdctx, config, client, ref)
|
||||
img, err := image.Pull(containerdctx, reg, client, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
@ -6,87 +6,35 @@ package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http/httpproxy"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
machineapi "github.com/talos-systems/talos/api/machine"
|
||||
"github.com/talos-systems/talos/cmd/installer/pkg/bootloader/syslinux"
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/sequencer"
|
||||
"github.com/talos-systems/talos/internal/pkg/event"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
|
||||
v1alpha1server "github.com/talos-systems/talos/internal/app/machined/internal/server/v1alpha1"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
v1alpha1runtime "github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/syslinux"
|
||||
"github.com/talos-systems/talos/pkg/constants"
|
||||
"github.com/talos-systems/talos/pkg/grpc/factory"
|
||||
"github.com/talos-systems/talos/pkg/proc/reaper"
|
||||
"github.com/talos-systems/talos/pkg/startup"
|
||||
)
|
||||
|
||||
// EventBusObserver is used to subscribe to the event bus.
|
||||
type EventBusObserver struct {
|
||||
*event.Embeddable
|
||||
}
|
||||
|
||||
func recovery() {
|
||||
if r := recover(); r != nil {
|
||||
log.Printf("recovered from: %+v\n", r)
|
||||
|
||||
if err := revert(); err != nil {
|
||||
log.Printf("failed to revert upgrade: %v", err)
|
||||
}
|
||||
|
||||
for i := 10; i >= 0; i-- {
|
||||
log.Printf("rebooting in %d seconds\n", i)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
if unix.Reboot(unix.LINUX_REBOOT_CMD_RESTART) == nil {
|
||||
select {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See http://man7.org/linux/man-pages/man2/reboot.2.html.
|
||||
func sync() {
|
||||
syncdone := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
defer close(syncdone)
|
||||
unix.Sync()
|
||||
}()
|
||||
|
||||
log.Printf("waiting for sync...")
|
||||
|
||||
for i := 29; i >= 0; i-- {
|
||||
select {
|
||||
case <-syncdone:
|
||||
log.Printf("sync done")
|
||||
return
|
||||
case <-time.After(time.Second):
|
||||
}
|
||||
|
||||
if i != 0 {
|
||||
log.Printf("waiting %d more seconds for sync to finish", i)
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("sync hasn't completed in time, aborting...")
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Explicitly set the default http client transport
|
||||
// to work around our fun proxy.Do once bug.
|
||||
// This is the http.DefaultTransport with the Proxy
|
||||
// func overridden so that the environment variables
|
||||
// with be reread/initialized each time the http call
|
||||
// is made.
|
||||
// Explicitly set the default http client transport to work around proxy.Do
|
||||
// once. This is the http.DefaultTransport with the Proxy func overridden so
|
||||
// that the environment variables with be reread/initialized each time the
|
||||
// http call is made.
|
||||
http.DefaultClient.Transport = &http.Transport{
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return httpproxy.FromEnvironment().ProxyFunc()(req.URL)
|
||||
@ -104,193 +52,112 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func revert() (err error) {
|
||||
f, err := os.OpenFile(syslinux.SyslinuxLdlinux, os.O_RDWR, 0700)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
func recovery() {
|
||||
if r := recover(); r != nil {
|
||||
var (
|
||||
err error
|
||||
ok bool
|
||||
)
|
||||
|
||||
err, ok = r.(error)
|
||||
if ok {
|
||||
handle(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
defer f.Close()
|
||||
|
||||
adv, err := syslinux.NewADV(f)
|
||||
func handle(err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
label, ok := adv.ReadTag(syslinux.AdvUpgrade)
|
||||
if !ok {
|
||||
return nil
|
||||
if err := syslinux.Revert(); err != nil {
|
||||
log.Printf("failed to revert upgrade: %v", err)
|
||||
}
|
||||
|
||||
if label == "" {
|
||||
adv.DeleteTag(syslinux.AdvUpgrade)
|
||||
if p := procfs.ProcCmdline().Get(constants.KernelParamPanic).First(); p != nil {
|
||||
if *p == "0" {
|
||||
log.Printf("panic=0 kernel flag found, sleeping forever")
|
||||
|
||||
if _, err = f.Write(adv); err != nil {
|
||||
return err
|
||||
exitSignal := make(chan os.Signal, 1)
|
||||
|
||||
signal.Notify(exitSignal, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
<-exitSignal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf("reverting default boot to %q", label)
|
||||
|
||||
var b []byte
|
||||
|
||||
if b, err = ioutil.ReadFile(syslinux.SyslinuxConfig); err != nil {
|
||||
return err
|
||||
for i := 10; i >= 0; i-- {
|
||||
log.Printf("rebooting in %d seconds\n", i)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
re := regexp.MustCompile(`^DEFAULT\s(.*)`)
|
||||
matches := re.FindSubmatch(b)
|
||||
v1alpha1runtime.SyncNonVolatileStorageBuffers()
|
||||
|
||||
if len(matches) != 2 {
|
||||
return fmt.Errorf("expected 2 matches, got %d", len(matches))
|
||||
if unix.Reboot(unix.LINUX_REBOOT_CMD_RESTART) == nil {
|
||||
// Wait forever.
|
||||
select {}
|
||||
}
|
||||
|
||||
b = re.ReplaceAll(b, []byte(fmt.Sprintf("DEFAULT %s", label)))
|
||||
|
||||
if err = ioutil.WriteFile(syslinux.SyslinuxConfig, b, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
adv.DeleteTag(syslinux.AdvUpgrade)
|
||||
|
||||
if _, err = f.Write(adv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
// This is main entrypoint into machined execution, control is passed here
|
||||
// from init after switch root.
|
||||
//
|
||||
// When machined terminates either on normal shutdown (reboot, poweroff), or
|
||||
// due to panic, control goes through recovery() and reboot() functions
|
||||
// below, which finalize node state - sync buffers, initiate poweroff or
|
||||
// reboot. Also on shutdown, other deferred function are called, for example
|
||||
// services are gracefully shutdown.
|
||||
|
||||
// On any return from init.main(), initiate host reboot or shutdown handle
|
||||
// any panics in the main goroutine, and proceed to reboot() above
|
||||
// Setup panic handler.
|
||||
defer recovery()
|
||||
|
||||
// Subscribe to events.
|
||||
init := EventBusObserver{&event.Embeddable{}}
|
||||
defer close(init.Channel())
|
||||
|
||||
event.Bus().Register(init)
|
||||
|
||||
defer event.Bus().Unregister(init)
|
||||
|
||||
// Initialize process reaper.
|
||||
// Initialize the process reaper.
|
||||
reaper.Run()
|
||||
defer reaper.Shutdown()
|
||||
|
||||
// Ensure rng is seeded.
|
||||
if err = startup.RandSeed(); err != nil {
|
||||
panic(err)
|
||||
if err := startup.RandSeed(); err != nil {
|
||||
handle(err)
|
||||
}
|
||||
|
||||
// Set the PATH env var.
|
||||
if err = os.Setenv("PATH", constants.PATH); err != nil {
|
||||
panic(errors.New("error setting PATH"))
|
||||
if err := os.Setenv("PATH", constants.PATH); err != nil {
|
||||
handle(errors.New("error setting PATH"))
|
||||
}
|
||||
|
||||
immediateReboot := false
|
||||
// Initialize the controller without a config.
|
||||
c, err := v1alpha1runtime.NewController(nil)
|
||||
if err != nil {
|
||||
handle(err)
|
||||
}
|
||||
|
||||
// Initialize the machine.
|
||||
if err = c.Run(runtime.SequenceInitialize, nil); err != nil {
|
||||
handle(err)
|
||||
}
|
||||
|
||||
// Start event listeners.
|
||||
go func() {
|
||||
if e := c.ListenForEvents(); e != nil {
|
||||
log.Printf("WARNING: signals and ACPI events will be ignored: %+v", e)
|
||||
}
|
||||
}()
|
||||
|
||||
// Start the API server.
|
||||
go func() {
|
||||
server := &v1alpha1server.Server{
|
||||
Controller: c,
|
||||
}
|
||||
|
||||
e := factory.ListenAndServe(server, factory.Network("unix"), factory.SocketPath(constants.MachineSocketPath))
|
||||
|
||||
handle(e)
|
||||
}()
|
||||
|
||||
// Perform an installation if required.
|
||||
if err = c.Run(runtime.SequenceInstall, nil); err != nil {
|
||||
handle(err)
|
||||
}
|
||||
|
||||
// Boot the machine.
|
||||
seq := sequencer.New(sequencer.V1Alpha1)
|
||||
|
||||
if err := seq.Boot(); err != nil {
|
||||
if errors.Is(err, runtime.ErrReboot) {
|
||||
immediateReboot = true
|
||||
} else {
|
||||
log.Println(err)
|
||||
panic(fmt.Errorf("boot failed: %w", err))
|
||||
}
|
||||
if err = c.Run(runtime.SequenceBoot, nil); err != nil {
|
||||
handle(err)
|
||||
}
|
||||
|
||||
// Wait for an event.
|
||||
|
||||
flag := unix.LINUX_REBOOT_CMD_RESTART
|
||||
|
||||
runShutdownOnImmediateReboot := true
|
||||
|
||||
for !immediateReboot {
|
||||
switch e := <-init.Channel(); e.Type {
|
||||
case event.Shutdown:
|
||||
flag = unix.LINUX_REBOOT_CMD_POWER_OFF
|
||||
fallthrough
|
||||
case event.Reboot:
|
||||
immediateReboot = true
|
||||
case event.Upgrade:
|
||||
var (
|
||||
req *machineapi.UpgradeRequest
|
||||
ok bool
|
||||
)
|
||||
|
||||
if req, ok = e.Data.(*machineapi.UpgradeRequest); !ok {
|
||||
log.Println("cannot perform upgrade, unexpected data type")
|
||||
continue
|
||||
}
|
||||
|
||||
if err := seq.Upgrade(req); err != nil {
|
||||
log.Println(err)
|
||||
panic(fmt.Errorf("upgrade failed: %w", err))
|
||||
}
|
||||
|
||||
immediateReboot = true
|
||||
runShutdownOnImmediateReboot = false
|
||||
case event.Reset:
|
||||
var (
|
||||
req *machineapi.ResetRequest
|
||||
ok bool
|
||||
)
|
||||
|
||||
if req, ok = e.Data.(*machineapi.ResetRequest); !ok {
|
||||
log.Println("cannot perform reset, unexpected data type")
|
||||
continue
|
||||
}
|
||||
|
||||
if err := seq.Reset(req); err != nil {
|
||||
log.Println(err)
|
||||
panic(fmt.Errorf("reset failed: %w", err))
|
||||
}
|
||||
|
||||
if !req.GetReboot() {
|
||||
flag = unix.LINUX_REBOOT_CMD_POWER_OFF
|
||||
}
|
||||
|
||||
immediateReboot = true
|
||||
}
|
||||
}
|
||||
|
||||
if runShutdownOnImmediateReboot {
|
||||
if err := seq.Shutdown(); err != nil {
|
||||
log.Println(err)
|
||||
panic(fmt.Errorf("shutdown failed: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
sync()
|
||||
|
||||
if err := unix.Reboot(flag); err != nil {
|
||||
log.Println(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Prevent a kernel panic.
|
||||
|
||||
// Wait forever.
|
||||
select {}
|
||||
}
|
||||
|
@ -2,62 +2,105 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package machine
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
stdx509 "crypto/x509"
|
||||
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
|
||||
"github.com/talos-systems/talos/pkg/blockdevice/probe"
|
||||
"github.com/talos-systems/talos/pkg/client/config"
|
||||
"github.com/talos-systems/talos/pkg/crypto/x509"
|
||||
)
|
||||
|
||||
// Type represents a machine type.
|
||||
type Type int
|
||||
// Configurator defines the configuration interface.
|
||||
type Configurator interface {
|
||||
Version() string
|
||||
Debug() bool
|
||||
Persist() bool
|
||||
Machine() MachineConfig
|
||||
Cluster() ClusterConfig
|
||||
Validate(Mode) error
|
||||
String() (string, error)
|
||||
Bytes() ([]byte, error)
|
||||
}
|
||||
|
||||
// ConfiguratorBundle defines the configuration bundle interface.
|
||||
type ConfiguratorBundle interface {
|
||||
Init() Configurator
|
||||
ControlPlane() Configurator
|
||||
Join() Configurator
|
||||
TalosConfig() *config.Config
|
||||
}
|
||||
|
||||
// Machine defines the runtime parameters.
|
||||
type Machine interface {
|
||||
State() MachineState
|
||||
Config() MachineConfig
|
||||
}
|
||||
|
||||
// MachineState defines the machined state.
|
||||
type MachineState interface {
|
||||
Disk() *probe.ProbedBlockDevice
|
||||
Close() error
|
||||
Installed() bool
|
||||
}
|
||||
|
||||
// MachineType represents a machine type.
|
||||
type MachineType int
|
||||
|
||||
const (
|
||||
// TypeInit represents an init node.
|
||||
TypeInit Type = iota
|
||||
// TypeControlPlane represents a control plane node.
|
||||
TypeControlPlane
|
||||
// TypeWorker represents a worker node.
|
||||
TypeWorker
|
||||
// MachineTypeInit represents a bootstrap node.
|
||||
MachineTypeInit MachineType = iota
|
||||
// MachineTypeControlPlane represents a control plane node.
|
||||
MachineTypeControlPlane
|
||||
// MachineTypeJoin represents a worker node.
|
||||
MachineTypeJoin
|
||||
)
|
||||
|
||||
const (
|
||||
machineTypeInit = "init"
|
||||
machineTypeControlPlane = "controlplane"
|
||||
machineTypeJoin = "join"
|
||||
)
|
||||
|
||||
// String returns the string representation of Type.
|
||||
func (t Type) String() string {
|
||||
return [...]string{"Init", "ControlPlane", "Join"}[t]
|
||||
func (t MachineType) String() string {
|
||||
return [...]string{machineTypeInit, machineTypeControlPlane, machineTypeJoin}[t]
|
||||
}
|
||||
|
||||
// ParseType parses string constant as Type
|
||||
func ParseType(t string) (Type, error) {
|
||||
// ParseMachineType parses string constant as Type
|
||||
func ParseMachineType(t string) (MachineType, error) {
|
||||
switch t {
|
||||
case "Init":
|
||||
return TypeInit, nil
|
||||
case "ControlPlane":
|
||||
return TypeControlPlane, nil
|
||||
case "Join":
|
||||
return TypeWorker, nil
|
||||
case machineTypeInit:
|
||||
return MachineTypeInit, nil
|
||||
case machineTypeControlPlane:
|
||||
return MachineTypeControlPlane, nil
|
||||
case machineTypeJoin:
|
||||
return MachineTypeJoin, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown type %q", t)
|
||||
return 0, fmt.Errorf("unknown machine type: %q", t)
|
||||
}
|
||||
}
|
||||
|
||||
// Machine defines the requirements for a config that pertains to machine
|
||||
// MachineConfig defines the requirements for a config that pertains to machine
|
||||
// related options.
|
||||
type Machine interface {
|
||||
type MachineConfig interface {
|
||||
Install() Install
|
||||
Security() Security
|
||||
Network() Network
|
||||
Network() MachineNetwork
|
||||
Disks() []Disk
|
||||
Time() Time
|
||||
Env() Env
|
||||
Files() ([]File, error)
|
||||
Type() Type
|
||||
Type() MachineType
|
||||
Kubelet() Kubelet
|
||||
Sysctls() map[string]string
|
||||
Registries() Registries
|
||||
@ -83,9 +126,9 @@ type Security interface {
|
||||
SetCertSANs([]string)
|
||||
}
|
||||
|
||||
// Network defines the requirements for a config that pertains to network
|
||||
// MachineNetwork defines the requirements for a config that pertains to network
|
||||
// related options.
|
||||
type Network interface {
|
||||
type MachineNetwork interface {
|
||||
Hostname() string
|
||||
SetHostname(string)
|
||||
Resolvers() []string
|
||||
@ -284,3 +327,96 @@ type Registries interface {
|
||||
// ExtraFiles generates TOML config for containerd CRI plugin.
|
||||
ExtraFiles() ([]File, error)
|
||||
}
|
||||
|
||||
// ClusterState defines the cluster state.
|
||||
type ClusterState interface{}
|
||||
|
||||
// ClusterConfig defines the requirements for a config that pertains to cluster
|
||||
// related options.
|
||||
type ClusterConfig interface {
|
||||
Name() string
|
||||
APIServer() APIServer
|
||||
ControllerManager() ControllerManager
|
||||
Scheduler() Scheduler
|
||||
Endpoint() *url.URL
|
||||
Token() Token
|
||||
CertSANs() []string
|
||||
SetCertSANs([]string)
|
||||
CA() *x509.PEMEncodedCertificateAndKey
|
||||
AESCBCEncryptionSecret() string
|
||||
Config(MachineType) (string, error)
|
||||
Etcd() Etcd
|
||||
Network() ClusterNetwork
|
||||
LocalAPIServerPort() int
|
||||
PodCheckpointer() PodCheckpointer
|
||||
CoreDNS() CoreDNS
|
||||
ExtraManifestURLs() []string
|
||||
ExtraManifestHeaderMap() map[string]string
|
||||
AdminKubeconfig() AdminKubeconfig
|
||||
}
|
||||
|
||||
// ClusterNetwork defines the requirements for a config that pertains to cluster
|
||||
// network options.
|
||||
type ClusterNetwork interface {
|
||||
CNI() CNI
|
||||
PodCIDR() string
|
||||
ServiceCIDR() string
|
||||
DNSDomain() string
|
||||
}
|
||||
|
||||
// CNI defines the requirements for a config that pertains to Kubernetes
|
||||
// cni.
|
||||
type CNI interface {
|
||||
Name() string
|
||||
URLs() []string
|
||||
}
|
||||
|
||||
// APIServer defines the requirements for a config that pertains to apiserver related
|
||||
// options.
|
||||
type APIServer interface {
|
||||
ExtraArgs() map[string]string
|
||||
}
|
||||
|
||||
// ControllerManager defines the requirements for a config that pertains to controller manager related
|
||||
// options.
|
||||
type ControllerManager interface {
|
||||
ExtraArgs() map[string]string
|
||||
}
|
||||
|
||||
// Scheduler defines the requirements for a config that pertains to scheduler related
|
||||
// options.
|
||||
type Scheduler interface {
|
||||
ExtraArgs() map[string]string
|
||||
}
|
||||
|
||||
// Etcd defines the requirements for a config that pertains to etcd related
|
||||
// options.
|
||||
type Etcd interface {
|
||||
Image() string
|
||||
CA() *x509.PEMEncodedCertificateAndKey
|
||||
ExtraArgs() map[string]string
|
||||
}
|
||||
|
||||
// Token defines the requirements for a config that pertains to Kubernetes
|
||||
// bootstrap token.
|
||||
type Token interface {
|
||||
ID() string
|
||||
Secret() string
|
||||
}
|
||||
|
||||
// PodCheckpointer defines the requirements for a config that pertains to bootkube
|
||||
// pod-checkpointer options.
|
||||
type PodCheckpointer interface {
|
||||
Image() string
|
||||
}
|
||||
|
||||
// CoreDNS defines the requirements for a config that pertains to bootkube
|
||||
// coredns options.
|
||||
type CoreDNS interface {
|
||||
Image() string
|
||||
}
|
||||
|
||||
// AdminKubeconfig defines settings for admin kubeconfig.
|
||||
type AdminKubeconfig interface {
|
||||
CertLifetime() time.Duration
|
||||
}
|
94
internal/app/machined/pkg/runtime/configurator_test.go
Normal file
94
internal/app/machined/pkg/runtime/configurator_test.go
Normal file
@ -0,0 +1,94 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// nolint: dupl,scopelint
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMachineType_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
t MachineType
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "init",
|
||||
t: MachineTypeInit,
|
||||
want: "init",
|
||||
},
|
||||
{
|
||||
name: "controlplane",
|
||||
t: MachineTypeControlPlane,
|
||||
want: "controlplane",
|
||||
},
|
||||
{
|
||||
name: "join",
|
||||
t: MachineTypeJoin,
|
||||
want: "join",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.t.String(); got != tt.want {
|
||||
t.Errorf("MachineType.String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMachineType(t *testing.T) {
|
||||
type args struct {
|
||||
t string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want MachineType
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "init",
|
||||
args: args{"init"},
|
||||
want: MachineTypeInit,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "controlplane",
|
||||
args: args{"controlplane"},
|
||||
want: MachineTypeControlPlane,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "join",
|
||||
args: args{"join"},
|
||||
want: MachineTypeJoin,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid",
|
||||
args: args{"invalid"},
|
||||
want: 0,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ParseMachineType(tt.args.t)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ParseMachineType() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ParseMachineType() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
29
internal/app/machined/pkg/runtime/controller.go
Normal file
29
internal/app/machined/pkg/runtime/controller.go
Normal file
@ -0,0 +1,29 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
)
|
||||
|
||||
// TaskSetupFunc defines the function that a task will execute for a specific runtime
|
||||
// mode.
|
||||
type TaskSetupFunc func(seq Sequence, data interface{}) TaskExecutionFunc
|
||||
|
||||
// TaskExecutionFunc defines the function that a task will execute for a specific runtime
|
||||
// mode.
|
||||
type TaskExecutionFunc func(context.Context, *log.Logger, Runtime) error
|
||||
|
||||
// Phase represents a collection of tasks to be performed concurrently.
|
||||
type Phase []TaskSetupFunc
|
||||
|
||||
// Controller represents the controller responsible for managing the execution
|
||||
// of sequences.
|
||||
type Controller interface {
|
||||
Runtime() Runtime
|
||||
Sequencer() Sequencer
|
||||
Run(Sequence, interface{}) error
|
||||
}
|
680
internal/app/machined/pkg/runtime/controller_test.go
Normal file
680
internal/app/machined/pkg/runtime/controller_test.go
Normal file
@ -0,0 +1,680 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// nolint: scopelint,dupl
|
||||
package runtime
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "net"
|
||||
// "testing"
|
||||
|
||||
// "github.com/talos-systems/go-procfs/procfs"
|
||||
|
||||
// "github.com/talos-systems/talos/api/machine"
|
||||
// )
|
||||
|
||||
// type MockSuccessfulSequencer struct{}
|
||||
|
||||
// // Boot is a mock method that overrides the embedded sequencer's Boot method.
|
||||
// func (s *MockSuccessfulSequencer) Boot() []Phase {
|
||||
// return []Phase{
|
||||
// &MockSuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Initialize is a mock method that overrides the embedded sequencer's Initialize method.
|
||||
// func (s *MockSuccessfulSequencer) Initialize() []Phase {
|
||||
// return []Phase{
|
||||
// &MockSuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Shutdown is a mock method that overrides the embedded sequencer's Shutdown method.
|
||||
// func (s *MockSuccessfulSequencer) Shutdown() []Phase {
|
||||
// return []Phase{
|
||||
// &MockSuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Upgrade is a mock method that overrides the embedded sequencer's Upgrade method.
|
||||
// func (s *MockSuccessfulSequencer) Upgrade(req *machine.UpgradeRequest) []Phase {
|
||||
// return []Phase{
|
||||
// &MockSuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Reboot is a mock method that overrides the embedded sequencer's Reboot method.
|
||||
// func (s *MockSuccessfulSequencer) Reboot() []Phase {
|
||||
// return []Phase{
|
||||
// &MockSuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Reset is a mock method that overrides the embedded sequencer's Reset method.
|
||||
// func (s *MockSuccessfulSequencer) Reset(req *machine.ResetRequest) []Phase {
|
||||
// return []Phase{
|
||||
// &MockSuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// type MockUnsuccessfulSequencer struct{}
|
||||
|
||||
// // Boot is a mock method that overrides the embedded sequencer's Boot method.
|
||||
// func (s *MockUnsuccessfulSequencer) Boot() []Phase {
|
||||
// return []Phase{
|
||||
// &MockUnsuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Initialize is a mock method that overrides the embedded sequencer's Initialize method.
|
||||
// func (s *MockUnsuccessfulSequencer) Initialize() []Phase {
|
||||
// return []Phase{
|
||||
// &MockUnsuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Shutdown is a mock method that overrides the embedded sequencer's Shutdown method.
|
||||
// func (s *MockUnsuccessfulSequencer) Shutdown() []Phase {
|
||||
// return []Phase{
|
||||
// &MockUnsuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Upgrade is a mock method that overrides the embedded sequencer's Upgrade method.
|
||||
// func (s *MockUnsuccessfulSequencer) Upgrade(req *machine.UpgradeRequest) []Phase {
|
||||
// return []Phase{
|
||||
// &MockUnsuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Reboot is a mock method that overrides the embedded sequencer's Reboot method.
|
||||
// func (s *MockUnsuccessfulSequencer) Reboot() []Phase {
|
||||
// return []Phase{
|
||||
// &MockUnsuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Reset is a mock method that overrides the embedded sequencer's Reset method.
|
||||
// func (s *MockUnsuccessfulSequencer) Reset(req *machine.ResetRequest) []Phase {
|
||||
// return []Phase{
|
||||
// &MockUnsuccessfulPhase{},
|
||||
// }
|
||||
// }
|
||||
|
||||
// type MockSuccessfulPhase struct{}
|
||||
|
||||
// func (*MockSuccessfulPhase) Tasks() []TaskSetupFunc {
|
||||
// return []TaskSetupFunc{&MockSuccessfulTask{}}
|
||||
// }
|
||||
|
||||
// type MockUnsuccessfulPhase struct{}
|
||||
|
||||
// func (*MockUnsuccessfulPhase) Tasks() []TaskSetupFunc {
|
||||
// return []TaskSetupFunc{&MockUnsuccessfulTask{}}
|
||||
// }
|
||||
|
||||
// type MockSuccessfulTask struct{}
|
||||
|
||||
// func (*MockSuccessfulTask) Func(Mode) TaskSetupFunc {
|
||||
// return func(Runtime) error {
|
||||
// return nil
|
||||
// }
|
||||
// }
|
||||
|
||||
// type MockUnsuccessfulTask struct{}
|
||||
|
||||
// func (*MockUnsuccessfulTask) Func(Mode) TaskSetupFunc {
|
||||
// return func(Runtime) error { return fmt.Errorf("error") }
|
||||
// }
|
||||
|
||||
// type MockPlatform struct{}
|
||||
|
||||
// func (*MockPlatform) Name() string {
|
||||
// return "mock"
|
||||
// }
|
||||
|
||||
// func (*MockPlatform) Configuration() ([]byte, error) {
|
||||
// return nil, nil
|
||||
// }
|
||||
|
||||
// func (*MockPlatform) ExternalIPs() ([]net.IP, error) {
|
||||
// return nil, nil
|
||||
// }
|
||||
|
||||
// func (*MockPlatform) Hostname() ([]byte, error) {
|
||||
// return nil, nil
|
||||
// }
|
||||
|
||||
// func (*MockPlatform) Mode() Mode {
|
||||
// return Metal
|
||||
// }
|
||||
|
||||
// func (*MockPlatform) KernelArgs() procfs.Parameters {
|
||||
// return procfs.Parameters{}
|
||||
// }
|
||||
|
||||
// type MockConfigurator struct{}
|
||||
|
||||
// func (*MockConfigurator) Version() string {
|
||||
// return ""
|
||||
// }
|
||||
|
||||
// func (*MockConfigurator) Debug() bool {
|
||||
// return false
|
||||
// }
|
||||
|
||||
// func (*MockConfigurator) Persist() bool {
|
||||
// return false
|
||||
// }
|
||||
|
||||
// func (*MockConfigurator) Machine() Machine {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (*MockConfigurator) Cluster() Cluster {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (*MockConfigurator) Validate(Mode) error {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (*MockConfigurator) String() (string, error) {
|
||||
// return "", nil
|
||||
// }
|
||||
|
||||
// func (*MockConfigurator) Bytes() ([]byte, error) {
|
||||
// return nil, nil
|
||||
// }
|
||||
|
||||
// type MockRuntime struct{}
|
||||
|
||||
// func (*MockRuntime) Platform() Platform {
|
||||
// return &MockPlatform{}
|
||||
// }
|
||||
|
||||
// func (*MockRuntime) Config() Configurator {
|
||||
// return &MockConfigurator{}
|
||||
// }
|
||||
|
||||
// func (*MockRuntime) Sequence() Sequence {
|
||||
// return Noop
|
||||
// }
|
||||
|
||||
// func TestController_Run(t *testing.T) {
|
||||
// type fields struct {
|
||||
// Sequencer Sequencer
|
||||
// Runtime Runtime
|
||||
// semaphore int32
|
||||
// }
|
||||
|
||||
// type args struct {
|
||||
// seq Sequence
|
||||
// data interface{}
|
||||
// }
|
||||
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// fields fields
|
||||
// args args
|
||||
// wantErr bool
|
||||
// }{
|
||||
// {
|
||||
// name: "boot",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Boot,
|
||||
// data: nil,
|
||||
// },
|
||||
// wantErr: false,
|
||||
// },
|
||||
// {
|
||||
// name: "initialize",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Initialize,
|
||||
// data: nil,
|
||||
// },
|
||||
// wantErr: false,
|
||||
// },
|
||||
// {
|
||||
// name: "shutdown",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Shutdown,
|
||||
// data: nil,
|
||||
// },
|
||||
// wantErr: false,
|
||||
// },
|
||||
// {
|
||||
// name: "upgrade with valid data",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Upgrade,
|
||||
// data: &machine.UpgradeRequest{},
|
||||
// },
|
||||
// wantErr: false,
|
||||
// },
|
||||
// {
|
||||
// name: "upgrade with invalid data",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Upgrade,
|
||||
// data: nil,
|
||||
// },
|
||||
// wantErr: true,
|
||||
// },
|
||||
// {
|
||||
// name: "upgrade with lock",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 1,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Upgrade,
|
||||
// data: &machine.UpgradeRequest{},
|
||||
// },
|
||||
// wantErr: true,
|
||||
// },
|
||||
// {
|
||||
// name: "reset with valid data",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Reset,
|
||||
// data: &machine.ResetRequest{},
|
||||
// },
|
||||
// wantErr: false,
|
||||
// },
|
||||
// {
|
||||
// name: "reset with invalid data",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Reset,
|
||||
// data: nil,
|
||||
// },
|
||||
// wantErr: true,
|
||||
// },
|
||||
// {
|
||||
// name: "unsuccessful phase",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockUnsuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Boot,
|
||||
// data: nil,
|
||||
// },
|
||||
// wantErr: true,
|
||||
// },
|
||||
// {
|
||||
// name: "undefined runtime",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: nil,
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// seq: Boot,
|
||||
// data: nil,
|
||||
// },
|
||||
// wantErr: true,
|
||||
// },
|
||||
// }
|
||||
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// c := &Controller{
|
||||
// Sequencer: tt.fields.Sequencer,
|
||||
// Runtime: tt.fields.Runtime,
|
||||
// semaphore: tt.fields.semaphore,
|
||||
// }
|
||||
// t.Logf("c.Sequencer: %v", c.Sequencer)
|
||||
// if err := c.Run(tt.args.seq, tt.args.data); (err != nil) != tt.wantErr {
|
||||
// t.Errorf("Controller.Run() error = %v, wantErr %v", err, tt.wantErr)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// func TestController_runPhase(t *testing.T) {
|
||||
// type fields struct {
|
||||
// Sequencer Sequencer
|
||||
// Runtime Runtime
|
||||
// semaphore int32
|
||||
// }
|
||||
|
||||
// type args struct {
|
||||
// phase Phase
|
||||
// }
|
||||
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// fields fields
|
||||
// args args
|
||||
// wantErr bool
|
||||
// }{
|
||||
// {
|
||||
// name: "successful phase",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// phase: &MockSuccessfulPhase{},
|
||||
// },
|
||||
// wantErr: false,
|
||||
// },
|
||||
// {
|
||||
// name: "unsuccessful phase",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// phase: &MockUnsuccessfulPhase{},
|
||||
// },
|
||||
// wantErr: true,
|
||||
// },
|
||||
// }
|
||||
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// c := &Controller{
|
||||
// Sequencer: tt.fields.Sequencer,
|
||||
// Runtime: tt.fields.Runtime,
|
||||
// semaphore: tt.fields.semaphore,
|
||||
// }
|
||||
// if err := c.runPhase(tt.args.phase); (err != nil) != tt.wantErr {
|
||||
// t.Errorf("Controller.runPhase() error = %v, wantErr %v", err, tt.wantErr)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// func TestController_runTask(t *testing.T) {
|
||||
// type fields struct {
|
||||
// Sequencer Sequencer
|
||||
// Runtime Runtime
|
||||
// semaphore int32
|
||||
// }
|
||||
|
||||
// type args struct {
|
||||
// t TaskSetupFunc
|
||||
// }
|
||||
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// fields fields
|
||||
// args args
|
||||
// wantErr bool
|
||||
// }{
|
||||
// {
|
||||
// name: "successful task",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// t: &MockSuccessfulTask{},
|
||||
// },
|
||||
// wantErr: false,
|
||||
// },
|
||||
// {
|
||||
// name: "unsuccessful task",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// Runtime: &MockRuntime{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// args: args{
|
||||
// t: &MockUnsuccessfulTask{},
|
||||
// },
|
||||
// wantErr: true,
|
||||
// },
|
||||
// }
|
||||
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// c := &Controller{
|
||||
// Sequencer: tt.fields.Sequencer,
|
||||
// Runtime: tt.fields.Runtime,
|
||||
// semaphore: tt.fields.semaphore,
|
||||
// }
|
||||
|
||||
// if err := c.runTask(tt.args.t); (err != nil) != tt.wantErr {
|
||||
// t.Errorf("Controller.runTask() error = %v, wantErr %v", err, tt.wantErr)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// func TestController_TryLock(t *testing.T) {
|
||||
// type fields struct {
|
||||
// Sequencer Sequencer
|
||||
// Runtime Runtime
|
||||
// semaphore int32
|
||||
// }
|
||||
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// fields fields
|
||||
// want bool
|
||||
// }{
|
||||
// {
|
||||
// name: "is locked",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// want: false,
|
||||
// },
|
||||
// {
|
||||
// name: "is unlocked",
|
||||
// fields: fields{
|
||||
// Sequencer: &MockSuccessfulSequencer{},
|
||||
// semaphore: 1,
|
||||
// },
|
||||
// want: true,
|
||||
// },
|
||||
// }
|
||||
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// c := &Controller{
|
||||
// Sequencer: tt.fields.Sequencer,
|
||||
// Runtime: tt.fields.Runtime,
|
||||
// semaphore: tt.fields.semaphore,
|
||||
// }
|
||||
// if got := c.TryLock(); got != tt.want {
|
||||
// t.Errorf("Controller.TryLock() = %v, want %v", got, tt.want)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// func TestController_Unlock(t *testing.T) {
|
||||
// type fields struct {
|
||||
// Sequencer Sequencer
|
||||
// Runtime Runtime
|
||||
// semaphore int32
|
||||
// }
|
||||
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// fields fields
|
||||
// want bool
|
||||
// }{
|
||||
// {
|
||||
// name: "did not unlock",
|
||||
// fields: fields{
|
||||
// semaphore: 0,
|
||||
// },
|
||||
// want: false,
|
||||
// },
|
||||
// {
|
||||
// name: "did unlock",
|
||||
// fields: fields{
|
||||
// semaphore: 1,
|
||||
// },
|
||||
// want: true,
|
||||
// },
|
||||
// }
|
||||
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// c := &Controller{
|
||||
// Sequencer: tt.fields.Sequencer,
|
||||
// Runtime: tt.fields.Runtime,
|
||||
// semaphore: tt.fields.semaphore,
|
||||
// }
|
||||
// if got := c.Unlock(); got != tt.want {
|
||||
// t.Errorf("Controller.Unlock() = %v, want %v", got, tt.want)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// import (
|
||||
// "errors"
|
||||
// "os"
|
||||
// "testing"
|
||||
|
||||
// "github.com/stretchr/testify/suite"
|
||||
|
||||
// "github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
// "github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/phase"
|
||||
// )
|
||||
|
||||
// type PhaseSuite struct {
|
||||
// suite.Suite
|
||||
|
||||
// platformExists bool
|
||||
// platformValue string
|
||||
// }
|
||||
|
||||
// type regularTask struct {
|
||||
// errCh <-chan error
|
||||
// }
|
||||
|
||||
// func (t *regularTask) TaskFunc(runtime.Mode) TaskFunc {
|
||||
// return func(runtime.Runtime) error {
|
||||
// return <-t.errCh
|
||||
// }
|
||||
// }
|
||||
|
||||
// type nilTask struct{}
|
||||
|
||||
// func (t *nilTask) TaskFunc(runtime.Mode) TaskFunc {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// type panicTask struct{}
|
||||
|
||||
// func (t *panicTask) TaskFunc(runtime.Mode) TaskFunc {
|
||||
// return func(runtime.Runtime) error {
|
||||
// panic("in task")
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (suite *PhaseSuite) SetupSuite() {
|
||||
// suite.platformValue, suite.platformExists = os.LookupEnv("PLATFORM")
|
||||
// suite.Require().NoError(os.Setenv("PLATFORM", "container"))
|
||||
// }
|
||||
|
||||
// func (suite *PhaseSuite) TearDownSuite() {
|
||||
// if !suite.platformExists {
|
||||
// suite.Require().NoError(os.Unsetenv("PLATFORM"))
|
||||
// } else {
|
||||
// suite.Require().NoError(os.Setenv("PLATFORM", suite.platformValue))
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (suite *PhaseSuite) TestRunSuccess() {
|
||||
// r, err := phase.NewRunner(nil, runtime.Noop)
|
||||
// suite.Require().NoError(err)
|
||||
|
||||
// taskErr := make(chan error)
|
||||
|
||||
// r.Add(phase.NewPhase("empty"))
|
||||
// r.Add(phase.NewPhase("phase1", ®ularTask{errCh: taskErr}, ®ularTask{errCh: taskErr}))
|
||||
// r.Add(phase.NewPhase("phase2", ®ularTask{errCh: taskErr}, &nilTask{}))
|
||||
|
||||
// errCh := make(chan error)
|
||||
|
||||
// go func() {
|
||||
// errCh <- r.Run()
|
||||
// }()
|
||||
|
||||
// taskErr <- nil
|
||||
// taskErr <- nil
|
||||
|
||||
// select {
|
||||
// case <-errCh:
|
||||
// suite.Require().Fail("should be still running")
|
||||
// default:
|
||||
// }
|
||||
|
||||
// taskErr <- nil
|
||||
|
||||
// suite.Require().NoError(<-errCh)
|
||||
// }
|
||||
|
||||
// func (suite *PhaseSuite) TestRunFailures() {
|
||||
// r, err := phase.NewRunner(nil, runtime.Noop)
|
||||
// suite.Require().NoError(err)
|
||||
|
||||
// taskErr := make(chan error, 1)
|
||||
|
||||
// r.Add(phase.NewPhase("empty"))
|
||||
// r.Add(phase.NewPhase("failphase", &panicTask{}, ®ularTask{errCh: taskErr}, &nilTask{}))
|
||||
// r.Add(phase.NewPhase("neverreached",
|
||||
// ®ularTask{}, // should never be reached
|
||||
// ))
|
||||
|
||||
// taskErr <- errors.New("test error")
|
||||
|
||||
// err = r.Run()
|
||||
// suite.Require().Error(err)
|
||||
// suite.Assert().Contains(err.Error(), "2 errors occurred")
|
||||
// suite.Assert().Contains(err.Error(), "test error")
|
||||
// suite.Assert().Contains(err.Error(), "panic recovered: in task")
|
||||
// }
|
||||
|
||||
// func TestPhaseSuite(t *testing.T) {
|
||||
// suite.Run(t, new(PhaseSuite))
|
||||
// }
|
@ -2,13 +2,6 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package cni_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
}
|
||||
// Package runtime defines interfaces for accessing runtime specific settings,
|
||||
// and state.
|
||||
package runtime
|
23
internal/app/machined/pkg/runtime/errors.go
Normal file
23
internal/app/machined/pkg/runtime/errors.go
Normal file
@ -0,0 +1,23 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package runtime
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrLocked indicates that the sequencer is currently locked, and processing
|
||||
// another sequence.
|
||||
ErrLocked = errors.New("locked")
|
||||
|
||||
// ErrReboot indicates that a task is requesting a reboot.
|
||||
ErrReboot = errors.New("reboot")
|
||||
|
||||
// ErrInvalidSequenceData indicates that the sequencer got data the wrong
|
||||
// data type for a sequence.
|
||||
ErrInvalidSequenceData = errors.New("invalid sequence data")
|
||||
|
||||
// ErrUndefinedRuntime indicates that the sequencer's runtime is not defined.
|
||||
ErrUndefinedRuntime = errors.New("undefined runtime")
|
||||
)
|
48
internal/app/machined/pkg/runtime/mode.go
Normal file
48
internal/app/machined/pkg/runtime/mode.go
Normal file
@ -0,0 +1,48 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Mode is a runtime mode.
|
||||
type Mode int
|
||||
|
||||
const (
|
||||
// ModeCloud is the cloud runtime mode.
|
||||
ModeCloud Mode = iota
|
||||
// ModeContainer is the container runtime mode.
|
||||
ModeContainer
|
||||
// ModeMetal is the metal runtime mode.
|
||||
ModeMetal
|
||||
)
|
||||
|
||||
const (
|
||||
cloud = "cloud"
|
||||
container = "container"
|
||||
metal = "metal"
|
||||
)
|
||||
|
||||
// String returns the string representation of a Mode.
|
||||
func (m Mode) String() string {
|
||||
return [...]string{cloud, container, metal}[m]
|
||||
}
|
||||
|
||||
// ParseMode returns a `Mode` that matches the specified string.
|
||||
func ParseMode(s string) (mod Mode, err error) {
|
||||
switch s {
|
||||
case cloud:
|
||||
mod = ModeCloud
|
||||
case container:
|
||||
mod = ModeContainer
|
||||
case metal:
|
||||
mod = ModeMetal
|
||||
default:
|
||||
return mod, fmt.Errorf("unknown runtime mode: %q", s)
|
||||
}
|
||||
|
||||
return mod, nil
|
||||
}
|
94
internal/app/machined/pkg/runtime/mode_test.go
Normal file
94
internal/app/machined/pkg/runtime/mode_test.go
Normal file
@ -0,0 +1,94 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// nolint: dupl,scopelint
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMode_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
m Mode
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "cloud",
|
||||
m: ModeCloud,
|
||||
want: "cloud",
|
||||
},
|
||||
{
|
||||
name: "container",
|
||||
m: ModeContainer,
|
||||
want: "container",
|
||||
},
|
||||
{
|
||||
name: "metal",
|
||||
m: ModeMetal,
|
||||
want: "metal",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.m.String(); got != tt.want {
|
||||
t.Errorf("Mode.String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMode(t *testing.T) {
|
||||
type args struct {
|
||||
s string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantM Mode
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "cloud",
|
||||
args: args{"cloud"},
|
||||
wantM: ModeCloud,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "container",
|
||||
args: args{"container"},
|
||||
wantM: ModeContainer,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "metal",
|
||||
args: args{"metal"},
|
||||
wantM: ModeMetal,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid",
|
||||
args: args{"invalid"},
|
||||
wantM: 0,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotM, err := ParseMode(tt.args.s)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ParseMode() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(gotM, tt.wantM) {
|
||||
t.Errorf("ParseMode() = %v, want %v", gotM, tt.wantM)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import (
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
)
|
||||
|
||||
// Platform is an interface describing a platform.
|
||||
// Platform defines the requirements for a platform.
|
||||
type Platform interface {
|
||||
Name() string
|
||||
Configuration() ([]byte, error)
|
@ -2,13 +2,11 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package api_test
|
||||
package runtime
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
// added for accurate coverage estimation
|
||||
//
|
||||
// please remove it once any unit-test is added
|
||||
// for this package
|
||||
// Runtime defines the runtime parameters.
|
||||
type Runtime interface {
|
||||
Config() Configurator
|
||||
SetConfig([]byte) error
|
||||
State() State
|
||||
}
|
87
internal/app/machined/pkg/runtime/sequencer.go
Normal file
87
internal/app/machined/pkg/runtime/sequencer.go
Normal file
@ -0,0 +1,87 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/talos-systems/talos/api/machine"
|
||||
)
|
||||
|
||||
// Sequence represents a sequence type.
|
||||
type Sequence int
|
||||
|
||||
const (
|
||||
// SequenceBoot is the boot sequence.
|
||||
SequenceBoot Sequence = iota
|
||||
// SequenceInitialize is the initialize sequence.
|
||||
SequenceInitialize
|
||||
// SequenceInstall is the install sequence.
|
||||
SequenceInstall
|
||||
// SequenceShutdown is the shutdown sequence.
|
||||
SequenceShutdown
|
||||
// SequenceUpgrade is the upgrade sequence.
|
||||
SequenceUpgrade
|
||||
// SequenceReset is the reset sequence.
|
||||
SequenceReset
|
||||
// SequenceReboot is the reboot sequence.
|
||||
SequenceReboot
|
||||
// SequenceNoop is the noop sequence.
|
||||
SequenceNoop
|
||||
)
|
||||
|
||||
const (
|
||||
boot = "boot"
|
||||
initialize = "initialize"
|
||||
install = "install"
|
||||
shutdown = "shutdown"
|
||||
upgrade = "upgrade"
|
||||
reset = "reset"
|
||||
reboot = "reboot"
|
||||
noop = "noop"
|
||||
)
|
||||
|
||||
// String returns the string representation of a `Sequence`.
|
||||
func (s Sequence) String() string {
|
||||
return [...]string{boot, initialize, install, shutdown, upgrade, reset, reboot, noop}[s]
|
||||
}
|
||||
|
||||
// ParseSequence returns a `Sequence` that matches the specified string.
|
||||
func ParseSequence(s string) (seq Sequence, err error) {
|
||||
switch s {
|
||||
case boot:
|
||||
seq = SequenceBoot
|
||||
case initialize:
|
||||
seq = SequenceInitialize
|
||||
case install:
|
||||
seq = SequenceInstall
|
||||
case shutdown:
|
||||
seq = SequenceShutdown
|
||||
case upgrade:
|
||||
seq = SequenceUpgrade
|
||||
case reset:
|
||||
seq = SequenceReset
|
||||
case reboot:
|
||||
seq = SequenceReboot
|
||||
case noop:
|
||||
seq = SequenceNoop
|
||||
default:
|
||||
return seq, fmt.Errorf("unknown runtime sequence: %q", s)
|
||||
}
|
||||
|
||||
return seq, nil
|
||||
}
|
||||
|
||||
// Sequencer describes the set of sequences required for the lifecycle
|
||||
// management of the operating system.
|
||||
type Sequencer interface {
|
||||
Boot(Runtime) []Phase
|
||||
Initialize(Runtime) []Phase
|
||||
Install(Runtime) []Phase
|
||||
Reboot(Runtime) []Phase
|
||||
Reset(Runtime, *machine.ResetRequest) []Phase
|
||||
Shutdown(Runtime) []Phase
|
||||
Upgrade(Runtime, *machine.UpgradeRequest) []Phase
|
||||
}
|
124
internal/app/machined/pkg/runtime/sequencer_test.go
Normal file
124
internal/app/machined/pkg/runtime/sequencer_test.go
Normal file
@ -0,0 +1,124 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// nolint: scopelint
|
||||
package runtime
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSequence_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
s Sequence
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "boot",
|
||||
s: SequenceBoot,
|
||||
want: "boot",
|
||||
},
|
||||
{
|
||||
name: "initialize",
|
||||
s: SequenceInitialize,
|
||||
want: "initialize",
|
||||
},
|
||||
{
|
||||
name: "shutdown",
|
||||
s: SequenceShutdown,
|
||||
want: "shutdown",
|
||||
},
|
||||
{
|
||||
name: "upgrade",
|
||||
s: SequenceUpgrade,
|
||||
want: "upgrade",
|
||||
},
|
||||
{
|
||||
name: "reboot",
|
||||
s: SequenceReboot,
|
||||
want: "reboot",
|
||||
},
|
||||
{
|
||||
name: "reset",
|
||||
s: SequenceReset,
|
||||
want: "reset",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.s.String(); got != tt.want {
|
||||
t.Errorf("Sequence.String() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseSequence(t *testing.T) {
|
||||
type args struct {
|
||||
s string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantSeq Sequence
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "boot",
|
||||
args: args{"boot"},
|
||||
wantSeq: SequenceBoot,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "initialize",
|
||||
args: args{"initialize"},
|
||||
wantSeq: SequenceInitialize,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "shutdown",
|
||||
args: args{"shutdown"},
|
||||
wantSeq: SequenceShutdown,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "upgrade",
|
||||
args: args{"upgrade"},
|
||||
wantSeq: SequenceUpgrade,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "reboot",
|
||||
args: args{"reboot"},
|
||||
wantSeq: SequenceReboot,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "reset",
|
||||
args: args{"reset"},
|
||||
wantSeq: SequenceReset,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid",
|
||||
args: args{"invalid"},
|
||||
wantSeq: 0,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotSeq, err := ParseSequence(tt.args.s)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ParseSequence() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if gotSeq != tt.wantSeq {
|
||||
t.Errorf("ParseSequence() = %v, want %v", gotSeq, tt.wantSeq)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -4,7 +4,9 @@
|
||||
|
||||
package runtime
|
||||
|
||||
import "errors"
|
||||
|
||||
// ErrReboot is raised to initiate early reboot sequence via panic.
|
||||
var ErrReboot = errors.New("reboot")
|
||||
// State defines the state.
|
||||
type State interface {
|
||||
Platform() Platform
|
||||
Machine() MachineState
|
||||
Cluster() ClusterState
|
||||
}
|
@ -14,52 +14,21 @@ import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mdlayher/genetlink"
|
||||
"github.com/mdlayher/netlink"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
|
||||
"github.com/talos-systems/talos/internal/pkg/event"
|
||||
"github.com/talos-systems/talos/internal/pkg/runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
// PowerButtonEvent is the ACPI event name associated with the power off
|
||||
// button.
|
||||
PowerButtonEvent = "button/power"
|
||||
)
|
||||
|
||||
// Handler represents the ACPI handler task.
|
||||
type Handler struct{}
|
||||
|
||||
// NewHandlerTask initializes and returns a ACPI handler task.
|
||||
func NewHandlerTask() phase.Task {
|
||||
return &Handler{}
|
||||
}
|
||||
|
||||
// TaskFunc returns the runtime function.
|
||||
func (task *Handler) TaskFunc(mode runtime.Mode) phase.TaskFunc {
|
||||
switch mode {
|
||||
case runtime.Container:
|
||||
return nil
|
||||
default:
|
||||
return task.standard
|
||||
}
|
||||
}
|
||||
|
||||
func (task *Handler) standard(r runtime.Runtime) (err error) {
|
||||
if err := listenForPowerButton(); err != nil {
|
||||
log.Printf("WARNING: power off events will be ignored: %+v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
// See https://github.com/torvalds/linux/blob/master/drivers/acpi/event.c
|
||||
acpiGenlFamilyName = "acpi_event"
|
||||
acpiGenlMcastGroupName = "acpi_mc_group"
|
||||
)
|
||||
|
||||
// StartACPIListener starts listening for ACPI netlink events.
|
||||
//
|
||||
//nolint: gocyclo
|
||||
func listenForPowerButton() (err error) {
|
||||
func StartACPIListener() (err error) {
|
||||
// Get the acpi_event family.
|
||||
conn, err := genetlink.Dial(nil)
|
||||
if err != nil {
|
||||
@ -87,37 +56,30 @@ func listenForPowerButton() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
// nolint: errcheck
|
||||
defer conn.Close()
|
||||
// nolint: errcheck
|
||||
defer conn.Close()
|
||||
|
||||
for {
|
||||
msgs, _, err := conn.Receive()
|
||||
if err != nil {
|
||||
log.Printf("error reading from ACPI channel: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(msgs) > 0 {
|
||||
ok, err := parse(msgs, PowerButtonEvent)
|
||||
if err != nil {
|
||||
log.Printf("failed to parse netlink message: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("shutdown via ACPI received")
|
||||
event.Bus().Notify(event.Event{Type: event.Shutdown})
|
||||
|
||||
return
|
||||
}
|
||||
for {
|
||||
msgs, _, err := conn.Receive()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading from ACPI channel: %w", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
if len(msgs) > 0 {
|
||||
ok, err := parse(msgs, PowerButtonEvent)
|
||||
if err != nil {
|
||||
log.Printf("failed to parse netlink message: %v", err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parse(msgs []genetlink.Message, event string) (bool, error) {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user