From 2bf854085528ae7c8a4c84dd7e3608d184821e59 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Fri, 27 Dec 2019 20:49:24 +0000 Subject: [PATCH] test: provision Talos clusters via Firecracker VMs This is initial PR to push the initial code, it has several known problems which are going to be addressed in follow-up PRs: 1. there's no "cluster destroy", so the only way to stop the VMs is to `pkill firecracker` 2. provisioner creates state in `/tmp` and never deletes it, that is required to keep cluster running when `osctl cluster create` finishes 3. doesn't run any controller process around firecracker to support reboots/CNI cleanup (vethxyz interfaces are lingering on the host as they're never cleaned up) The plan is to create some structure in `~/.talos` to manage cluster state, e.g. `~/.talos/clusters/` which will contain all the required files (disk images, file sockets, VM logs, etc.). This directory structure will also work as a way to detect running clusters and clean them up. For point number 3, `osctl cluster create` is going to exec lightweight process to control the firecracker VM process and to simulate VM reboots if firecracker finishes cleanly (when VM reboots). Signed-off-by: Andrey Smirnov --- Dockerfile | 6 +- Makefile | 1 + cmd/osctl/cmd/cluster.go | 73 +++++-- cmd/osctl/pkg/helpers/artifacts.go | 15 ++ go.mod | 5 +- go.sum | 65 ++++++ .../pkg/provision/providers/docker/docker.go | 6 + internal/pkg/provision/providers/factory.go | 25 +++ .../provision/providers/firecracker/README.md | 27 +++ .../provision/providers/firecracker/create.go | 107 ++++++++++ .../providers/firecracker/destroy.go | 26 +++ .../providers/firecracker/firecracker.go | 35 ++++ .../firecracker/inmemhttp/inmemhttp.go | 85 ++++++++ .../firecracker/inmemhttp/inmemhttp_test.go | 61 ++++++ .../providers/firecracker/network.go | 144 +++++++++++++ .../provision/providers/firecracker/node.go | 198 ++++++++++++++++++ .../provision/providers/firecracker/state.go | 28 +++ .../provision/providers/firecracker_linux.go | 18 ++ .../provision/providers/firecracker_other.go | 18 ++ internal/pkg/provision/provision.go | 8 +- internal/pkg/provision/request.go | 21 +- .../types/v1alpha1/generate/generate.go | 2 + pkg/config/types/v1alpha1/generate/options.go | 20 ++ pkg/constants/constants.go | 3 + 24 files changed, 975 insertions(+), 22 deletions(-) create mode 100644 cmd/osctl/pkg/helpers/artifacts.go create mode 100644 internal/pkg/provision/providers/factory.go create mode 100644 internal/pkg/provision/providers/firecracker/README.md create mode 100644 internal/pkg/provision/providers/firecracker/create.go create mode 100644 internal/pkg/provision/providers/firecracker/destroy.go create mode 100644 internal/pkg/provision/providers/firecracker/firecracker.go create mode 100644 internal/pkg/provision/providers/firecracker/inmemhttp/inmemhttp.go create mode 100644 internal/pkg/provision/providers/firecracker/inmemhttp/inmemhttp_test.go create mode 100644 internal/pkg/provision/providers/firecracker/network.go create mode 100644 internal/pkg/provision/providers/firecracker/node.go create mode 100644 internal/pkg/provision/providers/firecracker/state.go create mode 100644 internal/pkg/provision/providers/firecracker_linux.go create mode 100644 internal/pkg/provision/providers/firecracker_other.go diff --git a/Dockerfile b/Dockerfile index 411b153ae..eac55a53f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -178,9 +178,10 @@ ENTRYPOINT ["/networkd"] FROM base AS osctl-linux-build ARG SHA ARG TAG +ARG ARTIFACTS ARG VERSION_PKG="github.com/talos-systems/talos/pkg/version" WORKDIR /src/cmd/osctl -RUN --mount=type=cache,target=/.cache/go-build GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG}" -o /osctl-linux-amd64 +RUN --mount=type=cache,target=/.cache/go-build GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X github.com/talos-systems/talos/cmd/osctl/pkg/helpers.ArtifactsPath=${ARTIFACTS}" -o /osctl-linux-amd64 RUN chmod +x /osctl-linux-amd64 FROM scratch AS osctl-linux @@ -189,9 +190,10 @@ COPY --from=osctl-linux-build /osctl-linux-amd64 /osctl-linux-amd64 FROM base AS osctl-darwin-build ARG SHA ARG TAG +ARG ARTIFACTS ARG VERSION_PKG="github.com/talos-systems/talos/pkg/version" WORKDIR /src/cmd/osctl -RUN --mount=type=cache,target=/.cache/go-build GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG}" -o /osctl-darwin-amd64 +RUN --mount=type=cache,target=/.cache/go-build GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Client -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X github.com/talos-systems/talos/cmd/osctl/pkg/helpers.ArtifactsPath=${ARTIFACTS}" -o /osctl-darwin-amd64 RUN chmod +x /osctl-darwin-amd64 FROM scratch AS osctl-darwin diff --git a/Makefile b/Makefile index 66bdf9825..bec38dd0c 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ COMMON_ARGS += --build-arg=SHA=$(SHA) COMMON_ARGS += --build-arg=TAG=$(TAG) COMMON_ARGS += --build-arg=GO_VERSION=$(GO_VERSION) COMMON_ARGS += --build-arg=IMAGES=$(IMAGES) +COMMON_ARGS += --build-arg=ARTIFACTS=$(ARTIFACTS) COMMON_ARGS += --build-arg=TESTPKGS=$(TESTPKGS) all: initramfs kernel installer osctl talos diff --git a/cmd/osctl/cmd/cluster.go b/cmd/osctl/cmd/cluster.go index 2f7b50d29..89de1e67b 100644 --- a/cmd/osctl/cmd/cluster.go +++ b/cmd/osctl/cmd/cluster.go @@ -19,6 +19,7 @@ import ( "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/check" + "github.com/talos-systems/talos/internal/pkg/provision/providers" "github.com/talos-systems/talos/internal/pkg/provision/providers/docker" "github.com/talos-systems/talos/internal/pkg/runtime" "github.com/talos-systems/talos/pkg/config" @@ -28,19 +29,27 @@ import ( ) var ( + provisioner string clusterName string nodeImage string + nodeInstallImage string + nodeVmlinuxPath string + nodeInitramfsPath string networkCIDR string networkMTU int workers int masters int clusterCpus string clusterMemory int + clusterDiskSize int clusterWait bool clusterWaitTimeout time.Duration forceInitNodeAsEndpoint bool forceEndpoint string inputDir string + cniBinPath []string + cniConfDir string + cniCacheDir string ) // clusterCmd represents the cluster command @@ -84,29 +93,40 @@ func create(ctx context.Context) (err error) { } memory := int64(clusterMemory) * 1024 * 1024 + diskSize := int64(clusterDiskSize) * 1024 * 1024 // Validate CIDR range and allocate IPs - fmt.Println("validating CIDR and reserving master IPs") + fmt.Println("validating CIDR and reserving IPs") _, cidr, err := net.ParseCIDR(networkCIDR) if err != nil { return fmt.Errorf("error validating cidr block: %w", err) } - // Set starting ip at 2nd ip in range, ex: 192.168.0.2 - ips := make([]string, masters) + // Gateway addr at 1st IP in range, ex. 192.168.0.1 + var gatewayIP net.IP + + gatewayIP, err = talosnet.NthIPInNetwork(cidr, 1) + if err != nil { + return err + } + + // Set starting ip at 2nd ip in range, ex: 192.168.0.2 + ips := make([]net.IP, masters+workers) - var masterIP net.IP for i := range ips { - masterIP, err = talosnet.NthIPInNetwork(cidr, i+2) + ips[i], err = talosnet.NthIPInNetwork(cidr, i+2) if err != nil { return err } - - ips[i] = masterIP.String() } - provisioner, err := docker.NewProvisioner(ctx) + masterIPs := make([]string, 0, masters) + for _, ip := range ips[:masters] { + masterIPs = append(masterIPs, ip.String()) + } + + provisioner, err := providers.Factory(ctx, provisioner) if err != nil { return err } @@ -119,20 +139,24 @@ func create(ctx context.Context) (err error) { if inputDir != "" { configBundleOpts = append(configBundleOpts, config.WithExistingConfigs(inputDir)) } else { - var genOptions []generate.GenOption + genOptions := []generate.GenOption{ + generate.WithInstallImage(nodeInstallImage), + } + + genOptions = append(genOptions, provisioner.GenOptions()...) if forceEndpoint != "" { genOptions = append(genOptions, generate.WithEndpointList([]string{forceEndpoint})) provisionOptions = append(provisionOptions, provision.WithEndpoint(forceEndpoint)) } else if forceInitNodeAsEndpoint { - genOptions = append(genOptions, generate.WithEndpointList([]string{ips[0]})) + genOptions = append(genOptions, generate.WithEndpointList([]string{ips[0].String()})) } configBundleOpts = append(configBundleOpts, config.WithInputOptions( &config.InputOptions{ ClusterName: clusterName, - MasterIPs: ips, + MasterIPs: masterIPs, KubeVersion: kubernetesVersion, GenOptions: genOptions, }), @@ -152,12 +176,20 @@ func create(ctx context.Context) (err error) { Name: clusterName, Network: provision.NetworkRequest{ - Name: clusterName, - CIDR: *cidr, - MTU: networkMTU, + Name: clusterName, + CIDR: *cidr, + GatewayAddr: gatewayIP, + MTU: networkMTU, + CNI: provision.CNIConfig{ + BinPath: cniBinPath, + ConfDir: cniConfDir, + CacheDir: cniCacheDir, + }, }, Image: nodeImage, + KernelPath: nodeVmlinuxPath, + InitramfsPath: nodeInitramfsPath, KubernetesVersion: kubernetesVersion, } @@ -174,9 +206,10 @@ func create(ctx context.Context) (err error) { request.Nodes = append(request.Nodes, provision.NodeRequest{ Name: fmt.Sprintf("%s-master-%d", clusterName, i+1), - IP: net.ParseIP(ips[i]), + IP: ips[i], Memory: memory, NanoCPUs: nanoCPUs, + DiskSize: diskSize, Config: cfg, }) } @@ -185,8 +218,10 @@ func create(ctx context.Context) (err error) { request.Nodes = append(request.Nodes, provision.NodeRequest{ Name: fmt.Sprintf("%s-worker-%d", clusterName, i), + IP: ips[masters+i-1], Memory: memory, NanoCPUs: nanoCPUs, + DiskSize: diskSize, Config: configBundle.Join(), }) } @@ -263,19 +298,27 @@ func parseCPUShare() (int64, error) { } func init() { + clusterUpCmd.Flags().StringVar(&provisioner, "provisioner", "docker", "Talos cluster provisioner to use") clusterUpCmd.Flags().StringVar(&nodeImage, "image", defaultImage(constants.DefaultTalosImageRepository), "the image to use") + clusterUpCmd.Flags().StringVar(&nodeInstallImage, "install-image", defaultImage(constants.DefaultInstallerImageRepository), "the installer image to use") + clusterUpCmd.Flags().StringVar(&nodeVmlinuxPath, "vmlinux-path", helpers.ArtifactPath(constants.KernelUncompressedAsset), "the uncompressed kernel image to use") + clusterUpCmd.Flags().StringVar(&nodeInitramfsPath, "initrd-path", helpers.ArtifactPath(constants.InitramfsAsset), "the uncompressed kernel image to use") clusterUpCmd.Flags().IntVar(&networkMTU, "mtu", 1500, "MTU of the docker bridge network") clusterUpCmd.Flags().StringVar(&networkCIDR, "cidr", "10.5.0.0/24", "CIDR of the docker bridge network") clusterUpCmd.Flags().IntVar(&workers, "workers", 1, "the number of workers to create") clusterUpCmd.Flags().IntVar(&masters, "masters", 1, "the number of masters to create") clusterUpCmd.Flags().StringVar(&clusterCpus, "cpus", "1.5", "the share of CPUs as fraction (each container)") clusterUpCmd.Flags().IntVar(&clusterMemory, "memory", 1024, "the limit on memory usage in MB (each container)") + clusterUpCmd.Flags().IntVar(&clusterDiskSize, "disk", 4*1024, "the limit on disk size in MB (each VM)") clusterUpCmd.Flags().BoolVar(&clusterWait, "wait", false, "wait for the cluster to be ready before returning") clusterUpCmd.Flags().DurationVar(&clusterWaitTimeout, "wait-timeout", 20*time.Minute, "timeout to wait for the cluster to be ready") clusterUpCmd.Flags().BoolVar(&forceInitNodeAsEndpoint, "init-node-as-endpoint", false, "use init node as endpoint instead of any load balancer endpoint") clusterUpCmd.Flags().StringVar(&forceEndpoint, "endpoint", "", "use endpoint instead of provider defaults") clusterUpCmd.Flags().StringVar(&kubernetesVersion, "kubernetes-version", constants.DefaultKubernetesVersion, "desired kubernetes version to run") clusterUpCmd.Flags().StringVarP(&inputDir, "input-dir", "i", "", "location of pre-generated config files") + clusterUpCmd.Flags().StringSliceVar(&cniBinPath, "cni-bin-path", []string{"/opt/cni/bin"}, "search path for CNI binaries") + clusterUpCmd.Flags().StringVar(&cniConfDir, "cni-conf-dir", "/etc/cni/conf.d", "CNI config directory path") + clusterUpCmd.Flags().StringVar(&cniCacheDir, "cni-cache-dir", "/var/lib/cni", "CNI cache directory path") clusterCmd.PersistentFlags().StringVar(&clusterName, "name", "talos-default", "the name of the cluster") clusterCmd.AddCommand(clusterUpCmd) clusterCmd.AddCommand(clusterDownCmd) diff --git a/cmd/osctl/pkg/helpers/artifacts.go b/cmd/osctl/pkg/helpers/artifacts.go new file mode 100644 index 000000000..98663d7ca --- /dev/null +++ b/cmd/osctl/pkg/helpers/artifacts.go @@ -0,0 +1,15 @@ +// 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 helpers + +import "path/filepath" + +// ArtifactsPath is a path to artifacts output directory (set during the build). +var ArtifactsPath = "default/" + +// ArtifactPath returns path to the artifact by name. +func ArtifactPath(name string) string { + return filepath.Join(ArtifactsPath, name) +} diff --git a/go.mod b/go.mod index 3b746f1eb..0643d18bb 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.13 replace ( github.com/docker/distribution v2.7.1+incompatible => github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible + github.com/firecracker-microvm/firecracker-go-sdk v0.19.0 => github.com/smira/firecracker-go-sdk v0.19.1-0.20200110185541-4fce8cba9f84 github.com/kubernetes-sigs/bootkube => github.com/talos-systems/bootkube v0.14.1-0.20200114174616-69b2e9624d84 github.com/opencontainers/runtime-spec v1.0.1 => github.com/opencontainers/runtime-spec v0.1.2-0.20180301181910-fa4b36aa9c99 ) @@ -17,15 +18,17 @@ require ( github.com/containerd/containerd v1.3.2 github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb // indirect github.com/containerd/cri v1.11.1 - github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c // indirect github.com/containerd/go-cni v0.0.0-20191121212822-60d125212faf github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c // indirect github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd + github.com/containernetworking/cni v0.7.2-0.20190807151350-8c6c47d1c7fc + github.com/containernetworking/plugins v0.8.2 github.com/docker/distribution v2.7.1+incompatible github.com/docker/docker v1.13.1 github.com/docker/go-connections v0.4.0 github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/dustin/go-humanize v1.0.0 + github.com/firecracker-microvm/firecracker-go-sdk v0.19.0 github.com/fullsailor/pkcs7 v0.0.0-20180613152042-8306686428a5 github.com/gizak/termui/v3 v3.0.0 github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect diff --git a/go.sum b/go.sum index 65ea571a6..2667e4b7c 100644 --- a/go.sum +++ b/go.sum @@ -21,26 +21,32 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.78 h1:LaXy6lWR0YK7LKyuU0QWy2ws/LWTPfYV/UgfiBu4tvY= github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= @@ -55,6 +61,7 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -88,14 +95,20 @@ github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0x github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd h1:bRLyitWw3PT/2YuVaCKTPg0cA5dOFKFwKtkfcP2dLsA= github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containernetworking/cni v0.7.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE= github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.7.2-0.20190807151350-8c6c47d1c7fc h1:zUNdrf9w09mWodVhZ9hX4Yk4Uu84n/OgdfPattAwwt8= +github.com/containernetworking/cni v0.7.2-0.20190807151350-8c6c47d1c7fc/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.2 h1:5lnwfsAYO+V7yXhysJKy3E1A2Gy9oVut031zfdOzI9w= +github.com/containernetworking/plugins v0.8.2/go.mod h1:TxALKWZpWL79BC3GOYKJzzXr7U8R23PdhwaLp6F3adc= github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.18+incompatible h1:Zz1aXgDrFFi1nadh58tA9ktt06cmPTwNNP3dXwIq1lE= github.com/coreos/etcd v3.3.18+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-iptables v0.4.2/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= @@ -112,6 +125,10 @@ github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -163,49 +180,69 @@ github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70t github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5 h1:8b2ZgKfKIUTVQpTb77MoRDIMEIwvDVw40o3aOXdfYzI= github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.17.1/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY= github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.4 h1:5I4CCSqoWzT+82bBkNIvmLc0UOsoKKQ4Fz+3VxOB7SY= github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.17.1/go.mod h1:QO936ZXeisByFmZEO1IS1Dqhtf4QV1sYYFtIq6Ld86Q= github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4 h1:csnOgcgAiuGoM/Po7PEpKDoNulCcF3FGbSnbHfxgjMI= github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.17.1/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.3 h1:eRfyY5SkaNJCAwmmMcADjY31ow9+N7MCLW7oRkbsINA= github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.17.1/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.17.1/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.5 h1:QhCBKRYqZR+SKo4gl1lPhPahope8/RLt6EVgY8X80w0= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.3.0 h1:M695OaDJ5ipWvDPcoAg/YL9c3uORAegkEfBqTQF/fTQ= github.com/gogo/googleapis v1.3.0/go.mod h1:d+q1s/xVJxZGKWwC/6UfPIF33J+G1Tq4GYv9Y+Tg/EU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -295,6 +332,7 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/insomniacslk/dhcp v0.0.0-20190814082028-393ae75a101b h1:2PyiA5CVpWhQ4CPINgksFnopxYOGUN1n2IjKwrRqQDE= github.com/insomniacslk/dhcp v0.0.0-20190814082028-393ae75a101b/go.mod h1:CfMdguCK66I5DAUJgGKyNz8aB6vO5dZzkm9Xep6WGvw= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= @@ -310,10 +348,14 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/juju/errors v0.0.0-20180806074554-22422dad46e1/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -330,12 +372,14 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 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= @@ -357,6 +401,7 @@ github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdI github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -372,11 +417,13 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840= github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= @@ -434,14 +481,21 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smira/firecracker-go-sdk v0.19.1-0.20200110185541-4fce8cba9f84 h1:PNu2CXmtEYf8o56YXuRt92lMQT0OuCMnHdmKobGRX+A= +github.com/smira/firecracker-go-sdk v0.19.1-0.20200110185541-4fce8cba9f84/go.mod h1:kW0gxvPpPvMukUxxTO9DrpSlScrtrTDGY3VgjAj/Qwc= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c h1:gqEdF4VwBu3lTKGHS9rXE9x1/pEaSwCXRLOZRF6qtlw= +github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c/go.mod h1:eMyUVp6f/5jnzM+3zahzl7q6UXLbgSc3MKg/+ow9QW0= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -474,6 +528,7 @@ github.com/talos-systems/bootkube v0.14.1-0.20200114174616-69b2e9624d84 h1:KRx1o github.com/talos-systems/bootkube v0.14.1-0.20200114174616-69b2e9624d84/go.mod h1:zLrZfPQ49k0O6x6QN0pDSJn9iD0EMyj6J+5x1vqJSFw= github.com/talos-systems/grpc-proxy v0.2.0 h1:DN75bLfaW4xfhq0r0mwFRnfGhSB+HPhK1LNzuMEs9Pw= github.com/talos-systems/grpc-proxy v0.2.0/go.mod h1:sm97Vc/z2cok3pu6ruNeszQej4KDxFrDgfWs4C1mtC4= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= @@ -487,6 +542,10 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf h1:3J37+NPjNyGW/dbfXtj3yWuF9OEepIdGOXRaJGbORV8= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728 h1:sH9mEk+flyDxiUa5BuPiuhDETMbzrt9A20I2wktMvRQ= github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -502,6 +561,7 @@ go.etcd.io/etcd v3.3.13+incompatible h1:jCejD5EMnlGxFvcGRyEV4VGlENZc7oPQX6o0t7n3 go.etcd.io/etcd v3.3.13+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= @@ -525,6 +585,7 @@ go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -559,6 +620,7 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -694,6 +756,7 @@ google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -706,8 +769,10 @@ gopkg.in/freddierice/go-losetup.v1 v1.0.0-20170407175016-fc9adea44124 h1:aPcd9iB gopkg.in/freddierice/go-losetup.v1 v1.0.0-20170407175016-fc9adea44124/go.mod h1:6LXpUYtVsrx91XiupFRJ8jVKOqLZf5PrbEVSGHta/84= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= diff --git a/internal/pkg/provision/providers/docker/docker.go b/internal/pkg/provision/providers/docker/docker.go index 97ccef2d3..b741085fc 100644 --- a/internal/pkg/provision/providers/docker/docker.go +++ b/internal/pkg/provision/providers/docker/docker.go @@ -11,6 +11,7 @@ import ( "github.com/docker/docker/client" "github.com/talos-systems/talos/internal/pkg/provision" + "github.com/talos-systems/talos/pkg/config/types/v1alpha1/generate" ) type provisioner struct { @@ -39,3 +40,8 @@ func (p *provisioner) Close() error { return nil } + +// GenOptions provides a list of additional config generate options. +func (p *provisioner) GenOptions() []generate.GenOption { + return nil +} diff --git a/internal/pkg/provision/providers/factory.go b/internal/pkg/provision/providers/factory.go new file mode 100644 index 000000000..af92bd77b --- /dev/null +++ b/internal/pkg/provision/providers/factory.go @@ -0,0 +1,25 @@ +// 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 providers + +import ( + "context" + "fmt" + + "github.com/talos-systems/talos/internal/pkg/provision" + "github.com/talos-systems/talos/internal/pkg/provision/providers/docker" +) + +// Factory instantiates provision provider by name. +func Factory(ctx context.Context, name string) (provision.Provisioner, error) { + switch name { + case "docker": + return docker.NewProvisioner(ctx) + case "firecracker": + return newFirecracker(ctx) + default: + return nil, fmt.Errorf("unsupported provisioner %q", name) + } +} diff --git a/internal/pkg/provision/providers/firecracker/README.md b/internal/pkg/provision/providers/firecracker/README.md new file mode 100644 index 000000000..bb5bd22cf --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/README.md @@ -0,0 +1,27 @@ +Firecracker Talos Provisioner +============================= + +This code is experimental for now. + +Due to CNI, it requires `osctl` to be running with at least +`CAP_SYS_ADMIN` and `CAP_NET_ADMIN` Linux capabilities +(in order to have the ability to create and configure network namespaces). + +In any case, it requires `/dev/kvm` to be accessible for the user +running `osctl`: https://github.com/firecracker-microvm/firecracker/blob/master/docs/getting-started.md#prerequisites + +CNI configuration directory (could be overridden with `osctl` flags) should +exist, default location is `/etc/cni/conf.d`. + +Network namespace default mountpoint should be created as well: `/var/run/netns`. + +Following CNI plugins should be installed to the CNI binary path (default is `/opt/cni/bin`): + +* `bridge` +* `firewall` +* `tc-redirect-tap` + +First two CNI plugins are part of [Standard CNI plugins](https://github.com/containernetworking/cni), +last one can be built from [Firecracker Go SDK](https://github.com/firecracker-microvm/firecracker-go-sdk/tree/master/cni). + +Provisioner creates bridge interface with format `talos<8 hex chars>` and never deletes it (bug). diff --git a/internal/pkg/provision/providers/firecracker/create.go b/internal/pkg/provision/providers/firecracker/create.go new file mode 100644 index 000000000..775fb57d2 --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/create.go @@ -0,0 +1,107 @@ +// 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 firecracker + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "fmt" + "io/ioutil" + "time" + + "github.com/talos-systems/talos/internal/pkg/provision" + "github.com/talos-systems/talos/internal/pkg/provision/providers/firecracker/inmemhttp" +) + +// Create Talos cluster as a set of firecracker micro-VMs. +// +//nolint: gocyclo +func (p *provisioner) Create(ctx context.Context, request provision.ClusterRequest, opts ...provision.Option) (provision.Cluster, error) { + options := provision.DefaultOptions() + + for _, opt := range opts { + if err := opt(&options); err != nil { + return nil, err + } + } + + state := &state{} + + fmt.Fprintln(options.LogWriter, "creating network", request.Network.Name) + + // build bridge interface name by taking part of checksum of the network name + // so that interface name is defined by network name, and different networks have + // different bridge interfaces + networkNameHash := sha256.Sum256([]byte(request.Network.Name)) + state.bridgeInterfaceName = fmt.Sprintf("%s%s", "talos", hex.EncodeToString(networkNameHash[:])[:8]) + + if err := p.createNetwork(ctx, state, request.Network); err != nil { + return nil, fmt.Errorf("unable to provision CNI network: %w", err) + } + + httpServer, err := inmemhttp.NewServer(fmt.Sprintf("%s:0", request.Network.GatewayAddr)) + if err != nil { + return nil, err + } + + for _, node := range request.Nodes { + var cfg string + + cfg, err = node.Config.String() + if err != nil { + return nil, err + } + + if err = httpServer.AddFile(fmt.Sprintf("%s.yaml", node.Name), []byte(cfg)); err != nil { + return nil, err + } + } + + state.baseConfigURL = fmt.Sprintf("http://%s/", httpServer.GetAddr()) + + httpServer.Serve() + defer httpServer.Shutdown(ctx) //nolint: errcheck + + state.tempDir, err = ioutil.TempDir("", "talos") + if err != nil { + return nil, err + } + + fmt.Fprintf(options.LogWriter, "created temporary environment in %q\n", state.tempDir) + + var nodeInfo []provision.NodeInfo + + fmt.Fprintln(options.LogWriter, "creating master nodes") + + if nodeInfo, err = p.createNodes(ctx, state, request, request.Nodes.MasterNodes()); err != nil { + return nil, err + } + + fmt.Fprintln(options.LogWriter, "creating worker nodes") + + var workerNodeInfo []provision.NodeInfo + + if workerNodeInfo, err = p.createNodes(ctx, state, request, request.Nodes.WorkerNodes()); err != nil { + return nil, err + } + + nodeInfo = append(nodeInfo, workerNodeInfo...) + + // TODO: temporary, need to wait for all nodes to finish bootstrapping + // before shutting down config HTTP service + time.Sleep(30 * time.Second) + + state.clusterInfo = provision.ClusterInfo{ + ClusterName: request.Name, + Network: provision.NetworkInfo{ + Name: request.Network.Name, + CIDR: request.Network.CIDR, + }, + Nodes: nodeInfo, + } + + return state, nil +} diff --git a/internal/pkg/provision/providers/firecracker/destroy.go b/internal/pkg/provision/providers/firecracker/destroy.go new file mode 100644 index 000000000..530ee17ca --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/destroy.go @@ -0,0 +1,26 @@ +// 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 firecracker + +import ( + "context" + + "github.com/talos-systems/talos/internal/pkg/provision" +) + +// Destroy Talos cluster as set of Firecracker VMs. +func (p *provisioner) Destroy(ctx context.Context, cluster provision.Cluster, opts ...provision.Option) error { + options := provision.DefaultOptions() + + for _, opt := range opts { + if err := opt(&options); err != nil { + return err + } + } + + // TODO: implement me + + return nil +} diff --git a/internal/pkg/provision/providers/firecracker/firecracker.go b/internal/pkg/provision/providers/firecracker/firecracker.go new file mode 100644 index 000000000..dab4b2867 --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/firecracker.go @@ -0,0 +1,35 @@ +// 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 firecracker implements Provisioner via Firecracker VMs. +package firecracker + +import ( + "context" + + "github.com/talos-systems/talos/internal/pkg/provision" + "github.com/talos-systems/talos/pkg/config/types/v1alpha1/generate" +) + +type provisioner struct { +} + +// NewProvisioner initializes docker provisioner. +func NewProvisioner(ctx context.Context) (provision.Provisioner, error) { + p := &provisioner{} + + return p, nil +} + +// Close and release resources. +func (p *provisioner) Close() error { + return nil +} + +// GenOptions provides a list of additional config generate options. +func (p *provisioner) GenOptions() []generate.GenOption { + return []generate.GenOption{ + generate.WithInstallDisk("/dev/vda"), + } +} diff --git a/internal/pkg/provision/providers/firecracker/inmemhttp/inmemhttp.go b/internal/pkg/provision/providers/firecracker/inmemhttp/inmemhttp.go new file mode 100644 index 000000000..09b64702d --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/inmemhttp/inmemhttp.go @@ -0,0 +1,85 @@ +// 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 inmemhttp implements temporary HTTP server which is based off memory fs. +package inmemhttp + +import ( + "context" + "net" + "net/http" + "strconv" +) + +// Server is an in-memory http web server. +type Server interface { + AddFile(filename string, contents []byte) error + + GetAddr() net.Addr + Serve() + Shutdown(ctx context.Context) error +} + +type server struct { + l net.Listener + addr net.Addr + + srv *http.Server + mux *http.ServeMux +} + +// NewServer creates in-mem HTTP server. +func NewServer(address string) (Server, error) { + s := &server{ + mux: http.NewServeMux(), + } + + var err error + + s.l, err = net.Listen("tcp", address) + if err != nil { + return nil, err + } + + s.addr = s.l.Addr() + + s.srv = &http.Server{ + Handler: s.mux, + } + + return s, nil +} + +func (s *server) AddFile(filename string, contents []byte) error { + contentsCopy := append([]byte(nil), contents...) + + s.mux.Handle("/"+filename, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + switch req.Method { + case http.MethodHead: + w.Header().Add("Content-Length", strconv.Itoa(len(contentsCopy))) + w.WriteHeader(http.StatusOK) + case http.MethodGet: + w.Header().Add("Content-Length", strconv.Itoa(len(contentsCopy))) + w.WriteHeader(http.StatusOK) + + w.Write(contentsCopy) //nolint: errcheck + default: + w.WriteHeader(http.StatusNotImplemented) + } + })) + + return nil +} + +func (s *server) GetAddr() net.Addr { + return s.addr +} + +func (s *server) Serve() { + go s.srv.Serve(s.l) //nolint: errcheck +} + +func (s *server) Shutdown(ctx context.Context) error { + return s.srv.Shutdown(ctx) +} diff --git a/internal/pkg/provision/providers/firecracker/inmemhttp/inmemhttp_test.go b/internal/pkg/provision/providers/firecracker/inmemhttp/inmemhttp_test.go new file mode 100644 index 000000000..09bbd2ea4 --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/inmemhttp/inmemhttp_test.go @@ -0,0 +1,61 @@ +// 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 inmemhttp_test + +import ( + "context" + "fmt" + "io/ioutil" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/talos-systems/talos/internal/pkg/provision/providers/firecracker/inmemhttp" +) + +func TestServer(t *testing.T) { + srv, err := inmemhttp.NewServer("localhost:0") + assert.NoError(t, err) + + contents := []byte("DEADBEEF") + + assert.NoError(t, srv.AddFile("test.txt", contents)) + + srv.Serve() + defer srv.Shutdown(context.Background()) //nolint: errcheck + + resp, err := http.Get(fmt.Sprintf("http://%s/test.txt", srv.GetAddr())) + assert.NoError(t, err) + + defer resp.Body.Close() //nolint: errcheck + + assert.Equal(t, http.StatusOK, resp.StatusCode) + + got, err := ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + + assert.Equal(t, contents, got) + + assert.NoError(t, resp.Body.Close()) + + resp, err = http.Head(fmt.Sprintf("http://%s/test.txt", srv.GetAddr())) + assert.NoError(t, err) + + assert.Equal(t, http.StatusOK, resp.StatusCode) + + assert.EqualValues(t, 8, resp.ContentLength) + + assert.NoError(t, resp.Body.Close()) + + resp, err = http.Get(fmt.Sprintf("http://%s/test.txt2", srv.GetAddr())) + assert.NoError(t, err) + + assert.Equal(t, http.StatusNotFound, resp.StatusCode) + + assert.NoError(t, resp.Body.Close()) + + assert.NoError(t, srv.Shutdown(context.Background())) +} diff --git a/internal/pkg/provision/providers/firecracker/network.go b/internal/pkg/provision/providers/firecracker/network.go new file mode 100644 index 000000000..94d3e2901 --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/network.go @@ -0,0 +1,144 @@ +// 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 firecracker + +import ( + "bytes" + "context" + "fmt" + "os" + "path/filepath" + "text/template" + + "github.com/containernetworking/cni/libcni" + "github.com/containernetworking/plugins/pkg/testutils" + "github.com/google/uuid" + + "github.com/talos-systems/talos/internal/pkg/provision" + talosnet "github.com/talos-systems/talos/pkg/net" +) + +func (p *provisioner) createNetwork(ctx context.Context, state *state, network provision.NetworkRequest) error { + // bring up the bridge interface for the first time to get gateway IP assigned + t := template.Must(template.New("bridge").Parse(bridgeTemplate)) + + var buf bytes.Buffer + + err := t.Execute(&buf, struct { + NetworkName string + InterfaceName string + }{ + NetworkName: network.Name, + InterfaceName: state.bridgeInterfaceName, + }) + if err != nil { + return err + } + + bridgeConfig, err := libcni.ConfFromBytes(buf.Bytes()) + if err != nil { + return err + } + + cniConfig := libcni.NewCNIConfigWithCacheDir(network.CNI.BinPath, network.CNI.CacheDir, nil) + + ns, err := testutils.NewNS() + if err != nil { + return err + } + + defer testutils.UnmountNS(ns) //nolint: errcheck + + // pick a fake address to use for provisioning an interface + fakeIP, err := talosnet.NthIPInNetwork(&network.CIDR, 2) + if err != nil { + return err + } + + ones, bits := network.CIDR.IP.DefaultMask().Size() + containerID := uuid.New().String() + runtimeConf := libcni.RuntimeConf{ + ContainerID: containerID, + NetNS: ns.Path(), + IfName: "veth0", + Args: [][2]string{ + {"IP", fmt.Sprintf("%s/%d", fakeIP, bits-ones)}, + {"GATEWAY", network.GatewayAddr.String()}, + }, + } + + _, err = cniConfig.AddNetwork(ctx, bridgeConfig, &runtimeConf) + if err != nil { + return fmt.Errorf("error provisioning bridge CNI network: %w", err) + } + + err = cniConfig.DelNetwork(ctx, bridgeConfig, &runtimeConf) + if err != nil { + return fmt.Errorf("error deleting bridge CNI network: %w", err) + } + + // prepare an actual network config to be used by the VMs + t = template.Must(template.New("network").Parse(networkTemplate)) + + f, err := os.Create(filepath.Join(network.CNI.ConfDir, fmt.Sprintf("%s.conflist", network.Name))) + if err != nil { + return err + } + + defer f.Close() //nolint: errcheck + + err = t.Execute(f, struct { + NetworkName string + InterfaceName string + }{ + NetworkName: network.Name, + InterfaceName: state.bridgeInterfaceName, + }) + if err != nil { + return err + } + + return f.Close() +} + +const bridgeTemplate = ` +{ + "name": "{{ .NetworkName }}", + "cniVersion": "0.4.0", + "type": "bridge", + "bridge": "{{ .InterfaceName }}", + "ipMasq": true, + "isGateway": true, + "isDefaultGateway": true, + "ipam": { + "type": "static" + } +} +` + +const networkTemplate = ` +{ + "name": "{{ .NetworkName }}", + "cniVersion": "0.4.0", + "plugins": [ + { + "type": "bridge", + "bridge": "{{ .InterfaceName }}", + "ipMasq": true, + "isGateway": true, + "isDefaultGateway": true, + "ipam": { + "type": "static" + } + }, + { + "type": "firewall" + }, + { + "type": "tc-redirect-tap" + } + ] +} +` diff --git a/internal/pkg/provision/providers/firecracker/node.go b/internal/pkg/provision/providers/firecracker/node.go new file mode 100644 index 000000000..057c989b8 --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/node.go @@ -0,0 +1,198 @@ +// 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 firecracker + +import ( + "context" + "fmt" + "math" + "net" + "os" + "path/filepath" + + "github.com/firecracker-microvm/firecracker-go-sdk" + models "github.com/firecracker-microvm/firecracker-go-sdk/client/models" + "github.com/hashicorp/go-multierror" + + "github.com/talos-systems/talos/internal/pkg/kernel" + "github.com/talos-systems/talos/internal/pkg/provision" +) + +func (p *provisioner) createDisk(state *state, nodeReq provision.NodeRequest) (diskPath string, err error) { + diskPath = filepath.Join(state.tempDir, fmt.Sprintf("%s.disk", nodeReq.Name)) + + var diskF *os.File + + diskF, err = os.Create(diskPath) + if err != nil { + return + } + + defer diskF.Close() //nolint: errcheck + + err = diskF.Truncate(nodeReq.DiskSize) + + return +} + +func (p *provisioner) createNodes(ctx context.Context, state *state, clusterReq provision.ClusterRequest, nodeReqs []provision.NodeRequest) ([]provision.NodeInfo, error) { + errCh := make(chan error) + nodeCh := make(chan provision.NodeInfo, len(nodeReqs)) + + for _, nodeReq := range nodeReqs { + go func(nodeReq provision.NodeRequest) { + nodeInfo, err := p.createNode(ctx, state, clusterReq, nodeReq) + errCh <- err + + if err == nil { + nodeCh <- nodeInfo + } + }(nodeReq) + } + + var multiErr *multierror.Error + + for range nodeReqs { + multiErr = multierror.Append(multiErr, <-errCh) + } + + close(nodeCh) + + nodesInfo := make([]provision.NodeInfo, 0, len(nodeReqs)) + + for nodeInfo := range nodeCh { + nodesInfo = append(nodesInfo, nodeInfo) + } + + return nodesInfo, multiErr.ErrorOrNil() +} + +func (p *provisioner) createNode(ctx context.Context, state *state, clusterReq provision.ClusterRequest, nodeReq provision.NodeRequest) (provision.NodeInfo, error) { + socketPath := filepath.Join(state.tempDir, fmt.Sprintf("%s.sock", nodeReq.Name)) + + vcpuCount := int64(math.RoundToEven(float64(nodeReq.NanoCPUs) / 1000 / 1000 / 1000)) + if vcpuCount < 2 { + vcpuCount = 1 + } + + memSize := nodeReq.Memory / 1024 / 1024 + + diskPath, err := p.createDisk(state, nodeReq) + if err != nil { + return provision.NodeInfo{}, err + } + + cmdline := kernel.NewDefaultCmdline() + + // required to get kernel console + cmdline.Append("console", "ttyS0") + + // reboot configuration + cmdline.Append("reboot", "k") + cmdline.Append("panic", "1") + + // disable stuff we don't need + cmdline.Append("pci", "off") + cmdline.Append("acpi", "off") + cmdline.Append("i8042.noaux", "") + + // Talos config + cmdline.Append("talos.platform", "metal") + cmdline.Append("talos.config", fmt.Sprintf("%s%s.yaml", state.baseConfigURL, nodeReq.Name)) + + // networking + cmdline.Append("ip", fmt.Sprintf( + "%s::%s:%s:%s:eth0:off", + nodeReq.IP, + clusterReq.Network.GatewayAddr, + net.IP(clusterReq.Network.CIDR.Mask), + nodeReq.Name)) + + ones, bits := clusterReq.Network.CIDR.IP.DefaultMask().Size() + + cfg := firecracker.Config{ + DisableValidation: true, // TODO: enable when firecracker Go SDK is fixed + SocketPath: socketPath, + KernelImagePath: clusterReq.KernelPath, + KernelArgs: cmdline.String(), + InitrdPath: clusterReq.InitramfsPath, + ForwardSignals: []os.Signal{}, // don't forward any signals + MachineCfg: models.MachineConfiguration{ + HtEnabled: firecracker.Bool(false), + VcpuCount: firecracker.Int64(vcpuCount), + MemSizeMib: firecracker.Int64(memSize), + }, + NetworkInterfaces: firecracker.NetworkInterfaces{ + firecracker.NetworkInterface{ + CNIConfiguration: &firecracker.CNIConfiguration{ + BinPath: clusterReq.Network.CNI.BinPath, + ConfDir: clusterReq.Network.CNI.ConfDir, + CacheDir: clusterReq.Network.CNI.CacheDir, + NetworkName: clusterReq.Network.Name, + Args: [][2]string{ + {"IP", fmt.Sprintf("%s/%d", nodeReq.IP, bits-ones)}, + {"GATEWAY", clusterReq.Network.GatewayAddr.String()}, + }, + IfName: "veth0", + }, + }, + }, + Drives: []models.Drive{ + { + DriveID: firecracker.String("disk"), + IsRootDevice: firecracker.Bool(false), + IsReadOnly: firecracker.Bool(false), + PathOnHost: firecracker.String(diskPath), + }, + }, + } + + defer os.Remove(cfg.SocketPath) //nolint: errcheck + + logFile, err := os.OpenFile(filepath.Join(state.tempDir, fmt.Sprintf("%s.log", nodeReq.Name)), os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666) + if err != nil { + return provision.NodeInfo{}, err + } + + // defer logFile.Close() //nolint: errcheck + + // TODO: this loop is to boot VM for the first time, let installer do its work + // handle reboot and then leave it running + // this is going to change with control process to the non-hacky way + for i := 0; i < 2; i++ { + cmd := firecracker.VMCommandBuilder{}. + WithBin("firecracker"). + WithSocketPath(socketPath). + WithStdout(logFile). + WithStderr(logFile). + Build(ctx) + + m, err := firecracker.NewMachine(ctx, cfg, firecracker.WithProcessRunner(cmd)) + if err != nil { + return provision.NodeInfo{}, fmt.Errorf("failed to create new machine: %w", err) + } + + if err := m.Start(ctx); err != nil { + return provision.NodeInfo{}, fmt.Errorf("failed to initialize machine: %w", err) + } + + if i == 0 { + // wait for VMM to execute + if err := m.Wait(ctx); err != nil { + return provision.NodeInfo{}, err + } + } + } + + nodeInfo := provision.NodeInfo{ + ID: socketPath, + Name: nodeReq.Name, + Type: nodeReq.Config.Machine().Type(), + + PrivateIP: nodeReq.IP, + } + + return nodeInfo, nil +} diff --git a/internal/pkg/provision/providers/firecracker/state.go b/internal/pkg/provision/providers/firecracker/state.go new file mode 100644 index 000000000..9fe020fe5 --- /dev/null +++ b/internal/pkg/provision/providers/firecracker/state.go @@ -0,0 +1,28 @@ +// 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 firecracker + +import ( + "github.com/talos-systems/talos/cmd/osctl/pkg/client/config" + "github.com/talos-systems/talos/internal/pkg/provision" +) + +type state struct { + tempDir string + baseConfigURL string + bridgeInterfaceName string + + talosConfig *config.Config + + clusterInfo provision.ClusterInfo +} + +func (s *state) TalosConfig() *config.Config { + return s.talosConfig +} + +func (s *state) Info() provision.ClusterInfo { + return s.clusterInfo +} diff --git a/internal/pkg/provision/providers/firecracker_linux.go b/internal/pkg/provision/providers/firecracker_linux.go new file mode 100644 index 000000000..5753e8ed4 --- /dev/null +++ b/internal/pkg/provision/providers/firecracker_linux.go @@ -0,0 +1,18 @@ +// 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/. + +// +build linux + +package providers + +import ( + "context" + + "github.com/talos-systems/talos/internal/pkg/provision" + "github.com/talos-systems/talos/internal/pkg/provision/providers/firecracker" +) + +func newFirecracker(ctx context.Context) (provision.Provisioner, error) { + return firecracker.NewProvisioner(ctx) +} diff --git a/internal/pkg/provision/providers/firecracker_other.go b/internal/pkg/provision/providers/firecracker_other.go new file mode 100644 index 000000000..77acb8ebd --- /dev/null +++ b/internal/pkg/provision/providers/firecracker_other.go @@ -0,0 +1,18 @@ +// 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/. + +// +build !linux + +package providers + +import ( + "context" + "fmt" + + "github.com/talos-systems/talos/internal/pkg/provision" +) + +func newFirecracker(ctx context.Context) (provision.Provisioner, error) { + return nil, fmt.Errorf("firecracker is not supported on this platform") +} diff --git a/internal/pkg/provision/provision.go b/internal/pkg/provision/provision.go index 55e6aa6af..9824436ac 100644 --- a/internal/pkg/provision/provision.go +++ b/internal/pkg/provision/provision.go @@ -5,13 +5,19 @@ // Package provision provides abstract definitions for Talos cluster provisioners. package provision -import "context" +import ( + "context" + + "github.com/talos-systems/talos/pkg/config/types/v1alpha1/generate" +) // Provisioner is an interface each provisioner should implement. type Provisioner interface { Create(context.Context, ClusterRequest, ...Option) (Cluster, error) Destroy(context.Context, Cluster, ...Option) error + GenOptions() []generate.GenOption + Close() error } diff --git a/internal/pkg/provision/request.go b/internal/pkg/provision/request.go index e8bf86322..a7b366392 100644 --- a/internal/pkg/provision/request.go +++ b/internal/pkg/provision/request.go @@ -20,14 +20,27 @@ type ClusterRequest struct { Nodes NodeRequests Image string + KernelPath string + InitramfsPath string KubernetesVersion string } +// CNIConfig describes CNI part of NetworkRequest. +type CNIConfig struct { + BinPath []string + ConfDir string + CacheDir string +} + // NetworkRequest describe cluster network. type NetworkRequest struct { - Name string - CIDR net.IPNet - MTU int + Name string + CIDR net.IPNet + GatewayAddr net.IP + MTU int + + // CNI-specific parameters. + CNI CNIConfig } // NodeRequests is a list of NodeRequest. @@ -88,4 +101,6 @@ type NodeRequest struct { NanoCPUs int64 // Memory limit in bytes Memory int64 + // Disk (volume) size in bytes, if applicable + DiskSize int64 } diff --git a/pkg/config/types/v1alpha1/generate/generate.go b/pkg/config/types/v1alpha1/generate/generate.go index 7878303e1..18f6dfcac 100644 --- a/pkg/config/types/v1alpha1/generate/generate.go +++ b/pkg/config/types/v1alpha1/generate/generate.go @@ -309,6 +309,8 @@ func NewInput(clustername string, endpoint string, kubernetesVersion string, opt TrustdInfo: trustdInfo, AdditionalSubjectAltNames: additionalSubjectAltNames, AdditionalMachineCertSANs: additionalMachineCertSANs, + InstallDisk: options.InstallDisk, + InstallImage: options.InstallImage, } return input, nil diff --git a/pkg/config/types/v1alpha1/generate/options.go b/pkg/config/types/v1alpha1/generate/options.go index ba6767787..1946dc3f9 100644 --- a/pkg/config/types/v1alpha1/generate/options.go +++ b/pkg/config/types/v1alpha1/generate/options.go @@ -16,9 +16,29 @@ func WithEndpointList(endpoints []string) GenOption { } } +// WithInstallDisk specifies install disk to use in Talos cluster. +func WithInstallDisk(disk string) GenOption { + return func(o *GenOptions) error { + o.InstallDisk = disk + + return nil + } +} + +// WithInstallImage specifies install container image to use in Talos cluster. +func WithInstallImage(imageRef string) GenOption { + return func(o *GenOptions) error { + o.InstallImage = imageRef + + return nil + } +} + // GenOptions describes generate parameters. type GenOptions struct { EndpointList []string + InstallDisk string + InstallImage string } // DefaultGenOptions returns default options. diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index cfbdbe7f3..d1afeabcd 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -213,6 +213,9 @@ const ( // OSSocketPath is the path to file socket of os API. OSSocketPath = SystemRunPath + "/osd/osd.sock" + // KernelUncompressedAsset defines a well known name for our uncompressed kernel filename + KernelUncompressedAsset = "vmlinux" + // KernelAsset defines a well known name for our kernel filename KernelAsset = "vmlinuz"