none
Question about deploying multiple VMs with template

    Question

  • Hi guys,

    I would like to create a template that will create multiple VMs per users with their name on the resource, for example :

    test-dc-user1 and test-dc-nic-user1

    test-svr-user1 and test-svr-nic-user1

    test-client-user1 and test-client-nic-user1

    And same for user2, etc., but all of this with the same template, is it possible? If yes, do you have an example?

    Thanks.

    Monday, March 20, 2017 9:32 AM

Answers

  • There is no need to use scale sets to achieve what you want to do, you can do so using the CopyIndex function of the Arm template.

    By specifying this for your resource, you can create multiple copies of the resource, for example the below creates multiple web apps, based on a count  passed as a parameter:

     { 
          "name": "[concat('examplecopy-', copyIndex())]", 
          "type": "Microsoft.Web/sites", 
          "location": "East US", 
          "apiVersion": "2015-08-01",
          "copy": { 
             "name": "websitescopy", 
             "count": "[parameters('count')]" 
          }, 
          "properties": {
              "serverFarmId": "hostingPlanName"
          }
      } 

    When you do this, you can then use the copyIndex inside teh resource for naming etc. In this example it is used in the name:

    "[concat('examplecopy-', copyIndex())]",

    This will create names of examplecopy-1, examplcopy-2 etc.

    Where you need multiple resources like VM's, NICS etc you just use the same copyIndex parameter for each resource to get the same number of NICS as VM's, then when you reference the NIC in teh VM you use the copyIndex to get the NIC name.

    See this article for more details and examples.


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    • Marked as answer by Olddddd Thursday, March 23, 2017 2:50 PM
    Tuesday, March 21, 2017 9:30 AM

All replies

  • You can deploy multiple VM using the template. Virtual machine scale sets are an Azure Compute resource to deploy and manage a set of identical VMs. Refer the below article “Deploy multiple VMs from template with PowerCLI”.

    http://www.harryjohn.org/deploy-multiple-vms-from-template/

    https://communities.vmware.com/thread/455410

    For my information, you are planning to use multiple NIC’s or same NIC for creating multiple VM?

    Disclaimer: This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. Microsoft does not control these sites and has not tested any software or information found on these sites; therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

    Tuesday, March 21, 2017 3:38 AM
    Moderator
  • It's for a school environment, so each student need to have 3 VMs with 3 different NICs, and I don't need to scale my VMs because I know in advance how many students I will have and the VMs need to be fixed.

    The two links you provided me doesn't match with what I would like to do, I found a better link on Microsoft Doc : https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple

    But I have some questions, is it possible to have dynamic boxes (parameters) within the template deployment blade? For example, if I don't know how many students I will have and what will be their names, is it possible to have a parameter named "number of users", and when I assign a number to it, let's say 10, automatically 10 boxes are created for the users names, is it possible?

    If not, do you have an idea how can I name my VMs like that :

    test-dc-user1 with test-dc-nic-user1

    test-svr-user1 with test-svr-nic-user1

    test-client-user1 with ...

    test-dc-user2

    test-svr-user2

    test-client-user2

    and so on...

    Or maybe I will need to create a template for each VMs, for example, a template that creat all the users DCs, another for the users servers and the last for the users clients machines?


    • Edited by Olddddd Tuesday, March 21, 2017 9:22 AM
    Tuesday, March 21, 2017 8:09 AM
  • There is no need to use scale sets to achieve what you want to do, you can do so using the CopyIndex function of the Arm template.

    By specifying this for your resource, you can create multiple copies of the resource, for example the below creates multiple web apps, based on a count  passed as a parameter:

     { 
          "name": "[concat('examplecopy-', copyIndex())]", 
          "type": "Microsoft.Web/sites", 
          "location": "East US", 
          "apiVersion": "2015-08-01",
          "copy": { 
             "name": "websitescopy", 
             "count": "[parameters('count')]" 
          }, 
          "properties": {
              "serverFarmId": "hostingPlanName"
          }
      } 

    When you do this, you can then use the copyIndex inside teh resource for naming etc. In this example it is used in the name:

    "[concat('examplecopy-', copyIndex())]",

    This will create names of examplecopy-1, examplcopy-2 etc.

    Where you need multiple resources like VM's, NICS etc you just use the same copyIndex parameter for each resource to get the same number of NICS as VM's, then when you reference the NIC in teh VM you use the copyIndex to get the NIC name.

    See this article for more details and examples.


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    • Marked as answer by Olddddd Thursday, March 23, 2017 2:50 PM
    Tuesday, March 21, 2017 9:30 AM
  • I already saw this article, but I didin't find a way to do it like I want, the article gives only the possibility to create resources based on a number or on an array of strings, but what I want to do is more complex, I would like to do something like that:

    Create 3 VMs (Windows or Linux) and their NICs per users with their names on it:

    example-dc-user1 and example-dc-nic-user1

    example-svr1-user1 and example-svr1-nic-user1

    example-svr2-user1 and example-svr2-nic-user1

    And do the same with all my other users, I provide in my template an array with the user names (user1, user2, etc.).


    • Edited by Olddddd Tuesday, March 21, 2017 10:02 AM
    Tuesday, March 21, 2017 10:01 AM
  • You would pass in your list of students as an array, then use the size of this array as your count variable:

    "copy": {
        "name": "websitescopy",
        "count": "[length(parameters('studentNames'))]"
    }

    Then when it came to naming things you would do a lookup inside that array using the copy index

    "Name":"[concat('example-dc-', parameters('studentNames[copyIndex()]'))]",




    Sam Cogan Microsoft Azure MVP
    Blog | Twitter


    • Edited by SamCoganMVP Tuesday, March 21, 2017 10:31 AM
    Tuesday, March 21, 2017 10:30 AM
  • That's what I did, but I can't do the same for example-svr1 and example-svr2 within the same template, I need to create two more templates for that, right?

    And about your line:

    "Name":"[concat('example-dc-', parameters('studentNames[copyIndex()]'))]",

    It's not like that rather:

    "Name":"[concat('example-dc-', parameters('studentNames')[copyIndex()])]",

    Like it's written in the doc?

    Tuesday, March 21, 2017 10:54 AM
  • Or maybe, can I create 3 VMs and NICs resources within my template, and assign a different loop for each?

    Something like that :

    "resources": [

    {
                "type": "Microsoft.Network/networkInterfaces",
                "name": "[concat('schl-dc-nic-', parameters('studentName')[copyIndex()])]",
                "apiVersion": "2016-03-30",
                "location": "[variables('location')]",
                "copy": {
                    "name": "nicscopy",
                    "count": "[length(parameters('studentName'))]"
                },
                "properties": {
                    "ipConfigurations": [
                        {
                            "name": "ipconfig1",
                            "properties": {
                                "privateIPAllocationMethod": "Dynamic",
                                "subnet": {
                                    "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('vnetName')), '/subnets/labsubnet')]"
                                }
                            }
                        }
                    ],
                    "dnsSettings": {
                        "dnsServers": []
                    },
                    "enableIPForwarding": false,
                    "networkSecurityGroup": {
                        "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('nsgReference'))]"
                    }
                },
                "dependsOn": [
                    "[resourceId('Microsoft.Network/virtualNetworks/', variables('vnetName'))]"
                ]
            },
            {
                "type": "Microsoft.Network/networkInterfaces",
                "name": "[concat('schl-svr1-nic-', parameters('studentName')[copyIndex()])]",
                "apiVersion": "2016-03-30",
                "location": "[variables('location')]",
                "copy": {
                    "name": "nicscopy",
                    "count": "[length(parameters('studentName'))]"
                },
                "properties": {
                    "ipConfigurations": [
                        {
                            "name": "ipconfig1",
                            "properties": {
                                "privateIPAllocationMethod": "Dynamic",
                                "subnet": {
                                    "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('vnetName')), '/subnets/labsubnet')]"
                                }
                            }
                        }
                    ],
                    "dnsSettings": {
                        "dnsServers": []
                    },
                    "enableIPForwarding": false,
                    "networkSecurityGroup": {
                        "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('nsgReference'))]"
                    }
                },
                "dependsOn": [
                    "[resourceId('Microsoft.Network/virtualNetworks/', variables('vnetName'))]"
                ]
            },
            {
                "type": "Microsoft.Network/networkInterfaces",
                "name": "[concat('schl-svr2-nic-', parameters('studentName')[copyIndex()])]",
                "apiVersion": "2016-03-30",
                "location": "[variables('location')]",
                "copy": {
                    "name": "nicscopy",
                    "count": "[length(parameters('studentName'))]"
                },
                "properties": {
                    "ipConfigurations": [
                        {
                            "name": "ipconfig1",
                            "properties": {
                                "privateIPAllocationMethod": "Dynamic",
                                "subnet": {
                                    "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('vnetName')), '/subnets/labsubnet')]"
                                }
                            }
                        }
                    ],
                    "dnsSettings": {
                        "dnsServers": []
                    },
                    "enableIPForwarding": false,
                    "networkSecurityGroup": {
                        "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('nsgReference'))]"
                    }
                },
                "dependsOn": [
                    "[resourceId('Microsoft.Network/virtualNetworks/', variables('vnetName'))]"
                ]
            },
            {
                "type": "Microsoft.Compute/virtualMachines",
                "name": "[concat('schl-dc-', parameters('studentName')[copyIndex()])]",
                "apiVersion": "2016-04-30-preview",
                "location": "[variables('location')]",
                "copy": {
                    "name": "vmscopy",
                    "count": "[length(parameters('studentName'))]"
                },
                "properties": {
                    "hardwareProfile": {
                        "vmSize": "[parameters('vmSize')]"
                    },
                    "storageProfile": {
                        "imageReference": "[variables('imageReference')]",
                        "osDisk": {
                            "name": "[concat('schl-dc-', parameters('studentName')[copyIndex()], parameters('OS'))]",
                            "vhd": {
                                "uri": "[variables('osDiskVhdUri')]"
                            },
                            "createOption": "FromImage"
                        }
                    },
                    "osProfile": {
                        "computerName": "[concat('schl-dc-', parameters('studentName')[copyIndex()])]",
                        "adminUsername": "[parameters('adminUsername')]",
                        "adminPassword": "[parameters('adminPassword')]"
                    },
                    "networkProfile": {
                        "networkInterfaces": [
                            {
                                "id": "[resourceId('Microsoft.Network/networkInterfaces',concat('schl-dc-nic-', copyindex()))]"
                            }
                        ]
                    }
                }
            },
            {
                "type": "Microsoft.Compute/virtualMachines",
                "name": "[concat('schl-svr1-', parameters('studentName')[copyIndex()])]",
                "apiVersion": "2016-04-30-preview",
                "location": "[variables('location')]",
                "copy": {
                    "name": "vmscopy",
                    "count": "[length(parameters('studentName'))]"
                },
                "properties": {
                    "hardwareProfile": {
                        "vmSize": "[parameters('vmSize')]"
                    },
                    "storageProfile": {
                        "imageReference": "[variables('imageReference')]",
                        "osDisk": {
                            "name": "[concat('schl-svr1-', parameters('studentName')[copyIndex()], parameters('OS'))]",
                            "vhd": {
                                "uri": "[variables('osDiskVhdUri')]"
                            },
                            "createOption": "FromImage"
                        }
                    },
                    "osProfile": {
                        "computerName": "[concat('schl-svr1-', parameters('studentName')[copyIndex()])]",
                        "adminUsername": "[parameters('adminUsername')]",
                        "adminPassword": "[parameters('adminPassword')]"
                    },
                    "networkProfile": {
                        "networkInterfaces": [
                            {
                                "id": "[resourceId('Microsoft.Network/networkInterfaces',concat('schl-svr1-nic-', copyindex()))]"
                            }
                        ]
                    }
                }
            },
            {
                "type": "Microsoft.Compute/virtualMachines",
                "name": "[concat('schl-svr2-', parameters('studentName')[copyIndex()])]",
                "apiVersion": "2016-04-30-preview",
                "location": "[variables('location')]",
                "copy": {
                    "name": "vmscopy",
                    "count": "[length(parameters('studentName'))]"
                },
                "properties": {
                    "hardwareProfile": {
                        "vmSize": "[parameters('vmSize')]"
                    },
                    "storageProfile": {
                        "imageReference": "[variables('imageReference')]",
                        "osDisk": {
                            "name": "[concat('schl-svr2-', parameters('studentName')[copyIndex()], parameters('OS'))]",
                            "vhd": {
                                "uri": "[variables('osDiskVhdUri')]"
                            },
                            "createOption": "FromImage"
                        }
                    },
                    "osProfile": {
                        "computerName": "[concat('schl-svr2-', parameters('studentName')[copyIndex()])]",
                        "adminUsername": "[parameters('adminUsername')]",
                        "adminPassword": "[parameters('adminPassword')]"
                    },
                    "networkProfile": {
                        "networkInterfaces": [
                            {
                                "id": "[resourceId('Microsoft.Network/networkInterfaces',concat('schl-svr2-nic-', copyindex()))]"
                            }
                        ]
                    }
                }
            }

    ]


    • Edited by Olddddd Tuesday, March 21, 2017 1:47 PM
    Tuesday, March 21, 2017 11:37 AM
  • Yes, that's what I was getting at, sorry if it wasn't clear. Each different type of server should be it's own resource, but then use the loop to create as many of each one as you need. It does add some duplication, but becomes even more useful if you want to start using something like DSC to configure the VM's when they are up, as each different type of server will have a different DSC configuration.

    On your question of syntax, I would trust what is in the docs, my example was just off the top of my head so entirely possible my brackets are wrong.


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter


    • Edited by SamCoganMVP Tuesday, March 21, 2017 1:15 PM
    Tuesday, March 21, 2017 1:14 PM
  • Alright, I can't use an array for admin username, why?

    By default, the names are written like that in the box : "[\"user1\",\"user2\"]" but it tells me that user name cannot contain special characters.

    • Edited by Olddddd Tuesday, March 21, 2017 2:33 PM
    Tuesday, March 21, 2017 1:44 PM
  • VHD names can't have spaces in them, you'll need to remove the spaces from the name before doing so, you can use the replace function for this. So I would suggest something like:

    "name": "[concat('schl-dc-', parameters('studentName')[copyIndex()],'-',replace(parameters('OS'),' ','-'))]",

    This should produce "sch1-dc-user1-Windows-2012-R2.vhd"


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Tuesday, March 21, 2017 2:41 PM
  • Yes, I found my error before you answer, and I have modified my post with another question. ^^

    But if I want to replace space and point with "-", is it possible with replace function?

    Also, even I corrected this error, I get another one that said that my URI doesn't look to be correct blob URI, my URI looks like: https://example.blob.core.windows.net/vhds, I tried to remove the https:// but it doesn't work either.


    • Edited by Olddddd Tuesday, March 21, 2017 3:01 PM
    Tuesday, March 21, 2017 2:57 PM
  • Yes you can replace both space and point, you would just need two replace functions

    replace(replace(parameter(OS),' ','-'),'.','-')

    Not the most elegant but it works.

    Can you post the error message for your second issue please.

    Your admin username array should just be a plain array of strings, no need for escaping.


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Tuesday, March 21, 2017 3:16 PM
  • Alright, thanks.

    Fixed the issue with the storage account with this:

    "osDisk": {
           "name": "[concat('schl-svr2-', parameters('studentName')[copyIndex()],'-',replace(parameters('svr2OS'),' ','-'))]",
           "vhd": {
               "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')), '2016-01-01').primaryEndpoints.blob, variables('vmStorageAccountContainerName'), '/',concat('schl-dc-', parameters('studentName')[copyIndex()],'-',replace(parameters('dcOS'),' ','-')),'.vhd')]"
           },
           "createOption": "FromImage"

    It's not possible to call the name property within the uri property? If not, why I need to specify the name property if I can't use it? I made an error, the copyIndex is not compatible with property on a resource type, so how can I write this with the take function?

    EDIT : Finally, it's OK, I can use the copy function in the property of a resource, so why the doc says the opposite? There


    About admin username array, there is the error:

    For the student name box, the template wrote the names like that, I tried to do the same with the admin username but I get the same error.

    I get this error with two replace functions:

    The parenthesis looks correct.

    And about the admin username loop, is this code correct:

    "variables": {
    "userNameArray": [
                "bcarlton",
                "swill"
            ]
    },
    "resources": [
            {
                "type": "Microsoft.Compute/virtualMachines",
                "name": "[concat('schl-dc-', parameters('studentName')[copyIndex()])]",
                "apiVersion": "2016-04-30-preview",
                "location": "[variables('location')]",
                "copy": {
                    "name": "vmscopy",
                    "count": "[length(parameters('studentName'))]"
                },
                "properties": {
                    "osProfile": {
                        "computerName": "[concat('schl-dc-', parameters('studentName')[copyIndex()])]",
                        "adminUsername": "[take(variables('userNameArray'), length(variables('userNameArray')))]",
                        "adminPassword": "[parameters('adminPassword')]"
                    }
                }
            }
    ]

    I used the take function since the copy function is not compatible with resource properties.






    • Edited by Olddddd Wednesday, March 22, 2017 2:52 PM
    Tuesday, March 21, 2017 5:24 PM
  • I'm blocked, need help.
    Wednesday, March 22, 2017 12:33 PM
  • Can you please post your full Template file and any parameter files you are using.

    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Wednesday, March 22, 2017 2:56 PM
  • Here it is: http://pastebin.com/xJrRj7h2

    I didn't include the admin username array since it doesn't work.

    Wednesday, March 22, 2017 3:03 PM
  • Links not working now.

    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Wednesday, March 22, 2017 5:15 PM
    • Edited by Olddddd Wednesday, March 22, 2017 5:19 PM
    Wednesday, March 22, 2017 5:19 PM
  • Ok, I'm a bit confused now, can you please list in a new reply the issues you are currently experiencing with teh code in the pastebin. As it looks like  you have worked around some issues, which ones are actually preventing you deploying now?

    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Wednesday, March 22, 2017 5:48 PM
  • First, I don't understand why I can use the copy function within a resource property, osDisk here, while the doc says that it's not compatible and we need to use the take function instead.

    Secondly, when I want to use an array with my admin usernames, I get the error unable to parse the value into type 'array' like shows the screen above.

    Thirdly, when I use the double replace functions, I get this error during the deployment:

    Wednesday, March 22, 2017 5:57 PM
  • On the first question, I don't know, I suspect an issue with the documentation. That said, I would suggest you take a look at using managed disks for your VM's rather than the VHD and storage account approach, this means you don't need to care about VHD names and so on.

    For your admin array, how are you passing the values in when you run the deployment, are you using a parameter file, or just passing it in as part of your PowerShell command? Can  you post this.

    On your replace function, your missing some quotes around OS, it should be parameter('OS').


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Wednesday, March 22, 2017 10:13 PM
  • Alright. About managed disks, why I will not need to care about VHD names? It will rename them automatically with the VMs name? I want to facilitate the troubleshooting, that's why I care about VHD names. Also, it's the only advantage of managed disks compared to storage account? I saw that it provides scale functionality and it's better to use them with VMSS, but since I don't need scale ability and I don't use VMSS, I will use them only for my VHD names?

    For admin username array, I'm simply passing the values directly to the template file, into the parameters, like that:

    "parameters": {
    "adminUsername": {
                "type": "Array",
                "defaultValue": [
                    "bcarlton",
                    "swill"
                ],
                "metadata": {
                    "description": "Students's names for their VMs, first letter of the first name + last name"
                }
            },

    But I didn't think yet about a better way like providing names with a PowerShell or a parameter file. For PowerShell, I can provide names with the Add-Content cmdlet that will write into my template file, right? Or maybe I'm wrong? But for parameter file, I don't understand the utility since I provide already the parameters within my template file.

    Also, how can I use two copy function in the same resource, 1 for my studentName and the other for my adminUsername? copy1 with copy1Index() and copy2 with copy2Index()?

    I tried this but it doesn't work:

    {
                "type": "Microsoft.Compute/virtualMachines",
                "name": "[concat('schl-dc-', parameters('studentName')[copyIndex()])]",
                "apiVersion": "2017-03-30",
                "location": "[resourceGroup().location]",
                "copy": {
                    "name": "vmscopy",
                    "count": "[length(parameters('studentName'))]"
                },
                "properties": {
                    "copy": {
                        "name": "adminname",
                        "count": "[length(parameters('adminUsername'))]"
                    },
                    "osProfile": {
                        "computerName": "[concat('schl-dc-', parameters('studentName')[copyIndex()])]",
                        "adminUsername": "[parameters('adminUsername')[copyIndex()]]",
                        "adminPassword": "[parameters('adminPassword')]"
                    },
                }
    },

    Yes, indeed, I missed some quotes, thanks.

    • Edited by Olddddd Thursday, March 23, 2017 9:59 AM
    Thursday, March 23, 2017 8:19 AM
  • The benefit of managed disks is that you don't have to care about the underlying storage. If you use standard disks you need to create a storage account to store them in, if you have multiple VM's and you want best performance and availability you need to manually take care to spread them over multiple storage accounts. Additionally because managed disks are top level objects you can set RBAC permissions on them, to control who can manage the disk, you also have the ability to take snapshots of the disks. Finally, you don't have to deal with ensuring you name the disk uniquely, it will do it for you. You basically get a name of <vm name>_OSDisk_GUID.

    Parameter files are useful because you are separating your parameters out from your ARM template, so if you are likely to want to deploy multiple different configurations using the same template it can be really helpful. If you are only ever going to deploy this once, with one set of parameters, maybe less so. With parameter files you can have multiple different files, lets say for dev, test and prod environments, but use the same template file.

    You can't use more than one copy function inside a single resouce, it can only loop once.


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Thursday, March 23, 2017 10:10 AM
  • Alright for managed disks, but it costs much more than storage account, for a S10 size with 128 GB, I need to pay €2.483 (per disk) while a storage account I pay €0.0166 (LRS-HOT) + €0.0456 and €0.0034 for operations, 0.0656 for all my VHDs, I know that I will not have all the functionality that provide managed disks, but for a school environment, I don't think they will need all of these capabilities.

    About the two copy functions, I will use the same loop that the studentName for my adminUsername, but it means that if I want to have a different name that the studentName, I can't?


    Also, why we need to specify a name for the copy function while nothing use it?
    • Edited by Olddddd Thursday, March 23, 2017 11:38 AM
    Thursday, March 23, 2017 11:28 AM
  • Yeah it's a fair point if your using standard storage. If your using premium storage, which is a must for production workloads, then the price is the same whichever way you go, but obviously that would be overkill in your situation.

    You can still have a different admin name to student, as they are different arrays, but they would have to match on the index. so student[0] would get admin[0].

    You do use the copy name in some instance, for example if you are defining a dependency, so that all of your copy loops complete before the dependent resource runs.


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Thursday, March 23, 2017 5:56 PM
  • Got it.

    Something like that :

    "copy": {
         "name": "vmscopy",
         "count": "[length(parameters('studentName', 'adminUsername'))]"
            },
    			
          "computerName": "[concat('schl-dc-', parameters('studentName')[copyIndex(studentName)])]",
          "adminUsername": "[parameters('adminUsername')[copyIndex(adminUsername)]]",

    ?

    OK, thank you.

    Thursday, March 23, 2017 6:48 PM
  • No sorry, what I meant was you can only have one value in count, so you 'd have to do something like this:

    "copy": {
         "name": "vmscopy",
         "count": "[length(parameters('studentName'))]"
            },
    			
          "computerName": "[concat('schl-dc-', parameters('studentName')[copyIndex)]",
          "adminUsername": "[parameters('adminUsername')[copyIndex]]",

    This is assuming that your student and admin arrays are lined up, so adminUsername[0] is the admin name for student[0].


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    Thursday, March 23, 2017 8:46 PM
  • Alright, that was what I did first, but I thought I was wrong.

    Thanks for all your help Sam!

    Thursday, March 23, 2017 8:57 PM

  • Hi again,

    Is it possible to have another adminPassword parameter in order to see if it matches with the first one to avoid misstaping?
    6 hours 45 minutes ago
  • No, afraid now. I mean you can have another parameter, but there is no way to compare it in your ARM template. 

    You'd need to write your own script that calls the deployment process and does this check for you.


    Sam Cogan Microsoft Azure MVP
    Blog | Twitter

    6 hours 19 minutes ago
  • OK, thanks.
    5 hours 38 minutes ago