Skip to content

Commit

Permalink
Add support for HyperV platform
Browse files Browse the repository at this point in the history
This PR adds initial support for the Microsoft HyperV platform.  It uses
HyperV and MS WMI to read key/value pairs as provided by the Windows
host.  Because the size allocation of the value is quite small, the
ignition values will likely be split into at least 2 and more like more
parts which must be read and reassembled in ignition.

Supports coreos/fedora-coreos-tracker#1411

Signed-off-by: Brent Baude <[email protected]>
  • Loading branch information
baude committed Feb 14, 2023
1 parent 512108d commit 59c5eb8
Show file tree
Hide file tree
Showing 9 changed files with 299 additions and 1 deletion.
3 changes: 3 additions & 0 deletions docs/supported-platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Ignition is currently only supported for the following platforms:
* [DigitalOcean] (`digitalocean`) - Ignition will read its configuration from the droplet userdata. Cloud SSH keys and network configuration are handled separately.
* [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.
* [Microsoft HyperV] (`hyperv`) - Ignition will read its configuration from the WMI key-value kernel device. The ignition file must be split into key-values
on the Windows host (values must be less than 1Kb) and written to Microsoft's WMI pool 0. Ignition will reassemble the values into the ignition file.
* [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://`, `arn:`, or `gs://` schemes to specify a remote config.
Expand All @@ -41,6 +43,7 @@ For most cloud providers, cloud SSH keys and custom network configuration are ha
[DigitalOcean]: https://www.digitalocean.com/products/droplets/
[Exoscale]: https://www.exoscale.com/compute/
[Google Cloud]: https://cloud.google.com/compute
[Microsoft HyperV]: https://www.microsoft.com
[IBM Cloud]: https://www.ibm.com/cloud/vpc
[KubeVirt]: https://kubevirt.io
[Nutanix]: https://www.nutanix.com/products/ahv
Expand Down
5 changes: 5 additions & 0 deletions dracut/30ignition/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,8 @@ install() {
# needed for openstack config drive support
inst_rules 60-cdrom_id.rules
}

installkernel() {
# required by hyperv platform to read kvp from the kernel
instmods -c hv_utils
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
cloud.google.com/go/storage v1.29.0
github.com/aws/aws-sdk-go v1.44.199
github.com/beevik/etree v1.1.1-0.20200718192613-4a2f8b9d084c
github.com/containers/libhvee v0.0.0-20230214220824-8f58706cf6cc
github.com/coreos/go-semver v0.3.1
github.com/coreos/go-systemd/v22 v22.5.0
github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687
Expand Down Expand Up @@ -36,6 +37,7 @@ require (
github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/text v0.7.0 // indirect
Expand All @@ -44,5 +46,6 @@ require (
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 9 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ github.com/beevik/etree v1.1.1-0.20200718192613-4a2f8b9d084c/go.mod h1:0yGO2rna3
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containers/libhvee v0.0.0-20230214220824-8f58706cf6cc h1:e+T1zWTm431u7O4OKx5JDB7c9ELvi26QEbj20NszNM4=
github.com/containers/libhvee v0.0.0-20230214220824-8f58706cf6cc/go.mod h1:2zroU67Zh72KQzpmgj6ck8NYFS1/UQN1YKCzRv8caw0=
github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb h1:rmqyI19j3Z/74bIRhuC59RB442rXUazKNueVpfJPxg4=
github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb/go.mod h1:rcFZM3uxVvdyNmsAV2jopgPD1cs5SPWJWU5dOz2LUnw=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
Expand Down Expand Up @@ -75,6 +77,11 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pin/tftp v2.1.0+incompatible h1:Yng4J7jv6lOc6IF4XoB5mnd3P7ZrF60XQq+my3FAMus=
github.com/pin/tftp v2.1.0+incompatible/go.mod h1:xVpZOMCXTy+A5QMjEVN0Glwa1sUvaJhFXbr/aAxuxGY=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down Expand Up @@ -188,8 +195,9 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
5 changes: 5 additions & 0 deletions internal/platform/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/coreos/ignition/v2/internal/providers/exoscale"
"github.com/coreos/ignition/v2/internal/providers/file"
"github.com/coreos/ignition/v2/internal/providers/gcp"
"github.com/coreos/ignition/v2/internal/providers/hyperv"
"github.com/coreos/ignition/v2/internal/providers/ibmcloud"
"github.com/coreos/ignition/v2/internal/providers/kubevirt"
"github.com/coreos/ignition/v2/internal/providers/noop"
Expand Down Expand Up @@ -152,6 +153,10 @@ func init() {
name: "gcp",
fetch: gcp.FetchConfig,
})
configs.Register(Config{
name: "hyperv",
fetch: hyperv.FetchConfig,
})
configs.Register(Config{
name: "ibmcloud",
fetch: ibmcloud.FetchConfig,
Expand Down
20 changes: 20 additions & 0 deletions internal/providers/hyperv/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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.

package hyperv

var (
// key represents the prefix key name for finding kvp file parts
// in the key value pairs. it normally will have an integer added to the
// end when looking up keys sequentially
key = "com_coreos_ignition_kvp_"
)
46 changes: 46 additions & 0 deletions internal/providers/hyperv/kvp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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.

package hyperv

import (
"os/exec"

"github.com/containers/libhvee/pkg/kvp"
"github.com/coreos/ignition/v2/config/v3_4_experimental/types"
"github.com/coreos/ignition/v2/internal/providers/util"
"github.com/coreos/ignition/v2/internal/resource"
"github.com/coreos/vcontext/report"
)

func FetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) {
f.Logger.Info("attempting to read from kvp")

// To read key-value pairs from the Windows host through WMI, the hv_util kernel module
// must be loaded to create the kernel device itself.
_, err := f.Logger.LogCmd(exec.Command("modprobe", "hv_utils"), "loading hyperv kernel device module")
if err != nil {
return types.Config{}, report.Report{}, err
}

rawKvps, err := kvp.GetKeyValuePairs()
if err != nil {
return types.Config{}, report.Report{}, err
}

ign, _, err := kvp.GetSplitKeyValues(key, kvp.DefaultKVPPoolID, rawKvps)
if err != nil {
return types.Config{}, report.Report{}, err
}

return util.ParseConfig(f.Logger, []byte(ign))
}
Loading

0 comments on commit 59c5eb8

Please sign in to comment.