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

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

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

use Invoke-AzVMRunCommand -Params

I am trying to use the command like so:
a = 345
name = "myVM"
Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = "a"; "test" = "name"}
the script in the file isn't really important I am just trying to use params inside of it with values of params from the outside. If I put "b" = 345 it works but with the outside param (a), it doesn't so I wanted to know how to do it.
it does execute the script but ignores the commands using these params.
for reference the script is something like this:
New-Item -Path "." -Name "index.html" -ItemType "file" -Value $b
New-Item -Path "." -Name $test -ItemType "file" -Value "3333333"
We use Invoke-AzVMRunCommand to Invoke a run command on the VM. And the -Parameter is used to run the command parameter.
The the type for -Parameter is Hashtable, which maps keys to values. Any non-null object can be used as a key or as a value.
Invoke command is more like a batch script, so when we want to pass a pre-defined variable we have to use the $ symbol without any double quotes (""). So you can solve your problem by following the code snippet below.
#Example
a = 345
name = "myVM"
Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = $a; "test" = $name}
Read this Invoke-AzVMRunCommand document and about_Hash_Tables document for more information.
Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = $a; "test" = $name}
It don't work. The same problem.
I have the script which create VM in azure:
$password = ConvertTo-SecureString -String "Qwerty123456" -AsPlainText
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $password
$x = Get-Random 10000 -Minimum 10
$location = "East US"
$rgname = "testVM"+$x
$VMName = "vm1"
# Create Resource group
New-AzResourceGroup -name $rgname -Location $location
# Create VM, vnet, publicIP, port 3389
New-AzVM -ResourceGroupName $rgname `
-Location $location `
-Name "verdyshtest" `
-VirtualNetworkName "virtnet" `
-SubnetName 'verdyshnetwork' `
-PublicIpAddressName "verdyshpublicIP" `
-Image Win2019Datacenter `
-OpenPorts 3389 `
-Credential $cred
# Script only running after deploy
Invoke-AzVMRunCommand -ResourceGroupName $rgname -VMName $VMName -CommandId RunPowerShellScript -ScriptPath '.\2 Install app on VM.ps1'
In last count it can't to execute 'invoke-azvmruncommand', because of variable in parameters.
But in New-AzVM cmdlet variables works well.
Had a error:
error

The Azure PowerShell session has not been properly initialized. Please import the module and try again

I'm writing my first powershell script to load data from a CSV to an Azure Storage table. I'm not sure why the line
$storageAccountKey = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName)[0].Value
is throwing an error:
Running Get-Module gives this result:
This is a snippet of the code that I have written till now:
# Step 1, Set variables
# Enter Table Storage location data
$resourceGroupName = "ComputeTesting"
$storageAccountName = 'computetestingdiag'
$tableName = 'strtable'
$dateTime = get-date
# Step 2, Login to your Azure subscription
$sub = Get-AzSubscription -ErrorAction SilentlyContinue
if(-not($sub))
{
Connect-AzAccount
}
# If you have multiple subscriptions, set the one to use
# Select-AzSubscription -SubscriptionId "<SUBSCRIPTIONID>"
# Step 3, Get the access key for the Azure Storage account
$storageAccountKey = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName)[0].Value
# Step 4, Connect to Azure Table Storage
$storageCtx = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
$table = Get-AzureStorageTable -Name $tableName -Context $storageCtx
I checked some of the similar questions and what I understand that uninstalling and re-installing the Azure modules might help. Although I didn't try this yet, is there any other workaround for this? Any help whatsoever would be highly helpful.
According to the script you provided, you use the Az and AzureRM modules at the same PowerShell session. It may cause conflicts. I suggest you use the one module in one session.
For example
$resourceGroupName = "<>"
$storageAccountName = '<>'
$tableName = '<>'
Connect-AzAccount
$storageAccountKey = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName)[0].Value
$storageCtx = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
$table = Get-AzStorageTable -Name $tableName -Context $storageCtx
For more details about how to manage Azure table storage, please refer to the document

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