diff --git a/client/vm.go b/client/vm.go index 04c9163c..8606feca 100644 --- a/client/vm.go +++ b/client/vm.go @@ -184,28 +184,33 @@ func (c *Client) CreateVm(vmReq Vm, createTime time.Duration) (*Vm, error) { return nil, errors.New(fmt.Sprintf("cannot create VM when multiple templates are returned: %v", tmpl)) } - useExistingDisks := tmpl[0].isDiskTemplate() + var vdis = []interface{}{} + var existingDisks = map[string]interface{}{} installation := vmReq.Installation - if !useExistingDisks && installation.Method != "cdrom" && installation.Method != "network" { - return nil, errors.New("cannot create a VM from a diskless template without an ISO") - } - existingDisks := map[string]interface{}{} - vdis := []interface{}{} - disks := vmReq.Disks + if len(vmReq.Disks) != 0 { + useExistingDisks := tmpl[0].isDiskTemplate() - firstDisk := createVdiMap(disks[0]) - // Treat the first disk differently. This covers the - // case where we are using a template with an already - // installed OS or a diskless template. - if useExistingDisks { - existingDisks["0"] = firstDisk - } else { - vdis = append(vdis, firstDisk) - } + if !useExistingDisks && installation.Method != "cdrom" && installation.Method != "network" { + return nil, errors.New("cannot create a VM from a diskless template without an ISO") + } + + disks := vmReq.Disks - for i := 1; i < len(disks); i++ { - vdis = append(vdis, createVdiMap(disks[i])) + firstDisk := createVdiMap(disks[0]) + + // Treat the first disk differently. This covers the + // case where we are using a template with an already + // installed OS or a diskless template. + if useExistingDisks { + existingDisks["0"] = firstDisk + } else { + vdis = append(vdis, firstDisk) + } + + for i := 1; i < len(disks); i++ { + vdis = append(vdis, createVdiMap(disks[i])) + } } params := map[string]interface{}{ diff --git a/xoa/resource_xenorchestra_vm.go b/xoa/resource_xenorchestra_vm.go index d0a32a41..513e8461 100644 --- a/xoa/resource_xenorchestra_vm.go +++ b/xoa/resource_xenorchestra_vm.go @@ -267,7 +267,7 @@ func resourceVmSchema() map[string]*schema.Schema { }, "disk": &schema.Schema{ Type: schema.TypeList, - Required: true, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "sr_id": &schema.Schema{ diff --git a/xoa/resource_xenorchestra_vm_test.go b/xoa/resource_xenorchestra_vm_test.go index 0d8300df..2bf506bd 100644 --- a/xoa/resource_xenorchestra_vm_test.go +++ b/xoa/resource_xenorchestra_vm_test.go @@ -576,6 +576,27 @@ func TestAccXenorchestraVm_createWithDisklessTemplateAndISO(t *testing.T) { }) } +func TestAccXenorchestraVm_createWithoutDisks(t *testing.T) { + resourceName := "xenorchestra_vm.bar" + vmName := fmt.Sprintf("%s - %s", accTestPrefix, t.Name()) + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckXenorchestraVmDestroy, + Steps: []resource.TestStep{ + { + Config: testAccVmConfigWithoutDisks(vmName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccVmExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "cdrom.#", "1"), + internal.TestCheckTypeSetElemAttrPair(resourceName, "cdrom.0.*", "data.xenorchestra_vdi.iso", "id"), + ), + }, + }, + }) +} + func TestAccXenorchestraVm_insertAndEjectCd(t *testing.T) { resourceName := "xenorchestra_vm.bar" vmName := fmt.Sprintf("%s - %s", accTestPrefix, t.Name()) @@ -1542,6 +1563,36 @@ resource "xenorchestra_vm" "bar" { `, testIsoName, accTestPool.Id, accDefaultNetwork.NameLabel, accTestPool.Id, vmName, accDefaultSr.Id) } +func testAccVmConfigWithoutDisks(vmName string) string { + return testAccCloudConfigConfig(fmt.Sprintf("vm-template-%s", vmName), "template") + testAccNonDefaultTemplateConfig(disklessTestTemplate.NameLabel) + fmt.Sprintf(` +data "xenorchestra_vdi" "iso" { + name_label = "%s" + pool_id = "%s" +} + +data "xenorchestra_network" "network" { + name_label = "%s" + pool_id = "%s" +} + +resource "xenorchestra_vm" "bar" { + memory_max = 4295000000 + cpus = 1 + cloud_config = "${xenorchestra_cloud_config.bar.template}" + name_label = "%s" + name_description = "description" + template = "${data.xenorchestra_template.template.id}" + network { + network_id = "${data.xenorchestra_network.network.id}" + } + + cdrom { + id = data.xenorchestra_vdi.iso.id + } +} +`, testIsoName, accTestPool.Id, accDefaultNetwork.NameLabel, accTestPool.Id, vmName, accDefaultSr.Id) +} + func testAccVmConfigWithoutISO(vmName string) string { return testAccCloudConfigConfig(fmt.Sprintf("vm-template-%s", vmName), "template") + testAccNonDefaultTemplateConfig(disklessTestTemplate.NameLabel) + fmt.Sprintf(`