Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mantle/cmd/kola/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func syncCosaOptions() error {
}
}

if kola.Options.IgnitionVersion == "" {
if kola.Options.IgnitionVersion == "" && kola.QEMUOptions.DiskImage == "" {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me a while to debug why:

cosa run -d /path/to/rhcos-4.2.0.qcow2

was still getting spec3, it was because I was running from my /srv/walters/fcos builds directory...

I think in the future what we should do is basically synthesize a Build object if provided a --qemu-image and internally always reference that.

if kola.CosaBuild != nil {
kola.Options.IgnitionVersion = sdk.TargetIgnitionVersion(kola.CosaBuild)
}
Expand Down
80 changes: 17 additions & 63 deletions mantle/cmd/kola/qemuexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@
package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"

ignconverter "github.com/coreos/ign-converter"
v3 "github.com/coreos/ignition/v2/config/v3_0"
v3types "github.com/coreos/ignition/v2/config/v3_0/types"
"github.com/pkg/errors"
"github.com/spf13/cobra"

Expand Down Expand Up @@ -67,86 +65,42 @@ func init() {
cmdQemuExec.Flags().BoolVarP(&forceConfigInjection, "inject-ignition", "", false, "Force injecting Ignition config using guestfs")
}

func renderFragments() (string, error) {
buf, err := ioutil.ReadFile(ignition)
if err != nil {
return "", err
}
config, _, err := v3.Parse(buf)
func renderFragments(config v3types.Config) (*v3types.Config, error) {
for _, fragtype := range ignitionFragments {
switch fragtype {
case "autologin":
newconf := v3.Merge(config, conf.GetAutologin())
config = newconf
break
default:
return "", fmt.Errorf("Unknown fragment: %s", fragtype)
return nil, fmt.Errorf("Unknown fragment: %s", fragtype)
}
}
return &config, nil
}

newbuf, err := json.Marshal(config)
func runQemuExec(cmd *cobra.Command, args []string) error {
var err error
buf, err := ioutil.ReadFile(ignition)
if err != nil {
return "", err
return err
}
tmpf, err := ioutil.TempFile("", "qemuexec-ign")
config, _, err := v3.Parse(buf)
if err != nil {
return "", err
return errors.Wrapf(err, "parsing %s", ignition)
}
if _, err := tmpf.Write(newbuf); err != nil {
return "", err
}

return tmpf.Name(), nil
}

func runQemuExec(cmd *cobra.Command, args []string) error {
var err error
cleanupIgnition := false
if len(ignitionFragments) > 0 {
newconfig, err := renderFragments()
newconfig, err := renderFragments(config)
if err != nil {
return errors.Wrapf(err, "rendering fragments")
}
ignition = newconfig
cleanupIgnition = true
config = *newconfig
}
if kola.Options.IgnitionVersion == "v2" {
buf, err := ioutil.ReadFile(ignition)
if err != nil {
return err
}
config, _, err := v3.Parse(buf)
if err != nil {
return errors.Wrapf(err, "parsing %s", ignition)
}
ignc2, err := ignconverter.Translate3to2(config)
if err != nil {
return err
}
ignc2buf, err := json.Marshal(ignc2)
if err != nil {
return err
}
tmpf, err := ioutil.TempFile("", "qemuexec-ign-conv")
if err != nil {
return err
}
if _, err := tmpf.Write(ignc2buf); err != nil {
return err
}
if cleanupIgnition {
os.Remove(ignition)
}
cleanupIgnition = true
ignition = tmpf.Name()
builder, err := platform.NewBuilderFromParsed(config, kola.Options.IgnitionVersion == "v2")
if err != nil {
return errors.Wrapf(err, "creating qemu builder")
}
defer func() {
if cleanupIgnition {
os.Remove(ignition)
}
}()

builder := platform.NewBuilder(ignition, forceConfigInjection)
builder.ForceConfigInjection = forceConfigInjection
if len(knetargs) > 0 {
builder.IgnitionNetworkKargs = knetargs
}
Expand Down
45 changes: 45 additions & 0 deletions mantle/platform/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package platform

import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
Expand All @@ -25,6 +26,8 @@ import (
"strings"
"syscall"

ignconverter "github.com/coreos/ign-converter"
v3types "github.com/coreos/ignition/v2/config/v3_0/types"
"github.com/coreos/mantle/system"
"github.com/coreos/mantle/system/exec"
"github.com/coreos/mantle/util"
Expand All @@ -45,6 +48,7 @@ type Disk struct {

type QemuInstance struct {
qemu exec.Cmd
tmpConfig string
swtpmTmpd string
swtpm exec.Cmd
}
Expand Down Expand Up @@ -116,6 +120,9 @@ func (inst *QemuInstance) Wait() error {
}

func (inst *QemuInstance) Destroy() {
if inst.tmpConfig != "" {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this should be using a memfd_create() or so in the future, need to research Go bindings for that.

os.Remove(inst.tmpConfig)
}
if inst.qemu != nil {
if err := inst.qemu.Kill(); err != nil {
plog.Errorf("Error killing qemu instance %v: %v", inst.Pid(), err)
Expand Down Expand Up @@ -161,6 +168,9 @@ type QemuBuilder struct {

primaryDiskAdded bool

// cleanupConfig is true if we own the Ignition config
cleanupConfig bool

finalized bool
diskId uint
fds []*os.File
Expand All @@ -178,6 +188,37 @@ func NewBuilder(config string, forceIgnInjection bool) *QemuBuilder {
return &ret
}

func NewBuilderFromParsed(config v3types.Config, convSpec2 bool) (*QemuBuilder, error) {
var configBuf []byte
var err error
if convSpec2 {
ignc2, err := ignconverter.Translate3to2(config)
if err != nil {
return nil, err
}
configBuf, err = json.Marshal(ignc2)
if err != nil {
return nil, err
}
} else {
configBuf, err = json.Marshal(config)
if err != nil {
return nil, err
}
}
tmpf, err := ioutil.TempFile("", "mantle-qemu-ign")
if err != nil {
return nil, err
}
if _, err := tmpf.Write(configBuf); err != nil {
return nil, err
}

builder := NewBuilder(tmpf.Name(), false)
builder.cleanupConfig = true
return builder, nil
}

// AddFd appends a file descriptor that will be passed to qemu,
// returning a "/dev/fdset/<num>" argument that one can use with e.g.
// -drive file=/dev/fdset/<num>.
Expand Down Expand Up @@ -718,6 +759,10 @@ func (builder *QemuBuilder) Exec() (*QemuInstance, error) {
cmd.Stderr = os.Stderr
}

if builder.cleanupConfig {
inst.tmpConfig = builder.Config
}

if err = inst.qemu.Start(); err != nil {
return nil, err
}
Expand Down
16 changes: 0 additions & 16 deletions src/cmd-run
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,6 @@ fi
vmdiskdir=$(dirname "${VM_DISK}")
VM_DISK=$(realpath "${vmdiskdir}")/$(basename "${VM_DISK}")

# For future me: if you are in here wondering where this value is ultimately
# derived from, it exists in mantle/sdk/ignversion.go via `TargetIgnitionVersionFromName()`
ignition_version=$(disk_ignition_version "${VM_DISK}")
ign_validate="ignition-validate"

# Set name to coreos to be shorter, and default CPUs to host
set -- -name coreos -smp "${VM_NCPUS}" "$@"

Expand Down Expand Up @@ -230,24 +225,13 @@ cat > "${f}" <<EOF
}
}
EOF
if [ "${ignition_version}" = "2.2.0" ]; then
ign_validate="true"
spec2f=$(mktemp)
kola ign-convert2 < "${f}" > "${spec2f}"
mv "${spec2f}" "${f}"
fi

# We're using fd 9 to avoid clashing with kola's internal qemu fd mappings;
# this is a bug.
exec 9<>"${f}"
rm -f "${f}"
IGNITION_CONFIG_FILE=/proc/self/fd/9

if ! ${ign_validate} "${IGNITION_CONFIG_FILE}"; then
jq . < "${IGNITION_CONFIG_FILE}"
exit 1
fi

case "${DISK_CHANNEL}" in
virtio) ;;
nvme) kola_args+=('--qemu-nvme');;
Expand Down