Skip to content

Commit

Permalink
ignition: add support for ignition config file
Browse files Browse the repository at this point in the history
it adds support to pass an ignition config file to vfkit that handles the provisioning process.
Vfkit start a small server, listening to a unix socket to feed the config file, and create a virtio-vsock device using port 1024. This will be used by Ignition that read its configuration using an HTTP GET over a vsock connection on port 1024.
Server code taken from https://github.com/containers/podman/blob/6487940534c1065d6c7753e3b6dfbe253666537d/pkg/machine/applehv/ignition.go
  • Loading branch information
Luca Stocchi authored and Luca Stocchi committed Oct 17, 2024
1 parent c3e0460 commit fec258c
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 0 deletions.
52 changes: 52 additions & 0 deletions cmd/vfkit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ limitations under the License.
package main

import (
"bytes"
"fmt"
"io"
"net"
"net/http"
"os"
"os/signal"
"runtime"
Expand All @@ -33,6 +37,7 @@ import (
"github.com/crc-org/vfkit/pkg/rest"
restvf "github.com/crc-org/vfkit/pkg/rest/vf"
"github.com/crc-org/vfkit/pkg/vf"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -86,6 +91,10 @@ func newVMConfiguration(opts *cmdline.Options) (*config.VirtualMachine, error) {
return nil, err
}

if err := vmConfig.AddIgnitionFileFromCmdLine(opts.IgnitionPath); err != nil {
return nil, err
}

return vmConfig, nil
}

Expand Down Expand Up @@ -137,6 +146,15 @@ func runVFKit(vmConfig *config.VirtualMachine, opts *cmdline.Options) error {
}

func runVirtualMachine(vmConfig *config.VirtualMachine, vm *vf.VirtualMachine) error {
if vm.Config().Ignition.SocketPath != "" {
go func() {
if err := startServer(vmConfig.Ignition.ConfigPath, vmConfig.Ignition.SocketPath); err != nil {
logrus.Error(err)
}
logrus.Debug("ignition vsock server exited")
}()
}

if err := vm.Start(); err != nil {
return err
}
Expand Down Expand Up @@ -198,3 +216,37 @@ func runVirtualMachine(vmConfig *config.VirtualMachine, vm *vf.VirtualMachine) e

return <-errCh
}

func startServer(ignitionFile string, ignitionSocketPath string) error {
file, err := os.Open(ignitionFile)
if err != nil {
return err
}
defer file.Close()

buf := new(bytes.Buffer)
_, err = io.Copy(buf, file)
if err != nil {
return err
}

mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

Check failure on line 234 in cmd/vfkit/main.go

View workflow job for this annotation

GitHub Actions / lint

unused-parameter: parameter 'r' seems to be unused, consider removing or renaming it as _ (revive)
_, err := w.Write(buf.Bytes())
if err != nil {
logrus.Errorf("failed to serve ignition file: %v", err)
}
})

listener, err := net.Listen("unix", ignitionSocketPath)
if err != nil {
return err
}
logrus.Debugf("ignition socket device: %s", ignitionSocketPath)
defer func() {
if err := listener.Close(); err != nil {
logrus.Error(err)
}
}()
return http.Serve(listener, mux)

Check failure on line 251 in cmd/vfkit/main.go

View workflow job for this annotation

GitHub Actions / lint

G114: Use of net/http serve function that has no support for setting timeouts (gosec)
}
4 changes: 4 additions & 0 deletions pkg/cmdline/cmdline.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type Options struct {
LogLevel string

UseGUI bool

IgnitionPath string
}

const DefaultRestfulURI = "none://"
Expand Down Expand Up @@ -50,4 +52,6 @@ func AddFlags(cmd *cobra.Command, opts *Options) {
cmd.Flags().StringVar(&opts.LogLevel, "log-level", "", "set log level")
cmd.Flags().StringVar(&opts.RestfulURI, "restful-uri", DefaultRestfulURI, "URI address for RESTful services")

cmd.Flags().StringVar(&opts.IgnitionPath, "ignition", "", "path to the ignition file")

}
44 changes: 44 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"math"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"

Expand All @@ -30,6 +31,7 @@ type VirtualMachine struct {
Bootloader Bootloader `json:"bootloader"`
Devices []VirtioDevice `json:"devices,omitempty"`
Timesync *TimeSync `json:"timesync,omitempty"`
Ignition Ignition `json:"ignition,omitempty"`
}

// TimeSync enables synchronization of the host time to the linux guest after the host was suspended.
Expand All @@ -38,6 +40,11 @@ type TimeSync struct {
VsockPort uint32 `json:"vsockPort"`
}

type Ignition struct {
ConfigPath string
SocketPath string
}

// The VMComponent interface represents a VM element (device, bootloader, ...)
// which can be converted from/to commandline parameters
type VMComponent interface {
Expand Down Expand Up @@ -96,6 +103,10 @@ func (vm *VirtualMachine) ToCmdLine() ([]string, error) {
args = append(args, devArgs...)
}

if vm.Ignition.ConfigPath != "" {
args = append(args, "--ignition", vm.Ignition.ConfigPath)
}

return args, nil
}

Expand Down Expand Up @@ -191,6 +202,39 @@ func (vm *VirtualMachine) TimeSync() *TimeSync {
return vm.Timesync
}

func IgnitionNew(configPath string, socketPath string) (Ignition, error) {
if configPath == "" || socketPath == "" {
return Ignition{}, fmt.Errorf("config path and socket path cannot be empty")
}
return Ignition{
ConfigPath: configPath,
SocketPath: socketPath,
}, nil
}

func (vm *VirtualMachine) AddIgnitionFileFromCmdLine(cmdlineOpts string) error {
if cmdlineOpts == "" {
return nil
}
opts := strings.Split(cmdlineOpts, ",")
if len(opts) != 1 {
return fmt.Errorf("ignition only accept one option in command line argument")
}

socketPath := filepath.Join(os.TempDir(), "ignition.sock")
dev, err := VirtioVsockNew(1024, socketPath, true)
if err != nil {
return err
}
vm.Devices = append(vm.Devices, dev)
ignition, err := IgnitionNew(opts[0], socketPath)
if err != nil {
return err
}
vm.Ignition = ignition
return nil
}

func TimeSyncNew(vsockPort uint) (VMComponent, error) {

if vsockPort > math.MaxUint32 {
Expand Down

0 comments on commit fec258c

Please sign in to comment.