diff options
author | Alvaro Saurin <alvaro.saurin@gmail.com> | 2016-07-05 18:12:26 +0200 |
---|---|---|
committer | Alvaro <alvaro.saurin@gmail.com> | 2016-10-10 17:40:24 +0200 |
commit | 44a504bcc42e16a6f7d8589fe23f602581838d8a (patch) | |
tree | 5847e20d31293ec05da2641b51e891aa1f992f6e | |
parent | 47f938971bb94d24751664eb1f9bf807e27557fa (diff) | |
download | terraform-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.markdown | 36 | ||||
-rw-r--r-- | libvirt/domain_def.go | 21 | ||||
-rw-r--r-- | libvirt/resource_libvirt_domain.go | 48 | ||||
-rw-r--r-- | libvirt/resource_libvirt_domain_netiface.go | 1 |
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, |