Skip to content

Commit

Permalink
feat: added storage_config attribute in the resource,and created test…
Browse files Browse the repository at this point in the history
… case and doc
  • Loading branch information
PacoDw committed Jun 10, 2020
1 parent 4c5b1b4 commit 58597b7
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 23 deletions.
119 changes: 96 additions & 23 deletions nutanix/resource_nutanix_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"
"time"

"github.com/spf13/cast"
v3 "github.com/terraform-providers/terraform-provider-nutanix/client/v3"
"github.com/terraform-providers/terraform-provider-nutanix/utils"

Expand Down Expand Up @@ -662,6 +663,46 @@ func resourceNutanixVirtualMachine() *schema.Resource {
Optional: true,
Computed: true,
},
"storage_config": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"flash_mode": {
Type: schema.TypeString,
Optional: true,
},
"storage_container_reference": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"url": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kind": {
Type: schema.TypeString,
Optional: true,
Default: "storage_container",
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"uuid": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
},
},
},
"device_properties": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -1694,59 +1735,49 @@ func expandDiskList(d *schema.ResourceData, isCreation bool) ([]*v3.VMDisk, erro
dsk := v.([]interface{})
if len(dsk) > 0 {
dls := make([]*v3.VMDisk, len(dsk))

for k, val := range dsk {
hasDSRef := false
v := val.(map[string]interface{})
dl := &v3.VMDisk{}

// uuid
if v1, ok1 := v["uuid"]; ok1 && v1.(string) != "" {
dl.UUID = utils.StringPtr(v1.(string))
}
// storage_config
if v, ok1 := v["storage_config"]; ok1 {
dl.StorageConfig = expandStorageConfig(v.([]interface{}))
}
// device_properties
if v1, ok1 := v["device_properties"]; ok1 {
dvp := v1.([]interface{})
if len(dvp) > 0 {
d := dvp[0].(map[string]interface{})
dp := &v3.VMDiskDeviceProperties{}
if v1, ok := d["device_type"]; ok {
dp.DeviceType = utils.StringPtr(v1.(string))
}
if v2, ok := d["disk_address"]; ok && len(v2.(map[string]interface{})) > 0 {
da := v2.(map[string]interface{})
v3disk := &v3.DiskAddress{}
if di, diok := da["device_index"]; diok {
index, _ := strconv.Atoi(di.(string))
v3disk.DeviceIndex = utils.Int64Ptr(int64(index))
}
if di, diok := da["adapter_type"]; diok {
v3disk.AdapterType = utils.StringPtr(di.(string))
}
dp.DiskAddress = v3disk
}
dl.DeviceProperties = dp
}
dl.DeviceProperties = expandDeviceProperties(v1.([]interface{}))
}
// data_source_reference
if v1, ok := v["data_source_reference"]; ok && len(v1.(map[string]interface{})) != 0 {
hasDSRef = true
dsref := v1.(map[string]interface{})
dl.DataSourceReference = validateShortRef(dsref)
}
// volume_group_reference
if v1, ok := v["volume_group_reference"]; ok {
volgr := v1.(map[string]interface{})
dl.VolumeGroupReference = validateRef(volgr)
}

// disk_size_bytes
if v1, ok1 := v["disk_size_bytes"]; ok1 && v1.(int) != 0 {
if hasDSRef && isCreation {
return nil, fmt.Errorf(`"disk_list.%[1]d.disk_size_bytes": conflicts with disk_list.%[1]d.data_source_reference`, k)
}
dl.DiskSizeBytes = utils.Int64Ptr(int64(v1.(int)))
}
// disk_size_mib
if v1, ok := v["disk_size_mib"]; ok && v1.(int) != 0 {
if hasDSRef && isCreation {
return nil, fmt.Errorf(`"disk_list.%[1]d.disk_size_mib": conflicts with disk_list.%[1]d.data_source_reference`, k)
}
dl.DiskSizeMib = utils.Int64Ptr(int64(v1.(int)))
}

dls[k] = dl
}
return dls, nil
Expand All @@ -1755,6 +1786,48 @@ func expandDiskList(d *schema.ResourceData, isCreation bool) ([]*v3.VMDisk, erro
return nil, nil
}

func expandStorageConfig(storageConfig []interface{}) *v3.VMStorageConfig {
if len(storageConfig) > 0 {
v := storageConfig[0].(map[string]interface{})
scr := v["storage_container_reference"].([]interface{})[0].(map[string]interface{})

return &v3.VMStorageConfig{
FlashMode: cast.ToString(v["flash_mode"]),
StorageContainerReference: &v3.StorageContainerReference{
URL: cast.ToString(scr["url"]),
Kind: cast.ToString(scr["kind"]),
UUID: cast.ToString(scr["uuid"]),
},
}
}
return nil
}

func expandDeviceProperties(deviceProperties []interface{}) *v3.VMDiskDeviceProperties {
if len(deviceProperties) > 0 {
dp := &v3.VMDiskDeviceProperties{}
d := deviceProperties[0].(map[string]interface{})

if v, ok := d["device_type"]; ok {
dp.DeviceType = utils.StringPtr(v.(string))
}
if v, ok := d["disk_address"]; ok && len(v.(map[string]interface{})) > 0 {
da := v.(map[string]interface{})
v3disk := &v3.DiskAddress{}

if di, diOk := da["device_index"]; diOk {
v3disk.DeviceIndex = utils.Int64Ptr(cast.ToInt64(di))
}
if at, atOk := da["adapter_type"]; atOk {
v3disk.AdapterType = utils.StringPtr(at.(string))
}
dp.DiskAddress = v3disk
}
return dp
}
return nil
}

func expandSerialPortList(d *schema.ResourceData) []*v3.VMSerialPort {
if v, ok := d.GetOk("serial_port_list"); ok {
spl := v.([]interface{})
Expand Down
52 changes: 52 additions & 0 deletions nutanix/resource_nutanix_virtual_machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,25 @@ func TestAccNutanixVirtualMachine_cloningVM(t *testing.T) {
})
}

func TestAccNutanixVirtualMachine_withDiskContainer(t *testing.T) {
r := acctest.RandInt()

resourceName := "nutanix_virtual_machine.vm-disk"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckNutanixVirtualMachineDestroy,
Steps: []resource.TestStep{
{
Config: testAccNutanixVMConfigWithDiskContainer(r),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(resourceName, "disk_list.#"),
resource.TestCheckResourceAttr(resourceName, "disk_list.#", "1"),
),
},
}})
}

func testAccCheckNutanixVirtualMachineExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand Down Expand Up @@ -927,3 +946,36 @@ func testAccNutanixVMConfigHotAdd(vmName string, cpus, sockets, memory int, hotA
}
`, vmName, cpus, sockets, memory, hotAdd, imageName)
}

func testAccNutanixVMConfigWithDiskContainer(r int) string {
return fmt.Sprintf(`
data "nutanix_clusters" "clusters" {}
locals {
cluster1 = [
for cluster in data.nutanix_clusters.clusters.entities :
cluster.metadata.uuid if cluster.service_list[0] != "PRISM_CENTRAL"
][0]
}
resource "nutanix_virtual_machine" "vm-disk" {
name = "test-dou-vm-%[1]d"
cluster_uuid = local.cluster1
num_vcpus_per_socket = 1
num_sockets = 1
memory_size_mib = 186
disk_list {
disk_size_bytes = 68157440
disk_size_mib = 65
storage_config {
storage_container_reference {
kind = "storage_container"
uuid = "2bbe77bc-fd14-4697-8de1-6369757f9219"
}
}
}
}
`, r)
}
36 changes: 36 additions & 0 deletions website/docs/r/virtual_machine.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,31 @@ resource "nutanix_virtual_machine" "vm1" {
}
```

## Example Usage with storage config
```hcl
data "nutanix_clusters" "clusters" {}
resource "nutanix_virtual_machine" "vm" {
name = "myVm"
cluster_uuid = data.nutanix_clusters.clusters.entities.0.metadata.uuid
num_vcpus_per_socket = 1
num_sockets = 1
memory_size_mib = 186
disk_list {
disk_size_bytes = 68157440
disk_size_mib = 65
storage_config {
storage_container_reference {
kind = "storage_container"
uuid = "2bbe67bc-fd14-4637-8de1-6379257f4219"
}
}
}
}
```

## Argument Reference

The following arguments are supported:
Expand Down Expand Up @@ -92,6 +117,17 @@ The device_properties attribute supports the following.
* `device_type`: - A Disk type (default: DISK).
* `disk_address`: - Address of disk to boot from.

### Storage Config
User inputs of storage configuration parameters for VMs.

* `flash_mode`: - State of the storage policy to pin virtual disks to the hot tier. When specified as a VM attribute, the storage policy applies to all virtual disks of the VM unless overridden by the same attribute specified for a virtual disk.

* `storage_container_reference`: - Reference to a kind. Either one of (kind, uuid) or url needs to be specified.
* `storage_container_reference.#.url`: - GET query on the URL will provide information on the source.
* `storage_container_reference.#.kind`: - kind of the container reference
* `storage_container_reference.#.name`: - name of the container reference
* `storage_container_reference.#.uuid`: - uiid of the container reference

### Sysprep

The guest_customization_sysprep attribute supports the following:
Expand Down

0 comments on commit 58597b7

Please sign in to comment.