Search code examples
powershellazureazure-automation

Testing Azure Automaton Runbooks with Error: WriteErrorException


So I've entered the following code into a Run Book inside an Automation Account under a Free Trial Azure subscription.

The purpose of this Run Book is to automate the shutting down of my VM during the weekends and to automate the start up of this VM on the Monday morning. There are no issues in the scheduling creation.

The parameters are labelled as "optional" and it does select the correct Virtual Machine (ITAMTradingVPS) when all external parameter fields are left blank. No problems there either.

However, when I undergo a "Test" to ensure that all the coding is correct and that the script does what it's supposed to be doing, why am I getting the following errors and what do I need to do to fix this?

The Run Book was created from the Automation Account Blade with a "Powershell Runbook"

If you need any further information, or need me to clarify anything, feel free to comment.

Thanks

ITAMTradingVPS failed to stop. Error was:
+ CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException


Status was 
+ CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
+ CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

This is the code I have for the automation process

param (
  
    [Parameter(Mandatory=$false)] 
    [String] $VMName ,
 
    [Parameter(Mandatory=$false)] 
    [String] $ResourceGroupName
)
 
$connectionName = "AzureRunAsConnection"
try
{
    # Get the connection "AzureRunAsConnection "
    $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         
 
    "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
}
catch {
    if (!$servicePrincipalConnection)
    {
        $ErrorMessage = "Connection $connectionName not found."
        throw $ErrorMessage
    } else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}
 
 
# If there is a specific resource group, then get all VMs in the resource group,
# otherwise get all VMs in the subscription.
if ($ResourceGroupName -And $VMName) 
{ 
    $VMs = Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $VMName
}
elseif ($ResourceGroupName)
{
    $VMs = Get-AzureRmVM -ResourceGroupName $ResourceGroupName
 
}
else 
{ 
    $VMs = Get-AzureRmVM
}
# Start each of the VMs
# Stop each of the VMs
foreach ($VM in $VMs)
{
    $StopRtn = $VM | Stop-AzureRmVM -Force -ErrorAction Continue
 
    if ($StopRtn.Status -ne 'succeeded')
    {
        # The VM failed to stop, so send notice
        Write-Output ($VM.Name + " failed to stop")
        Write-Error ($VM.Name + " failed to stop. Error was:") -ErrorAction Continue
        Write-Error ("Status was "+ $StopRtn.Status) -ErrorAction Continue
        Write-Error (ConvertTo-Json $StopRtn.Error) -ErrorAction Continue
    }
    else
    {
        # The VM stopped, so send notice
        Write-Output ($VM.Name + " has been stopped")
    }
}


Solution

  • I test your script on my local machine powershell, works fine. But run it in Azure runbook, get the same error message as you.

    Because $StopRtn out put is this:

    RequestId IsSuccessStatusCode StatusCode ReasonPhrase
    --------- ------------------- ---------- ------------
                             True         OK OK          
    

    So we should modify the powershell script like this:

    param (
    
        [Parameter(Mandatory=$false)] 
        [String] $VMName ,
    
        [Parameter(Mandatory=$false)] 
        [String] $ResourceGroupName
    )
    
    $connectionName = "AzureRunAsConnection"
    try
    {
        # Get the connection "AzureRunAsConnection "
        $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         
    
        "Logging in to Azure..."
        Add-AzureRmAccount `
            -ServicePrincipal `
            -TenantId $servicePrincipalConnection.TenantId `
            -ApplicationId $servicePrincipalConnection.ApplicationId `
            -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
    }
    catch {
        if (!$servicePrincipalConnection)
        {
            $ErrorMessage = "Connection $connectionName not found."
            throw $ErrorMessage
        } else{
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
    }
    
    
    # If there is a specific resource group, then get all VMs in the resource group,
    # otherwise get all VMs in the subscription.
    if ($ResourceGroupName -And $VMName) 
    { 
        $VMs = Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $VMName
    }
    elseif ($ResourceGroupName)
    {
        $VMs = Get-AzureRmVM -ResourceGroupName $ResourceGroupName
    
    }
    else 
    { 
        $VMs = Get-AzureRmVM
    }
    
    $vms
    # Start each of the VMs
    # Stop each of the VMs
    foreach ($VM in $VMs)
    {
        $StopRtn = $VM | Stop-AzureRmVM -Force -ErrorAction Continue
        $StopRtn
        Write-Output " this is $StopRtn "
    
        if ($StopRtn.IsSuccessStatusCode -eq 'True')
        {
            # The VM stopped, so send notice
            Write-Output ($VM.Name + " has been stopped")
    
        }
        else
        {
            # The VM failed to stop, so send notice
            Write-Output ($VM.Name + " failed to stopped")
        }
    }
    

    Hope this helps.