Skip to content

Commit

Permalink
Only use q35 machine type if supported
Browse files Browse the repository at this point in the history
Default EL7 qemu version does not support the q35 machine type.
Trying to create a VM which uses it will fail, and thus unconditionally
using q35 means crc no longer works on EL7.
This can be worked around by using the qemu-ev package, which needs
additional subscription, or by upgrading to EL8.

This commit will only try to use q35 if it's available.

This fixes crc-org/crc#1708
  • Loading branch information
cfergeau authored and praveenkumar committed Dec 4, 2020
1 parent 2990546 commit 4574845
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 8 deletions.
8 changes: 5 additions & 3 deletions pkg/libvirt/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

const macAddress = "52:fd:fc:07:21:82"

func domainXML(d *Driver) (string, error) {
func domainXML(d *Driver, machineType string) (string, error) {
domain := libvirtxml.Domain{
Type: "kvm",
Name: d.MachineName,
Expand Down Expand Up @@ -34,8 +34,7 @@ func domainXML(d *Driver) (string, error) {
},
OS: &libvirtxml.DomainOS{
Type: &libvirtxml.DomainOSType{
Machine: "q35",
Type: "hvm",
Type: "hvm",
},
BootDevices: []libvirtxml.DomainBootDevice{
{
Expand Down Expand Up @@ -93,6 +92,9 @@ func domainXML(d *Driver) (string, error) {
},
},
}
if machineType != "" {
domain.OS.Type.Machine = machineType
}
if d.Network != "" {
domain.Devices.Interfaces = []libvirtxml.DomainInterface{
{
Expand Down
7 changes: 4 additions & 3 deletions pkg/libvirt/domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestTemplating(t *testing.T) {
IOMode: "threads",
VSock: false,
},
})
}, "q35")

assert.NoError(t, err)
assert.Equal(t, `<domain type="kvm">
Expand Down Expand Up @@ -84,9 +84,10 @@ func TestVSockTemplating(t *testing.T) {
IOMode: "threads",
VSock: true,
},
})
}, "")
assert.NoError(t, err)
assert.Regexp(t, `(?s)<devices>(.*?)<vsock model="virtio">\s*<cid auto="yes">\s*</cid>\s*</vsock>(.*?)</devices>`, xml)
assert.Regexp(t, `(?s)<os>(.*?)<type>hvm</type>(.*?)</os>`, xml)
}

func TestNetworkTemplating(t *testing.T) {
Expand All @@ -106,7 +107,7 @@ func TestNetworkTemplating(t *testing.T) {
IOMode: "threads",
VSock: true,
},
})
}, "q35")
assert.NoError(t, err)
assert.Contains(t, xml, `<interface type="network">
<mac address="52:fd:fc:07:21:82"></mac>
Expand Down
39 changes: 37 additions & 2 deletions pkg/libvirt/libvirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,19 +334,54 @@ func (d *Driver) setupDiskImage() error {
return nil
}

func getMachineType(conn *libvirt.Connect) (string, error) {
capsXML, err := conn.GetCapabilities()
if err != nil {
return "", err
}
caps := &libvirtxml.Caps{}
err = caps.Unmarshal(capsXML)
if err != nil {
return "", fmt.Errorf("Error parsing libvirt capabilities: %w", err)
}

var capsGuestArch *libvirtxml.CapsGuestArch
for _, guest := range caps.Guests {
if guest.OSType == "hvm" && guest.Arch.Name == caps.Host.CPU.Arch {
log.Debugf("Found %s hypervisor with 'hvm' capabilities", caps.Host.CPU.Arch)
capsGuestArch = &guest.Arch
break
}
}

if capsGuestArch == nil {
return "", fmt.Errorf("Could not find a %s hypervisor with 'hvm' capabilities", caps.Host.CPU.Arch)
}
for _, machine := range capsGuestArch.Machines {
if machine.Name == "q35" || machine.Canonical == "q35" {
log.Debugf("Found q35 machine type")
return "q35", nil
}
}

log.Debugf("No q35 machine type")
return "", nil
}

func (d *Driver) Create() error {
err := d.setupDiskImage()
if err != nil {
return err
}

log.Debugf("Defining VM...")
xml, err := domainXML(d)
conn, err := d.getConn()
if err != nil {
return err
}
machineType, _ := getMachineType(conn)

conn, err := d.getConn()
xml, err := domainXML(d, machineType)
if err != nil {
return err
}
Expand Down

0 comments on commit 4574845

Please sign in to comment.