The template below has been modified to use image from Azure compute gallery(ACG), eariler it used to reference the blob url of a vhd. Now, the requirement has been changed to create VM from image referenced from ACG. The ACG is in a different resource group and the VM which has to be created will be in a different resource group.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"artifactsBaseUrl": {
"type": "string",
"defaultValue": "https://mypub.blob.core.windows.net/template-artifacts",
"metadata": {
"description": "Base URL of the solution template",
"artifactsBaseUrl": ""
}
},
"location": {
"type": "string",
"metadata": {
"description": "Azure cloud location for testing cluster"
}
},
"clusterName": {
"type": "string",
"metadata": {
"description": "testing cluster name used as prefix for host names"
}
},
"storageAccountType": {
"type": "string",
"defaultValue": "Premium_LRS",
"allowedValues": [
"Premium_LRS",
"Standard_LRS"
],
"metadata": {
"description": "Storage account type"
}
},
"adminUserName": {
"type": "string",
"metadata": {
"description": "username used to administer testing (must be 'azure-user')"
}
},
"authType": {
"type": "string",
"defaultValue": "password",
"allowedValues": [
"password",
"sshPublicKey"
],
"metadata": {
"description": "Authentication type for the virtual machines"
}
},
"adminPassword": {
"type": "securestring",
"defaultValue": "",
"metadata": {
"description": "Password to login into testing cluster nodes"
}
},
"adminSshPublicKey": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "OpenSSH public key used to login into testing cluster nodes as alternative to password"
}
},
"vmSize": {
"type": "string",
"defaultValue": "Standard_DS13_v2",
"metadata": {
"description": "testing cluster node VM type"
}
},
"vmCount": {
"type": "int",
"defaultValue": 2,
"maxValue": 100,
"minValue": 1,
"metadata": {
"description": "Number of nodes for testing cluster"
}
},
"dataDisksProfile": {
"type": "string",
"defaultValue": "min",
"allowedValues": [
"min",
"min2"
],
"metadata": {
"description": "Data disks configuration for each VM"
}
},
"vnetNewOrExisting": {
"type": "string",
"defaultValue": "new",
"allowedValues": [
"new",
"existing"
],
"metadata": {
"description": "Specifies if a new or an existing virtual network should be used for deploying VMs"
}
},
"vnetResourceGroup": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "Virtual Network Resource Group"
}
},
"vnetName": {
"type": "string",
"metadata": {
"description": "Virtual Network name"
}
},
"vnetAddressSpace": {
"type": "string",
"defaultValue": "10.0.0.0/16",
"metadata": {
"description": "Virtual Network Address Prefix (i.e. CIDR)"
}
},
"subnetName": {
"type": "string",
"defaultValue": "subnet-ctest",
"metadata": {
"description": "all testing nodes will be deployed into this subnet within the Virtual Network"
}
},
"subnetAddressSpace": {
"type": "string",
"defaultValue": "10.0.0.0/24",
"metadata": {
"description": "Virtual Network subnet Address Prefix (i.e. CIDR)"
}
},
"privateIPAllocationMethod": {
"type": "string",
"defaultValue": "dynamic",
"allowedValues": [
"static",
"dynamic"
],
"metadata": {
"description": "Specifies whether testing head's private IP address is statically or dynamically assigned"
}
},
"privateIPAddress": {
"type": "string",
"defaultValue": "10.0.0.10",
"metadata": {
"description": "Private IP address of the head node in the subnet, if statically assigned"
}
},
"publicIPAddressNewOrExisting": {
"type": "string",
"defaultValue": "new",
"allowedValues": [
"new",
"existing",
"none"
],
"metadata": {
"description": "Specifies if a new or an existing public IP should be used for deployment"
}
},
"publicIPAddressResourceGroup": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "Public IP resource group for cases when existing public IP is used"
}
},
"publicIPAddressName": {
"type": "string",
"defaultValue": "",
"metadata": { "description": "Public IP Address name" }
},
"publicIPAddressDomainNameLabel": {
"type": "string",
"defaultValue": "",
"metadata": { "description": "Public IP DNS label" }
},
"startUp": {
"type": "string",
"defaultValue": "start",
"allowedValues": [
"start",
"config",
"none"
],
"metadata": {
"description": "Cluster start-up type"
}
},
"galleryName": {
"type": "string",
"defaultValue": "imgallery"
},
"srcImageName": {
"type": "string",
"defaultValue": "someapp"
},
"imageVersion": {
"type": "string",
"defaultValue": "1.0.1"
},
"sourceGalleryResourceGroup": {
"type": "string",
"defaultValue": "imgallery"
}
},
"variables": {
"preview": "",
"storageAccountType": "[parameters('storageAccountType')]",
"storageAccountNameStandard": "[toLower(take(replace(replace(concat(parameters('clusterName'),uniqueString(resourceGroup().name,parameters('clusterName'))),'-',''),'_',''),24))]",
"storageAccountTypeStandard": "Standard_LRS",
"imageId": "[subscriptionResourceId('Microsoft.Compute/galleries/images/versions', parameters('galleryName'), parameters('srcImageName'), parameters('imageVersion'))]",
"dataDiskSize_min": 128,
"dataDisks_min": [
{
"diskSizeGB": "[variables('dataDiskSize_min')]",
"lun": 0,
"caching": "None",
"createOption": "Empty",
"managedDisk": {
"storageAccountType": "[variables('storageAccountType')]"
}
}
],
"dataDisks_min2": [
{
"diskSizeGB": "[variables('dataDiskSize_min')]",
"lun": 0,
"caching": "None",
"createOption": "Empty",
"managedDisk": {
"storageAccountType": "[variables('storageAccountType')]"
}
},
{
"diskSizeGB": "[variables('dataDiskSize_min')]",
"lun": 1,
"caching": "None",
"createOption": "Empty",
"managedDisk": {
"storageAccountType": "[variables('storageAccountType')]"
}
}
],
"dataDisksConfig": "[variables(concat('dataDisks_', parameters('dataDisksProfile')))]",
"hostName": "[concat(parameters('clusterName'), '-vm')]",
"subdeploymentSuffix": "[uniqueString(deployment().name)]",
"baseUrl": "[concat(parameters('artifactsBaseUrl'),'/')]",
"startScriptName": "azure-ctest-san-start.sh",
"startScriptUrl": "[concat(variables('baseUrl'),variables('startScriptName'))]",
"templateUrlVnet": "[concat(variables('baseUrl'),'vnet-',parameters('vnetNewOrExisting'),'.json')]",
"templateUrlPublicIP": "[concat(variables('baseUrl'),'publicIP-',parameters('publicIPAddressNewOrExisting'),'.json')]",
"vnetID": "[resourceId(parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]",
"subnetID": "[concat(variables('vnetID'), '/subnets/', parameters('subnetName'))]",
"sshKeyPath": "[concat('/home/',parameters('adminUserName'),'/.ssh/authorized_keys')]",
"linuxConfiguration_sshPublicKey": {
"disablePasswordAuthentication": "true",
"ssh": {
"publicKeys": [
{
"path": "[variables('sshKeyPath')]",
"keyData": "[parameters('adminSshPublicKey')]"
}
]
}
},
"linuxConfiguration_password": { },
"linuxConfiguration": "[variables(concat('linuxConfiguration_',parameters('authType')))]",
"computeApiVersion": "2017-03-30",
"networkApiVersion": "2016-12-01",
"storageApiVersion": "2015-06-15",
"resourceApiVersion": "2016-09-01"
},
"resources": [
{
"apiVersion": "[variables('storageApiVersion')]",
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountNameStandard')]",
"location": "[parameters('location')]",
"tags": {
"ctestClusterName": "[parameters('clusterName')]"
},
"properties": {
"accountType": "[variables('storageAccountTypeStandard')]"
}
},
{
"apiVersion": "[variables('resourceApiVersion')]",
"type": "Microsoft.Resources/deployments",
"name": "[concat('ctest-vnet-',variables('subdeploymentSuffix'))]",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[variables('templateUrlVnet')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": {
"value": "[parameters('location')]"
},
"clusterName": {
"value": "[parameters('clusterName')]"
},
"vnetName": {
"value": "[parameters('vnetName')]"
},
"vnetResourceGroup": {
"value": "[parameters('vnetResourceGroup')]"
},
"vnetAddressSpace": {
"value": "[parameters('vnetAddressSpace')]"
},
"subnetName": {
"value": "[parameters('subnetName')]"
},
"subnetAddressSpace": {
"value": "[parameters('subnetAddressSpace')]"
}
}
}
},
{
"apiVersion": "[variables('resourceApiVersion')]",
"type": "Microsoft.Resources/deployments",
"name": "[concat('ctest-pubIP-',variables('subdeploymentSuffix'))]",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[variables('templateUrlPublicIP')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": {
"value": "[parameters('location')]"
},
"clusterName": {
"value": "[parameters('clusterName')]"
},
"publicIPAddressName": {
"value": "[parameters('publicIPAddressName')]"
},
"publicIPAddressType": {
"value": "Dynamic"
},
"publicIPAddressDomainNameLabel": {
"value": "[toLower(parameters('publicIPAddressDomainNameLabel'))]"
},
"publicIPAddressResourceGroup": {
"value": "[parameters('publicIPAddressResourceGroup')]"
}
}
}
},
{
"apiVersion": "[variables('networkApiVersion')]",
"type": "Microsoft.Network/networkInterfaces",
"name": "[concat(variables('hostName'),'-nic0')]",
"location": "[parameters('location')]",
"tags": {
"ctestClusterName": "[parameters('clusterName')]"
},
"dependsOn": [
"[concat('Microsoft.Resources/deployments/ctest-vnet-',variables('subdeploymentSuffix'))]",
"[concat('Microsoft.Resources/deployments/ctest-pubIP-',variables('subdeploymentSuffix'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ip1",
"properties": {
"privateIPAllocationMethod": "[parameters('privateIPAllocationMethod')]",
"privateIPAddress": "[if(equals(parameters('privateIPAllocationMethod'), 'static'), parameters('privateIPAddress'), json('null'))]",
"publicIPAddress": "[if(equals(reference(concat('Microsoft.Resources/deployments/ctest-pubIP-',variables('subdeploymentSuffix')),'2015-01-01').outputs.publicIPProperties.value.id, ''), json('null'), reference(concat('Microsoft.Resources/deployments/ctest-pubIP-',variables('subdeploymentSuffix')),'2015-01-01').outputs.publicIPProperties.value)]",
"subnet": {
"id": "[reference(concat('Microsoft.Resources/deployments/ctest-vnet-',variables('subdeploymentSuffix')),'2015-01-01').outputs.subnetID.value]"
}
}
}
],
"enableAcceleratedNetworking": true
}
},
{
"apiVersion": "[variables('computeApiVersion')]",
"type": "Microsoft.Compute/virtualMachines",
"name": "[concat(variables('hostName'),'-0')]",
"location": "[parameters('location')]",
"tags": {
"ctestClusterName": "[parameters('clusterName')]"
},
"dependsOn": [
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountNameStandard'))]",
"[concat('Microsoft.Network/networkInterfaces/', variables('hostName'), '-nic0')]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSize')]"
},
"osProfile": {
"computerName": "[concat(variables('hostName'),'-0')]",
"adminUserName": "[parameters('adminUserName')]",
"adminPassword": "[parameters('adminPassword')]",
"linuxConfiguration": "[variables('linuxConfiguration')]"
},
"storageProfile": {
"imageReference": {
"id": "[variables('imageId')]"
},
"osDisk": {
"createOption": "FromImage",
"managedDisk": {
"storageAccountType": "Standard_LRS"
}
},
"dataDisks": "[variables('dataDisksConfig')]"
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('hostName'),'-nic0'))]"
}
]
},
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": "false",
"storageUri": "[concat('http://',variables('storageAccountNameStandard'),'.blob.core.windows.net')]"
}
}
}
},
{
"type": "Microsoft.Compute/virtualMachineScaleSets",
"name": "[concat(parameters('clusterName'), '-ss')]",
"location": "[parameters('location')]",
"tags": {
"ctestClusterName": "[parameters('clusterName')]"
},
"apiVersion": "[variables('computeApiVersion')]",
"dependsOn": [
"[concat('Microsoft.Resources/deployments/ctest-vnet-',variables('subdeploymentSuffix'))]",
"[concat('Microsoft.Network/networkInterfaces/', variables('hostName'), '-nic0')]",
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountNameStandard'))]"
],
"sku": {
"name": "[parameters('vmSize')]",
"tier": "Standard",
"capacity": "[sub(parameters('vmCount'),1)]"
},
"properties": {
"overprovision": "true",
"upgradePolicy": {
"mode": "Manual"
},
"virtualMachineProfile": {
"osProfile": {
"computerNamePrefix": "[variables('hostName')]",
"adminUserName": "[parameters('adminUserName')]",
"adminPassword": "[parameters('adminPassword')]",
"linuxConfiguration": "[variables('linuxConfiguration')]"
},
"storageProfile": {
"imageReference": {
"id": "[variables('imageId')]"
},
"osDisk": {
"createOption": "FromImage",
"managedDisk": {
"storageAccountType": "Standard_LRS"
}
},
"dataDisks": "[variables('dataDisksConfig')]"
},
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": "false",
"storageUri": "[concat('http://',variables('storageAccountNameStandard'),'.blob.core.windows.net')]"
}
},
"networkProfile": {
"networkInterfaceConfigurations": [
{
"name": "[concat(parameters('clusterName'), '-nic')]",
"properties": {
"primary": "true",
"ipConfigurations": [
{
"name": "[concat(parameters('clusterName'), '-ipconfig')]",
"properties": {
"subnet": {
"id": "[reference(concat('Microsoft.Resources/deployments/ctest-vnet-',variables('subdeploymentSuffix')),'2015-01-01').outputs.subnetID.value]"
},
"privateIPAllocationMethod": "Dynamic"
}
}
],
"enableAcceleratedNetworking": true
}
}
]
},
"extensionProfile": {
"extensions": [
{
"name": "ctest-setup",
"properties": {
"publisher": "Microsoft.OSTCExtensions",
"type": "CustomScriptForLinux",
"typeHandlerVersion": "1.4",
"autoUpgradeMinorVersion": true,
"settings": {
"fileUris": [
"[variables('startScriptUrl')]"
],
"commandToExecute": "[concat('bash ',variables('startScriptName'),' ',reference(concat(variables('hostName'),'-nic0')).ipConfigurations[0].properties.privateIPAddress,' ',parameters('clusterName'),' ',parameters('vmCount'),' ',1 )]"
}
}
}
]
}
}
}
},
{
"apiVersion": "[variables('computeApiVersion')]",
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(variables('hostName'),'-0','/ctest-setup-head')]",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('hostName'),'-0')]",
"[concat('Microsoft.Compute/virtualMachineScaleSets/', parameters('clusterName'), '-ss')]"
],
"properties": {
"publisher": "Microsoft.OSTCExtensions",
"type": "CustomScriptForLinux",
"typeHandlerVersion": "1.3",
"settings": {
"fileUris": [
"[variables('startScriptUrl')]"
],
"commandToExecute": "[concat('bash ',variables('startScriptName'),' -s ',parameters('startUp'),' ',reference(concat(variables('hostName'),'-nic0')).ipConfigurations[0].properties.privateIPAddress,' ',parameters('clusterName'),' ',parameters('vmCount'),' ',0 )]"
}
}
}
],
"outputs": {
"fqdn": {
"value": "[reference(concat('ctest-pubIP-',variables('subdeploymentSuffix'))).outputs.fqdn.value]",
"type": "string"
},
"sshCommand": {
"value": "[concat('ssh ', parameters('adminUserName'), '@', reference(concat('ctest-pubIP-',variables('subdeploymentSuffix'))).outputs.fqdn.value)]",
"type": "string"
},
"privateIP": {
"value": "[reference(concat(variables('hostName'),'-nic0')).ipConfigurations[0].properties.privateIPAddress]",
"type": "string"
}
}
}
I have python script to deploy, which throws an error when I made the change
ERROR: {"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-deployment-operations for usage details.","details":[{"code":"BadRequest","message":"{rn "error": {rn "code": "BadRequest",rn "message": "Id /subscriptions/<subscription-id>/providers/Microsoft.Compute/galleries/imgallery/images/someapp/versions/1.0.1 is not a valid resource reference."rn }rn}"},{"code":"BadRequest","message":"{rn "error": {rn "code": "BadRequest",rn "message": "Id /subscriptions/fdedab26-abdc-4387-8176-012f6778d00d/providers/Microsoft.Compute/galleries/imgallery/images/someapp/versions/1.0.1 is not a valid resource reference."rn }rn}"}]}}
azure call failed, return code: 1
As from the error it’s clear that the path for the image version is not correct, so I created a vm from the same image version from the portal and on observing the deployment template (which gets automatically generated) found
"imageReference": {
"id": "/subscriptions/XXXX-XXXX-XXXX/resourceGroups/imgallery/providers/Microsoft.Compute/galleries/nliterepo/images/nlite/versions/1.0.1"
},
If I replace the imageReference in the above template with this "id", get this error
ERROR: {'code': 'InvalidTemplateDeployment', 'message': "The template deployment 'testimg2-2024-08-20-11-57-29' is not valid according to the validation procedure. The tracking id is '5197dcc9-7acc-43e1-9a4d-cba9e5f9ad6f'. See inner errors for details."}
Inner Errors:
{'code': 'InvalidParameter', 'target': 'imageReference.id', 'message': "Resource 'testimg2-vm-0' has invalid parameters. Details: The value of parameter imageReference.id is invalid."}
azure call failed, return code: 1
2
Answers
Well the problem is fixed after changing the apiversion of
computeApiVersion
in json to2024-03-01
Here is the ARM template for creating a VM from an Azure Compute Gallery image.
Output:
Existing VM configuration
The VM has been created using the
ARM template
with an image reference from the Azure Compute Gallery.