lib/fog/azurerm/requests/compute/attach_data_disk_to_vm.rb
module Fog
module Compute
class AzureRM
# This class provides the actual implementation for service calls.
class Real
def attach_data_disk_to_vm(disk_params, async)
# Variable un-packing for easy access
vm_name = disk_params[:vm_name]
vm_resource_group = disk_params[:vm_resource_group]
disk_name = disk_params[:disk_name]
disk_resource_group = disk_params[:disk_resource_group]
disk_size = disk_params[:disk_size_gb]
storage_account_name = disk_params[:storage_account_name]
caching = disk_params[:caching] || nil
msg = "Attaching Data Disk #{disk_name} to Virtual Machine #{vm_name} in Resource Group #{vm_resource_group}"
Fog::Logger.debug msg
vm = get_virtual_machine_instance(vm_resource_group, vm_name)
lun = get_logical_unit_number(vm.storage_profile.data_disks)
# Attach data disk to VM
if storage_account_name
# Un-managed data disk
access_key = get_storage_access_key(vm_resource_group, storage_account_name)
data_disk = get_unmanaged_disk_object(disk_name, disk_size, lun, storage_account_name, access_key)
elsif disk_resource_group
# Managed data disk
data_disk = get_data_disk_object(disk_resource_group, disk_name, lun, caching)
end
vm.storage_profile.data_disks.push(data_disk)
begin
if async
response = @compute_mgmt_client.virtual_machines.create_or_update_async(vm_resource_group, vm_name, vm)
else
virtual_machine = @compute_mgmt_client.virtual_machines.create_or_update(vm_resource_group, vm_name, vm)
end
rescue MsRestAzure::AzureOperationError => e
if e.body.to_s =~ /InvalidParameter/ && e.body.to_s =~ /already exists/
Fog::Logger.debug 'The disk is already attached'
else
raise_azure_exception(e, msg)
end
end
if async
response
else
Fog::Logger.debug "Data Disk #{disk_name} attached to Virtual Machine #{vm_name} successfully."
virtual_machine
end
end
private
def get_virtual_machine_instance(resource_group, vm_name)
msg = "Getting Virtual Machine #{vm_name} from Resource Group #{resource_group}"
Fog::Logger.debug msg
begin
virtual_machine = @compute_mgmt_client.virtual_machines.get(resource_group, vm_name)
rescue MsRestAzure::AzureOperationError => e
raise_azure_exception(e, msg)
end
Fog::Logger.debug "Getting Virtual Machine #{vm_name} from Resource Group #{resource_group} successful"
virtual_machine
end
def get_logical_unit_number(data_disks)
lun_range_list = (0..15).to_a
data_disks.each do |disk|
lun_range_list.delete(disk.lun)
end
if lun_range_list.empty?
msg = 'Error Attaching Data Disk to Virtual Machine. No slot available.'
raise msg
end
lun_range_list[0]
end
def get_data_disk_object(disk_resource_group, disk_name, lun, caching)
msg = "Getting Managed Disk #{disk_name} from Resource Group #{disk_resource_group}"
begin
disk = @compute_mgmt_client.disks.get(disk_resource_group, disk_name)
rescue MsRestAzure::AzureOperationError => e
Fog::Logger.debug msg
raise_azure_exception(e, msg)
end
managed_disk = Azure::ARM::Compute::Models::DataDisk.new
managed_disk.name = disk_name
managed_disk.lun = lun
managed_disk.create_option = Azure::ARM::Compute::Models::DiskCreateOptionTypes::Attach
# Managed Disk Caching Type
managed_disk.caching = case caching
when 'ReadOnly'
Azure::ARM::Compute::Models::CachingTypes::ReadOnly
when 'ReadWrite'
Azure::ARM::Compute::Models::CachingTypes::ReadWrite
when 'None', nil
Azure::ARM::Compute::Models::CachingTypes::None
else
raise "Invalid Disk Caching Option: #{caching}"
end
# Managed disk parameter
managed_disk_params = Azure::ARM::Compute::Models::ManagedDiskParameters.new
managed_disk_params.id = disk.id
managed_disk.managed_disk = managed_disk_params
managed_disk
end
def get_storage_access_key(resource_group, storage_account_name)
msg = "Getting Storage Access Keys from Resource Group #{resource_group}"
Fog::Logger.debug msg
begin
storage_account_keys = @storage_mgmt_client.storage_accounts.list_keys(resource_group, storage_account_name)
rescue MsRestAzure::AzureOperationError => e
raise_azure_exception(e, msg)
end
Fog::Logger.debug "Getting Storage Access Keys from Resource Group #{resource_group} successful"
storage_account_keys.keys[0].value
end
def get_unmanaged_disk_object(disk_name, disk_size, lun, storage_account_name, access_key)
data_disk = Azure::ARM::Compute::Models::DataDisk.new
data_disk.name = disk_name
data_disk.lun = lun
data_disk.disk_size_gb = disk_size.to_s
data_disk.vhd = Azure::ARM::Compute::Models::VirtualHardDisk.new
data_disk.vhd.uri = "https://#{storage_account_name}.blob.core.windows.net/vhds/#{storage_account_name}-#{disk_name}.vhd"
data_disk.caching = Azure::ARM::Compute::Models::CachingTypes::ReadWrite
blob_name = "#{storage_account_name}-#{disk_name}.vhd"
disk_exist = check_blob_exist(storage_account_name, blob_name, access_key)
data_disk.create_option = Azure::ARM::Compute::Models::DiskCreateOptionTypes::Empty
data_disk.create_option = Azure::ARM::Compute::Models::DiskCreateOptionTypes::Attach if disk_exist
data_disk
end
def check_blob_exist(storage_account_name, blob_name, access_key)
client = Azure::Storage::Client.new(storage_account_name: storage_account_name, storage_access_key: access_key)
blob_service = Azure::Storage::Blob::BlobService.new(client: client)
begin
blob_prop = blob_service.get_blob_properties('vhds', blob_name)
true unless blob_prop.nil?
rescue Azure::Core::Http::HTTPError => e
return false if e.status_code == 404
raise_azure_exception(e, 'Checking blob existence')
end
end
end
# This class provides the mock implementation for unit tests.
class Mock
def attach_data_disk_to_vm(*)
vm = {
'location' => 'West US',
'id' => '/subscriptions/########-####-####-####-############/resourceGroups/fog-test-rg/providers/Microsoft.Compute/virtualMachines/fog-test-server',
'name' => 'fog-test-server',
'type' => 'Microsoft.Compute/virtualMachines',
'properties' =>
{
'hardwareProfile' =>
{
'vmSize' => 'Basic_A0'
},
'storageProfile' =>
{
'imageReference' =>
{
'publisher' => 'Canonical',
'offer' => 'UbuntuServer',
'sku' => '14.04.2-LTS',
'version' => 'latest'
},
'osDisk' =>
{
'name' => 'fog-test-server_os_disk',
'vhd' =>
{
'uri' => 'http://mystorage1.blob.core.windows.net/vhds/fog-test-server_os_disk.vhd'
},
'createOption' => 'FromImage',
'osType' => 'Linux',
'caching' => 'ReadWrite'
},
'dataDisks' => [{
'lun' => 0,
'name' => 'fog-test-server_data_disk',
'vhd_uri' => 'https://confizrg7443.blob.core.windows.net/vhds/fog-test-server_data_disk.vhd',
'create_option' => 'empty',
'disk_size_gb' => 1
}]
},
'osProfile' =>
{
'computerName' => 'fog',
'adminUsername' => 'Fog=123',
'linuxConfiguration' =>
{
'disablePasswordAuthentication' => true
},
'secrets' => []
},
'networkProfile' =>
{
'networkInterfaces' =>
[
{
'id' => '/subscriptions/########-####-####-####-############/resourceGroups/fog-test-rg/providers/Microsoft.Network/networkInterfaces/fog-test-vnet'
}
]
},
'provisioningState' => 'Succeeded'
}
}
vm_mapper = Azure::ARM::Compute::Models::VirtualMachine.mapper
@compute_mgmt_client.deserialize(vm_mapper, vm, 'result.body')
end
end
end
end
end