summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Saurin <alvaro.saurin@gmail.com>2016-07-05 18:12:26 +0200
committerAlvaro <alvaro.saurin@gmail.com>2016-10-10 17:40:24 +0200
commit44a504bcc42e16a6f7d8589fe23f602581838d8a (patch)
tree5847e20d31293ec05da2641b51e891aa1f992f6e
parent47f938971bb94d24751664eb1f9bf807e27557fa (diff)
downloadterraform-provider-libvirt-44a504bcc42e16a6f7d8589fe23f602581838d8a.tar
terraform-provider-libvirt-44a504bcc42e16a6f7d8589fe23f602581838d8a.tar.gz
Implement firmware/nvram for domains, so we can use UEFI images
Minor fixes
-rw-r--r--docs/providers/libvirt/r/domain.html.markdown36
-rw-r--r--libvirt/domain_def.go21
-rw-r--r--libvirt/resource_libvirt_domain.go48
-rw-r--r--libvirt/resource_libvirt_domain_netiface.go1
4 files changed, 99 insertions, 7 deletions
diff --git a/docs/providers/libvirt/r/domain.html.markdown b/docs/providers/libvirt/r/domain.html.markdown
index c06490e8..d5fb93a2 100644
--- a/docs/providers/libvirt/r/domain.html.markdown
+++ b/docs/providers/libvirt/r/domain.html.markdown
@@ -41,6 +41,42 @@ The following arguments are supported:
cloud-init won't cause the domain to be recreated, however the change will
have effect on the next reboot.
+Some extra arguments are also provided for using UEFI images:
+
+* `firmware` - (Optional) The UEFI rom images for exercising UEFI secure boot in a qemu
+environment. Users should usually specify one of the standard _Open Virtual Machine
+Firmware_ (_OVMF_) images available for their distributions. The file will be opened
+read-only.
+* `nvram` - (Optional) the _nvram_ variables file corresponding to the firmware. When provided,
+this file must be writable and specific to this domain, as it will be updated when running
+the domain. However, `libvirt` can manage this automatically (and this is the recommended solution)
+if a mapping for the firmware to a _variables file_ exists in `/etc/libvirt/qemu.conf:nvram`.
+In that case, `libvirt` will copy that variables file into a file specific for this domain.
+
+So you should typically use the firmware as this,
+
+```
+
+resource "libvirt_domain" "my_machine" {
+ name = "my_machine"
+ firmware = "/usr/share/qemu/ovmf-x86_64-code.bin"
+ memory = "2048"
+
+ disk {
+ volume_id = "${libvirt_volume.volume.id}"
+ }
+ ...
+}
+```
+
+and `/etc/libvirt/qemu.conf` should contain:
+
+```
+nvram = [
+ "/usr/share/qemu/ovmf-x86_64-code.bin:/usr/share/qemu/ovmf-x86_64-vars.bin"
+]
+```
+
The `disk` block supports:
* `volume_id` - (Required) The volume id to use for this disk.
diff --git a/libvirt/domain_def.go b/libvirt/domain_def.go
index b44cbbfe..7246d943 100644
--- a/libvirt/domain_def.go
+++ b/libvirt/domain_def.go
@@ -53,23 +53,36 @@ type defMetadata struct {
}
type defOs struct {
- Type defOsType `xml:"type"`
+ Type defOsType `xml:"type"`
+ Loader *defLoader `xml:"loader,omitempty"`
+ NvRam *defNvRam `xml:"nvram,omitempty"`
}
type defOsType struct {
Arch string `xml:"arch,attr,omitempty"`
Machine string `xml:"machine,attr,omitempty"`
- Name string `xml:"chardata"`
+ Name string `xml:",chardata"`
}
type defMemory struct {
Unit string `xml:"unit,attr"`
- Amount int `xml:"chardata"`
+ Amount int `xml:",chardata"`
}
type defVCpu struct {
Placement string `xml:"unit,attr"`
- Amount int `xml:"chardata"`
+ Amount int `xml:",chardata"`
+}
+
+type defLoader struct {
+ ReadOnly string `xml:"readonly,attr,omitempty"`
+ Type string `xml:"type,attr,omitempty"`
+ File string `xml:",chardata"`
+}
+
+// <nvram>/var/lib/libvirt/qemu/nvram/sled12sp1_VARS.fd</nvram>
+type defNvRam struct {
+ File string `xml:",chardata"`
}
// Creates a domain definition with the defaults
diff --git a/libvirt/resource_libvirt_domain.go b/libvirt/resource_libvirt_domain.go
index 5783928e..49eb111d 100644
--- a/libvirt/resource_libvirt_domain.go
+++ b/libvirt/resource_libvirt_domain.go
@@ -7,6 +7,7 @@ import (
"net"
"strings"
"time"
+ "os"
"github.com/davecgh/go-spew/spew"
libvirt "github.com/dmacvicar/libvirt-go"
@@ -48,6 +49,16 @@ func resourceLibvirtDomain() *schema.Resource {
Default: 512,
ForceNew: true,
},
+ "firmware": &schema.Schema{
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ },
+ "nvram": &schema.Schema{
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ },
"running": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
@@ -117,6 +128,28 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
domainDef.Metadata.TerraformLibvirt.Xml = metadata.(string)
}
+ if firmware, ok := d.GetOk("firmware"); ok {
+ firmwareFile := firmware.(string)
+ if _, err := os.Stat(firmwareFile); os.IsNotExist(err) {
+ return fmt.Errorf("Could not find firmware file '%s'.", firmwareFile)
+ }
+ domainDef.Os.Loader = &defLoader{
+ File: firmwareFile,
+ ReadOnly: "yes",
+ Type: "pflash",
+ }
+
+ if nvram, ok := d.GetOk("nvram"); ok {
+ nvramFile := nvram.(string)
+ if _, err := os.Stat(nvramFile); os.IsNotExist(err) {
+ return fmt.Errorf("Could not find nvram file '%s'.", nvramFile)
+ }
+ domainDef.Os.NvRam = &defNvRam{
+ File: nvramFile,
+ }
+ }
+ }
+
domainDef.Memory.Amount = d.Get("memory").(int)
domainDef.VCpu.Amount = d.Get("vcpu").(int)
@@ -478,6 +511,8 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("Error retrieving libvirt domain XML description: %s", err)
}
+ log.Printf("[DEBUG] read: obtained XML desc for domain:\n%s", xmlDesc)
+
domainDef := newDomainDef()
err = xml.Unmarshal([]byte(xmlDesc), &domainDef)
if err != nil {
@@ -488,6 +523,8 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
d.Set("metadata", domainDef.Metadata.TerraformLibvirt.Xml)
d.Set("vpu", domainDef.VCpu)
d.Set("memory", domainDef.Memory)
+ d.Set("firmware", domainDef.Os.Loader)
+ d.Set("nvram", domainDef.Os.NvRam)
running, err := isDomainRunning(domain)
if err != nil {
@@ -656,8 +693,15 @@ func resourceLibvirtDomainDelete(d *schema.ResourceData, meta interface{}) error
}
}
- if err := domain.Undefine(); err != nil {
- return fmt.Errorf("Couldn't undefine libvirt domain: %s", err)
+ if err := domain.UndefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_NVRAM); err != nil {
+ if e := err.(libvirt.VirError); e.Code == libvirt.VIR_ERR_NO_SUPPORT || e.Code == libvirt.VIR_ERR_INVALID_ARG {
+ log.Printf("libvirt does not support undefine flags: will try again without flags")
+ if err := domain.Undefine(); err != nil {
+ return fmt.Errorf("Couldn't undefine libvirt domain: %s", err)
+ }
+ } else {
+ return fmt.Errorf("Couldn't undefine libvirt domain with flags: %s", err)
+ }
}
return nil
diff --git a/libvirt/resource_libvirt_domain_netiface.go b/libvirt/resource_libvirt_domain_netiface.go
index 88c5e69b..879496b0 100644
--- a/libvirt/resource_libvirt_domain_netiface.go
+++ b/libvirt/resource_libvirt_domain_netiface.go
@@ -32,7 +32,6 @@ func networkInterfaceCommonSchema() map[string]*schema.Schema {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
- Computed: true,
},
"passthrough": &schema.Schema{
Type: schema.TypeString,