summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hipp <thomashipp@gmail.com>2017-09-22 12:22:06 +0200
committerGitHub <noreply@github.com>2017-09-22 12:22:06 +0200
commit5dc5400f354238a7b6df72b8ae84d2ef45339914 (patch)
tree27954c23dc801dfe0a244f4fec869d41e2846853
parent8dcb4a10b34acadd150f933d1ab744a169d9795f (diff)
parentae27c1b16dc6dbd6c83a8a6e3689ccb425ae5305 (diff)
downloadterraform-provider-libvirt-5dc5400f354238a7b6df72b8ae84d2ef45339914.tar
terraform-provider-libvirt-5dc5400f354238a7b6df72b8ae84d2ef45339914.tar.gz
Merge pull request #180 from deasmi/machinearchupdate
Full support for arch,machine & emulator settings
-rw-r--r--libvirt/domain_def.go29
-rw-r--r--libvirt/resource_libvirt_domain.go49
-rw-r--r--libvirt/utils_domain_def.go50
-rw-r--r--libvirt/utils_libvirt.go15
-rw-r--r--libvirt/utils_libvirt_test.go96
-rwxr-xr-xtravis/run-tests-inside-guest2
-rw-r--r--website/docs/r/domain.html.markdown1
7 files changed, 230 insertions, 12 deletions
diff --git a/libvirt/domain_def.go b/libvirt/domain_def.go
index 250fc642..1ade1f5a 100644
--- a/libvirt/domain_def.go
+++ b/libvirt/domain_def.go
@@ -1,9 +1,9 @@
package libvirt
import (
+ libvirt "github.com/libvirt/libvirt-go"
+ libvirtxml "github.com/libvirt/libvirt-go-xml"
"os"
-
- "github.com/libvirt/libvirt-go-xml"
)
func newFilesystemDef() libvirtxml.DomainFilesystem {
@@ -20,7 +20,9 @@ func newDomainDef() libvirtxml.Domain {
domainDef := libvirtxml.Domain{
OS: &libvirtxml.DomainOS{
Type: &libvirtxml.DomainOSType{
- Type: "hvm",
+ Type: "hvm",
+ Arch: "x86_64",
+ Machine: "pc",
},
},
Memory: &libvirtxml.DomainMemory{
@@ -75,3 +77,24 @@ func newDomainDef() libvirtxml.Domain {
return domainDef
}
+
+func newDomainDefForConnection(virConn *libvirt.Connect) (libvirtxml.Domain, error) {
+ d := newDomainDef()
+ caps, err := getHostCapabilities(virConn)
+ if err != nil {
+ return d, err
+ }
+ guest, err := getGuestForArchType(caps, d.OS.Type.Arch, d.OS.Type.Type)
+ if err != nil {
+ return d, err
+ }
+
+ d.Devices.Emulator = guest.Arch.Emulator
+
+ canonicalmachine, err := getCanonicalMachineName(caps, d.OS.Type.Arch, d.OS.Type.Type, d.OS.Type.Machine)
+ if err != nil {
+ return d, err
+ }
+ d.OS.Type.Machine = canonicalmachine
+ return d, nil
+}
diff --git a/libvirt/resource_libvirt_domain.go b/libvirt/resource_libvirt_domain.go
index 64f1b914..fadc62a6 100644
--- a/libvirt/resource_libvirt_domain.go
+++ b/libvirt/resource_libvirt_domain.go
@@ -148,12 +148,14 @@ func resourceLibvirtDomain() *schema.Resource {
Required: false,
},
"machine": &schema.Schema{
- Type: schema.TypeString,
+ Type: schema.TypeString,
Optional: true,
+ Default: "pc",
},
"arch": &schema.Schema{
- Type: schema.TypeString,
+ Type: schema.TypeString,
Optional: true,
+ Default: "x86_64",
},
"boot_device": &schema.Schema{
Type: schema.TypeList,
@@ -163,6 +165,11 @@ func resourceLibvirtDomain() *schema.Resource {
Schema: bootDeviceSchema(),
},
},
+ "emulator": &schema.Schema{
+ Type: schema.TypeString,
+ Default: "/usr/bin/qemu-system-x86_64",
+ Optional: true,
+ },
},
}
}
@@ -208,8 +215,10 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("The libvirt connection was nil.")
}
- domainDef := newDomainDef()
-
+ domainDef, err := newDomainDefForConnection(virConn)
+ if err != nil {
+ return err
+ }
if name, ok := d.GetOk("name"); ok {
domainDef.Name = name.(string)
}
@@ -270,7 +279,8 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
domainDef.OS.Type.Arch = d.Get("arch").(string)
domainDef.OS.Type.Machine = d.Get("machine").(string)
-
+ domainDef.Devices.Emulator = d.Get("emulator").(string)
+
if firmware, ok := d.GetOk("firmware"); ok {
firmwareFile := firmware.(string)
if _, err := os.Stat(firmwareFile); os.IsNotExist(err) {
@@ -811,7 +821,11 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] read: obtained XML desc for domain:\n%s", xmlDesc)
- domainDef := newDomainDef()
+ domainDef, err := newDomainDefForConnection(virConn)
+ if err != nil {
+ return err
+ }
+
err = xml.Unmarshal([]byte(xmlDesc), &domainDef)
if err != nil {
return fmt.Errorf("Error reading libvirt domain XML description: %s", err)
@@ -828,7 +842,24 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
d.Set("firmware", domainDef.OS.Loader)
d.Set("nvram", domainDef.OS.NVRam)
d.Set("cpu", domainDef.CPU)
+ d.Set("arch", domainDef.OS.Type.Arch)
d.Set("autostart", autostart)
+ d.Set("arch", domainDef.OS.Type.Arch)
+
+ caps, err := getHostCapabilities(virConn)
+ if err != nil {
+ return err
+ }
+ machine, err := getOriginalMachineName(caps, domainDef.OS.Type.Arch, domainDef.OS.Type.Type,
+ domainDef.OS.Type.Machine)
+ if err != nil {
+ return err
+ }
+ d.Set("machine", machine)
+
+ // Emulator is the same as the default don't set it in domainDef
+ // or it will show as changed
+ d.Set("emulator", domainDef.Devices.Emulator)
running, err := isDomainRunning(*domain)
if err != nil {
@@ -1009,7 +1040,11 @@ func resourceLibvirtDomainDelete(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("Error retrieving libvirt domain XML description: %s", err)
}
- domainDef := newDomainDef()
+ domainDef, err := newDomainDefForConnection(virConn)
+ if err != nil {
+ return err
+ }
+
err = xml.Unmarshal([]byte(xmlDesc), &domainDef)
if err != nil {
return fmt.Errorf("Error reading libvirt domain XML description: %s", err)
diff --git a/libvirt/utils_domain_def.go b/libvirt/utils_domain_def.go
new file mode 100644
index 00000000..2f7f74a6
--- /dev/null
+++ b/libvirt/utils_domain_def.go
@@ -0,0 +1,50 @@
+package libvirt
+
+import (
+ "fmt"
+ libvirtxml "github.com/libvirt/libvirt-go-xml"
+ "log"
+)
+
+func getGuestForArchType(caps libvirtxml.Caps, arch string, virttype string) (libvirtxml.CapsGuest, error) {
+ for _, guest := range caps.Guests {
+ log.Printf("[TRACE] Checking for %s/%s against %s/%s\n", arch, virttype, guest.Arch.Name, guest.OSType)
+ if guest.Arch.Name == arch && guest.OSType == virttype {
+ log.Printf("[DEBUG] Found %d machines in guest for %s/%s", len(guest.Arch.Machines), arch, virttype)
+ return guest, nil
+ }
+ }
+ return libvirtxml.CapsGuest{}, fmt.Errorf("[DEBUG] Could not find any guests for architecure type %s/%s", virttype, arch)
+}
+
+func getCanonicalMachineName(caps libvirtxml.Caps, arch string, virttype string, targetmachine string) (string, error) {
+ guest, err := getGuestForArchType(caps, arch, virttype)
+ if err != nil {
+ return "", err
+ }
+
+ for _, machine := range guest.Arch.Machines {
+ if machine.Name == targetmachine {
+ if machine.Canonical != nil {
+ return *machine.Canonical, nil
+ }
+ return machine.Name, nil
+ }
+ }
+ return "", fmt.Errorf("[WARN] Cannot find machine type %s for %s/%s in %v", targetmachine, virttype, arch, caps)
+}
+
+
+func getOriginalMachineName(caps libvirtxml.Caps, arch string, virttype string, targetmachine string) (string, error) {
+ guest, err := getGuestForArchType(caps, arch, virttype)
+ if err != nil {
+ return "", err
+ }
+
+ for _, machine := range guest.Arch.Machines {
+ if machine.Canonical != nil && *machine.Canonical == targetmachine {
+ return machine.Name, nil
+ }
+ }
+ return targetmachine, nil // There wasn't a canonical mapping to this
+}
diff --git a/libvirt/utils_libvirt.go b/libvirt/utils_libvirt.go
index cc86b1ec..22816769 100644
--- a/libvirt/utils_libvirt.go
+++ b/libvirt/utils_libvirt.go
@@ -5,7 +5,7 @@ import (
"log"
libvirt "github.com/libvirt/libvirt-go"
- "github.com/libvirt/libvirt-go-xml"
+ libvirtxml "github.com/libvirt/libvirt-go-xml"
)
func getHostXMLDesc(ip, mac, name string) string {
@@ -68,3 +68,16 @@ func getHostArchitecture(virConn *libvirt.Connect) (string, error) {
return capabilities.Host.CPU.Arch, nil
}
+
+func getHostCapabilities(virConn *libvirt.Connect) (libvirtxml.Caps, error) {
+ // We should perhaps think of storing this on the connect object
+ // on first call to avoid the back and forth
+ caps := libvirtxml.Caps{}
+ capsXML, err := virConn.GetCapabilities()
+ if err != nil {
+ return caps, err
+ }
+ xml.Unmarshal([]byte(capsXML), &caps)
+ log.Printf("[TRACE] Capabilities of host \n %+v", caps)
+ return caps, nil
+}
diff --git a/libvirt/utils_libvirt_test.go b/libvirt/utils_libvirt_test.go
index fa76cd84..38d90136 100644
--- a/libvirt/utils_libvirt_test.go
+++ b/libvirt/utils_libvirt_test.go
@@ -3,8 +3,11 @@ package libvirt
import (
"encoding/xml"
"testing"
+ "time"
+ libvirt "github.com/libvirt/libvirt-go"
"github.com/libvirt/libvirt-go-xml"
+ "os"
)
func TestGetHostXMLDesc(t *testing.T) {
@@ -32,3 +35,96 @@ func TestGetHostXMLDesc(t *testing.T) {
t.Errorf("expected name %s, got %s", name, dd.Name)
}
}
+
+func connect(t *testing.T) *libvirt.Connect {
+ conn, err := libvirt.NewConnect(os.Getenv("LIBVIRT_DEFAULT_URI"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ return conn
+}
+
+func TestGetHostArchitecture(t *testing.T) {
+
+ conn := connect(t)
+ defer conn.Close()
+
+ arch, err := getHostArchitecture(conn)
+
+ if err != nil {
+ t.Errorf("error %v", err)
+ }
+
+ t.Logf("[DEBUG] arch - %s", arch)
+
+ if arch == "" {
+ t.Errorf("arch is blank.")
+ }
+}
+
+func TestGetCanonicalMachineName(t *testing.T) {
+
+ conn := connect(t)
+ defer conn.Close()
+ arch := "x86_64"
+ virttype := "hvm"
+ machine := "pc"
+
+ caps,err := getHostCapabilities(conn)
+ if err != nil {
+ t.Error(err)
+ }
+
+ name, err := getCanonicalMachineName(caps, arch, virttype, machine)
+
+ if err != nil {
+ t.Errorf("Could not get canonical name for %s/%s", arch, machine)
+ return
+ }
+
+ t.Logf("Canonical name for %s/%s = %s", arch, machine, name)
+}
+
+func TestGetOriginalMachineName(t *testing.T) {
+ conn := connect(t)
+ defer conn.Close()
+ arch := "x86_64"
+ virttype := "hvm"
+ machine := "pc"
+
+ caps,err := getHostCapabilities(conn)
+ if err != nil {
+ t.Error(err)
+ }
+
+ canonname, err := getCanonicalMachineName(caps, arch, virttype, machine)
+ if err != nil {
+ t.Error(err)
+ }
+ reversename, err := getOriginalMachineName(caps, arch, virttype, canonname)
+ if err != nil {
+ t.Error(err)
+ }
+ if reversename != machine {
+ t.Errorf("Cannot reverse canonical machine lookup")
+ }
+
+ t.Logf("Reverse canonical lookup for %s is %s which matches %s", canonname, reversename, machine)
+}
+
+func TestGetHostCapabilties(t *testing.T) {
+ start := time.Now()
+ conn := connect(t)
+ defer conn.Close()
+ caps,err := getHostCapabilities(conn)
+ if err != nil {
+ t.Errorf("Can't get host capabilties")
+ }
+ if caps.Host.UUID == "" {
+ t.Errorf("Host has no UUID!")
+ }
+
+ elapsed := time.Since(start)
+ t.Logf("[DEBUG] Get host capabilites took %s", elapsed)
+}
diff --git a/travis/run-tests-inside-guest b/travis/run-tests-inside-guest
index 63fbb0c5..4499297f 100755
--- a/travis/run-tests-inside-guest
+++ b/travis/run-tests-inside-guest
@@ -16,4 +16,4 @@ go build .
export TERRAFORM_LIBVIRT_TEST_DOMAIN_TYPE=qemu
export LIBVIRT_DEFAULT_URI="qemu:///system"
export TF_ACC=true
-go test -v -covermode=count -coverprofile=profile.cov ./libvirt
+go test -v -covermode=count -coverprofile=profile.cov -timeout=1200s ./libvirt
diff --git a/website/docs/r/domain.html.markdown b/website/docs/r/domain.html.markdown
index 82b354b9..c9bbfbaa 100644
--- a/website/docs/r/domain.html.markdown
+++ b/website/docs/r/domain.html.markdown
@@ -57,6 +57,7 @@ The following arguments are supported:
defaults to the wrong machine type for your template
* `boot_device` - (Optional) A list of devices (dev) which defines boot order. Example
[below](#define-boot-device-order).
+* `emulator` - (Optional) The path of the emulator to use
### UEFI images