Check if vm has backup enabled, if not enable it (Azure) - azure

I'm building Azure runbook (powershell) which check if vm has backup enabled if it's not, it will enable it. I have problem with adding and building IF statement to make it better.
This is how I do it now and it works, but If vm has backup enabled, runbook will print a lot of red and thats not good. This is part of bigger runbook and those all are running inside on foreach.
$vault= Get-AzureRmRecoveryServicesVault -ResourceGroupName "RGName" -Name "VaultName"
Set-AzureRmRecoveryServicesVaultContext -Vault $vault
Write-Output "Configuring Azure backup to $($vm.Name)"
$policy = Get-AzureRmRecoveryServicesBackupProtectionPolicy -Name "PolicyName"
Enable-AzureRmRecoveryServicesBackupProtection `
-ResourceGroupName $vm.ResourceGroupName `
-Name $vm.Name `
-Policy $policy
Then I wanted to add IF statement there so if backup has been enable on vm, it would just skip it. The below command will print the results of backup ( true or false) but I don't know how to implement that into if statement so if results would be false, it would run the script block and if result would be true, it would just skip and print out $vm.Name has already configured to Azure backup.
Get-AzRecoveryServicesBackupStatus -Name 'VmName' -ResourceGroupName 'RgName' -Type AzureVM
Results of command
if ()
{
$vault= Get-AzureRmRecoveryServicesVault -ResourceGroupName "RgName" -Name "VaultName"
Set-AzureRmRecoveryServicesVaultContext -Vault $vault
Write-Output "Configuring Azure backup to $($vm.Name)"
$policy = Get-AzureRmRecoveryServicesBackupProtectionPolicy -Name "PolicyName"
Enable-AzureRmRecoveryServicesBackupProtection `
-ResourceGroupName $vm.ResourceGroupName `
-Name $vm.Name `
-Policy $policy
}
else {
Write-Output "$vm.Name has already configured to Azure backup"
}
So any tips how to do it? Can I do it somehow like this:
if (Get-AzRecoveryServicesBackupStatus -Name 'vmanme' -ResourceGroupName 'rgname' -Type AzureVM backedup -match false) ?

You can use the command Get-AzRecoveryServicesBackupStatus in the if statement like below to check if is BackedUp or not:
(Get-AzRecoveryServicesBackupStatus -Name 'vmname' -ResourceGroupName 'rgname' -Type AzureVM).BackedUp
If we update your existing code like if backup does not exists it will perform the backup else it will show that Backup is already configured :
if (!(Get-AzRecoveryServicesBackupStatus -Name 'vmname' -ResourceGroupName 'rgname' -Type AzureVM).BackedUp) {
$vault= Get-AzureRmRecoveryServicesVault -ResourceGroupName "RgName" -Name "VaultName"
Set-AzureRmRecoveryServicesVaultContext -Vault $vault
Write-Output "Configuring Azure backup to $($vm.Name)"
$policy = Get-AzureRmRecoveryServicesBackupProtectionPolicy -Name "PolicyName"
Enable-AzureRmRecoveryServicesBackupProtection `
-ResourceGroupName $vm.ResourceGroupName `
-Name $vm.Name `
-Policy $policy
} else {
Write-Output "$vm.Name has already configured to Azure backup"
}

Related

Azure VMs fails as public ip is allocated to other resource

I am using a powershell script to create multiple Vms based on an image. The first Vm is ok but when attempting the second Vm I get an error saying that :
| Resource /subscriptions/....../networkInterfaces/xxxxx/ipConfigurations/xxxxx is referencing public IP address
| /subscriptions/xxxxxxxxx/providers/Microsoft.Network/publicIPAddresses/Microsoft.Azure.Commands.Network.Models.PSPublicIpAddress that is already allocated to
| resource /subscriptions/......./networkInterfaces/xxxxx/ipConfigurations/xxxxx.
Here is the script I am using:
param(
[string] $WeekNo="NoWeek",
[int] $VmCount=0
)
#$cred = Get-Credential -Message "Enter a username and password for the virtual machine."
## VM Account
# Credentials for Local Admin account you created in the sysprepped (generalized) vhd image
$VMLocalAdminUser = "xxxxx"
$VMLocalAdminSecurePassword = ConvertTo-SecureString "xxxxxxx" -AsPlainText -Force
$image = "/subscriptions/xxxxxxx/resourceGroups/xxxxxx/providers/Microsoft.Compute/images/xxxxxxxxx"
## Azure Account
$LocationName = "SwedenCentral"
$ResourceGroupName = "xxxx_" + $WeekNo
if( -Not( Get-AzureRmResourceGroup -Name $ResourceGroupName -Location $LocationName -ErrorAction Ignore)) {
New-AzureRmResourceGroup -Name $ResourceGroupName -Location $LocationName
Write-Host "ResourceGroup" $ResourceGroupName "created"
$VMSize = "Standard_B2ms"
## Networking
$NetworkName = "xxxxxx_" + $WeekNo + "_net" # "MyNet"
$SubnetName = "MySubnet"
$SubnetAddressPrefix = "10.0.0.0/24"
$VnetAddressPrefix = "10.0.0.0/16"
$SingleSubnet = New-AzVirtualNetworkSubnetConfig -Name $SubnetName -AddressPrefix $SubnetAddressPrefix
$Vnet = New-AzVirtualNetwork -Name $NetworkName -ResourceGroupName $ResourceGroupName -Location $LocationName -AddressPrefix $VnetAddressPrefix -Subnet $SingleSubnet
}
$Credential = New-Object System.Management.Automation.PSCredential ($VMLocalAdminUser, $VMLocalAdminSecurePassword);
$VMName = "xxxx" + $WeekNo
##New-AzVM -ResourceGroupName $ResourceGroupName -Location $LocationName -VM $VirtualMachine -Verbose -Image $image
for($i=1; $i -le $VmCount; $i++){
$VMBaseName = "iCPSEDU" + $WeekNo + $i
$StorageAccount = "xxxxx" + $WeekNo + $i
$PublicIPAddressName = $VMBaseName + "PIP$(Get-Random)"
$NICName = $VMBaseName + "NIC"
$DNSNameLabel = "xxxx" + $WeekNo + $i + "dns" # mydnsname.westus.cloudapp.azure.com
$PIP = New-AzPublicIpAddress -Name $PublicIPAddressName -DomainNameLabel $DNSNameLabel -ResourceGroupName $ResourceGroupName -Location $LocationName -AllocationMethod Dynamic
$NIC = New-AzNetworkInterface -Name $NICName -ResourceGroupName $ResourceGroupName -Location $LocationName -SubnetId $Vnet.Subnets[0].Id -PublicIpAddressId $PIP.Id
Write-Host "Creating VM " $VMBaseName
New-AzVm `
-ResourceGroupName $ResourceGroupName `
-Name $VMBaseName `
-ImageName $image `
-Location $LocationName `
-VirtualNetworkName $Vnet `
-SubnetName $SubnetName `
-SecurityGroupName "myImageNSG" `
-PublicIpAddressName $PIP -Credential $Credential -Size $VMSize -PublicIpSku Standard
Write-Host "VM " $VMBaseName " Created"
Stop-AzVM -ResourceGroupName $ResourceGroupName $VMBaseName -Force -NoWait
Write-Host "VM " $VMBaseName " Stopped"
}
Write-Host "Done."`
To me it seems that the variable used for the PIP is not "flushed" properly between the executions but I have no idea on how to do this?
Or is there something else causing the error?
I have tried adding some delays but without effect.
Create a public IP address and specify a DNS name
Create a NSG
Create a NIC and associate with created pub IP address and NSG
Create a virtual machine configuration and assign the NIC
Create the VM with the config
https://github.com/Azure/azure-docs-powershell-samples/blob/master/virtual-machine/create-vm-detailed/create-windows-vm-detailed.ps1
rough summary of important steps:
$pip = New-AzPublicIpAddress -ResourceGroupName $resourceGroup -Location $location `
-Name "mypublicdns$(Get-Random)" -AllocationMethod Static -IdleTimeoutInMinutes 4
$nsg = New-AzNetworkSecurityGroup -ResourceGroupName $resourceGroup -Location $location `
-Name myNetworkSecurityGroup -SecurityRules $nsgRuleRDP
$nic = New-AzNetworkInterface -Name myNic -ResourceGroupName $resourceGroup -Location $location `
-SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id
$vmConfig = New-AzVMConfig -VMName $vmName -VMSize Standard_D1 | `
Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $cred | `
Set-AzVMSourceImage -PublisherName MicrosoftWindowsServer -Offer WindowsServer -Skus 2016-Datacenter -Version latest | `
Add-AzVMNetworkInterface -Id $nic.Id
New-AzVM -ResourceGroupName $resourceGroup -Location $location -VM $vmConfig
MS is providing well tested powershell code for various tasks:
I prefer the github samples https://github.com/Azure/azure-docs-powershell-samples over the steps in learn and doc.microsoft.com
also have a deeper look at the Azure CLI examples and template based deployments. It seems to me that MS is abandoning PS a bit.

Cannot parse the request - MissingJsonReferenceId : Error while creating NIC using PowerShell Az command

I am using below Az PowerShell command to create the NIC for virtual machine.
# Create a NIC for the web server VM.
$nicVMweb = New-AzNetworkInterface -ResourceGroupName $rgName -Location $location `
-Name $VmFrontendNICCardName -PublicIpAddress $publicipvm1 `
-NetworkSecurityGroup $nsgfe -Subnet $virtualNetwork.Subnets[0]
Cannot parse the request. StatusCode: 400 ReasonPhrase: Bad Request ErrorCode: InvalidRequestFormat ErrorMessage: Cannot parse the request. Additional details: Code: MissingJsonReferenceId Message: Value for
| reference id is missing. Path properties.ipConfigurations[0].properties.subnet. OperationID : 78525e42-a036-460f-10f9-5b993b7ca5e6
Issue Resolved by Below PowerShell
$Subnet = Get-AzVirtualNetwork -Name $virtualNetworkName -ResourceGroupName $rgName
$IPconfig = New-AzNetworkInterfaceIpConfig -Name $VmFrontendIpConfigName -PrivateIpAddressVersion IPv4 -PrivateIpAddress "10.0.0.10" -SubnetId $Subnet.Subnets[0].Id
$nicVMweb = New-AzNetworkInterface -Name $VmFrontendNICCardName -ResourceGroupName $rgName -Location $location -IpConfiguration $IPconfig
What is the issue in first command?
Could not reproduce your issue, your first command works fine on my side.
$virtualNetwork = Get-AzVirtualNetwork -Name "<vnet-name>" -ResourceGroupName "<group-name>"
$publicipvm1 = Get-AzPublicIpAddress -ResourceGroupName <group-name> -Name joyvm-ip2
$nsgfe = Get-AzNetworkSecurityGroup -Name joyvm-nsg -ResourceGroupName <group-name>
$nicVMweb = New-AzNetworkInterface -ResourceGroupName <group-name> -Location "West US 2" -Name "joyinter" -PublicIpAddress $publicipvm1 -NetworkSecurityGroup $nsgfe -Subnet $virtualNetwork.Subnets[0]
For this issue, it may be related to the version of Az.Network module, I use the 3.3.0 version, try to update it to the latest version:
Update-Module -Name Az.Network

Powershell + Azure App Service + Azure Container Registry

I am using powershell to handle various CI/CD functions.
=============================================
Here is what I have done so far.
Build NodeJS App
Package NodeJS App in Container
Publish Container to Private Azure Container Registry
=============================================
Here is what I am trying to figure out.
Create App Service Plan on the Fly
Create Web App (Container) on the Fly
Pull in Container from ACR into App Service
Here is my code. It doesn't seem to be working.
$azureContainerCredential = Get-AzContainerRegistryCredential -ResourceGroupName $env:AZURE_CONTAINER_REGISTRY_RESOURCE_GROUP -Name $env:AZURE_CONTAINER_REGISTRY_NAME
$azureSecuredPassword = ConvertTo-SecureString $azureContainerCredential.Password -AsPlainText -Force
$azureContainerRegistry = Get-AzContainerRegistry -ResourceGroupName $env:AZURE_CONTAINER_REGISTRY_RESOURCE_GROUP
$azureAppServicePlan = Get-AzAppServicePlan -ResourceGroupName "amlihelloworld" -Name "amlihelloworld-app-service-plan"
if($null -eq $azureAppServicePlan)
{
"==============================================================================="
Write-Output "CREATING HELLO WORLD WEB APPLICATION"
$azureAppServicePlan = New-AzAppServicePlan -Name "amlihelloworld-app-service-plan" -Location "Central
US" -ResourceGroupName "amlihelloworld" -Tier Standard
$azureApp = New-AzWebApp -ResourceGroupName "amlihelloworld" -Name "amlihelloworld2" -AppServicePlan
$azureAppServicePlan.Name -ContainerImageName "amlihelloworld:20200422.7" -ContainerRegistryPassword
$azureSecuredPassword -ContainerRegistryUrl $azureContainerRegistry.LoginServer -
ContainerRegistryUser $azureContainerCredential.Username
$azureAppSlot = New-AzWebAppSlot -Name $azureApp.Name -ResourceGroupName "amlihelloworld" -Slot
"development"
}
$azureApp1 = Get-AzWebApp -ResourceGroupName "amlihelloworld" -Name "amlihelloworld"
=============================================
Here is whats happening
When I switch the slots to my app for production.
It doesn't seem to be showing my app at all.
How can I tell if it uploaded my app or not?
Actually, I don't think there is a logic problem in the code, but a problem for the commands itself.
First, if you want to cut the PowerShell command into multiple lines, you need to add the character ` append each line except the last one. And you'd better use the same web app name if you want to get it. So you'd like to make a little change in your code:
$azureContainerCredential = Get-AzContainerRegistryCredential -ResourceGroupName $env:AZURE_CONTAINER_REGISTRY_RESOURCE_GROUP -Name $env:AZURE_CONTAINER_REGISTRY_NAME
$azureSecuredPassword = ConvertTo-SecureString $azureContainerCredential.Password -AsPlainText -Force
$azureContainerRegistry = Get-AzContainerRegistry -ResourceGroupName $env:AZURE_CONTAINER_REGISTRY_RESOURCE_GROUP
$azureAppServicePlan = Get-AzAppServicePlan -ResourceGroupName "amlihelloworld" -Name "amlihelloworld-app-service-plan"
if($null -eq $azureAppServicePlan)
{
"==============================================================================="
Write-Output "CREATING HELLO WORLD WEB APPLICATION"
$azureAppServicePlan = New-AzAppServicePlan -Name "amlihelloworld-app-service-plan" -Location "Central
US" -ResourceGroupName "amlihelloworld" -Tier Standard
$azureApp = New-AzWebApp -ResourceGroupName "amlihelloworld" -Name "amlihelloworld2" `
-AppServicePlan $azureAppServicePlan.Name `
-ContainerImageName "amlihelloworld:20200422.7" `
-ContainerRegistryPassword $azureSecuredPassword `
-ContainerRegistryUrl $azureContainerRegistry.LoginServer `
-ContainerRegistryUser $azureContainerCredential.Username
$azureAppSlot = New-AzWebAppSlot -Name $azureApp.Name -ResourceGroupName "amlihelloworld" -Slot
"development"
}
$azureApp1 = Get-AzWebApp -ResourceGroupName "amlihelloworld" -Name "amlihelloworld2"
You also need to check carefully if your environment variables exist as normal.
Apparently it's a bug on Microsoft side and it's not possible to publish containers through powershell scripts.
Please read here:
https://github.com/Azure/azure-powershell/issues/10645

How to copy custom images in Azure from one subscription to another

I am running my virtual machines on Azure which consists of multiple directories and each directory has two-three subscriptions in it. I made a custom image for my infrastructure environment under my default subscription (say "Visual Studio Enterprise: BizSpark").
I want to copy this custom image to other subscriptions under different directories so that this image is easily accessible throughout my Azure account.
I was following this link : Copy Managed Images by Michael S. Collier
but I got stuck at this snippet:
diskName=$(az vm show --resource-group linux -n vm --query "storageProfile.osDisk.name" -o tsv)
Error:
The Resource 'Microsoft.Compute/virtualMachines/vm' under resource group 'linux' was not found.
Any lead on this will be appreciated.
For a managed disk or managed image, you can not directly move it from one subscription to another subscription which is existed in a different tenant. The error may indicate that you have connected to a different tenant.
If the original managed disk exists, you could refer this blog to move Azure Managed Disk between Tenants
You can create a snapshot of the managed disk and move it to a storage
account in the source subscription, then copy the snapshot to a
storage account in the destination subscription and create a managed
disk out of the snapshot and a VM with the managed disk afterward.
Here are the main steps in PowerShell.
A: Download the disk snapshot to a storage account
$sourceSubscriptionId = ''
$sourceStorageAccountName = "SourceStorageAccount"
$sourceStorageAccountKey = "9O1...Kg=="
$sourceStorageAccountContainer = "containername"
# path of the download URL of the snapshot
$VHDDownloadUri = "https://....blob.core.windows.net/..."
$targetSnapshotName = "snapshot.vhd"
#download snapshot to StorageAccount-Source (the storage account is located in the source subscription)
Select-AzureRmSubscription -SubscriptionId $sourceSubscriptionId
$sourceStorageAccountContext = New-AzureStorageContext –StorageAccountName $sourceStorageAccountName -StorageAccountKey $sourceStorageAccountKey
Start-AzureStorageBlobCopy -AbsoluteUri $VHDDownloadUri -DestContainer $sourceStorageAccountContainer -DestContext $sourceStorageAccountContext -DestBlob $targetSnapshotName
B: Copy the snapshot to a storage account in the destination subscription of an other tenant:
$destSubscriptionId = ''
$destStorageAccount = "DestStorageAccount"
$destStorageAccountKey = "Pqn.../Q=="
$destStorageAccountContainer = "container"
Select-AzureRmSubscription -SubscriptionId $destSubscriptionId
$destStorageAccountContext = New-AzureStorageContext –StorageAccountName $destStorageAccount -StorageAccountKey $destStorageAccountKey
Get-AzureStorageBlobCopyState -Context $destStorageAccountContext -Blob $targetSnapshotName
$blobCopy = Start-AzureStorageBlobCopy -DestContainer $destStorageAccountContainer -DestContext $destStorageAccountContext -SrcBlob $targetSnapshotName -Context $sourceStorageAccountContext -SrcContainer $sourceStorageAccountContainer
Write-Host ($blobCopy | Get-AzureStorageBlobCopyState).CopyId
Write-Host ($blobCopy | Get-AzureStorageBlobCopyState).TotalBytes
Write-Host ($blobCopy | Get-AzureStorageBlobCopyState).BytesCopied
while(($blobCopy | Get-AzureStorageBlobCopyState).Status -eq "Pending")
{
Start-Sleep -s 5
#$blobCopy | Get-AzureStorageBlobCopyState
$output = "`r" + ($blobCopy | Get-AzureStorageBlobCopyState).BytesCopied
Write-Host $output -NoNewline
}
The copy process runs asynchronous. If you need to stop the copy process, get the CopyId and use the Stop-AzureStorageBlogCopy command: Stop-AzureStorageBlobCopy -Container $destStorageAccountContainer -Blob $targetSnapshotName -CopyId "<GUID>" -Context $destStorageAccountContext
C: Create a new VM and use the snapshot.vhd from the DestStorageAccount as base image for the managed disk:
$rgName = "DestResourceGroup"
$location = "northeurope"
$storageName = "MyVMstorage"
$storageType = "Standard_LRS"
$nicname = "MyVM-nic"
$subnet1Name = "MyVM-subnet"
$vnetName = "MyVM-vnet"
$vnetAddressPrefix = "10.0.0.0/16"
$vnetSubnetAddressPrefix = "10.0.0.0/24"
$vmName = "MyVM"
$vmSize = "Standard_D2s_v3"
$osDiskName = $vmName + "osDisk"
$osDiskUri = "https://deststorageaccount.blob.core.windows.net/container/snapshot.vhd"
$storageacc = New-AzureRmStorageAccount -ResourceGroupName $rgName -Name $storageName -Type $storageType -Location $location
$pip = New-AzureRmPublicIpAddress -Name $nicname -ResourceGroupName $rgName -Location $location -AllocationMethod Dynamic
$subnetconfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet1Name -AddressPrefix $vnetSubnetAddressPrefix
$vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $location -AddressPrefix $vnetAddressPrefix -Subnet $subnetconfig
$nic = New-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $rgName -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id
$vm = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize
$vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id
$discStorageAcc = Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroup -Name $destStorageAccount
$diskConfig = New-AzureRmDiskConfig -AccountType 'PremiumLRS' -Location $location -CreateOption Import -StorageAccountId ($discStorageAcc.Id) -SourceUri $osDiskUri
$disk = New-AzureRmDisk -Disk $diskConfig -ResourceGroupName $rgName -DiskName "managedsnapshot"
$vm = Set-AzureRmVMOSDisk -VM $vm -ManagedDiskId $disk.Id -CreateOption Attach -Windows
New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vm -Verbose
first command just retrieves disk name, so if you know disk name you dont have to run it. just do:
diskName="diskname_goes_here"

Azure Automation moving blobs hashtable error

I am trying to create a script to move blobs from one container to another after they are processed by another automation process. The code I am using is below.
workflow Move-AttendeeFiles
{
$connectionName = Get-AutomationConnection -Name 'AzureConnection'
$storageAccountName = Get-AutomationVariable -Name 'StorageAccountName'
$storageContainerName = Get-AutomationVariable -Name 'toprocessContainer'
$destContainerName = Get-AutomationVariable -Name 'processedContainer'
Connect-Azure `
-AzureConnectionName $connectionName
inlineScript{
Select-AzureSubscription `
-SubscriptionName $Using:connectionName
Set-AzureSubscription `
-SubscriptionName $Using:connectionName `
-CurrentStorageAccount $Using:storageAccountName
Get-AzureStorageBlob `
-Container $Using:storageContainerName | Start-AzureStorageBlobCopy `
-DestContainer $Using:destContainerName
}
}
It is throwing the below error
Could not retrieve 'System.Collections.Hashtable' connection asset.
Check that you created this first in the Automation service.
I can't seem to get it running and must be staring at it to long. Any help would be much appreciated.
The Connect-Azure runbook takes as a string the connection asset name. You are passing it the connection, itself. Pass the connection name instead.
Joe's answer got my past the Hashtable error but I had some other errors in my code. I wanted to post the working code for everyone.
workflow Move-AttendeeFiles
{
$connectionName = Get-AutomationVariable -Name 'azureConnectionName'
$subId = Get-AutomationVariable -Name 'azureSubscriptionId'
$storageAccountName = Get-AutomationVariable -Name 'StorageAccountName'
$storageContainerName = Get-AutomationVariable -Name 'toprocessContainer'
$destContainerName = Get-AutomationVariable -Name 'processedContainer'
Connect-Azure `
-AzureConnectionName $connectionName
inlineScript{
Select-AzureSubscription `
-SubscriptionName $Using:connectionName
Set-AzureSubscription `
-CurrentStorageAccountName $Using:storageAccountName `
-SubscriptionId $Using:subId
}
}
Note the difference in the Set-AzureSubscription code to use the -SubscriptionId instead of -SubscriptionName as that is not the proper variable.

Resources