From ce2acaee7bd6f752b1dd5fed2733942a3da64f98 Mon Sep 17 00:00:00 2001 From: Roman Mohr Date: Fri, 18 Mar 2022 09:37:40 +0100 Subject: [PATCH 1/2] Add kubevirt platform ID The KubeVirt platform provides config drive files compatible to the openstack config drive like nutanix does. It provides a disk with a `config-2` label (lower case). Signed-off-by: Roman Mohr --- internal/platform/platform.go | 5 ++ internal/providers/kubevirt/kubevirt.go | 91 +++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 internal/providers/kubevirt/kubevirt.go diff --git a/internal/platform/platform.go b/internal/platform/platform.go index bd393e6a3..1aa0bc8bd 100644 --- a/internal/platform/platform.go +++ b/internal/platform/platform.go @@ -29,6 +29,7 @@ import ( "github.com/coreos/ignition/v2/internal/providers/file" "github.com/coreos/ignition/v2/internal/providers/gcp" "github.com/coreos/ignition/v2/internal/providers/ibmcloud" + "github.com/coreos/ignition/v2/internal/providers/kubevirt" "github.com/coreos/ignition/v2/internal/providers/noop" "github.com/coreos/ignition/v2/internal/providers/nutanix" "github.com/coreos/ignition/v2/internal/providers/openstack" @@ -141,6 +142,10 @@ func init() { name: "ibmcloud", fetch: ibmcloud.FetchConfig, }) + configs.Register(Config{ + name: "kubevirt", + fetch: kubevirt.FetchConfig, + }) configs.Register(Config{ name: "metal", fetch: noop.FetchConfig, diff --git a/internal/providers/kubevirt/kubevirt.go b/internal/providers/kubevirt/kubevirt.go new file mode 100644 index 000000000..ca7ef67b1 --- /dev/null +++ b/internal/providers/kubevirt/kubevirt.go @@ -0,0 +1,91 @@ +// Copyright 2021 Red Hat. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The KubeVirt (https://kubevirt.io) provider fetches +// configuration from the userdata available in the config-drive. It is similar +// to Openstack and uses the same APIs. + +package kubevirt + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "time" + + "github.com/coreos/ignition/v2/config/v3_4_experimental/types" + "github.com/coreos/ignition/v2/internal/distro" + "github.com/coreos/ignition/v2/internal/log" + "github.com/coreos/ignition/v2/internal/providers/util" + "github.com/coreos/ignition/v2/internal/resource" + ut "github.com/coreos/ignition/v2/internal/util" + + "github.com/coreos/vcontext/report" +) + +const ( + configDriveUserdataPath = "/openstack/latest/user_data" +) + +func FetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) { + data, err := fetchConfigFromDevice(f.Logger, filepath.Join(distro.DiskByLabelDir(), "config-2")) + if err != nil { + return types.Config{}, report.Report{}, err + } + + return util.ParseConfig(f.Logger, data) +} + +func fileExists(path string) bool { + _, err := os.Stat(path) + return (err == nil) +} + +func fetchConfigFromDevice(logger *log.Logger, path string) ([]byte, error) { + // There is not always a config drive in kubevirt, but we can limit ignition usage + // to VMs with config drives. Block forever if there is none. + for !fileExists(path) { + logger.Debug("config drive (%q) not found. Waiting...", path) + time.Sleep(time.Second) + } + + logger.Debug("creating temporary mount point") + mnt, err := ioutil.TempDir("", "ignition-configdrive") + if err != nil { + return nil, fmt.Errorf("failed to create temp directory: %v", err) + } + defer os.Remove(mnt) + + cmd := exec.Command(distro.MountCmd(), "-o", "ro", "-t", "auto", path, mnt) + if _, err := logger.LogCmd(cmd, "mounting config drive"); err != nil { + return nil, err + } + defer func() { + _ = logger.LogOp( + func() error { + return ut.UmountPath(mnt) + }, + "unmounting %q at %q", path, mnt, + ) + }() + + mntConfigDriveUserdataPath := filepath.Join(mnt, configDriveUserdataPath) + if !fileExists(mntConfigDriveUserdataPath) { + return nil, nil + } + + return ioutil.ReadFile(mntConfigDriveUserdataPath) +} From 9958ff9fd667784380aaef36c568a94bad2e9fee Mon Sep 17 00:00:00 2001 From: Roman Mohr Date: Fri, 18 Mar 2022 09:40:30 +0100 Subject: [PATCH 2/2] Document KubeVirt support Signed-off-by: Roman Mohr --- docs/supported-platforms.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/supported-platforms.md b/docs/supported-platforms.md index ee6a20259..35e41b6cd 100644 --- a/docs/supported-platforms.md +++ b/docs/supported-platforms.md @@ -16,6 +16,7 @@ Ignition is currently only supported for the following platforms: * [Exoscale] (`exoscale`) - Ignition will read its configuration from the instance userdata. Cloud SSH keys are handled separately. * [Google Cloud] (`gcp`) - Ignition will read its configuration from the instance metadata entry named "user-data". Cloud SSH keys are handled separately. * [IBM Cloud] (`ibmcloud`) - Ignition will read its configuration from the instance userdata. Cloud SSH keys are handled separately. +* [KubeVirt] (`kubevirt`) - Ignition will read its configuration from the instance userdata via config drive. Cloud SSH keys are handled separately. * Bare Metal (`metal`) - Use the `ignition.config.url` kernel parameter to provide a URL to the configuration. The URL can use the `http://`, `https://`, `tftp://`, `s3://`, or `gs://` schemes to specify a remote config. * [Nutanix] (`nutanix`) - Ignition will read its configuration from the instance userdata via config drive. Cloud SSH keys are handled separately. * [OpenStack] (`openstack`) - Ignition will read its configuration from the instance userdata via either metadata service or config drive. Cloud SSH keys are handled separately. @@ -41,6 +42,7 @@ For most cloud providers, cloud SSH keys and custom network configuration are ha [Exoscale]: https://www.exoscale.com/compute/ [Google Cloud]: https://cloud.google.com/compute [IBM Cloud]: https://www.ibm.com/cloud/vpc +[KubeVirt]: https://kubevirt.io [Nutanix]: https://www.nutanix.com/products/ahv [OpenStack]: https://www.openstack.org/ [Equinix Metal]: https://metal.equinix.com/product/