diff options
-rw-r--r-- | examples/uefi/libvirt.tf | 38 | ||||
-rw-r--r-- | libvirt/resource_libvirt_domain.go | 29 | ||||
-rw-r--r-- | libvirt/resource_libvirt_domain_test.go | 96 | ||||
-rwxr-xr-x | travis/setup-guest | 2 | ||||
-rw-r--r-- | website/docs/r/domain.html.markdown | 53 |
5 files changed, 202 insertions, 16 deletions
diff --git a/examples/uefi/libvirt.tf b/examples/uefi/libvirt.tf new file mode 100644 index 00000000..1419806f --- /dev/null +++ b/examples/uefi/libvirt.tf @@ -0,0 +1,38 @@ +provider "libvirt" { + uri = "qemu:///system" +} + +resource "libvirt_volume" "ubuntu-cloud-uefi" { + name = "ubuntu-cloud-uefi" + source = "https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-uefi1.img" +} + +resource "libvirt_volume" "volume" { + name = "vm${count.index}" + base_volume_id = "${libvirt_volume.ubuntu-cloud-uefi.id}" + count = 1 +} + +resource "libvirt_domain" "domain" { + count = 2 + name = "ubuntu-cloud-${count.index}" + memory = "512" + vcpu = 1 + # This file is usually present as part of the ovmf firmware package in many + # Linux distributions. + firmware = "/usr/share/OVMF/OVMF_CODE.fd" + nvram { + # This is the file which will back the UEFI NVRAM content. + file = "/var/lib/libvirt/qemu/nvram/vm${count.index}_VARS.fd" + # This file needs to be provided by the user. + template = "/srv/provisioning/terraform/debian-stable-uefi_VARS.fd" + } + disk { + volume_id = "${element(libvirt_volume.volume.*.id, count.index)}" + } + graphics { + type = "spice" + listen_type = "address" + autoport = true + } + diff --git a/libvirt/resource_libvirt_domain.go b/libvirt/resource_libvirt_domain.go index 66b6a122..844b6cf7 100644 --- a/libvirt/resource_libvirt_domain.go +++ b/libvirt/resource_libvirt_domain.go @@ -75,7 +75,7 @@ func resourceLibvirtDomain() *schema.Resource { ForceNew: true, }, "nvram": &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeMap, Optional: true, ForceNew: true, }, @@ -244,21 +244,30 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error if _, err := os.Stat(firmwareFile); os.IsNotExist(err) { return fmt.Errorf("Could not find firmware file '%s'.", firmwareFile) } - domainDef.OS = &libvirtxml.DomainOS{ - Loader: &libvirtxml.DomainLoader{ - Path: firmwareFile, - Readonly: "yes", - Type: "pflash", - }, + domainDef.OS.Loader = &libvirtxml.DomainLoader{ + Path: firmwareFile, + Readonly: "yes", + Type: "pflash", + Secure: "no", } if nvram, ok := d.GetOk("nvram"); ok { - nvramFile := nvram.(string) + nvram_map := nvram.(map[string]interface{}) + + nvramFile := nvram_map["file"].(string) if _, err := os.Stat(nvramFile); os.IsNotExist(err) { return fmt.Errorf("Could not find nvram file '%s'.", nvramFile) } + nvramTemplateFile := "" + if nvram_template, ok := nvram_map["template"]; ok { + nvramTemplateFile = nvram_template.(string) + if _, err := os.Stat(nvramTemplateFile); os.IsNotExist(err) { + return fmt.Errorf("Could not find nvram template file '%s'.", nvramTemplateFile) + } + } domainDef.OS.NVRam = &libvirtxml.DomainNVRam{ - NVRam: nvramFile, + NVRam: nvramFile, + Template: nvramTemplateFile, } } } @@ -768,7 +777,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error { } d.Set("name", domainDef.Name) - d.Set("vpu", domainDef.VCPU) + d.Set("vcpu", domainDef.VCPU) d.Set("memory", domainDef.Memory) d.Set("firmware", domainDef.OS.Loader) d.Set("nvram", domainDef.OS.NVRam) diff --git a/libvirt/resource_libvirt_domain_test.go b/libvirt/resource_libvirt_domain_test.go index 1410b639..e4d2f542 100644 --- a/libvirt/resource_libvirt_domain_test.go +++ b/libvirt/resource_libvirt_domain_test.go @@ -3,6 +3,7 @@ package libvirt import ( "encoding/xml" "fmt" + "io/ioutil" "log" "testing" @@ -587,3 +588,98 @@ func testAccCheckLibvirtScsiDisk(n string, domain *libvirt.Domain) resource.Test return nil } } + +func createNvramFile() (string, error) { + // size of an accepted, valid, nvram backing store + nvram_dummy_buffer := make([]byte, 131072) + file, err := ioutil.TempFile("/tmp", "nvram") + if err != nil { + return "", err + } + file.Chmod(0777) + _, err = file.Write(nvram_dummy_buffer) + if err != nil { + return "", err + } + if file.Close() != nil { + return "", err + } + return file.Name(), nil +} + +func TestAccLibvirtDomain_FirmwareNoTemplate(t *testing.T) { + nvram_path, err := createNvramFile() + if err != nil { + t.Fatal(err) + } + + var domain libvirt.Domain + var config = fmt.Sprintf(` + resource "libvirt_domain" "acceptance-test-domain" { + name = "terraform-test-firmware-no-template" + firmware = "/usr/share/ovmf/OVMF.fd" + nvram { + file = "%s" + } + }`, nvram_path) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLibvirtDomainDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testAccCheckLibvirtDomainExists("libvirt_domain.acceptance-test-domain", &domain), + resource.TestCheckResourceAttr( + "libvirt_domain.acceptance-test-domain", "name", "terraform-test-firmware-no-template"), + resource.TestCheckResourceAttr( + "libvirt_domain.acceptance-test-domain", "nvram.file", nvram_path), + resource.TestCheckResourceAttr( + "libvirt_domain.acceptance-test-domain", "firmware", "/usr/share/ovmf/OVMF.fd"), + ), + }, + }, + }) +} + +func TestAccLibvirtDomain_FirmwareTemplate(t *testing.T) { + nvram_path, err := createNvramFile() + if err != nil { + t.Fatal(err) + } + + var domain libvirt.Domain + var config = fmt.Sprintf(` + resource "libvirt_domain" "acceptance-test-domain" { + name = "terraform-test-firmware-with-template" + firmware = "/usr/share/ovmf/OVMF.fd" + nvram { + file = "%s" + template = "/usr/share/qemu/OVMF.fd" + } + }`, nvram_path) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLibvirtDomainDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testAccCheckLibvirtDomainExists("libvirt_domain.acceptance-test-domain", &domain), + resource.TestCheckResourceAttr( + "libvirt_domain.acceptance-test-domain", "name", "terraform-test-firmware-with-template"), + resource.TestCheckResourceAttr( + "libvirt_domain.acceptance-test-domain", "nvram.file", nvram_path), + resource.TestCheckResourceAttr( + "libvirt_domain.acceptance-test-domain", "nvram.template", "/usr/share/qemu/OVMF.fd"), + resource.TestCheckResourceAttr( + "libvirt_domain.acceptance-test-domain", "firmware", "/usr/share/ovmf/OVMF.fd"), + ), + }, + }, + }) +} diff --git a/travis/setup-guest b/travis/setup-guest index 43b87853..e5f982a5 100755 --- a/travis/setup-guest +++ b/travis/setup-guest @@ -13,7 +13,7 @@ while check_network ; [ $? -ne 0 ];do done apt-get -qq update -apt-get install -y qemu libvirt-bin libvirt-dev golang-1.8 +apt-get install -y qemu libvirt-bin libvirt-dev golang-1.8 ovmf echo -e "<pool type='dir'>\n<name>default</name>\n<target>\n<path>/pool-default</path>\n</target>\n</pool>" > pool.xml mkdir /pool-default chmod a+rwx /pool-default diff --git a/website/docs/r/domain.html.markdown b/website/docs/r/domain.html.markdown index 6c40cb10..bdb71077 100644 --- a/website/docs/r/domain.html.markdown +++ b/website/docs/r/domain.html.markdown @@ -59,11 +59,14 @@ Some extra arguments are also provided for using UEFI images: 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. +* `nvram` - (Optional) this block allows specifying the following attributes related to the _nvram_: + * `file` - path to the file backing the NVRAM store for non-volatile variables. 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. + * `template` - (Optional) path to the file used to override variables from the master NVRAM + store. So you should typically use the firmware as this, @@ -88,6 +91,46 @@ nvram = [ ] ``` +In case you need (or want) to specify the path for the NVRAM store, the domain definition should +look like this: + +```hcl +resource "libvirt_domain" "my_machine" { + name = "my_machine" + firmware = "/usr/share/qemu/ovmf-x86_64-code.bin" + nvram { + file = "/usr/local/share/qemu/custom-vars.bin" + } + memory = "2048" + + disk { + volume_id = "${libvirt_volume.volume.id}" + } + ... +} + +``` + +Finally, if you want the initial values for the NVRAM to be overridden by custom initial values +coming from a template, the domain definition should look like this: + +```hcl +resource "libvirt_domain" "my_machine" { + name = "my_machine" + firmware = "/usr/share/qemu/ovmf-x86_64-code.bin" + nvram { + file = "/usr/local/share/qemu/custom-vars.bin" + template = "/usr/local/share/qemu/template-vars.bin" + } + memory = "2048" + + disk { + volume_id = "${libvirt_volume.volume.id}" + } + ... +} +``` + ### Handling disks The `disk` block supports: |