Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

While using existing storage account deployment fails for creating VM with ARM Template #375

Closed
parth618 opened this issue Apr 19, 2016 · 8 comments
Assignees

Comments

@parth618
Copy link

parth618 commented Apr 19, 2016

All the other resources mentioned for creating ARM works fine and are provisioned but at last it generates failure error as shown below.

/usr/local/rvm/gems/ruby-2.1.8/gems/ms_rest_azure-0.1.1/lib/ms_rest_azure/azure_service_client.rb:72:in `get_put_operation_result': Long running operation failed with status Failed (MsRestAzure::AzureOperationError).

Also, the status as displayed on Azure portal was 'failed'
existing storage error
existing storage error1

I tried redeploying from the portal but it gives error as: "Failed to redeploy the virtual machine. Error: Blob already exists. Please provide a different blob URI as target for disk 'Test1'."

Reference: http://stackoverflow.com/questions/36155624/failure-in-vm-deployment-with-arm-template-while-using-existing-storage-account

@vishrutshah
Copy link
Contributor

@parth618 Thanks for reporting the issue. We'll look into it soon and get back to you.

@vishrutshah
Copy link
Contributor

Hello @parth618,

I've tried to create a new vm for existing resource group and storage account using the ARM clients. I see that it is able to create the vm with the existing storage account. Please refer the following sample code and let us know your feedback.

In the following code method create_vm method is aligned with the one document at azure_mgmt_compute. Please replace the necessary parameters in the below code according to your azure account. The current version of azure_mgmt_* gems are 0.2.1.

require 'ms_rest_azure'
require 'azure_mgmt_resources'
require 'azure_mgmt_compute'
require 'azure_mgmt_storage'
require 'azure_mgmt_network'

include MsRest
include MsRestAzure
include Azure::ARM::Compute
include Azure::ARM::Compute::Models
include Azure::ARM::Network
include Azure::ARM::Network::Models
include Azure::ARM::Resources
include Azure::ARM::Storage

class Main
  RESOURCE_GROUP_NAME = '<EXISTING_RESOURCEGROUP_NAME>'
  STORAGE_NAME = '<EXISTING_STORAGE_ACC_NAME>'
  LOCATION = 'westus'

  attr_accessor :compute_client
  attr_accessor :network_client

  def initialize
    tenant_id = "<AZURE_TENANT_ID>"
    client_id = "<AZURE_CLIENT_ID>"
    secret = "<AZURE_CLIENT_SECRET>"
    subscription_id = "<AZURE_SUBSCRIPTION_ID>"

    token_provider = ApplicationTokenProvider.new(tenant_id, client_id, secret)
    credentials = TokenCredentials.new(token_provider)

    @compute_client = ComputeManagementClient.new(credentials)
    @compute_client.subscription_id = subscription_id

    @network_client = NetworkManagementClient.new(credentials)
    @network_client.subscription_id = subscription_id
  end

  def create_vm
    # Create a model for new virtual machine
    props = VirtualMachineProperties.new

    windows_config = WindowsConfiguration.new
    windows_config.provision_vmagent = true
    windows_config.enable_automatic_updates = true

    os_profile = OSProfile.new
    os_profile.computer_name = 'testvm1'
    os_profile.admin_username = 'testvm1'
    os_profile.admin_password = 'P@ssword1'
    os_profile.windows_configuration = windows_config
    os_profile.secrets = []
    props.os_profile = os_profile

    hardware_profile = HardwareProfile.new
    hardware_profile.vm_size = 'Standard_A0'
    props.hardware_profile = hardware_profile

    props.storage_profile = create_storage_profile
    props.network_profile = create_network_profile

    params = VirtualMachine.new
    params.type = 'Microsoft.Compute/virtualMachines'
    params.properties = props
    params.location = LOCATION

    promise = @compute_client.virtual_machines.create_or_update(RESOURCE_GROUP_NAME, 'new_vm', params)
    result = promise.value!

    puts result
  end

  def create_storage_profile
    storage_profile = StorageProfile.new
    storage_profile.image_reference = get_image_reference
    os_disk = OSDisk.new
    os_disk.caching = 'None'
    os_disk.create_option = 'fromImage'
    os_disk.name = 'Test'
    virtual_hard_disk = VirtualHardDisk.new
    virtual_hard_disk.uri = generate_os_vhd_uri STORAGE_NAME
    os_disk.vhd = virtual_hard_disk
    storage_profile.os_disk = os_disk
    storage_profile
  end

  def create_network_profile
    vn = create_virtual_network
    @subnet = create_subnet(vn, RESOURCE_GROUP_NAME, @network_client.subnets)
    network_interface = create_network_interface

    profile = NetworkProfile.new
    profile.network_interfaces = [network_interface]

    profile
  end

  def get_image_reference
    ref = ImageReference.new
    ref.publisher = 'MicrosoftWindowsServer'
    ref.offer = 'WindowsServer'
    ref.sku = '2012-R2-Datacenter'
    ref.version = 'latest'
    ref
  end

  def generate_os_vhd_uri(storage_name)
    container_name = 'testcontainer'
    vhd_container = "https://#{storage_name}.blob.core.windows.net/#{container_name}"
    os_vhduri = "#{vhd_container}/os#{'test'}.vhd"
    os_vhduri
  end

  def create_virtual_network
    virtualNetworkName = "testvnet53464"
    params = build_virtual_network_params(LOCATION)
    @network_client.virtual_networks.create_or_update(RESOURCE_GROUP_NAME, virtualNetworkName, params).value!.body
  end

  def build_virtual_network_params(location)
    params = VirtualNetwork.new
    props = VirtualNetworkPropertiesFormat.new
    params.location = location
    address_space = AddressSpace.new
    address_space.address_prefixes = ['10.0.0.0/16']
    props.address_space = address_space
    dhcp_options = DhcpOptions.new
    dhcp_options.dns_servers = %w(10.1.1.1 10.1.2.4)
    props.dhcp_options = dhcp_options
    sub2 = Subnet.new
    sub2_prop = SubnetPropertiesFormat.new
    sub2.name = 'subnet253464'
    sub2_prop.address_prefix = '10.0.2.0/24'
    sub2.properties = sub2_prop
    props.subnets = [sub2]
    params.properties = props
    params
  end

  def create_subnet(virtual_network, resource_group_name, subnet_client)
    subnet_name = 'testsubnet53464'
    params = build_subnet_params

    subnet_client.create_or_update(resource_group_name, virtual_network.name, subnet_name, params).value!.body
  end

  def build_subnet_params
    params = Subnet.new
    prop = SubnetPropertiesFormat.new
    params.properties = prop
    prop.address_prefix = '10.0.1.0/24'
    params
  end

  def create_network_interface
    params = build_network_interface_param
    @network_client.network_interfaces.create_or_update(RESOURCE_GROUP_NAME, params.name, params).value!.body
  end

  def build_network_interface_param
    params = NetworkInterface.new
    params.location = LOCATION
    network_interface_name = 'testnic53464'
    ip_config_name = 'ip_name53464'
    params.name = network_interface_name
    props = NetworkInterfacePropertiesFormat.new
    ip_configuration = NetworkInterfaceIPConfiguration.new
    params.properties = props
    props.ip_configurations = [ip_configuration]
    ip_configuration_properties = NetworkInterfaceIPConfigurationPropertiesFormat.new
    ip_configuration.properties = ip_configuration_properties
    ip_configuration.name = ip_config_name
    ip_configuration_properties.private_ipallocation_method = 'Dynamic'
    ip_configuration_properties.public_ipaddress = create_public_ip_address(LOCATION, RESOURCE_GROUP_NAME)
    ip_configuration_properties.subnet = @subnet
    params
  end

  def create_public_ip_address(location, resource_group_name)
    public_ip_address_name = 'test_ip_name'
    params = build_public_ip_params(location)
    @network_client.public_ipaddresses.create_or_update(resource_group_name, public_ip_address_name, params).value!.body
  end

  def build_public_ip_params(location)
    public_ip = PublicIPAddress.new
    public_ip.location = location
    props = PublicIPAddressPropertiesFormat.new
    props.public_ipallocation_method = 'Dynamic'
    public_ip.properties = props
    domain_name = 'testdomain53464'
    dns_settings = PublicIPAddressDnsSettings.new
    dns_settings.domain_name_label = domain_name
    props.dns_settings = dns_settings
    public_ip
  end
end

object = Main.new
object.create_vm

@parth618
Copy link
Author

Hello @vishrutshah
In the above case we didn't used the create storage account function which may be neccessary to create if we don't know whether that storage account exists. The version of azure_mgmt_* gems which i am using is 0.1.1. The problem, which i am facing still exists even when i tried not using create storage account function giving the existing storage account name as included.
Also while provisioning storage account with existing one it gave status 200 OK which shows it was already provisioned (as it was existing) along with other resources (storage profile, network profile) required to create a VM. Error raised only at final stage.

@vishrutshah
Copy link
Contributor

Hi @parth618, Thanks for the response.

Could you please give us some isolated sample code & error/exception stack trace that you are running to help us reproduce your scenario? That'd help us in investigation.

Thanks,

@parth618
Copy link
Author

parth618 commented Apr 29, 2016

Hii @vishrutshah ,
The following was the error which i received on re-deployment

"Failed to redeploy the virtual machine 'VMName'. Error: Blob http://storagexxx.blob.core.windows.net/containerxx/Linux.vhd already exists. Please provide a different blob URI as target for disk 'Test1'."

It seems that even on deleting the VM the Blob storage was still present and thus virtual hard disk remain attached and storage URI showed that it already exists due to which the deployment was failing again and again. Will like to know more on this if possible.

Thanks

@devigned
Copy link
Member

@ravbhatnagar can you comment on why this isn't idempotent?

@devigned
Copy link
Member

@ravbhatnagar or @rjmax is the expected behavior?

@ravbhatnagar
Copy link

ravbhatnagar commented May 16, 2016

@parth618 - Can you please share the template/sample code you were using when you ran into this issue? It should be idempotent. You can refer to this template for creating a VM which uses a storage account for the vhd - https://github.com/Azure/azure-quickstart-templates/blob/master/101-vm-simple-windows/azuredeploy.json

As a side note, you can also try to use the newOrExisting pattern as described in this sample - https://github.com/rjmax/ArmExamples/blob/master/NewOrExistingTemplate.json

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants