Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MS] Adding support for VMSS Data Disks using Managed Disk feature #14608

Merged
merged 2 commits into from
May 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions builtin/providers/azurerm/resource_arm_virtual_machine_scale_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,47 @@ func resourceArmVirtualMachineScaleSet() *schema.Resource {
Set: resourceArmVirtualMachineScaleSetStorageProfileOsDiskHash,
},

"storage_profile_data_disk": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"lun": {
Type: schema.TypeInt,
Required: true,
},

"create_option": {
Type: schema.TypeString,
Required: true,
},

"caching": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},

"disk_size_gb": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ValidateFunc: validateDiskSizeGB,
},

"managed_disk_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{
string(compute.PremiumLRS),
string(compute.StandardLRS),
}, true),
},
},
},
},

"storage_profile_image_reference": {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -450,6 +491,15 @@ func resourceArmVirtualMachineScaleSetCreate(d *schema.ResourceData, meta interf
return err
}
storageProfile.OsDisk = osDisk

if _, ok := d.GetOk("storage_profile_data_disk"); ok {
dataDisks, err := expandAzureRMVirtualMachineScaleSetsStorageProfileDataDisk(d)
if err != nil {
return err
}
storageProfile.DataDisks = &dataDisks
}

if _, ok := d.GetOk("storage_profile_image_reference"); ok {
imageRef, err := expandAzureRmVirtualMachineScaleSetStorageProfileImageReference(d)
if err != nil {
Expand Down Expand Up @@ -586,6 +636,12 @@ func resourceArmVirtualMachineScaleSetRead(d *schema.ResourceData, meta interfac
return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Storage Profile OS Disk error: %#v", err)
}

if resp.VirtualMachineProfile.StorageProfile.DataDisks != nil {
if err := d.Set("storage_profile_data_disk", flattenAzureRmVirtualMachineScaleSetStorageProfileDataDisk(properties.VirtualMachineProfile.StorageProfile.DataDisks)); err != nil {
return fmt.Errorf("[DEBUG] Error setting Virtual Machine Scale Set Storage Profile Data Disk error: %#v", err)
}
}

if properties.VirtualMachineProfile.ExtensionProfile != nil {
extension, err := flattenAzureRmVirtualMachineScaleSetExtensionProfile(properties.VirtualMachineProfile.ExtensionProfile)
if err != nil {
Expand Down Expand Up @@ -802,6 +858,26 @@ func flattenAzureRmVirtualMachineScaleSetStorageProfileOSDisk(profile *compute.V
return []interface{}{result}
}

func flattenAzureRmVirtualMachineScaleSetStorageProfileDataDisk(disks *[]compute.VirtualMachineScaleSetDataDisk) interface{} {
result := make([]interface{}, len(*disks))
for i, disk := range *disks {
l := make(map[string]interface{})
if disk.ManagedDisk != nil {
l["managed_disk_type"] = string(disk.ManagedDisk.StorageAccountType)
}

l["create_option"] = disk.CreateOption
l["caching"] = string(disk.Caching)
if disk.DiskSizeGB != nil {
l["disk_size_gb"] = *disk.DiskSizeGB
}
l["lun"] = *disk.Lun

result[i] = l
}
return result
}

func flattenAzureRmVirtualMachineScaleSetStorageProfileImageReference(profile *compute.ImageReference) []interface{} {
result := make(map[string]interface{})
result["publisher"] = *profile.Publisher
Expand Down Expand Up @@ -1149,6 +1225,46 @@ func expandAzureRMVirtualMachineScaleSetsStorageProfileOsDisk(d *schema.Resource
return osDisk, nil
}

func expandAzureRMVirtualMachineScaleSetsStorageProfileDataDisk(d *schema.ResourceData) ([]compute.VirtualMachineScaleSetDataDisk, error) {
disks := d.Get("storage_profile_data_disk").([]interface{})
dataDisks := make([]compute.VirtualMachineScaleSetDataDisk, 0, len(disks))
for _, diskConfig := range disks {
config := diskConfig.(map[string]interface{})

createOption := config["create_option"].(string)
managedDiskType := config["managed_disk_type"].(string)
lun := int32(config["lun"].(int))

dataDisk := compute.VirtualMachineScaleSetDataDisk{
Lun: &lun,
CreateOption: compute.DiskCreateOptionTypes(createOption),
}

managedDiskVMSS := &compute.VirtualMachineScaleSetManagedDiskParameters{}

if managedDiskType != "" {
managedDiskVMSS.StorageAccountType = compute.StorageAccountTypes(managedDiskType)
} else {
managedDiskVMSS.StorageAccountType = compute.StorageAccountTypes(compute.StandardLRS)
}

//assume that data disks in VMSS can only be Managed Disks
dataDisk.ManagedDisk = managedDiskVMSS
if v := config["caching"].(string); v != "" {
dataDisk.Caching = compute.CachingTypes(v)
}

if v := config["disk_size_gb"]; v != nil {
diskSize := int32(config["disk_size_gb"].(int))
dataDisk.DiskSizeGB = &diskSize
}

dataDisks = append(dataDisks, dataDisk)
}

return dataDisks, nil
}

func expandAzureRmVirtualMachineScaleSetStorageProfileImageReference(d *schema.ResourceData) (*compute.ImageReference, error) {
storageImageRefs := d.Get("storage_profile_image_reference").(*schema.Set).List()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ func TestAccAzureRMVirtualMachineScaleSet_loadBalancer(t *testing.T) {
})
}

func TestAccAzureRMVirtualMachineScaleSet_loadBalancerManagedDataDisks(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSetLoadbalancerTemplateManagedDataDisks, ri, ri, ri, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMVirtualMachineScaleSetDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMVirtualMachineScaleSetExists("azurerm_virtual_machine_scale_set.test"),
testCheckAzureRMVirtualMachineScaleSetHasDataDisks("azurerm_virtual_machine_scale_set.test"),
),
},
},
})
}

func TestAccAzureRMVirtualMachineScaleSet_overprovision(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccAzureRMVirtualMachineScaleSetOverprovisionTemplate, ri, ri, ri, ri, ri, ri)
Expand Down Expand Up @@ -369,6 +388,39 @@ func testCheckAzureRMVirtualMachineScaleSetExtension(name string) resource.TestC
}
}

func testCheckAzureRMVirtualMachineScaleSetHasDataDisks(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
// Ensure we have enough information in state to look up in API
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}

name := rs.Primary.Attributes["name"]
resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
if !hasResourceGroup {
return fmt.Errorf("Bad: no resource group found in state for virtual machine: scale set %s", name)
}

conn := testAccProvider.Meta().(*ArmClient).vmScaleSetClient
resp, err := conn.Get(resourceGroup, name)
if err != nil {
return fmt.Errorf("Bad: Get on vmScaleSetClient: %s", err)
}

if resp.StatusCode == http.StatusNotFound {
return fmt.Errorf("Bad: VirtualMachineScaleSet %q (resource group: %q) does not exist", name, resourceGroup)
}

storageProfile := resp.VirtualMachineProfile.StorageProfile.DataDisks
if storageProfile == nil || len(*storageProfile) == 0 {
return fmt.Errorf("Bad: Could not get data disks configurations for scale set %v", name)
}

return nil
}
}

var testAccAzureRMVirtualMachineScaleSet_basic = `
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
Expand Down Expand Up @@ -1286,3 +1338,84 @@ resource "azurerm_virtual_machine_scale_set" "test" {
}
}
`

var testAccAzureRMVirtualMachineScaleSetLoadbalancerTemplateManagedDataDisks = `
resource "azurerm_resource_group" "test" {
name = "acctestrg-%d"
location = "southcentralus"
}
resource "azurerm_virtual_network" "test" {
name = "acctvn-%d"
address_space = ["10.0.0.0/16"]
location = "southcentralus"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_subnet" "test" {
name = "acctsub-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.0.2.0/24"
}
resource "azurerm_lb" "test" {
name = "acctestlb-%d"
location = "southcentralus"
resource_group_name = "${azurerm_resource_group.test.name}"
frontend_ip_configuration {
name = "default"
subnet_id = "${azurerm_subnet.test.id}"
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_lb_backend_address_pool" "test" {
name = "test"
resource_group_name = "${azurerm_resource_group.test.name}"
loadbalancer_id = "${azurerm_lb.test.id}"
}
resource "azurerm_virtual_machine_scale_set" "test" {
name = "acctvmss-%d"
location = "southcentralus"
resource_group_name = "${azurerm_resource_group.test.name}"
upgrade_policy_mode = "Manual"
sku {
name = "Standard_A0"
tier = "Standard"
capacity = 1
}
os_profile {
computer_name_prefix = "testvm-%d"
admin_username = "myadmin"
admin_password = "Passwword1234"
}
network_profile {
name = "TestNetworkProfile"
primary = true
ip_configuration {
name = "TestIPConfiguration"
subnet_id = "${azurerm_subnet.test.id}"
load_balancer_backend_address_pool_ids = [ "${azurerm_lb_backend_address_pool.test.id}" ]
}
}

storage_profile_os_disk {
name = ""
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}

storage_profile_data_disk {
lun = 0
caching = "ReadWrite"
create_option = "Empty"
disk_size_gb = 10
managed_disk_type = "Standard_LRS"
}

storage_profile_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04.0-LTS"
version = "latest"
}
}
`
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ resource "azurerm_virtual_machine_scale_set" "test" {
managed_disk_type = "Standard_LRS"
}

storage_profile_data_disk {
lun = 0
caching = "ReadWrite"
create_option = "Empty"
disk_size_gb = 10
}

os_profile {
computer_name_prefix = "testvm"
admin_username = "myadmin"
Expand Down Expand Up @@ -248,6 +255,7 @@ The following arguments are supported:
* `os_profile_linux_config` - (Required, when a linux machine) A Linux config block as documented below.
* `network_profile` - (Required) A collection of network profile block as documented below.
* `storage_profile_os_disk` - (Required) A storage profile os disk block as documented below
* `storage_profile_data_disk` - (Optional) A storage profile data disk block as documented below
* `storage_profile_image_reference` - (Optional) A storage profile image reference block as documented below.
* `extension` - (Optional) Can be specified multiple times to add extension profiles to the scale set. Each `extension` block supports the fields documented below.
* `tags` - (Optional) A mapping of tags to assign to the resource.
Expand Down Expand Up @@ -329,6 +337,15 @@ The following arguments are supported:
When setting this field `os_type` needs to be specified. Cannot be used when `vhd_containers`, `managed_disk_type` or `storage_profile_image_reference ` are specified.
* `os_type` - (Optional) Specifies the operating system Type, valid values are windows, linux.

`storage_profile_data_disk` supports the following:

* `lun` - (Required) Specifies the Logical Unit Number of the disk in each virtual machine in the scale set.
`Premium_LRS`.
* `create_option` - (Optional) Specifies how the data disk should be created. The only possible options are `FromImage` and `Empty`.
* `caching` - (Optional) Specifies the caching requirements. Possible values include: `None` (default), `ReadOnly`, `ReadWrite`.
* `disk_size_gb` - (Optional) Specifies the size of the disk in GB. This element is required when creating an empty disk.
* `managed_disk_type` - (Optional) Specifies the type of managed disk to create. Value must be either `Standard_LRS` or

`storage_profile_image_reference` supports the following:

* `publisher` - (Required) Specifies the publisher of the image used to create the virtual machines
Expand Down