13 Replies Latest reply on Sep 19, 2017 5:43 PM by dcornell

    Disabling Hardware Health Sensors

    zackm

      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!

        • Re: Disabling Hardware Health Sensors
          tdanner

          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 )
          
          1 of 1 people found this helpful
            • Re: Disabling Hardware Health Sensors
              zackm

              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

                • Re: Disabling Hardware Health Sensors
                  tdanner

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

                    • Re: Disabling Hardware Health Sensors
                      zackm

                      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

                        • Re: Disabling Hardware Health Sensors
                          pstranak

                          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

                          1 of 1 people found this helpful
                  • Re: Disabling Hardware Health Sensors
                    dcornell

                    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("{http://schemas.solarwinds.com/2007/08/HardwareHealth}HardwareInfoID",$hardwareItem.HardwareInfoID)
                            $e2 = New-Object System.Xml.Linq.XElement("{http://schemas.solarwinds.com/2007/08/HardwareHealth}HardwareCategoryStatusID",$hardwareItem.HardwareCategoryStatusID)
                            $e3 = New-Object System.Xml.Linq.XElement("{http://schemas.solarwinds.com/2007/08/HardwareHealth}UniqueName",$hardwareItem.UniqueName)
                            [void]$hardwareHealthItemKeyElem.Add($e1)
                            [void]$hardwareHealthItemKeyElem.Add($e2)
                            [void]$hardwareHealthItemKeyElem.Add($e3)
                            $itemKeys = New-Object System.Xml.Linq.XElement("{http://schemas.solarwinds.com/2007/08/HardwareHealth}HardwareHealthItemKey", $hardwareHealthItemKeyElem)
                            [void]$hardwareHealthItemKeyElemArray.Add($itemKeys)
                        }
                      
                        $root = New-Object System.Xml.Linq.XElement("{http://schemas.solarwinds.com/2007/08/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."
                            }
                        }   
                    }

                     

                      • Re: Disabling Hardware Health Sensors
                        pstranak

                        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