1
votes

Following on from this question, I need to go a step further and be able to create multiple data disks of different sizes, where quantity and sizes are specified at deploy-time.

My latest incarnation is creating the (managed) disks in their own resource outside the VM resource and then trying to attach them.

It seems that the copyindex resets for each resource so I believe I need to create them all in one copy so the "attach" part in the VM resource can use the length function, but I cannot think of a way to change any property inside the copy loop when a certain iteration is reached (I would understand why this isn't possible).

I'm thinking I need to use something like:

"count": "[variables('numberOfDisks')[parameters('DiskSize')]]" 

But unsure how to proceed.

I've also thought about nested templates, but again, this falls foul of not being able to change parameters inside a loop.

In programming, I could create a 2d array or dictionary object, but cannot find a way to do this in ARM templates, although, I have just found Intersection.

Datadisk configuration examples: It is only the size and quantity that vary per deployment. All other properties are anticipated to be the same for all disks for any given VM.

  • VM 1: 2x @ 256GB, 4x @ 512GB, 4x @ 1023GB
  • VM 2: 1x @ 1023GB, 1x @ 80GB
  • VM 3: 1x @ 1023GB, 1x @ 80GB, 2x @ 256GB, 2x @ 512GB

My template only deploys one VM, but the number and size of disks are unknown. The idea as that DSC will come along and create volumes, collating the disks based on their size.

I'm not going to paste my workings as they are long, wrong and bulk out this post. Hopefully the above is enough to prove I have been trying to work things out for myself.

1
can you write how exactly disks need to differ? What are the break points? what needs to differ? - 4c74356b41
Updated disk config examples. Thanks - woter324
I think I know how to do this, but I'm a bit overwhelmed with events right now. I'll get back to this in roughly 10 hours. ping me here if I forget - 4c74356b41

1 Answers

1
votes

So I've managed to achieve it. Possibly not the most elegant, but it works. Although Microsoft seem to suggest using a top-level resource to create the datadisks, I can't see how this will work as I don't know of a way to use copy[] inside DependsOn[] which is required if you are creating the disks and vm in the same template, they'll try and deploy simultaneously.

For those that may be interested, here is my solution:

Firstly, I am triggering the template using PowerShell's New-AzureRmResourceDeployment. I'm not using a parameters file. The parameters are generated in PS.

$RG = "ResourceGroup where VM resides"

$Disks = @(
    @{name = "datadisk-001";diskSizeGB = "256";lun = 0}
    @{name = "datadisk-002";diskSizeGB = "256";lun = 1}
    @{name = "datadisk-003";diskSizeGB = "512";lun = 2}
    @{name = "datadisk-004";diskSizeGB = "512";lun = 3}
    @{name = "datadisk-005";diskSizeGB = "512";lun = 4}
    @{name = "datadisk-006";diskSizeGB = "512";lun = 5}
)

$params = @{
    diskConfig = $disks 
    storageAccounttype = "Standard_LRS"
    vmName = "AUCADN102007006"
}

New-AzureRmResourceGroupDeployment -Name "SomeDeploymentName" `
                                       -ResourceGroupName $RG `
                                       -Mode Incremental `
                                       -DeploymentDebugLogLevel All `
                                       -TemplateFile C:\Temp\DiskTest.json" `
                                       -Verbose `
                                       @params

The template itself is seriously cut down, and doesn't actually create the VM. The referenced VM needs to exist. I've taken out as much as possible.

    {
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
  "parameters": {
    "vmName": {
      "type": "string"
    },
    "diskConfig": {
      "type": "array"
    },
    "storageAccountType": {
      "type": "string",
      "defaultValue": "Standard_LRS",
      "allowedValues": [
        "Standard_LRS",
        "Premium_LRS"
      ],
      "metadata": {
        "description": "Type of disk"
      }
    }
  },
  "variables": {
    "vmSize": "Standard_DS4_v2",
    "sharedVariables": {
      "storageAccountType": "[parameters('storageAccountType')]"
    }
  },
  "resources": [
    {
      "apiVersion": "2017-03-30",
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[parameters('vmName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
      ],
      "properties": {
        "storageProfile": {
          "copy": [
            {
              "name": "dataDisks",
              "count": "[length(parameters('diskConfig'))]",
              "input": {
                "name": "[concat(parameters('vmName'),'-',parameters('diskConfig')[CopyIndex('dataDisks')].name)]",
                "diskSizeGB": "[parameters('diskConfig')[CopyIndex('dataDisks')].diskSizeGB]",
                "lun": "[parameters('diskConfig')[copyIndex('dataDisks')].lun]",
                "createOption": "Empty",
                "managedDisk": {
                  "storageAccountType": "[variables('sharedVariables').storageAccountType]"
                }
              }
            }
          ]
          }
        }
       }
     ],
        "outputs": {
          "arrayOutput1": {
            "type": "array",
            "value": "[parameters('diskConfig')]"
          },
          "arrayCount": {
            "type": "int",
            "value": "[length(parameters('diskConfig'))]"
          }
        }
      }

Thanks to this post where the author demonstrates the use of indexing:

"properties": {
 "accountType": "  [parameters('storageAccountList')[copyIndex()].storageAccountType]"  
    }

Note how copyIndex() is in [ ]

ToDo: Do something better with $Disks, either using PS to create the hashtable or create it inside the template.

HTH