This discussion has been locked. The information referenced herein may be inaccurate due to age, software updates, or external references.
You can no longer post new replies to this discussion. If you have a similar question you can start a new discussion in this forum.

Disabling Hardware Health Sensors

tdanner​ et. al;

Can anyone identify what the "DisableSensors" verb is looking for in Orion.HardwareHealth.HardwareItem ?

Trying the ID is coming back with an error in PowerShell:

Script:

# Clear PowerShell and add the SwisSnapin

Clear-Host

if (-not (Get-PSSnapin | Where-Object { $_.Name -eq 'SwisSnapin' })) {

    Add-PSSnapin 'SwisSnapin'

}

# Connect to SWIS using AD pass-through

$hostname = 'SolarWindsPoller'

$swis = Connect-Swis -Hostname $hostname -Trusted

# Query SWIS to get an array of Sensor IDs to disable

$query = "SELECT ID, FullyQualifiedName FROM Orion.HardwareHealth.HardwareItem WHERE Name LIKE 'System Memory'"

$results = Get-SwisData $swis $query

#  Loop through the array to disable the sensors

Foreach($sensor in $results){

    Invoke-SwisVerb $swis Orion.HardwareHealth.HardwareItem DisableSensors $($sensor[0].ID)

    Write-Host "Disabling Hardware Sensor On: $($sensor[0].FullyQualifiedName)"

}

This is an example of what is being passed (adding a Write-Host to the front of the Invoke)

Invoke-SwisVerb SolarWinds.InformationService.Contract2.InfoServiceProxy Orion.HardwareHealth.HardwareItem DisableSensors 136

Disabling Hardware Sensor On: System Memory on hostname.domain.local

And this is the error:

Invoke-SwisVerb : Verb Orion.HardwareHealth.HardwareItem.DisableSensors cannot unpackage parameter 0 of type System.Collections.Generic.IEnumerable`1[SolarWinds.HardwareHealth.Common.Models.HardwareHealth.HardwareHealthItemKey]

At line:36 char:2

+     Invoke-SwisVerb $swis Orion.HardwareHealth.HardwareItem DisableSe ...

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [Invoke-SwisVerb], FaultException`1

    + FullyQualifiedErrorId : SwisError,SwisPowerShell.InvokeSwisVerb

Any and all help is appreciated!

  • Getting the HardwareHealthItemKey in the right format is undocumented and tricky. This will do it:

    $swis = connect-swis  # connection details here

    # you need these three properties from the sensors to disable

    $sensor = Get-SwisData $swis "SELECT TOP 1 HardwareCategoryStatusID, HardwareInfoID, UniqueName FROM Orion.HardwareHealth.HardwareItem WHERE IsDisabled=0"

    function HardwareHealthItemKeyXml([int]$HardwareInfoID, [int]$HardwareCategoryStatusID, [string]$UniqueName) {

        return @"

        <HardwareHealthItemKey xmlns='http://schemas.solarwinds.com/2007/08/HardwareHealth'>

            <HardwareInfoID>$HardwareInfoID</HardwareInfoID>

            <HardwareCategoryStatusID>$HardwareCategoryStatusID</HardwareCategoryStatusID>

            <UniqueName>$UniqueName</UniqueName>

        </HardwareHealthItemKey>

    "@

    }

    $itemKeyXml = HardwareHealthItemKeyXml $sensor.HardwareInfoID $sensor.HardwareCategoryStatusID $sensor.UniqueName

    $itemKeys = ([xml]"<array>$itemKeyXml</array>").DocumentElement

    Invoke-SwisVerb $swis Orion.HardwareHealth.HardwareItem DisableSensors @( $itemKeys )

  • That's closer, but it's still not executing the actual disabling...

    So, here's the script:

    $swis = Connect-Swis -Hostname $hostname -Trusted

    # you need these three properties from the sensors to disable

    $sensor = Get-SwisData $swis "SELECT i.HardwareCategoryStatusID, i.HardwareInfo.ID AS [HardwareInfoID], i.UniqueName FROM Orion.HardwareHealth.HardwareItem i WHERE i.ID = 136"

    function HardwareHealthItemKeyXml([int]$HardwareInfoID, [int]$HardwareCategoryStatusID, [string]$UniqueName) {

        return @"

        <HardwareHealthItemKey xmlns='http://schemas.solarwinds.com/2007/08/HardwareHealth'>

            <HardwareInfoID>$HardwareInfoID</HardwareInfoID>

            <HardwareCategoryStatusID>$HardwareCategoryStatusID</HardwareCategoryStatusID>

            <UniqueName>$UniqueName</UniqueName>

        </HardwareHealthItemKey>

    "@

    }

    $itemKeyXml = HardwareHealthItemKeyXml $sensor.HardwareInfoID $sensor.HardwareCategoryStatusID $sensor.UniqueName

    $itemKeys = ([xml]"<array>$itemKeyXml</array>").DocumentElement

    Invoke-SwisVerb $swis Orion.HardwareHealth.HardwareItem DisableSensors @( $itemKeys )

    Note that I changed the query a bit to call the actual HardwareInfoID from the linked table. I also tried this using the ID field in the HardwareItem table, but got the same results...

    Here's the output for $itemKeyXml and $itemKeys

    <HardwareHealthItemKey xmlns='http://schemas.solarwinds.com/2007/08/HardwareHealth'> 

      <HardwareInfoID>12</HardwareInfoID> 

      <HardwareCategoryStatusID>23</HardwareCategoryStatusID> 

      <UniqueName>2000.0</UniqueName> 

    </HardwareHealthItemKey> 

    HardwareHealthItemKey

    ---------------------

    HardwareHealthItemKey

    And here's the output after running the script:

    nil  xmlns                                                                          d1p1                                          i                                      

    ---  -----                                                                          ----                                          -                                      

    true http://schemas.datacontract.org/2004/07/SolarWinds.InformationService.Contract http://schemas.datacontract.org/2004/07/System http://www.w3.org/2001/XMLSchema-instance

    And here's the result:

    2017-03-23_17-25-32.png

  • I'll need to get the product team involved to figure this out then. What product version(s) are you running?

  • This is the footer from the lab I'm testing in:

    Orion Platform 2016.2.100,

    VNQM 4.2.4,

    SRM 6.3.0,

    IPAM 4.3.2,

    SAM 6.3.0,

    DPA 10.2.0,

    NCM 7.5.1,

    VIM 7.0.0,

    QoE 2.2.0,

    Toolset 11.0.2,

    NetPath 1.0.1,

    NPM 12.0.1,

    NTA 4.2.1,

    UDT 3.2.4,

    WPM 2.2.1

  • Hi,

    in that case you need to use "NodeId" instead of "HardwareInfoID" when you create "HardwareHealthItemKey". "HardwareInfoID" is used in newer versions of HardwareHealth.

    So, your script should look like this:

    $swis = Connect-Swis -Hostname $hostname -Trusted 

    # you need these three properties from the sensors to disable  

    $sensor = Get-SwisData $swis "SELECT i.HardwareCategoryStatusID, i.NodeID, i.UniqueName FROM Orion.HardwareHealth.HardwareItem i WHERE i.ID = 136"  

    function HardwareHealthItemKeyXml([int]$NodeId, [int]$HardwareCategoryStatusID, [string]$UniqueName) {  

        return @"  

        <HardwareHealthItemKey xmlns='http://schemas.solarwinds.com/2007/08/HardwareHealth'>  

            <NodeId>$NodeId</NodeId>  

            <HardwareCategoryStatusID>$HardwareCategoryStatusID</HardwareCategoryStatusID>  

            <UniqueName>$UniqueName</UniqueName>  

        </HardwareHealthItemKey>  

    "@  

    }

    $itemKeyXml = HardwareHealthItemKeyXml $sensor.NodeID $sensor.HardwareCategoryStatusID $sensor.UniqueName  

    $itemKeys = ([xml]"<array>$itemKeyXml</array>").DocumentElement

    Invoke-SwisVerb $swis Orion.HardwareHealth.HardwareItem DisableSensors @( $itemKeys )

    Peter

  • That works perfectly!

    Is it safe to assume that the HardwareInfoID is for Platform 2017.x and later then?

  • I love the idea of using a function to return formatted XML. Totally stealing that method! emoticons_happy.png

  • That is correct.

    Starting with 2017.x, HardwareHealth is no longer bound to just nodes. We can also use it with Orion Storage Resource Monitor entities. Hence the change from "NodeId" to something more universal.

  • I have 10's of thousand of hardware items that I need to disable. We use Arista and I love them, but the SPF's we are using don't provide some of the sensor values the Arista SPF's do and they show as critical events. This makes all of our Arista devices look like they are in a critical state. As anyone else would do, I started using the SDK and the Orion.HardwareHealth.HardwareItem DisableSensor method to disable the non-functioning sensors (which requires an XML body as part of the post unlike most of the other methods).

    I found this post and tried using it, but I had issues using the here-text and I could not get it to work. I decided to use the XDocument class.

    Now that it is working, the hardware items I have disabled (IsDisabled = True) are somehow getting enabled? What??

    All the posts seem successful, but only about 2/3 of the hardware items on a device get changed to IsDisabled = True. So I run the script again and more are disabled, but not all of them.

    I though that maybe I was hitting the API too hard, so I added a sleep which didn't solve anything. Next I thought I would do batches, and then I noticed that the number of hardware items that where marked IsDisabled = true was declining over time - how are they getting set to false ?

    I need help with this issue; any ideas? I am on the latest GA of NPM, NCM, SAM

    Here is my code if anyone is interested:

    [CmdLetBinding()]
    param
    (
        [Parameter(Mandatory = $true, Position = 0)]
        [string[]]$OrionApiServers,
        [Parameter(Mandatory = $false, Position = 1)]
        [System.Management.Automation.PSCredential]$Credentials,
        [Parameter(Mandatory = $false, Position = 2)]
        [Switch]$DebugEnabled = $true
    )
    # Need a class to use to build Hardware Health Item.
    $HardwareHealthItemKeyClass = @"
        public class HardwareHealthItemKey
        {
            public int HardwareInfoID { get; set; }
            public int HardwareCategoryStatusID { get; set; }
            public string UniqueName { get; set; }
        }
    "@
    Add-Type -Language CSharp -TypeDefinition $HardwareHealthItemKeyClass
    # Imports a module if it is not loaded already.
    function Import-CustomModule
    {
        [CmdletBinding()]
    param
    (
            [Parameter(Mandatory = $true, Position = 0)]
      [string]$ModuleName,
           
            [Parameter(Mandatory = $true, Position = 1)]
      [string]$ModulePath       
    )
       
        if(!(Test-Path -Path $ModulePath))
        {
            Throw ("Module path does not exist: {0}" -f $ModulePath)
        }
        $ModuleInfo = Get-Module -Name $ModuleName
        if(!$ModuleInfo)
        {
            Import-Module $ModulePath
        }
    }
    # Creates an XML document for an array of Hardware Health Items
    function New-ArrayOfHardwareHealthItemKey
    {
        [CmdletBinding()]
        param
        (
            [System.Collections.Generic.IEnumerable[HardwareHealthItemKey]] $HardwareItems
        )
        [Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq")
       
        $hardwareHealthItemKeyElemArray = New-Object 'System.Collections.generic.list[System.Xml.Linq.XElement]'
        foreach($hardwareItem in $hardwareItems)
        { 
            $hardwareHealthItemKeyElem = New-Object 'System.Collections.generic.list[System.Xml.Linq.XElement]'
            $e1 = New-Object System.Xml.Linq.XElement("{">schemas.solarwinds.com/.../HardwareHealth}HardwareInfoID",$hardwareItem.HardwareInfoID)
            $e2 = New-Object System.Xml.Linq.XElement("{">schemas.solarwinds.com/.../HardwareHealth}HardwareCategoryStatusID",$hardwareItem.HardwareCategoryStatusID)
            $e3 = New-Object System.Xml.Linq.XElement("{">schemas.solarwinds.com/.../HardwareHealth}UniqueName",$hardwareItem.UniqueName)
            [void]$hardwareHealthItemKeyElem.Add($e1)
            [void]$hardwareHealthItemKeyElem.Add($e2)
            [void]$hardwareHealthItemKeyElem.Add($e3)
            $itemKeys = New-Object System.Xml.Linq.XElement("{">schemas.solarwinds.com/.../HardwareHealth}HardwareHealthItemKey", $hardwareHealthItemKeyElem)
            [void]$hardwareHealthItemKeyElemArray.Add($itemKeys)
        }
     
        $root = New-Object System.Xml.Linq.XElement("{">schemas.solarwinds.com/.../HardwareHealth}ArrayOfHardwareHealthItemKey", $hardwareHealthItemKeyElemArray)
        $declaration = New-Object System.Xml.Linq.XDeclaration("1.0","utf-8",$null)
        $doc = New-Object System.Xml.Linq.XDocument($declaration)
        $doc = New-Object System.Xml.Linq.XDocument($root)   
        $doc.Root.Name = $ns + $doc.Root.Name.LocalName
        return $doc
    }
    if($DebugEnabled){
    $DebugPreference = "Continue"
    write-Debug "Debugging enabled"
    }
    Import-CustomModule -ModuleName "SwisPowerShell" -ModulePath "C:\Program Files (x86)\SolarWinds\Orion SDK\SWQL Studio\SwisPowerShell.dll"
    [string]$aristaQuery = "SELECT N.Caption, N.Nodeid from Orion.Nodes N where N.Vendor LIKE 'Arista%'"
    [int]$count = 0
    foreach($orionApiServer in $OrionApiServers)
    {
        $swis = Connect-Swis -Credential $credential -Hostname $OrionApiServer
       
        $aristaNodes = Get-SwisData -SwisConnection $swis -Query $aristaQuery
       
        foreach($node in $aristaNodes)
        {  
            Write-Host("{0} - {1}" -f $orionApiServer, $node.Caption)
            # Get all the Interface DOM RX/TX sensors.
            $sensorQuery = (@"
            SELECT HI.HardwareInfoID,HI.HardwareCategoryStatusID, HI.IsDisabled,HI.UniqueName,HI.DisplayName
            FROM Orion.HardwareHealth.HardwareItem HI
            WHERE HI.NodeID = {0} AND HI.IsDisabled = false AND (HI.DisplayName LIKE 'DOM TX%' OR HI.DisplayName LIKE 'DOM RX%')
    "@) -f $node.nodeid

            $sensors = Get-SwisData -SwisConnection $swis -Query $sensorQuery

            $list = New-Object System.Collections.Generic.List[HardwareHealthItemKey]

            foreach($sensor in $sensors)
            {
                if($sensor.IsDisabled -eq $false)
                {
                    $item = New-Object HardwareHealthItemKey
                    $item.HardwareCategoryStatusID = $sensor.HardwareCategoryStatusID
                    $item.HardwareInfoID = $sensor.HardwareInfoID
                    $item.UniqueName = $sensor.UniqueName  

                    $list.Add($item)

                    Write-Debug("{0}:{1}" -f $node.Caption, $sensor.DisplayName)
                    $count++         
                } 
            }

            if($list.Count -gt 0)
            {     
                $xml = New-ArrayOfHardwareHealthItemKey $list   

                $result = Invoke-SwisVerb -SwisConnection $swis -EntityName Orion.HardwareHealth.HardwareItem DisableSensors $xml.Root
            }
            else
            {
                Write-Host "No Items found that need to be updated."
            }
        }  
    }

  • Hi,

    I'm not sure why you see such behavior. Especially the part about automatically re-enabled sensors. That should not happen. If you really see such behavior (a sensor, that was manually disabled gets re-enabled again), I'd suggest opening a support ticket. That way it would be easier to troubleshoot the problem and share data like diagnostics.

    Anyway, what versions of NPM and SAM do you have? We are currently releasing new ones, so "the latest" is not exactly precise right now. Also, do you see any error occurring in "c:\ProgramData\Solarwinds\InformationService\v3.0\Orion.InformationService.log" at the time you run the script?

    Peter