Attach managed data disks to a vm - azure

I am trying to develop a script to attach data diskscreating from snapshots to another Azure VM
Create SNAPSHOTS of existing data disks from source VM
Create new DATADISKS from the SNAPSHOTS created from step 1
Attach the new DATADISKS to the destination VM
however I keep getting error when trying to attach the disks(step 3).
Get-AzDisk : The Resource 'Microsoft.Compute/disks/disk_name2' under resource group 'RG-Test' was not found.
ErrorCode: ResourceNotFound
ErrorMessage: The Resource 'Microsoft.Compute/disks/disk_name2' under resource group 'RG-Test' was not found.
ErrorTarget:
StatusCode: 404
ReasonPhrase: Not Found
OperationID : 67319e0f-3f8f-416a-bb25-9d0547e661a4
Au caractère Ligne:22 : 13
+ $disk = Get-AzDisk -ResourceGroupName $resourceGroupName -DiskNam ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError : (:) [Get-AzDisk], ComputeCloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.Automation.GetAzureRmDisk
Add-AzVMDataDisk : Impossible de valider l'argument sur le paramètre « ManagedDiskId ». L’argument est Null ou vide. Indiquez un argument qui n’est pas Null ou vide et réessayez.
Au caractère Ligne:24 : 110
+ ... nation_vm_object -CreateOption Attach -ManagedDiskId $disk.Id -Lun $l ...
+ ~~~~~~~~
+ CategoryInfo : InvalidData : (:) [Add-AzVMDataDisk], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Azure.Commands.Compute.AddAzureVMDataDiskCommand
The code :
## Create Snapshot from a Managed Disk ##
$resourceGroupName = 'RG-Test'
$location = 'east us 2'
$source_vm_name = 'VMS'
$destination_vm_name = 'VMD'
$data_disk_list = Get-azDisk | where {$_.ManagedBy -match $source_vm_name -and $_.OsType -eq $null}
$snapshot_list = New-Object System.Collections.ArrayList($null)
foreach($data_disk_list_iterator in $data_disk_list){
$snapshotName = $destination_vm_name + "_Snapshot_" + $data_disk_list_iterator.Name
$snapshot_config = New-AzSnapshotConfig -SourceUri $data_disk_list_iterator.id -Location $location -CreateOption copy
$snapshot_object = New-AzSnapshot -Snapshot $snapshot_config -SnapshotName $snapshotName -ResourceGroupName $resourceGroupName
$snapshot_list.Add($snapshot_object.Id)
}
## Create Managed Data Disk from snapshot created above ##
$i=0
$destination_datadisk_list = New-Object System.Collections.ArrayList($null)
$destination_vm_object = Get-AzVM -Name $destination_vm_name -ResourceGroupName $resourceGroupName
$lun_count = 1
foreach($snapshot_list_iterator in $snapshot_list){
$disk_name = $destination_vm_name + "_datadisk_" + $i
$i += 1
$diskConfig = New-AzDiskConfig -AccountType $storageType -Location $location -CreateOption Copy -SourceResourceId $snapshot_list_iterator
$datadisk_object = New-AzDisk -Disk $diskConfig -ResourceGroupName $resourceGroupName -DiskName $disk_name
$disk = Get-AzDisk -ResourceGroupName $resourceGroupName -DiskName disk_name$i
$destination_vm_object = Add-AzVMDataDisk -VM $destination_vm_object -CreateOption Attach -ManagedDiskId $disk.Id -Lun $lun_count
$lun_count += 1
Update-AzVM -VM $destination_vm_object -ResourceGroupName $resourceGroupName
}
Could someone help me resolve this error?

As commented, the error message shows that you have just made a typo in the code here:
$disk = Get-AzDisk -ResourceGroupName $resourceGroupName -DiskName disk_name$i
Within that second loop, you are defining a variable $disk_name by concatenating the loopcounter $i at the end. That code is fine.
However, inside the loop you are trying to add this loopcounter to the name again but at the same time use disk_name without the $ sign in front. Without the dollar sign, the name is taken as literal string.
All you have to do to make it work is change the above mentiond line of code into:
$disk = Get-AzDisk -ResourceGroupName $resourceGroupName -DiskName $disk_name

Related

Need help spiting Azure snapshots into another tenant/subscription

I have a script which snapshots all my disks in a certain RG.
However when I do the snapshotting, I need them to be spat out into another tenant/subscription for a migration project!
I've got as far as snapshotting everything and spitting them into a different RG but I need to take it a step further and spit them into the same named RG but in a different tenant/sub.
My script is below:
Login-AzureRmAccount -Credential $psCred –SubscriptionId $SubscriptionId -ErrorAction Stop | out-null
Connect-AzureRmAccount
Get-AzureRmSubscription -SubscriptionId $SubscriptionId | Select-AzureRmSubscription
$tagResList = Get-AzureRmResource -TagName Environment -TagValue Staging
#$tagResList = Find-AzureRmResource -ResourceGroupNameEquals testrs
#$tagRsList[0].ResourceId.Split("//")
#subscriptions
#<SubscriptionId>
#resourceGroups
#<ResourceGroupName>
#providers
#Microsoft.Compute
#virtualMachines
#<vmName>
foreach($tagRes in $tagResList) {
if($tagRes.ResourceId -match "Microsoft.Compute")
{
$vmInfo = Get-AzureRmVM sandbox207478603000 #$tagRes.ResourceId.Split("//")[4] -Name $tagRes.ResourceId.Split("//")[8]
#Set local variables
$location = $vmInfo.Location
$resourceGroupName = $vmInfo.ResourceGroupName
$timestamp = Get-Date -f MM-dd-yyyy_HH_mm_ss
#Snapshot name of OS data disk
$snapshotName = $vmInfo.Name + $timestamp
#Create snapshot configuration
$snapshot = New-AzureRmSnapshotConfig -SourceUri $vmInfo.StorageProfile.OsDisk.ManagedDisk.Id -Location $location -CreateOption copy
#Take snapshot
New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName snapshots $resourceGroupName
if($vmInfo.StorageProfile.DataDisks.Count -ge 1){
#Condition with more than one data disks
for($i=0; $i -le $vmInfo.StorageProfile.DataDisks.Count - 1; $i++){
#Snapshot name of OS data disk
$snapshotName = $vmInfo.StorageProfile.DataDisks[$i].Name + $timestamp
#Create snapshot configuration
$snapshot = New-AzureRmSnapshotConfig -SourceUri $vmInfo.StorageProfile.DataDisks[$i].ManagedDisk.Id -Location $location -CreateOption copy
#Take snapshot
New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName snapshots $ResourceGroupName
}
}
else{
Write-Host $vmInfo.Name + " doesn't have any additional data disk."
}
}
else{
$tagRes.ResourceId + " is not a compute instance"
}
}
$tagRgList = Get-AzureRmResourceGroup -Tag #{ Environment = "Staging" }
I am not sure if you can save snapshot in another tenant in one command as you'd need to be authenticated there.
I would suggest using azcopy tool to move snapshot files between storage accounts
#######################################
Reviewed your comment and found that indeed you can't use azcopy on vm images.
But you may create access to the snapshot
#Generate the SAS for the snapshot
$sas = Grant-AzSnapshotAccess -ResourceGroupName $ResourceGroupName -SnapshotName $SnapshotName -DurationInSecond $sasExpiryDuration -Access Read
and save it to the destination storage account:
#Copy the snapshot to the storage account
Start-AzStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer $storageContainerName -DestContext $destinationContext -DestBlob $destinationVHDFileName
More details canbe found here

AzCosmosDBSqlContainer : "Object reference not set to an instance of an object."

I am using AzCosmosDBSqlContainer to check details of a CosmosDB (SQL api) container in PowerShell; I am getting this error
Object reference not set to an instance of an object
However Get-AzCosmosDBAccount and Get-AzCosmosDBSqlDatabase commands are working fine.
Can someone help me with this?
Command used:
$ResourceGroup="MyResourceGroup"
$CDBAccountName="mycosmosaccount"
$dbname="myDatabase"
$containername="MyContainer"
$cosmosaccount=Get-AzCosmosDBAccount -ResourceGroupName $ResourceGroup -Name $CDBAccountName
$cosmosdbname=Get-AzCosmosDBSqlDatabase -AccountName $cosmosaccount.Name -ResourceGroupName $ResourceGroup -Name $dbname
Get-AzCosmosDBSqlContainer -ResourceGroupName $ResourceGroup -AccountName $cosmosaccount.Name -DatabaseName $cosmosdbname.Name -Name $containername
I found a workaround after getting an update from Microsoft team.
https://github.com/Azure/azure-powershell/issues/11381
This issue is going to be fixed in upcoming version of Az.CosmosDB 0.1.4
Workaround:
Replace "my***Name" with your own values
$resourceGroupName = "myResourceGroupName"
$accountName = "myAccountName"
$databaseName = "mYDatabaseName"
$containerName = "myContainerName"
$apiVersion = "2020-03-01"
$databaseResourceName = $accountName + "/" + $databaseName
$containerResourceName = $databaseResourceName + "/" + $containerName
$containerResourceType = "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
Write-Host "List containers in the database"
Get-AzResource -ResourceType $containerResourceType -ApiVersion $apiVersion
-ResourceGroupName $resourceGroupName -Name $databaseResourceName
Write-Host "Show specified container"
Get-AzResource -ResourceType $containerResourceType -ApiVersion $apiVersion
-ResourceGroupName $resourceGroupName -Name $containerResourceName

How to initialize a disk after I append a data disk to VM automatucally?

Based on this doc :
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/attach-managed-disk-portal I can append a data disk to my windows Azure VMs and initialize the disk manually by login to the VM. Everything works for me.
BUT it is not enough as I want to make the whole process automatually by code. Could you please give me some code sample or guide about it ? Thanks!
#ShirazBhaiji provided a helpful doc that will meet your requirement, but there is a new feature that you can run commands on Azure VMs directly, no need to enable WinRM.
Just try the Powershell below :
This is the command to init a data disk in windows :
$disks = Get-Disk | Where partitionstyle -eq 'raw' | sort number
$letters = 70..89 | ForEach-Object { [char]$_ }
$count = 0
$labels = "data1","data2"
foreach ($disk in $disks) {
$driveLetter = $letters[$count].ToString()
$disk |
Initialize-Disk -PartitionStyle MBR -PassThru |
New-Partition -UseMaximumSize -DriveLetter $driveLetter |
Format-Volume -FileSystem NTFS -NewFileSystemLabel $labels[$count] -Confirm:$false -Force
$count++
}
Save it as a .ps1 file.
Use this command to append a disk and run the above command directly :
$vm = Get-AzVM -Name <your VM name> -ResourceGroupName <your vm resource group name>
$dataDiskName = $vm.Name + '_datadisk1'
$diskConfig = New-AzDiskConfig -SkuName 'Premium_LRS' -Location $vm.Location -CreateOption Empty -DiskSizeGB 128 -Zone 1
$dataDisk1 = New-AzDisk -DiskName $dataDiskName -Disk $diskConfig -ResourceGroupName $vm.ResourceGroupName
Add-AzVMDataDisk -VM $vm -Name $dataDiskName -CreateOption Attach -ManagedDiskId $dataDisk1.Id -Lun 1
Update-AzVM -VM $vm -ResourceGroupName $vm.ResourceGroupName
Invoke-AzVMRunCommand -VM $vm -CommandId 'RunPowerShellScript' -ScriptPath "<path of the previous .ps1 file>"
Result :
Hope it helps!
You can do this using powershell, you need to have windows remote management enabled on the VM.
Example scripts can be found here:
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/attach-disk-ps

What is the equivalent script in powershell for image-copy-extension extension from Azure CLI

I need to create a VM in locationA from Image ImageB which is in locationB using powershell. Since I'm not able to do it I'm trying to create a copy of ImageB into locationA, so that it will easy for me to create the VM.
I have searched for scripts to copy the images and got many results. I found one particular link which has simple script to copy images. But it is AzureCLI cmdlets. I need powershell scripts to do the job as the tool I'm using understands only powershell scripts.
I have searched for an equivalent powershell script but couldn't find any.Can anyone help me here.
Here is a script to copy the image. You could create a snapshot and copy it to anther region, then create the image.
Create a snapshot:
<# -- Create a snapshot of the OS (and optionally data disks) from the generalized VM -- #>
$vm = Get-AzureRmVM -ResourceGroupName $resourceGroupName -Name $vmName
$disk = Get-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName $vm.StorageProfile.OsDisk.Name
$snapshot = New-AzureRmSnapshotConfig -SourceUri $disk.Id -CreateOption Copy -Location $region
$snapshotName = $imageName + "-" + $region + "-snap"
New-AzureRmSnapshot -ResourceGroupName $resourceGroupName -Snapshot $snapshot -SnapshotName $snapshotName
Copy the snapshot:
# Create the name of the snapshot, using the current region in the name.
$snapshotName = $imageName + "-" + $region + "-snap"
# Get the source snapshot
$snap = Get-AzureRmSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName
# Create a Shared Access Signature (SAS) for the source snapshot
$snapSasUrl = Grant-AzureRmSnapshotAccess -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName -DurationInSecond 3600 -Access Read
# Set up the target storage account in the other region
$targetStorageContext = (Get-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName).Context
New-AzureStorageContainer -Name $imageContainerName -Context $targetStorageContext -Permission Container
# Use the SAS URL to copy the blob to the target storage account (and thus region)
Start-AzureStorageBlobCopy -AbsoluteUri $snapSasUrl.AccessSAS -DestContainer $imageContainerName -DestContext $targetStorageContext -DestBlob $imageBlobName
Get-AzureStorageBlobCopyState -Container $imageContainerName -Blob $imageBlobName -Context $targetStorageContext -WaitForComplete
# Get the full URI to the blob
$osDiskVhdUri = ($targetStorageContext.BlobEndPoint + $imageContainerName + "/" + $imageBlobName)
# Build up the snapshot configuration, using the target storage account's resource ID
$snapshotConfig = New-AzureRmSnapshotConfig -AccountType StandardLRS `
-OsType Windows `
-Location $targetRegionName `
-CreateOption Import `
-SourceUri $osDiskVhdUri `
-StorageAccountId "/subscriptions/${sourceSubscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.Storage/storageAccounts/${storageAccountName}"
# Create the new snapshot in the target region
$snapshotName = $imageName + "-" + $targetRegionName + "-snap"
$snap2 = New-AzureRmSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName -Snapshot $snapshotConfig
Create the image:
<# -- In the second subscription, create a new Image from the copied snapshot --#>
Select-AzureRmSubscription -SubscriptionId $targetSubscriptionId
$snap = Get-AzureRmSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName
$imageConfig = New-AzureRmImageConfig -Location $destinationRegion
Set-AzureRmImageOsDisk -Image $imageConfig `
-OsType Windows `
-OsState Generalized `
-SnapshotId $snap.Id
New-AzureRmImage -ResourceGroupName $resourceGroupName `
-ImageName $imageName `
-Image $imageConfig
For more details, refer to this link.

How to move an azure VM image to a different location

I have an azure VM image with a managed disk in east US and I want to move/copy it to West Europe.
Is there an easy way to do it?
I saw that there's an azure cli extension called az-image-copy but it doesn't work for me because it outputs an error which says that it can't find the OS disk (even though the resource ID is correct and I can see it in the azure portal)
ERROR: Resource ServerLinux_OsDisk_1_c208679747734937b10a1525aa84a7d7 is not found
So is there any other way to do it?
You could use azure powershell to copy the managed images, create a snapshot and copy it to anther region, then create the image. Here is a similar issue.
Create a snapshot:
<# -- Create a snapshot of the OS (and optionally data disks) from the generalized VM -- #>
$vm = Get-AzureRmVM -ResourceGroupName $resourceGroupName -Name $vmName
$disk = Get-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName $vm.StorageProfile.OsDisk.Name
$snapshot = New-AzureRmSnapshotConfig -SourceUri $disk.Id -CreateOption Copy -Location $region
$snapshotName = $imageName + "-" + $region + "-snap"
New-AzureRmSnapshot -ResourceGroupName $resourceGroupName -Snapshot $snapshot -SnapshotName $snapshotName
Copy the snapshot:
# Create the name of the snapshot, using the current region in the name.
$snapshotName = $imageName + "-" + $region + "-snap"
# Get the source snapshot
$snap = Get-AzureRmSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName
# Create a Shared Access Signature (SAS) for the source snapshot
$snapSasUrl = Grant-AzureRmSnapshotAccess -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName -DurationInSecond 3600 -Access Read
# Set up the target storage account in the other region
$targetStorageContext = (Get-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName).Context
New-AzureStorageContainer -Name $imageContainerName -Context $targetStorageContext -Permission Container
# Use the SAS URL to copy the blob to the target storage account (and thus region)
Start-AzureStorageBlobCopy -AbsoluteUri $snapSasUrl.AccessSAS -DestContainer $imageContainerName -DestContext $targetStorageContext -DestBlob $imageBlobName
Get-AzureStorageBlobCopyState -Container $imageContainerName -Blob $imageBlobName -Context $targetStorageContext -WaitForComplete
# Get the full URI to the blob
$osDiskVhdUri = ($targetStorageContext.BlobEndPoint + $imageContainerName + "/" + $imageBlobName)
# Build up the snapshot configuration, using the target storage account's resource ID
$snapshotConfig = New-AzureRmSnapshotConfig -AccountType StandardLRS `
-OsType Windows `
-Location $targetRegionName `
-CreateOption Import `
-SourceUri $osDiskVhdUri `
-StorageAccountId "/subscriptions/${sourceSubscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.Storage/storageAccounts/${storageAccountName}"
# Create the new snapshot in the target region
$snapshotName = $imageName + "-" + $targetRegionName + "-snap"
$snap2 = New-AzureRmSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName -Snapshot $snapshotConfig
Create the image:
<# -- In the second subscription, create a new Image from the copied snapshot --#>
Select-AzureRmSubscription -SubscriptionId $targetSubscriptionId
$snap = Get-AzureRmSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName
$imageConfig = New-AzureRmImageConfig -Location $destinationRegion
Set-AzureRmImageOsDisk -Image $imageConfig `
-OsType Windows `
-OsState Generalized `
-SnapshotId $snap.Id
New-AzureRmImage -ResourceGroupName $resourceGroupName `
-ImageName $imageName `
-Image $imageConfig
For more details, refer to this link.
If the resources are under the same subscription then you can get move resources to from the Resource Group 01 (East Us) to the Resource Group 02 (West Europe).
For your help you can check these documents:
Move Managed Disks and VMs
Move resources to new resource group or subscription
Copy managed disks in the same subscription or different subscription with PowerShell
Migrating Azure IaaS solutions using MigAz
The last link is about the MigAz tool, which allow to migrate resources on Azure.

Resources