Microsoft Virtualization Discussions
Microsoft Virtualization Discussions
Hi Community,
In my scripts, I’m using try and catch blocks to handle terminating errors.
I don’t know why, but with Invoke-NaSnapmirrorUpdate, my catch block is never called…
For example :
try {Invoke-NaSnapmirrorUpdate -Destination "filer_foo:vol_foo"}
catch {Write-Host "Invoke-NaSnapmirrorUpdate returned an error"}
Any idea why?
Thank you.
Solved! See The Solution
The majority of cmdlets in the Toolkit don't throw terminating errors if the underlying Data ONTAP API fails, thus allowing them to continue processing pipeline input.
PowerShell provides the -ErrorAction and $ErrorActionPreference mechanisms to define the behavior when errors occur. You can use "-ErrorAction Stop" with any cmdlet, or you can set $ErrorActionPreference = "Stop" to affect all cmdlets. Either will cause an error to terminate the pipeline with a catchable exception.
Import-Module DataONTAP
Write-Host "Sending invalid command"
try
{
Get-NaVolAutosize -Name "nonexistent_volume" -ErrorAction Stop
}
catch
{
Write-Host "Caught exception: $_."
}
Write-Host "Done"
This works with trap as well, but try/catch is definitely preferable.
In order to use a catch block, the cmdlet needs to return an exception. If I call "Invoke-nasnapmirrorupdate $null", then an exception is returned, a ParameterBindingValidationException:
Invoke-NaSnapmirrorUpdate : Cannot bind argument to parameter 'Destination' because it is null.
At line:1 char:26
+ invoke-nasnapmirrorupdate <<<< $null
+ CategoryInfo : InvalidData: (:) [Invoke-NaSnapmirrorUpdate], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,DataONTAP.PowerShell.SDK.Cmdlets.Snapmirror.InvokeNaSnapmirrorUpdate
In that case,
try {invoke-nasnapmirrorupdate $null} catch {"Invoke-NaSnapMirrorUpdate returned an error"}
does indeed work printing "Invoke-NaSnapMirrorUpdate returned an error" on the console.
The problem here seems to be that if invalid parameters make it past validation and are sent in the underlying ZAPI call, like:
PS C:\> try {invoke-nasnapmirrorupdate -Source SIM1:vol1 vol1} catch {"Invoke-NaSnapMirrorUpdate returned an error"}
Invoke-NaSnapmirrorUpdate : Snapmirror error: destination is not in snapmirrored state
At line:1 char:31
+ try {invoke-nasnapmirrorupdate <<<< -Source SIM1:vol1 vol1} catch {"Invoke-NaSnapMirrorUpdate returned an error"}
+ CategoryInfo : InvalidOperation: (NetApp.Ontapi.Filer.NaController:NaController) [Invoke-NaSnapmirrorUpdate], ESNAPMIRRORERROR
+ FullyQualifiedErrorId : ApiException,DataONTAP.PowerShell.SDK.Cmdlets.Snapmirror.InvokeNaSnapmirrorUpdate
As you can see, the problem here is that the cmdlet is not raising an exception at this point for catch to catch. You'd want to specify the error or use trap.
J
The majority of cmdlets in the Toolkit don't throw terminating errors if the underlying Data ONTAP API fails, thus allowing them to continue processing pipeline input.
PowerShell provides the -ErrorAction and $ErrorActionPreference mechanisms to define the behavior when errors occur. You can use "-ErrorAction Stop" with any cmdlet, or you can set $ErrorActionPreference = "Stop" to affect all cmdlets. Either will cause an error to terminate the pipeline with a catchable exception.
Import-Module DataONTAP
Write-Host "Sending invalid command"
try
{
Get-NaVolAutosize -Name "nonexistent_volume" -ErrorAction Stop
}
catch
{
Write-Host "Caught exception: $_."
}
Write-Host "Done"
This works with trap as well, but try/catch is definitely preferable.
Excellent point Clinton,
If you change the behavior to throw a terminating error, then you can use try/catch. Beware however if you use this with a pipeline. Let's say I do something like:
PS C:\> $SIM1=connect-nacontroller SIM1
PS C:\> Write-Host "Sending invalid command"
Sending invalid command
PS C:\> try {get-navol -Controller $SIM1| Invoke-nasnapmirrorupdate} catch {Write-Host "Caught exception."}
Invoke-NaSnapmirrorUpdate : Source not set on command line or in /etc/snapmirror.conf file.
At line:1 char:60
+ try {get-navol -Controller $SIM1| Invoke-nasnapmirrorupdate <<<< } catch {Write-Host "Caught exception."}
+ CategoryInfo : InvalidOperation: (NetApp.Ontapi.Filer.NaController:NaController) [Invoke-NaSnapmirrorUpdate], ESNAPMIRRORPARSERERROR
+ FullyQualifiedErrorId : ApiException,DataONTAP.PowerShell.SDK.Cmdlets.Snapmirror.InvokeNaSnapmirrorUpdate
Invoke-NaSnapmirrorUpdate : Source not set on command line or in /etc/snapmirror.conf file.
At line:1 char:60
+ try {get-navol -Controller $SIM1| Invoke-nasnapmirrorupdate <<<< } catch {Write-Host "Caught exception."}
+ CategoryInfo : InvalidOperation: (NetApp.Ontapi.Filer.NaController:NaController) [Invoke-NaSnapmirrorUpdate], ESNAPMIRRORPARSERERROR
+ FullyQualifiedErrorId : ApiException,DataONTAP.PowerShell.SDK.Cmdlets.Snapmirror.InvokeNaSnapmirrorUpdate
Invoke-NaSnapmirrorUpdate : Source not set on command line or in /etc/snapmirror.conf file.
At line:1 char:60
+ try {get-navol -Controller $SIM1| Invoke-nasnapmirrorupdate <<<< } catch {Write-Host "Caught exception."}
+ CategoryInfo : InvalidOperation: (NetApp.Ontapi.Filer.NaController:NaController) [Invoke-NaSnapmirrorUpdate], ESNAPMIRRORPARSERERROR
+ FullyQualifiedErrorId : ApiException,DataONTAP.PowerShell.SDK.Cmdlets.Snapmirror.InvokeNaSnapmirrorUpdate
Invoke-NaSnapmirrorUpdate : Source not set on command line or in /etc/snapmirror.conf file.
At line:1 char:60
+ try {get-navol -Controller $SIM1| Invoke-nasnapmirrorupdate <<<< } catch {Write-Host "Caught exception."}
+ CategoryInfo : InvalidOperation: (NetApp.Ontapi.Filer.NaController:NaController) [Invoke-NaSnapmirrorUpdate], ESNAPMIRRORPARSERERROR
+ FullyQualifiedErrorId : ApiException,DataONTAP.PowerShell.SDK.Cmdlets.Snapmirror.InvokeNaSnapmirrorUpdate
Invoke-NaSnapmirrorUpdate : Source not set on command line or in /etc/snapmirror.conf file.
At line:1 char:60
+ try {get-navol -Controller $SIM1| Invoke-nasnapmirrorupdate <<<< } catch {Write-Host "Caught exception."}
+ CategoryInfo : InvalidOperation: (NetApp.Ontapi.Filer.NaController:NaController) [Invoke-NaSnapmirrorUpdate], ESNAPMIRRORPARSERERROR
+ FullyQualifiedErrorId : ApiException,DataONTAP.PowerShell.SDK.Cmdlets.Snapmirror.InvokeNaSnapmirrorUpdate
PS C:\> Write-Host "Done"
Done
PS C:\>
I have several volumes, but no snapmirror relationships. because I piped the output of get na-vol to Invoke-nasnapmirrorupdate, I see a failure for each volume in my collection. This happens specifically because the error is non-terminating. Now, if I make it a terminating error and put it in try-catch:
PS C:\> $SIM1=connect-nacontroller SIM1
PS C:\> Write-Host "Sending invalid command"
Sending invalid command
PS C:\> try {get-navol -Controller $SIM1| Invoke-nasnapmirrorupdate -ErrorAction Stop} catch {Write-Host "Caught exception."}
Caught exception.
PS C:\> Write-Host "Done"
Done
PS C:\>
It bails on the first error and does not even try the rest of the volumes in my collection. What to do? I pipe the output of get-navol to a foreach-object statement where I process the try-catch:
PS C:\> $SIM1=connect-nacontroller SIM1
PS C:\> Write-Host "Sending invalid command"
Sending invalid command
PS C:\> get-navol | foreach-object -Process {try {Invoke-nasnapmirrorupdate $_ -ErrorAction Stop} catch {Write-Host "Caught exception."}}
Caught exception.
Caught exception.
Caught exception.
Caught exception.
Caught exception.
PS C:\> Write-Host "Done"
Done
PS C:\>
Happy Scripting
J
Thank you very much to both of you for your answers.
Now I understand the reason, and in my specific script, the "-ErrorAction Stop" parameter is exactly what I need. (Basic but sorry: I'm new to Powershell
Thanks again.
Benoit.