S2D: Datakälla för identifiering av volym

Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Discovery.DataSource.Volume (DataSourceModuleType)

Datakälla för identifiering av volym.

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsDefault
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
Scheduler DataSource System.Discovery.Scheduler Default
Script ProbeAction Microsoft.Windows.PowerShellDiscoveryProbe Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Intervall (sek)
SyncTimestring$Config/SyncTime$Synkroniseringstid
TimeoutSecondsint$Config/TimeoutSeconds$Tidsgräns (sek)
DebugModebool$Config/DebugMode$Aktivera utdata från felsökningAktivera utdata från felsökning

Source Code:

<DataSourceModuleType ID="Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Discovery.DataSource.Volume" Accessibility="Internal">
<Configuration>
<IncludeSchemaTypes>
<SchemaType>Windows!Microsoft.Windows.PowerShellSchema</SchemaType>
<SchemaType>System!System.ExpressionEvaluatorSchema</SchemaType>
</IncludeSchemaTypes>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" maxOccurs="1" name="TimeoutSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SyncTime" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="DebugMode" type="xsd:boolean"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
<OverrideableParameter ID="DebugMode" Selector="$Config/DebugMode$" ParameterType="bool"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="Scheduler" TypeID="System!System.Discovery.Scheduler">
<Scheduler>
<SimpleReccuringSchedule>
<Interval>$Config/IntervalSeconds$</Interval>
<SyncTime>$Config/SyncTime$</SyncTime>
</SimpleReccuringSchedule>
<ExcludeDates/>
</Scheduler>
</DataSource>
<ProbeAction ID="Script" TypeID="Windows!Microsoft.Windows.PowerShellDiscoveryProbe">
<ScriptName>VolumeDiscoveryDatasourceScript.ps1</ScriptName>
<ScriptBody><Script>

param($serverPrincipalName, $SourceId, $ManagedEntityId,$DebugMode)



#general variables
#-----------------
$errorActionPreference = 'Stop'

$errEvent = [System.Diagnostics.EventLogEntryType]::Error;
$infoEvent = [System.Diagnostics.EventLogEntryType]::Information;
$GenericInformationEvent = 8671;
$GenericFailureEvent = 8672;
$DiscoveryGenericInformationEvent = 8861;
$DiscoveryGenericFailureEvent = 8862;
$script:traceMsg = "";
$ObjectNotFoundCode = -2146233087
$msft_namespace = "root\microsoft\windows\storage"
$cluster_namespace = "root\mscluster"

# Guid length for Virtual Disk
$guidLength = 38
$PadLength = 1 #Object Id ended with double quote


if ($false -eq [string]::IsNullOrEmpty($DebugMode))
{
$DebugMode = [string]::Equals("true",$DebugMode,[System.StringComparison]::OrdinalIgnoreCase)
}
else
{
$DebugMode = $false
}

$momAPI = New-Object -comObject 'MOM.ScriptAPI'

#Common Functions
Function Get-Guid([string]$sguid)
{
if ([string]::IsNullOrEmpty($sguid))
{
return $null
}

$guid = [guid]::NewGuid()
if ($false -eq [guid]::TryParse($sguid,[ref] $guid))
{
return $null;
}

return $guid
}

Function GetDiskIdFilterFromVdObjectId([string]$ObjectId)
{
if ($true -eq [string]::IsNullOrEmpty($ObjectId))
{
return $null
}

$Length = $ObjectId.Length
#check guid length - 38 in {guid} format
$rGuidLength = $guidLength + $PadLength
if ($Length -lt $rGuidLength) {return $null;}

$sguid = $ObjectId.Substring($Length - $rGuidLength,$guidLength)

$guid = Get-Guid -sguid $sguid

if ($null -eq $guid) {return $null;}

return "DiskId='\\\\?\\Disk{$guid}'"
}

Function GetVolumesFromVd($vd)
{
$errorActionPreference = "Stop"

$Filter = GetDiskIdFilterFromVdObjectId -ObjectId $vd.ObjectId
if ($null -eq $Filter ) {return $null;}

$partitions = Get-CimInstance -ClassName "MSFT_Partition" -Namespace $msft_namespace -Filter $Filter | Where-Object {$_.AccessPaths -ne $null}
$volumes = @{}

foreach ($partition in $partitions)
{
$Volume = Get-CimAssociatedInstance -Association "MSFT_PartitionToVolume" -InputObject $partition -Namespace $msft_namespace
if ($null -ne $Volume -and "CSVFS" -eq $Volume.FileSystem )
{
$volumes[$Volume] = 1;
}
}

return $volumes
}

Function AddTraceMessage
{
param($message)

$errorActionPreference = 'SilentlyContinue'
$timeStamp = (get-date -format "HH:mm:ss:fff");
$script:traceMsg = $script:traceMsg + "`n[" + $timeStamp + "] " + $message;
}

Function Log-FinalDebugData([int]$FailureEvent,[int]$InformationEvent,$exception,[string]$SCRIPT_NAME,[string]$traceMsg,[bool]$DebugMode = $false,$message = [string]::Empty)
{
$ErrorActionPreference = "SilentlyContinue"

if ($null -ne $exception)
{
if ([string]::Empty -eq $message) {$message = "Error occured during script execution:"}
$momAPI.LogScriptEvent($SCRIPT_NAME, $FailureEvent, 1, "$message $($exception.Message)");
}

if ($script:traceMsg -ne $null -and $true -eq $DebugMode)
{
$momAPI.LogScriptEvent($SCRIPT_NAME,$InformationEvent, 0, $traceMsg);
}
}

Function Check-CimError($Exception)
{
$errorActionPreference = 'SilentlyContinue'
$result = $false

if ($null -eq $Exception)
{
return $result
}

$error.Clear()
$type = $Exception.GetType()

if (0 -ne $error.Count)
{
$error.Clear()
return $result
}

if ("Microsoft.PowerShell.Cmdletization.Cim.CimJobException" -eq $type.FullName -and $ObjectNotFoundCode -eq $Exception.HResult)
{
$result = $true
}

return $result
}

Function Get-FaultException($exception,$IsObjectExist)
{
if ($false -eq $IsObjectExist)
{
$IsError = Check-CimError -Exception $exception
if ($true -eq $IsError)
{
$exception = $null
}

}

return $exception

}

Function Load-Module ([string] $ModuleName)
{
if ([string]::IsNullOrEmpty($ModuleName) )
{
return $false
}

$ErrorActionPreference="SilentlyContinue"
$error.Clear()

$retval = $false
$Tmodule = Get-Module -Name $ModuleName

########Check for powershell 1.0
if ($error.Count -ne 0)
{
$Exception = $error[0].Exception

if ($null -ne $Exception)
{
$type = $Exception.GetType()
if ([System.Management.Automation.CommandNotFoundException] -eq $type)
{
$error.Clear()
return $retval
}
}

$error.Clear()
}

if ($null -eq $Tmodule)
{
$Tmodule = Get-Module -Name $ModuleName -ListAvailable
if ($error.Count -ne 0){ return $retval;}
if ($null -eq $Tmodule) {return $retval;}

Import-Module $ModuleName
if ($error.Count -eq 0){ $retval = $true;}

}
else
{
$retval = $true
}

return $retval

}

AddTraceMessage -message "Start on Node: $env:COMPUTERNAME"
$IsStorageModuleReady = Load-Module -ModuleName "Storage"

if ($false -eq $IsStorageModuleReady)
{
if ($error.Count -ne 0)
{
$message = "Cannot initializa Storage module. Error: " + $error[0].ToString()

}
else
{
$message = "Cannot load Storage module."
}

AddTraceMessage -message $message

}

#Load cimcmdlets
$IsCimReady = Load-Module -ModuleName "CimCmdLets"







$scriptName = "VolumeDiscoveryDatasourceScript.ps1"

Function Main
{
$IsReady = $true
if ($false -eq $IsStorageModuleReady)
{
$IsReady = $false
$momAPI.LogScriptEvent($scriptName, $DiscoveryGenericFailureEvent, 1, $script:traceMsg);
}

$oDiscoveryData = $momAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId);

if ($false -eq $IsReady)
{
$oDiscoveryData.IsSnapshot = $false
}
else
{
if ((DoDiscovery $serverPrincipalName $oDiscoveryData) -ne 0)
{
$oDiscoveryData = $momAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
$oDiscoveryData.IsSnapshot = $false
}
}

$oDiscoveryData
}

Function Get-Resiliency
{
param ($InputVolume)

try
{
$Partition = $InputVolume | Get-Partition
$Disk = $Partition | Get-Disk
$VirtualDisk = $Disk | Get-VirtualDisk

$Tiers = $VirtualDisk | Get-StorageTier

[hashtable]$returnValues = @{}



If ($Tiers.Length -Eq 0) {
$ReadFrom = $VirtualDisk # No Tiers
}
Else {
$ReadFrom = $Tiers[0] # First/Only Tier
}
$Interleave = $ReadFrom.Interleave / 1KB
$Resiliency = "$($ReadFrom.ResiliencySettingName) , Columns : $($ReadFrom.NumberOfColumns.ToString()) , Interleave : $($Interleave) KB"
$returnValues.Add("Resiliency",$Resiliency)

try
{
$IsDeduplicationReady = Load-Module -ModuleName "Deduplication"
if ($false -eq $IsDeduplicationReady)
{
if ($error.Count -ne 0)
{
$message = "Cannot initializa Storage module. Error: " + $error[0].ToString()
}
else
{
$message = "Cannot load Storage module."
}
AddTraceMessage -message $message
$returnValues.Add("Deduplication","Disabled")
}
else
{
$DedupVolume = Get-DedupVolume -VolumeId $InputVolume.UniqueId -ErrorAction SilentlyContinue;

if($DedupVolume -ne $null)
{
if($DedupVolume.Enabled)
{
$returnValues.Add("Deduplication","Enabled")
}
else
{
$returnValues.Add("Deduplication","Disabled")
}
}
else
{
$returnValues.Add("Deduplication","Disabled")
}
}
}
Catch
{
$returnValues.Add("Deduplication","Disabled")
}


}
Catch
{
#$errorCount = 1
AddTraceMessage -message $_.Exception.Message
$Resiliency = ""
#Check if virtual disk doesn't exist in case of lag in discovery
#$exception = Get-FaultException -exception $_.Exception -IsObjectExist $IsVirtualDiskFound

}
Finally
{
AddTraceMessage -message "ErrorCount: $errorCount"
Log-FinalDebugData -FailureEvent $DiscoveryGenericFailureEvent -InformationEvent $DiscoveryGenericInformationEvent -exception $exception -SCRIPT_NAME $scriptName -traceMsg $script:traceMsg -DebugMode $DebugMode
}

return $returnValues
}
Function DiscoveryVolume
{
param ([string] $argVDUniqueId, $argPrincipalName, $oDisc,$Volume,$storageSubSystem)

$errorActionPreference = "Stop"

if($null -eq $Volume)
{
AddTraceMessage -message "Volume Object is empty."
return
}
[hashtable]$return = @{}
$return = Get-Resiliency $Volume
$ResiliencyValue = $return["Resiliency"]
$DeduplicationValue = $return["Deduplication"]

$VolumeSize = "$($Volume.Size / 1GB) GB"
AddTraceMessage -message "Adding Volume: "
AddTraceMessage -message "Volume UniqueId: $($curVolume.UniqueID)"
AddTraceMessage -message "Volume ObjectId: $($curVolume.ObjectId)"
AddTraceMessage -message " Volume Label: $diskpart.VolumeLabel"

$Label = $Volume.FileSystemLabel

$volumeInstance = $oDisc.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Volume']$");
$volumeInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $argPrincipalName)
$volumeInstance.AddProperty("$MPElement[Name='MicrosoftStorageLibrary!Microsoft.Storage.Library.Windows.Disk']/UniqueID$", $argVDUniqueId)
$volumeInstance.AddProperty("$MPElement[Name='MicrosoftStorageLibrary!Microsoft.Storage.Library.Windows.Volume']/UniqueID$", $Volume.UniqueID)
$volumeInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Volume']/ObjectId$", $Volume.ObjectId)
$volumeInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Volume']/FileSystem$", $Volume.FileSystem)
$volumeInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Volume']/Size$",$VolumeSize)
$volumeInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Volume']/Resiliency$", $ResiliencyValue)
$volumeInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Volume']/Deduplication$", $DeduplicationValue)
$volumeInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Volume']/ClusterName$", $storageSubSystem.Name)
$volumeInstance.AddProperty("$MPElement[Name='MicrosoftStorageLibrary!Microsoft.Storage.Library.Windows.Volume']/VolumeLabel$", $Label)
$volumeInstance.AddProperty("$MPElement[Name='MicrosoftStorageLibrary!Microsoft.Storage.Library.Windows.Volume']/Name$", $Label)
$volumeInstance.AddProperty("$MPElement[Name='MicrosoftStorageLibrary!Microsoft.Storage.Library.Windows.Volume']/IsClustered$", $true)
$volumeInstance.AddProperty("$MPElement[Name='MicrosoftStorageLibrary!Microsoft.Storage.Library.Windows.Volume']/IsClusterSharedVolume$", $true)
$volumeInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $Label)

$oDisc.AddInstance($volumeInstance)

#Create instance for the containment relationship
$substorInstance = $oDisc.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.StorageSubSystem']$");
$substorInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $argPrincipalName);
$substorInstance.AddProperty("$MPElement[Name='MicrosoftStorageLibrary!Microsoft.Storage.Library.StorageArray']/UniqueID$", $storageSubSystem.UniqueID);

$oRelationshipInstance = $oDisc.CreateRelationshipInstance("$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.StorageSubSystemContatainsVolume']$")
$oRelationshipInstance.Source = $substorInstance;
$oRelationshipInstance.Target = $volumeInstance;
$oDisc.AddInstance($oRelationshipInstance)

}

Function DoDiscovery
{
param ($argPrincipalName, $oDisc)
$error.Clear()
$errorCount = 0
$IsVirtualDiskFound = $false
$errorActionPreference = "Stop"
try
{

AddTraceMessage -message "Script started"

$oVirtualDisks = (Get-VirtualDisk | Where-Object FriendlyName -ne "ClusterPerformanceHistory").UniqueId
foreach($argVDUniqueId in $oVirtualDisks)
{
$virtualDisk = Get-VirtualDisk -UniqueID $argVDUniqueId
AddTraceMessage -message "VD UniqueID = $argVDUniqueId"

$IsVirtualDiskFound = $true

if ($null -eq $virtualDisk)
{
AddTraceMessage -message "Can't find Storage VirtualDisk with the provided UniqueID: $argvdUniqueID"
Log-FinalDebugData -FailureEvent $DiscoveryGenericFailureEvent -InformationEvent $DiscoveryGenericInformationEvent -exception $exception -SCRIPT_NAME $scriptName -traceMsg $script:traceMsg -DebugMode $DebugMode
return $errorCount
}

AddTraceMessage -message "Storage VirtualDisk with the provided UniqueID: $vdUniqueID was found successfully."
AddTraceMessage -message "VD Status : $($virtualDisk.OperationalStatus)"

if ("OK" -ne $virtualDisk.OperationalStatus)
{
$errorCount = 1
AddTraceMessage -message "Virtual Disk is unhealthy. Exiting without updated discovery data."

}

$storageSubSystem = Get-CimAssociatedInstance -InputObject $virtualDisk -Association MSFT_StorageSubSystemToVirtualDisk -Namespace $msft_namespace

if ($null -eq $storageSubSystem)
{
#Can't find related substorage (But virtual disk was found!)
$errorCount = 1
AddTraceMessage -message "Can't find the related storage subsystem. Exiting without updated discovery data."
Log-FinalDebugData -FailureEvent $DiscoveryGenericFailureEvent -InformationEvent $DiscoveryGenericInformationEvent -exception $exception -SCRIPT_NAME $scriptName -traceMsg $script:traceMsg -DebugMode $DebugMode
return $errorCount
}

AddTraceMessage -message "Related Storage Subsystem was found successfully"

$volumes = GetVolumesFromVd -vd $virtualDisk
if ($null -eq $volumes)
{
$errorCount = 1
AddTraceMessage -message "Can't find volumes for virtual disk."
}
else
{
foreach ($volume in $volumes.Keys)
{
DiscoveryVolume -argVDUniqueId $argVDUniqueId -argPrincipalName $argPrincipalName -oDisc $oDisc -Volume $volume -storageSubSystem $storageSubSystem
}
}

}
}
Catch
{
$errorCount = 1
AddTraceMessage -message $_.Exception.Message
#Check if virtual disk doesn't exist in case of lag in discovery
$exception = Get-FaultException -exception $_.Exception -IsObjectExist $IsVirtualDiskFound
if ($null -eq $exception) {$errorCount = 0}
}
Finally
{

AddTraceMessage -message "ErrorCount: $errorCount"
Log-FinalDebugData -FailureEvent $DiscoveryGenericFailureEvent -InformationEvent $DiscoveryGenericInformationEvent -exception $exception -SCRIPT_NAME $scriptName -traceMsg $script:traceMsg -DebugMode $DebugMode
}

return $errorCount
}

Main</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>serverPrincipalName</Name>
<Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
</Parameter>
<Parameter>
<Name>SourceId</Name>
<Value>$MPElement$</Value>
</Parameter>
<Parameter>
<Name>ManagedEntityId</Name>
<Value>$Target/Id$</Value>
</Parameter>
<Parameter>
<Name>DebugMode</Name>
<Value>$Config/DebugMode$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<StrictErrorHandling>true</StrictErrorHandling>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="Script">
<Node ID="Scheduler"/>
</Node>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>