I am trying to create an ARM template for a VM to deploy a custom application.
VM is based on this ARM template quickstart for a SQL Server VM:
https://azure.microsoft.com/en-us/resources/templates/101-sql-vm-new-storage/
I need to create one disk first for my application, followed by the "copy" function to define the remaining disks.
This is how the quickstart originally defines the disks: (the createOption in the variables is "empty")
"copy": [
{
"name": "dataDisks",
"count": "[add(parameters('sqlDataDisksCount'), parameters('sqlLogDisksCount'))]",
"input": {
"lun": "[copyIndex('dataDisks')]",
"createOption": "[variables('dataDisks').createOption]",
"caching": "[if(greaterOrEquals(copyIndex('dataDisks'), parameters('sqlDataDisksCount')) ,'None', variables('dataDisks').caching )]",
"writeAcceleratorEnabled": "[variables('dataDisks').writeAcceleratorEnabled]",
"diskSizeGB": "[variables('dataDisks').diskSizeGB]",
"managedDisk": {
"storageAccountType": "[variables('dataDisks').storageAccountType]"
}
}
}
]
As I need an extra 512 GB disk for the application that I want to place at the beginning, I modified my template as follows:
"copy": [
{
"name": "dataDisks",
"count": "[add(1, add(parameters('sqlDataDisksCount'), parameters('sqlLogDisksCount')))]",
"input": {
"lun": "[copyIndex('dataDisks')]",
"createOption": "[variables('dataDisks').createOption]",
"caching": "[if(greaterOrEquals(copyIndex('dataDisks'), add(1, parameters('sqlDataDisksCount'))) ,'None', variables('dataDisks').caching )]",
"writeAcceleratorEnabled": "[variables('dataDisks').writeAcceleratorEnabled]",
"diskSizeGB": "[if(equals(copyIndex('dataDisks'), 0), 512, variables('dataDisks').diskSizeGB)]",
"managedDisk": {
"storageAccountType": "[variables('dataDisks').storageAccountType]"
}
}
}
]
When the VM is created my desired disk is unallocated, it does not appear as a usable disk.
I tried changing the createOption configuration to be:
"createOption": "[if(equals(copyIndex('dataDisks'), 0), 'attach', variables('dataDisks').createOption)]"
But that throws an error of
18:58:27 - New-AzureRmResourceGroupDeployment : 6:58:27 PM - Resource Microsoft.Compute/virtualMachines 'myVM' failed with
18:58:27 - message '{
18:58:27 - "error": {
18:58:27 - "code": "InvalidParameter",
18:58:27 - "message": "Required parameter 'dataDisk.managedDisk.id' is missing (null).",
18:58:27 - "target": "dataDisk.managedDisk.id"
18:58:27 - }
18:58:27 - }'
I also tried to define the other disk outside the copy loop but that did not work either.
Not sure how I should go about this. Help??
Related
Background Information
I have function app with 3 different functions inside. I also have written a powershell script that deploys these functions upstream to Azure portal. It basically just calls this function:
func azure functionapp publish $FUNCTION_APP.name --publish-local-settings -i --overwrite-settings -y
Whenever I run the powershell script, I see the following error message:
Setting PExtStorageQueue = ****
Syncing triggers...
Syncing triggers...
Syncing triggers...
Syncing triggers...
Syncing triggers...
Syncing triggers...
Error calling sync triggers (BadRequest). Request ID = 'b4a22cd4-5c5b-4b2b-a9d4-537cb9cdf96a'.
The functions do end up being deployed and I can trigger them. But none of them have URLs in the "Get URL" option.
What I've checked so far
Based on other posts, it seems that enabling slots might cause issues so I've verified that I DO NOT have slots enabled.
Container OS. I'm using Linux containers. The version of the Linux container is dotnet|3.1 for the function app. I've also tried to change it to "dotnetcore|6.0" per this article: https://medium.com/medialesson/solved-the-parameter-linuxfxversion-has-an-invalid-value-net6-linux-533c759456cd. But that just causes the script to die with the following error when I use dotnetcore:
Line |
38 | New-AzResourceGroupDeployment -ResourceGroupName $currentEnv.AZ_RESOU …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 3:05:27 PM - The deployment 'myresourcegroupname-resources' failed with error(s). Showing 1 out of 1 error(s). Status Message: The parameter LinuxFxVersion has an invalid value. (Code: BadRequest)
| - The parameter LinuxFxVersion has an invalid value. (Code:) - (Code:BadRequest) - (Code:) CorrelationId: 6f7e4efb-a0b9-46c1-9d4a-df8f6c8d155e
ARM Template for App Plan
Here's the section in the template for the app service plan:
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2020-06-01",
"name": "[variables('appServicePlanPortalName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Y1",
"tier": "Dynamic",
"size": "Y1",
"family": "Y",
"capacity": 0
},
"kind": "functionapp,linux",
"properties": {
"name": "[variables('appServicePlanPortalName')]",
"reserved": true,
"computeMode": "Dynamic"
}
},
ARM Template for the Function App
And here's a snippet from the ARM template showing you what I'm doing for the function app itself:
{
"type": "Microsoft.Web/sites",
"apiVersion": "2020-06-01",
"name": "[parameters('functionAppName')]",
"location": "[parameters('location')]",
"kind": "functionapp,linux",
"identity": {
"type": "UserAssigned",
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]": {}
}
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanPortalName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]"
],
"properties": {
"reserved": true,
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanPortalName'))]",
"siteConfig": {
"linuxFxVersion": "dotnet|3.1",
"appSettings": [
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('Microsoft.Insights/components', variables('appInsightsName')), '2015-05-01').InstrumentationKey]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value)]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~4"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
}
]
}
}
}
Any help would be appreciated.
EDIT 1
In case it helps, I've been testing these changes to the ARM template: (git diff showing you what's been changed)
--- a/arm_templates/myresourcegroup-resources.json
+++ b/arm_templates/myresourcegroup-resources.json
## -168,17 +168,13 ##
"name": "[variables('appServicePlanPortalName')]",
"location": "[parameters('location')]",
"sku": {
- "name": "Y1",
- "tier": "Dynamic",
- "size": "Y1",
- "family": "Y",
- "capacity": 0
+ "tier": "Standard",
+ "name": "S1"
},
"kind": "functionapp,linux",
"properties": {
"name": "[variables('appServicePlanPortalName')]",
- "reserved": true,
- "computeMode": "Dynamic"
+ "reserved": true
}
},
{
## -201,7 +197,7 ##
"reserved": true,
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanPortalName'))]",
"siteConfig": {
- "linuxFxVersion": "dotnet|3.1",
+ "linuxFxVersion": "DOTNETCORE|6.0",
"appSettings": [
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
It takes a super long time to publish but it eventually finishes.
It isn't able to list all my functions though, but I think I'm ok with that. This is what I see in the powershell script window:
Getting site publishing info...
Creating archive for current directory...
Uploading 13 MB [#################################################################################]
Upload completed successfully.
Deployment completed successfully.
App setting AzureWebJobsStorage is different between azure and local.settings.json
Overwriting setting in azure with local value because '--overwrite-settings [-y]' was specified.
Setting FUNCTIONS_WORKER_RUNTIME = ****
Setting PExtStorageTableName = ****
Setting PExtStorageQueue = ****
Functions in myresourcegroup-6z2ybl3tvqf6y-app:
PS C:\Users\me\src\azureTestDeploy>
But now I have URLs defined in the upstream functions!
Woot woot!
I'm going to revert each line again to try to narrow it down to the specific ARM change that solved the issue.
I'm guessing it'll be some combination, including the DOTNETCORE|6.0 change.
EDIT 2
I've been trying to play around with the different versions of the APIs to see how I can define a dynamic application service plan (Y1).
but I can't seem to get it working. I know our subscription supports Y1 in eastus for Windows. But I can't seem to get it working for Linux.
Anytime I use dynamic it gives me an error saying "The parameter LinuxFxVersion has an invalid value. (Code: BadRequest)"
I am using copy to create multiple VM's and want to have multiple datadisks for each vm.
I know i can do it this way:
{
"name": "[concat('dataDisk-',parameters('vm-name'),'-0',copyIndex(1))]",
"diskSizeGB": "[parameters('dataDisksize')]",
"lun": 0,
"createOption": "Empty"
},
{
"name": "[concat('dataDisk1-',parameters('vm-name'),'-0',copyIndex(1))]",
"diskSizeGB": "[parameters('dataDisksize')]",
"lun": 1,
"createOption": "Empty"
}
Now I have to create 20 disks with the same name and this doesn't seem to be good workaround. Getting issue with disk name while using copy. For my case i can use the same disksize for all 20 disks
You can use the copy element to repeat properties:
"copy": [
{
"name": "dataDisks",
"count": "[parameters('numberOfDataDisks')]",
"input": {
"lun": "[copyIndex('dataDisks')]",
"createOption": "Empty",
"diskSizeGB": 1023
}
}
]
More information here: https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/copy-properties
Now I have to create 20 disks with the same name and this doesn't seem
to be good workaround. Getting issue with disk name while using copy.
Creating multiple disks using same name is impossible. you need concat either copyindex values to disk name or the VMnames to the Names of the disk..
In our template we have used the copy function block in the below manner to deploy multiple disks for a single virtual Machine & we have tested this in our local environment which is working fine.
Here is the ARM template that we have created :
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"dataDiskCount": {
"type": "int","minvalue" : 1,"maxValue" :20,"defaultValue" : 4,
"metadata": {
"description": "number of data disks."
}
}
},
"variables": {}
"resources": [
{
"copy": [
{
"name": "dataDisks",
"count": "[parameters('dataDiskCount')]",
"input": {
"diskSizeGB": "20",
"lun": "[copyIndex('dataDisks')]",
"createOption": "Empty",
"name":"[concat('disk',copyIndex('dataDisks'),'dk')]"
}
}
},
"outputs": {}
}
Here is the sample output screen shot for reference:
I have created a template which is meant to deploy a complete network solution, which includes 2-subnets, vnet, vnetgw and pubip. I am looking for a way to programmatically reference some of the resource id's such that it makes the template more dynamic and can be used as many times as possible. secondly, the templates generates an error on deployment which obviously is as a result of the the references i mentioned earlier. Pls see error below;
New-AzResourceGroupDeployment: Line | 3 |
New-AzResourceGroupDeployment -ResourceGroupName rg-vnet-dev -Templat
…
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 19:05:58 - Resource Microsoft.Network/virtualNetworkGateways 'rgvnetdev-vnetgw' failed with message '{ "error": {
"code": "InvalidTemplate",
"message": "Unable to process template language expressions for resource
'/subscriptions/77dd2569-6341-4c72-880d-ef59413db99e/resourceGroups/rg-vnet-dev/providers/Microsoft.Network/virtualNetworkGateways/rgvnetdev-vnetgw'
at line '279' and column '9'. 'Unable to evaluate template language
function 'resourceId': the type
'Microsoft.Network/virtualNetworks/subnets' requires '2' resource name
argument(s). Please see
https://aka.ms/arm-template-expressions/#resourceid for usage
details.'",
"additionalInfo": [
{
"type": "TemplateViolation",
"info": {
"lineNumber": 279,
"linePosition": 9,
"path": ""
}
}
] } }
I will be happy to share the code, if this would assist in resolving my issue. The error relates to referencing the vnet dependson for creating vnetgw.
From the error message, it seems that referenced subnet id is invalid. This function resourceId format is
resourceId([subscriptionId], [resourceGroupName], resourceType, resourceName1, [resourceName2], ...)
In this case, you probably lacks the VNet name at line '279', the referenced subnet id should be like this:
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('subnet1Name'))]"
},
{
"type": "Microsoft.Network/virtualNetworkGateways",
"apiVersion": "2019-12-01",
"name": "[variables('vnetgwname')]",
"location": "[parameters('Location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses',variables('pubIp'))]",
"[resourceId('Microsoft.Network/virtualNetworks',variables('VNetName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "vnetgatewayconfig",
"properties": {
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('pubIp'))]"
},
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets',variables('VNetName'),variables('Uniquegwsubnet'))]"
},
"privateIPAllocationMethod": "[parameters('publicIPAllocationMethod')]"
}
}
],
"sku": {
"name": "[parameters('sku')]",
"tier": "[parameters('sku')]"
},
"gatewayType": "[parameters('gatewayType')]",
"vpnType": "[parameters('VpnType')]",
"activeActive": false,
"enableBgp": false,
"vpnGatewayGeneration": "[parameters('vpnGatewayGeneration')]"
}
},
During the cleanup process of Azure VM. I am trying to identify all resources associated with Deallocated VM, Like network, storage and nic.
I ran below query to get details, but unable to write a query to get other details in the same query parameter to get a result of nic, storge in table format.
az vm list -d --query "[?powerState=='VM deallocated']" -o table
qa-automation-10 TEST-QA-AUTOMATION
qa-automation-11 TEST-QA-AUTOMATION
qa-automation-12 TEST-QA-AUTOMATION
qa-automation-13 TEST-QA-AUTOMATION
qa-automation-14 TEST-QA-AUTOMATIO
Any help will be appreciable, I am especially looking for az client query. As VM deallocated list is big so I will run through gitlab pipeline.
},
"id": "/subscriptions/xxxxxxxx/resourceGroups/xxxx/providers/Microsoft.Compute/virtualMachines/x023901",
"identity": null,
"licenseType": null,
"location": "x",
"macAddresses": "",
"name": "x023901",
"networkProfile": {
"networkInterfaces": [
{
"id": "/subscriptions/x/resourceGroups/rGroup-ENV0239/providers/Microsoft.Network/networkInterfaces/x023901nic",
"primary": null,
"resourceGroup": "rGroup-ENV0239"
}
]
},
"osProfile": null,
"plan": null,
"powerState": "VM deallocated",
"privateIps": "x.x.x.x",
"provisioningState": "Succeeded",
"publicIps": "",
"resourceGroup": "RGROUP-ENV0239",
"resources": [
{
"autoUpgradeMinorVersion": true,
"forceUpdateTag": null,
"id": "/subscriptions/xxxxxxx/resourceGroups/RGROUP-ENV0239/providers/Microsoft.Compute/virtualMachines/x023901/extensions/OmsAgentForLinux",
"instanceView": null,
"location": "x",
"name": "OmsAgentForLinux",
"protectedSettings": null,
"provisioningState": "Succeeded",
"publisher": "Microsoft.EnterpriseCloud.Monitoring",
"resourceGroup": "RGROUP-ENV0239",
"settings": {
"stopOnMultipleConnections": true,
"workspaceId": "xx"
},
"tags": null,
"type": "Microsoft.Compute/virtualMachines/extensions",
"typeHandlerVersion": "1.0",
"virtualMachineExtensionType": "OmsAgentForLinux"
}
],
"storageProfile": {
"dataDisks": [
{
"caching": "None",
"createOption": "Attach",
"diskSizeGb": 20,
"image": null,
"lun": 0,
"managedDisk": null,
"name": "x-data1.vhd",
"vhd": {
"uri": "https://x.core.windows.net/vhds/x-data1.vhd"
},
"writeAcceleratorEnabled": null
}
],
"imageReference": null,
"osDisk": {
"caching": "ReadWrite",
"createOption": "Attach",
"diffDiskSettings": null,
"diskSizeGb": 30,
"encryptionSettings": null,
"image": null,
"managedDisk": null,
"name": "xosDisk",
"osType": "Linux",
"vhd": {
"uri": "https://xblob.core.windows.net/vhds/x.vhd"
},
"writeAcceleratorEnabled": null
}
},
"tags": null,
"type": "Microsoft.Compute/virtualMachines",
"vmId": "x",
"zones": null
},
The VMs in Azure has two types, one is the managed VM while the other is unmanaged VM. When you want to show the details of all the VMs, you should pay attention to this.
In addition, there no property about the storage account. You can store the files in the storage account and do not associate to the VM. So you just get a little info about the storage account if the VM is unmanaged.
Get a list of the VM with some resources just like vmName, NIC, osDisk or osDiskURI, the CLI command here:
az vm list --query "[].{VMName:name, nicId:networkProfile.networkInterfaces[0].id, managedDiskId:storageProfile.osDisk.managedDisk.id, UnmanagedDiskURL:storageProfile.osDisk.vhd.uri}" -o table
You can change the info that you want if you can find it in the VM details through the CLI command az vm show. Hope this will help. Any more question you can give me the message.
You will need to use a query like below:
az vm show -g RG-DemoAutomation -n DemoVM101 --query "{VMName:name, admin:osProfile.adminUsername,nicId:networkProfile.networkInterfaces[0].id, osDiskId:storageProfile.osDisk.managedDisk.id}" -o table
As you mentioned you will need to iterate through the output of the az vm list and then for each VM you will need to run az vm show as I showed in the sample above.
You can have filter and data selection in one query as "[?query here].{customColName1:value1, customColName2:value2}" but the problem is that az vm list does not have the details that you are looking for. That detail is available with az vm show command.
For values in the above syntax, the query uses JMESPATH and you can find the exact value by using a neat utility available here: JMESPath Terminal
Also, try using the output as json (-o json) as that will be much more readable unless you want to dump the output into an excel sheet.
The question in the title: "how to create VM with Json arm template using define VHD (or disk,snapshot) in azure?" Thanks for your help!
You can create the vm from VHD file through the template. The steps are that you can upload the VHD file to an Azure storage account and create a managed disk from the VHD file. Then attach it to the VM.
Create the managed disk from the VHD file:
{
"type": "Microsoft.Compute/disks",
"apiVersion": "2018-04-01",
"name": "[variables('diskName')]",
"location": "[parameters('location')]",
"properties": {
"creationData": {
"createOption": "Import",
"sourceUri": "[parameters('osDiskVhdUri')]"
},
"osType": "[parameters('osType')]"
}
}
Attach the managed disk to the VM:
"storageProfile": {
"osDisk": {
"osType": "[parameters('osType')]",
"createOption": "Attach",
"managedDisk": {
"id": "[resourceId('Microsoft.Compute/disks', variables('diskName'))]"
}
}
}
You can get the whole template here.