Get-AzureRmRecoveryServicesBackupContainer : Requested value 'NotRegistered' was not found - azure

I am using below command in Azure Automation Powershell script to get status of Recovery Services container - it simply checks if a VM is registered for backup.
Get-AzureRmRecoveryServicesVault -Name $AzureRecoveryServicesName | Set-AzureRmRecoveryServicesVaultContext
$BackupStatus = Get-AzureRmRecoveryServicesBackupContainer -ContainerType AzureVM -FriendlyName $VirtualMachineName -ResourceGroupName $ResourceGroupName
If a VM is not registered it throws an error and $BackupStatus is empty:
Get-AzureRmRecoveryServicesBackupContainer : Requested value 'NotRegistered' was not found.
At line:53 char:21
... kupStatus = Get-AzureRmRecoveryServicesBackupContainer -ContainerType ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidArgument: (:) [Get-AzureRmReco...BackupContainer], ArgumentException
FullyQualifiedErrorId :
Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets.GetAzureRmRecoveryServicesBackupContainer
And if it is already registered I get $BackupStatus = Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets.Models.AzureVmContainer.
I've tried:
$BackupStatus = (Get-AzureRmRecoveryServicesBackupContainer -ContainerType AzureVM -FriendlyName $VirtualMachineName -ResourceGroupName $ResourceGroupName).Status
But then the only difference is that I get $BackupStatus = Registered when VM is already in a container but same error occurs when VM is not registered.
What is the proper way to check if a VM is registered for backup or not? I am ok with what I'm getting - I can handle $BackupStatus values in a script - but I don't want this error message to show.
Strange thing is that in Powershell on PC with same Azure modules versions loaded (AzureRM​.RecoveryServices​.Backup 2.5.0) as in Automation Account I am getting a different behavior:
PS C:\windows\system32> $BackupStatus = Get-AzureRmRecoveryServicesBackupContainer -ContainerType AzureVM -FriendlyName $VirtualMachineName -ResourceGroupName $ResourceGroupName
PS C:\windows\system32> $BackupStatus
Name ResourceGroupName Status ContainerType
---- ----------------- ------ -------------
UbuntuBckptest rhel68128 Registered AzureVM
It returns an object instead of a string.

If you want to set $BackupStatus value according to Get-AzureRmRecoveryServicesBackupContainer command executed result. We could put the Get-AzureRmRecoveryServicesBackupContainer in try...catch.
The following just the code sample
$BackupStatus;
try
{
$BackupStatus=Get-AzureRmRecoveryServicesBackupContainer
}
catch
{
# we can add condition for example : if($BackupStatus.Contains("NotRegistered"))
$BackupStatus = "NotRegistered"
}
# we can add condition :get the type of $BackupStatus for example :if($BackupStatus.GetType().Name.equals("String"))`
$BackupStatus = "Registered"

Related

Powershell to Stop Azure backups

So i'm running into a Bad Request error using the Stop-AzRecoveryServicesBackupJob powershell command. The documentation isn't helpfull as it only requires -JobID $Job.InstanceId as a parameter. BUT, InstanceId doesn't exist. JobID does, but returns the bad request error.
My code: The bad request is on Stop-AzRecoveryServicesBackupJob -JobID $BackupJob.JobId
#get RSV
$myVault = Get-AzRecoveryServicesVault -ResourceGroupName $myResourceGroup -Name $vaultName
#Disable soft delete on RSV
$myVault.ID | Set-AzRecoveryServicesVaultProperty -SoftDeleteFeatureState Disable | Out-Null
$BackupJob = $myVault.ID | Get-AzRecoveryServicesBackupJob -Operation Backup
Stop-AzRecoveryServicesBackupJob -JobID $BackupJob.JobId
Error msg:
Stop-AzRecoveryServicesBackupJob : Cannot cancel the job. Only in progress jobs can be cancelled. Please attempt cancellation only on an in progress job.
At C:\Users\azureuser\Documents\WindowsPowerShell\temp.ps1:20 char:1
Stop-AzRecoveryServicesBackupJob -Job $BackupJob
+ CategoryInfo : InvalidOperation: (:) [Stop-AzRecoveryServicesBackupJob], CloudException
+ FullyQualifiedErrorId : BMSUserErrorJobNotInProgressToCancel,Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets.StopAzureRmRecoveryServicesBackupJo
b
So following up on the "In Progress Job" Stop-AzRecoveryServicesBackupJob will only stop the job while it is in progress. If you want to stop the backup of jobs that aren't currently in progress you need to use Disable-AzRecoveryServicesBackupProtection. No exactly self explanitory.
correct code :
$Cont = Get-AzRecoveryServicesBackupContainer -ContainerType AzureVM -Status Registered
$PI = Get-AzRecoveryServicesBackupItem -Container $Cont[0] -WorkloadType AzureVM
Disable-AzRecoveryServicesBackupProtection -Item $PI[0]
This will change the status to disabled. (Even though the choice manually is "Stop Backup") 🤷‍♂️

Get-AzRecoveryServicesBackupItem : Cannot validate argument on parameter 'Container'. The argument is null or empty

I am working on this official tutorial from MS Azure team on Back up a virtual machine in Azure with PowerShell. But while running runbook from Start a backup job section, I get the error shown below. Question: What I may be missing here, and how the issue can be fixed?
Following lines runs fine:
PS C:\Users\myUserName> $vault = Get-AzRecoveryServicesVault -ResourceGroupName "rg-cs-ansible1" -Name "myRecoveryServicesVault"
>> $backupcontainer = Get-AzRecoveryServicesBackupContainer -ContainerType "AzureVM" -Status "Registered" -FriendlyName "myVM" -VaultId $vault.ID
But when I run the following line, I get the error shown below.
PS C:\Users\myUserName> $item = Get-AzRecoveryServicesBackupItem -Container $backupcontainer -WorkloadType AzureVM -VaultId $vault.ID
Error
Get-AzRecoveryServicesBackupItem : Cannot validate argument on parameter 'Container'. The argument is null or empty.
Provide an argument that is not null or empty, and then try the command again.
At line:2 char:16
+ -Container $backupcontainer `
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-AzRecoveryServicesBackupItem], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlet
s.GetAzureRmRecoveryServicesBackupItem
Per my test, your commands work fine on my side. I can just reproduce your issue with a wrong VM name this command, even if your VM name is wrong, it will not give an error, but the $backupcontainer will be null, it will cause the error in the next command.
$backupcontainer = Get-AzRecoveryServicesBackupContainer -ContainerType "AzureVM" -Status "Registered" -FriendlyName "myVM" -VaultId $vault.ID
So in your case, please make sure myVM is the correct VM name used for -FriendlyName parameter.

Azure: create a new API Management service without a service URL

My intent is to configure an API (e.g. an Azure Function) into an API Manegement service using only policies. I don't want to specify a Service URL.
This is possible using Portal UI:
but not using PowerShell Az module.
Following code:
New-AzApiManagementApi -Context $context -Name $fullName -Protocols #('https') `
-Path $path -ProductIds #($product) `
-ApiVersionSetId $apiMgmtVersion.ApiVersionSetId
raises this exception:
Error : Unable to create 'news' managed API version 1.
Cannot validate argument on parameter 'ServiceUrl'. The argument is null or empty. Provide an argument that is not null or empty, and then try the
command again.
At C:\Projects\Intranet.ai\component_tools\Install-ApiMgmt.ps1:105 char:76
+ ... able to create '$fullName' managed API version $version.`n$_" | Error
+ ~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Error
Is there a way to define an API without a service URL? Maybe using directly New-AzResource?
Thanks to anyone who will help!
Is there a way to define an API without a service URL? Maybe using directly New-AzResource?
The New-AzApiManagementApi seems not support that, you could use the New-AzResource directly, please try the sample below, it works on my side.
$PropertiesObject = #{
"name" = "test22"
"serviceUrl" = $null
"path" = "testaaa"
"protocols" = #("https")
}
New-AzResource -PropertyObject $PropertiesObject -ResourceGroupName <Group-name> -ResourceType Microsoft.ApiManagement/service/apis -ResourceName "<API-management-servie-name>/test22" -ApiVersion 2018-01-01 -Force
Check in the portal:
Update:
If you want to include the apiVersionSetId, please try the one below.
$versionSet = Get-AzApiManagementApiVersionSet -Context $context -ApiVersionSetId "d41e7f92-9cf8-48fb-8552-d9ae5d4690d3"
$Id = $versionSet.Id -replace "apiVersionSets","api-version-sets"
$PropertiesObject = #{
"name" = "test22"
"serviceUrl" = $null
"path" = "testaaa"
"protocols" = #("https")
"apiVersionSetId" = $Id
}
New-AzResource -PropertyObject $PropertiesObject -ResourceGroupName <Group-name> -ResourceType Microsoft.ApiManagement/service/apis -ResourceName "<API-management-servie-name>/test22" -ApiVersion 2018-01-01 -Force

Set-AzVMCustomScriptExtension in catch?

Attempting to add an extension when not detected but keep failing to find the secret sauce to get this to work. Mind you I am a BASH guy and this is a first foray into PowerShell..
#requires -version 2
# Required parameter $subscription: name of the subscription to enable Custom Script Extensions in
param (
# NOTE: See below for reason...
# [Parameter(Mandatory = $true)] [String] $subscription
# NOTE: Prompting is great for using the script interactively, but if this will also be executed
# from a build server or ...
# NOTE: Once the parameter is marked as mandatory PowerShell it will prompt for value. That said,
# if you remove the mandatory attribute then you can set a default value as a T_THROW ...
# NOTE: This _does_ contain shortcomings if this will be used as a pipeline param ...
# https://stackoverflow.com/questions/33600279/is-it-possible-to-force-powershell-script-to-throw-if-a-required-pipeline-para
[Parameter()]
[ValidateNotNullOrEmpty()]
[String]$SubscriptionName=$(Throw "`SubscriptionName` is mandatory, please provide a value...")
)
# Connect to the current Azure account
Write-Output "Pulling Azure account credentials..."
Start-Process "https://microsoft.com/devicelogin" # steals focus...
# Login to Azure account
Connect-AzAccount
# Set the active subscription
$null = Get-AzSubscription -SubscriptionName "$SubscriptionName" |Set-AzContext
# TODO: error handling
$vms = Get-AzVM
$cseName = "VulnerabilityManagementTools"
ForEach ($vm in $vms) {
try {
$cseStatus = Get-AzVMCustomScriptExtension `
-ResourceGroupName $vm.ResourceGroupName `
-VMName $vm.Name `
-Name $cseName `
-Status
}
catch {
Write-Output "Enabling Custom Script Extension for $vm."
Set-AzVMCustomScriptExtension `
-ResourceGroupName $vm.ResourceGroup `
-Location $vm.Location `
-VMName $vm.Name `
-Name $cseName `
-TypeHandlerVersion "1.1" `
-StorageAccountName "VulnerabilityManagementTools" `
-FileName "VulnerabilityManagementInstaller.ps1" `
-ContainerName "VulnerabilityManagementTools"
}
}
End up err'ing out with
PS /.../automation-scripts> ./EnableCustomScriptExtension.ps1 SubscriptionName
Pulling Azure account credentials...
WARNING: To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXX to authenticate.
Account SubscriptionName TenantId Environment
------- ---------------- -------- -----------
XXXX#analytics.com SubName XXXXXX-XXXX AzureCloud
Get-AzVMCustomScriptExtension : The Resource 'Microsoft.Compute/virtualMachines/XXXX/extensions/VulnerabilityManagementTools' under resource group '{NAME}' was not found.
ErrorCode: ResourceNotFound
ErrorMessage: The Resource 'Microsoft.Compute/virtualMachines/XXXX/extensions/VulnerabilityManagementTools' under resource group '{NAME}' was not found.
ErrorTarget:
StatusCode: 404
ReasonPhrase: Not Found
At /.../automation-scripts/EnableCustomScriptExtension.ps1:59 char:18
+ $cseStatus = Get-AzVMCustomScriptExtension `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzVMCustomScriptExtension], ComputeCloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.GetAzureVMCustomScriptExtensionCommand
Get-AzVMCustomScriptExtension : The Resource 'Microsoft.Compute/virtualMachines/XXXXX/extensions/VulnerabilityManagementTools' under resource group '{RESOURCE_GROUPNAME}' was not found.
ErrorCode: ResourceNotFound
ErrorMessage: The Resource 'Microsoft.Compute/virtualMachines/XXXX/extensions/VulnerabilityManagementTools' under resource group '{RESOURCE_GROUPNAME}' was not found.
ErrorTarget:
StatusCode: 404
ReasonPhrase: Not Found
At /.../automation-scripts/EnableCustomScriptExtension.ps1:59 char:18
+ $cseStatus = Get-AzVMCustomScriptExtension `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzVMCustomScriptExtension], ComputeCloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.GetAzureVMCustomScriptExtensionCommand
Get-AzVMCustomScriptExtension : The Resource 'Microsoft.Compute/virtualMachines/{VMName}/extensions/VulnerabilityManagementTools' under resource group '{RESOURCEX_GROUPNAME}' was not found.
ErrorCode: ResourceNotFound
ErrorMessage: The Resource 'Microsoft.Compute/virtualMachines/{VMName}/extensions/VulnerabilityManagementTools' under resource group '{RESOURCEX_GROUPNAME}' was not found.
ErrorTarget:
StatusCode: 404
ReasonPhrase: Not Found
At /.../automation-scripts/EnableCustomScriptExtension.ps1:59 char:18
+ $cseStatus = Get-AzVMCustomScriptExtension `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzVMCustomScriptExtension], ComputeCloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.GetAzureVMCustomScriptExtensionCommand`
In your case, you just need to use the if(){}else{} statement, try the script as below instead of the ForEach part of yours, it works fine on my side.
ForEach ($vm in $vms) {
$cseStatus = Get-AzVMCustomScriptExtension `
-ResourceGroupName $vm.ResourceGroupName `
-VMName $vm.Name `
-Name $cseName `
-Status `
-ErrorAction SilentlyContinue
if ($cseStatus){
Write-Host "The extension has been set for" $vm.Name
}else{
Write-Host "Enabling Custom Script Extension for" $vm.Name
Set-AzVMCustomScriptExtension `
-ResourceGroupName $vm.ResourceGroup `
-Location $vm.Location `
-VMName $vm.Name `
-Name $cseName `
-TypeHandlerVersion "1.1" `
-StorageAccountName "VulnerabilityManagementTools" `
-FileName "VulnerabilityManagementInstaller.ps1" `
-ContainerName "VulnerabilityManagementTools"
}
}
Test result:
You'll need to create an Azure AD Service Principal using password authentication and use the credentials of this to pass to the Connect-AzAccount cmdlet as follows:
$credentials = Get-Credential
Connect-AzAccount -ServicePrincipal -Credentials $credentials
The service account will need to have the necessary permissions to use the Set-AzVMCustomScriptExtensions cmdlet.
More information on creating the service account here:
https://learn.microsoft.com/en-us/powershell/azure/create-azure-service-principal-azureps?view=azps-2.8.0

Azure Powershell command cannot find my VM under my resource group?

I'm trying to change the TCP Port timeout on my Ubuntu VM in Azure, and am following this guide to do so, however I seem to get stuck at Step 8 where I have to type the following command:
Get-AzureRmVM -Name "digitron" -ResourceGroup "DIGITRON-RG" |
Get-AzureRmPublicIpAddress
Where it spits back the following error:
Get-AzureRmPublicIpAddress : The Resource 'Microsoft.Network/publicIPAddresses/digitron' under resource group
'DIGITRON-RG' was not found.
StatusCode: 404
ReasonPhrase: Not Found
OperationID : '5031da35-262c-4e1a-a85b-885a6a0fd36c'
At line:1 char:63
+ ... "digitron" -ResourceGroup "DIGITRON-RG" | Get-AzureRmPublicIpAddress
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzureRmPublicIpAddress], NetworkCloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Network.GetAzurePublicIpAddressCommand
What's strange here is if I run the command Get-AzureRmVm, the powershell will spit back:
ResourceGroupName Name Location VmSize OsType NIC ProvisioningState
DIGITRON-RG digitron eastus Standard_DS2_v2 Linux digitron727 Succeeded
Now reading the error makes me think that the VM itself has no public IP address, but I've set it in the Azure Portal as seen in this image (where it says 40.71.98.172 etc):
Why is the Powershell giving me this error?
The Resource 'Microsoft.Network/publicIPAddresses/digitron' under
resource group 'DIGITRON-RG' was not found.
Because Get-AzureRmPublicIpAddress can't get the right parameter, this error means the resource can't find in DIGITRON-RG. For test, we can use Get-AzureRmResource to test the resource exist or not:
PS > Get-AzureRmResource | ?{$_.name = "digitron"}
By the way, the command Get-AzureRmPublicIpAddress need parameters: -Name (the name of the public IP address), -ResourceGroupName (the name of the resource group)
PS > Get-AzureRmPublicIpAddress -Name "jason-ip" -ResourceGroupName "jason"
Name : jason-ip
ResourceGroupName : jason
Location : eastus
Id : /subscriptions/5xxxxabb-222b-49c3-9488-0361e29a7b15/resourceGroups/jason/providers/Microsoft.Network/publicIPAddresses/jason-ip
Etag : W/"5a7200b2-7c2b-4c7a-be27-0bbb7c8f4665"
ResourceGuid : 32xxxf-750a-46a4-abda-c25xxx2b64
ProvisioningState : Succeeded
Tags :
PublicIpAllocationMethod : Dynamic
IpAddress : 13.92.255.103
PublicIpAddressVersion : IPv4
IdleTimeoutInMinutes : 30
IpConfiguration : {
"Id": "/subscriptions/5xxxxb-222b-49c3-9xx8-0361e29a7b15/resourceGroups/jason/providers/Microsoft.Network/networkInterfaces/jason647/ipConfigurations/ipconfig1"
}
DnsSettings : null
We can use this command to get the public IP direct, and increase the timrout to 30 minutes.
Below is the script I used to get the Private and Public IP for an Azure ARM VM:
$rg = Get-AzureRmResourceGroup -Name "MyResourceGroup01"
$vm = Get-AzureRmVM -ResourceGroupName $rg.ResourceGroupName -Name "MyVM01"
$nic = Get-AzureRmNetworkInterface -ResourceGroupName $rg.ResourceGroupName -Name $(Split-Path -Leaf $VM.NetworkProfile.NetworkInterfaces[0].Id)
$nic | Get-AzureRmNetworkInterfaceIpConfig | Select-Object Name,PrivateIpAddress,#{'label'='PublicIpAddress';Expression={Set-Variable -name pip -scope Global -value $(Split-Path -leaf $_.PublicIpAddress.Id);$pip}}
(Get-AzureRmPublicIpAddress -ResourceGroupName $rg.ResourceGroupName -Name $pip).IpAddress
#Output:
Name PrivateIpAddress PublicIpAddress
---- ---------------- ---------------
ipconfig1 10.0.0.10 MyVM01-pip
40.80.217.1

Resources