Clustered Data ONTAP: Storage Efficiency Task

DataONTAP.Cluster.DataONTAP.AdminVserver.StorageEfficiency.Task (Task)

This task updates Clustered Data ONTAP storage efficiency data for selected cluster. Rather than waiting for the storage efficiency rule to run, the operator may wish to run this task to look at the real time data.

Element properties:

TargetDataONTAP.Cluster.AdminVserver
AccessibilityPublic
CategoryMaintenance
EnabledTrue
RemotableFalse
Timeout43200

Member Modules:

ID Module Type TypeId RunAs 
WA WriteAction Microsoft.Windows.PowerShellWriteAction DataONTAP.SecureReference.RunAsProfile

Source Code:

<Task ID="DataONTAP.Cluster.DataONTAP.AdminVserver.StorageEfficiency.Task" Accessibility="Public" Target="DataONTAP.Cluster.AdminVserver" Timeout="43200" Enabled="true" Remotable="true">
<Category>Maintenance</Category>
<WriteAction ID="WA" TypeID="Windows!Microsoft.Windows.PowerShellWriteAction" RunAs="DS!DataONTAP.SecureReference.RunAsProfile">
<ScriptName>StorageEfficiency.ps1</ScriptName>
<ScriptBody><Script>##############################################################################
# Copyright (c) 2013 NetApp.
#
# StorageEfficiency.ps1
#
# This script to collect storage efficiency statistics.
#
##############################################################################
Param($VserverUUID)

##############################################################################
#Script utilities
function GetInstallPath
{
$netappRegPath = "HKLM:\SOFTWARE\NetApp\OnCommand\MS_Plugin"
$ibmRegPath = "HKLM:\SOFTWARE\IBM\OnCommand\MS_Plugin"

if (Test-Path -path $netappRegPath)
{
# Check for the registry key value of the install location for NetApp
$key = get-itemproperty $netappRegPath
}
elseif (Test-Path -path $ibmRegPath)
{
# Check for IBM registry key since can't find NetApp
$key= get-itemproperty $ibmRegPath
}
else
{
throw ("OnCommand Plug-in for Microsoft is not installed on " + $env:COMPUTERNAME + "`r`n")
}

return $key.InstallPath
}

function CreateAppDomain
{
$setup = [AppDomain]::CurrentDomain.SetupInformation;
$setup.ShadowCopyFiles = $true
return [AppDomain]::CreateDomain("OC.Cluster.OM.Powershell.NonDefaultAppDomain",
$null,
$setup);
}

function InvokeMethodInAppDomain([AppDomain]$appDomain,
[string]$assemblyPath,
[string]$typename,
[array]$contructorParameters,
[string]$methodName,
[array]$methodParameters)
{
#In SCOM a Powershell script is executed in a MonitoringHost.exe process.
#Lifetime of a MonitoringHost.exe is not controlled by us and it continues to run after the script is done, possibly
#running other scripts or the same script again. A script is executed in a default AppDomain (by SCOM design) and
#as a result any assemblies loaded by script can not be unloaded because the defualt AppDomain can not be unloaded.
#Impossibility of unloading an assembly becomes a problem when then the assembly DLL is being updated
#(i.e. during an istallation), the problem is that even after the assembly DLL is updated,
#the new assembly code is not loaded if the assembly is already loaded.
#The solution for this problem is to load an assembly to a non-default domain which can be unloaded when the script is done.

#The OC.Cluster.OM.AppDomainInvoker assembly has to be in the GAC
$AppDomainInvokerAssembly = [System.Reflection.Assembly]::LoadWithPartialName('OC.Cluster.OM.AppDomainInvoker')

$result = [OC.Cluster.OM.AppDomainInvoker.AppDomainInvoker]::InvokeMethod($appDomain,
$assemblyPath,
$typename,
$contructorParameters,
$methodName,
$methodParameters)

return $result
}
##############################################################################

import-module operationsmanager

$Error.Clear();

$scriptName = "StorageEfficiency.ps1"

try
{

$api = new-object -comObject 'MOM.ScriptAPI'

$api.LogScriptEvent($scriptName, 4000, 0, "Getting storage efficiency for Clustered Data ONTAP storage.")

$nonDefaultAppDomain = CreateAppDomain

$installPath = GetInstallPath

$taskOutput = InvokeMethodInAppDomain $nonDefaultAppDomain `
(Join-Path $installPath 'OC.Cluster.OM.Server.dll') `
"OC.Cluster.OM.Server.Monitoring.StorageEfficiency" `
@("localhost") `
"GetStorageEfficiency" `
@($VserverUUID)

#Write task output to the script output
$taskOutput

$api.LogScriptEvent($scriptName, 4001, 0, "Getting storage efficiency for Clustered Data ONTAP storage succeeded.`r`n" + $taskOutput)
}
catch
{
if ($api)
{
$api.LogScriptEvent($scriptName, 4002, 1, "Getting storage efficiency for Clustered Data ONTAP storage failed.`r`n" + $Error)
}

#throw the current error so that it will be displayed in the SCOM task output and status of the task will be set as failed
throw
}
finally
{
if ($nonDefaultAppDomain)
{
[AppDomain]::Unload($nonDefaultAppDomain)
$nonDefaultAppDomain = $null
}
}</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>VserverUUID</Name>
<Value>$Target/Property[Type="DataONTAP.Cluster.AbstractVserver"]/UUID$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>1800</TimeoutSeconds>
</WriteAction>
</Task>