azureterraform

How Azure creates VMs from generalized images with data disks in terraform


I made a generalized image of a Windows virtual machine with a separate data disk attached. In the Azure Portal, generalized images containing this data disk are well-created, but with terraform code, the following error occurs in this generalized image.

Virtual Machine Name: "test-vm"): performing CreateOrUpdate: unexpected status 400 (400 Bad Request) with error: InvalidParameter: StorageProfile.dataDisks.lun does not have required value(s) for image specified in storage profile.
│
│   with azurerm_windows_virtual_machine.vm["vm1"],
│   on vm.tf line 67, in resource "azurerm_windows_virtual_machine" "vm":
│   67: resource "azurerm_windows_virtual_machine" "vm" {

My code is as below.

############################
### Location & Network 
############################
### Location
variable "location" {
  type      = string
  default   = "Korea Central"
}

### Resource Group Valiable - Network
variable "network_rg" {
  type      = string
  default   = "test-vm-rg"
}

### Virtual Network Valiable
variable "network_vnet" {
  type      = string
  default   = "vnet-test-vm"
}

### Subnet Valiable
variable "network_subnet" {
  type      = string
  default   = "subnet-test-vm"
}

### Private IP Setting
variable "private-ip-type" {
  type    = string
  default = "Static"
}

############################
### Resource & OS env
############################
### Resource Group
variable "system_rg" {
  type    = string
  default = "test-vm-d-rg"
}

############################
### Image Information
############################
### Image Publisher
variable "vm_template" {
  type = map(any)
  default = {
    vm1 = {
      source_image_id = "/subscriptions/0000000000000/resourceGroups/test-vm-rg/providers/Microsoft.Compute/images/vm-test-vm-image-v1"
      vm_name      = "test-vm"
      hostname     = "test-vm"
      os_publisher = "MicrosoftWindowsServer"
      os_offer     = "WindowsServer"
      os_sku       = "2022-datacenter-azure-edition"
      license_type = "Windows_Server"
      os_version   = "latest"
      osdisk_type  = "StandardSSD_LRS"
      osdisk_size  = "128"
      vm_type      = "Standard_D2s_v5"
      adminid      = "testadmin"
      private_ip   = "10.10.10.10"
      nic          = "nic01"
      os_disk      = "osdisk01"
    }
  }
}
data "azurerm_resource_group" "system_rg_name" {
  name = var.system_rg
}

data "azurerm_subnet" "network_subnet" {
  name                 = var.network_subnet
  virtual_network_name = var.network_vnet
  resource_group_name  = var.network_rg
}

resource "azurerm_network_interface" "nic" {
  for_each            = var.vm_template
  name                = "${each.value.vm_name}-${each.value.nic}"
  location            = var.location
  resource_group_name = data.azurerm_resource_group.system_rg_name.name
  accelerated_networking_enabled = true

  ip_configuration {
    name      = "internal"
    subnet_id = data.azurerm_subnet.network_subnet.id

    private_ip_address_allocation = var.private-ip-type
    private_ip_address            = each.value.private_ip

  }
}

resource "azurerm_windows_virtual_machine" "vm" {
  for_each            = var.vm_template
  name                = each.value.vm_name
  location            = var.location
  resource_group_name = data.azurerm_resource_group.system_rg_name.name
  source_image_id     = each.value.source_image_id
  license_type        = each.value.license_type
  size                = each.value.vm_type
  network_interface_ids = [
    azurerm_network_interface.nic[each.key].id,
  ]

  identity {
    type = "SystemAssigned"
  }

  os_disk {
    name                 = "${each.value.vm_name}-${each.value.os_disk}"
    caching              = "ReadWrite"
    storage_account_type = each.value.osdisk_type
    disk_size_gb         = each.value.osdisk_size
  }

  computer_name  = each.value.hostname
  admin_username = each.value.adminid
  admin_password = data.azurerm_key_vault_secret.password.value
  timezone       = "Korea Standard Time"

}

How do I create code to restore the data disks contained in the generalized VM image? Looking at the generalized VM images, I can see that there is a data disk, but I don't know how to use this in Terraform. One thing is for sure, you can use Azure Portal. But I would like to use Terraform.

enter image description here


Solution

  • I encountered the same error when trying to create a VM from a generalized VM using the azurerm_windows_virtual_machine module..

    Error: creating Windows Virtual Machine (Subscription: "ttttyyyyyyyyyyyy" │ Resource Group Name: "Venkatvm-RG" │ Virtual Machine Name: "venkat-vm1"): 
    performing CreateOrUpdate: unexpected status 400 (400 Bad Request) with error: InvalidParameter: StorageProfile.dataDisks.lun does not have required value(s) for image specified in storage profile
    

    To resolve the error, you can use azurerm_virtual_machine to create a VM using a gallery image. Here is the updated Terraform code to create a VM with a data disk.

    variable.tf

    variable "location" {
      type    = string
      default = "eastus"  # Update with your desired location
    }
    
    variable "resource_group_name" {
      type    = string
      default = "Venkatvm-RG"  # Update with your resource group name
    }
    
    variable "image_id" {
      type    = string
      default = "/subscriptions/<SUB_ID>/resourceGroups/Venkat/providers/Microsoft.Compute/galleries/Venkatgallery1/images/Venkat-vmdefinition"  
    }
    variable "vm_size" {
      type    = string
      default = "Standard_DS2_v2"  # Update with your desired VM size
    }
    
    variable "admin_username" {
      type    = string
      default = "adminuser"  # Update with your desired admin username
    }
    
    variable "admin_password" {
      type    = string
      default = "P@ssw0rd123!"  # Update with your desired admin password
    }
    
    
    

    main.tf

        provider "azurerm" {
          features {}
        }
        
        # Resource Group
        resource "azurerm_resource_group" "rg" {
          name     = var.resource_group_name
          location = var.location
        }
        
        data "azurerm_managed_disk" "existing" {
          name                = "venkat-vm_DataDisk_0"
          resource_group_name = "Venkat"
        }
        
        resource "azurerm_virtual_network" "example" {
          name                = "example-networkq"
          address_space       = ["10.0.0.0/16"]
          location            = azurerm_resource_group.rg.location
          resource_group_name = azurerm_resource_group.rg.name
        }
        
        resource "azurerm_subnet" "example" {
          name                 = "internal1"
          resource_group_name  = azurerm_resource_group.rg.name
          virtual_network_name = azurerm_virtual_network.example.name
          address_prefixes     = ["10.0.2.0/24"]
        }
        
        resource "azurerm_network_interface" "example" {
          name                = "example-nic1"
          location            = azurerm_resource_group.rg.location
          resource_group_name = azurerm_resource_group.rg.name
        
          ip_configuration {
            name                          = "internal"
            subnet_id                     = azurerm_subnet.example.id
            private_ip_address_allocation = "Dynamic"
          }
        }
        resource "azurerm_virtual_machine" "testingvm" {
              name                        = "galleryimage"
              resource_group_name         = azurerm_resource_group.rg.name
              location                    = azurerm_resource_group.rg.location
              vm_size                     = var.vm_size
              network_interface_ids       = [azurerm_network_interface.example.id]
            
              storage_image_reference {
                id = var.image_id 
                }
              storage_os_disk {
                name                      = "galleryimage-os"
                caching                   = "ReadWrite"
                create_option             = "FromImage"
                managed_disk_type         = "Standard_LRS"
              } 
              os_profile {
                computer_name  = "venkatvm1"
                admin_username = var.admin_username
                admin_password = var.admin_password
              }
              os_profile_windows_config {
              }
            }
    

    Here is my existing image, from which I created a gallery image.

    enter image description here

    The VM with a data disk has been created from the gallery image.

    enter image description here