Adding a volume via swis powershell

Hoping I can get some insight on an issue I am running in to. I am using powershell and the swis module to automate several tasks in regards to creating a new node. Everything seems to work properly for me, however despite me adding a new volume (fixed disk), it doesn't automatically check that box under "List Resources"

I know I can do a full network discovery on the node, but this is extremely resource heavy and at the end of the discovery it notifies the entire dept of the change. It's a bit unnecessary and as I mentioned too demanding to just check that box. However if I deploy 20+ virtual machines and then use my script to add the new nodes into Solarwinds, I'd really like for that drive to be checked under "List Resources". The other devices (physical & virtual memory) get checked automatically so I'm not sure what's preventing the volume from being checked.

Here is the code block for how I am adding the volume

#================ Hard Drive Monitoring

#Get drive Info from the server directly
$Drives = Get-CimInstance -ComputerName $node -ClassName Win32_LogicalDisk -Property * | Where-Object { $_.VolumeSerialNumber -ne $NULL }

$VolumeIndex = 3

#Set the properties of our new volume(s) based on the information from above
foreach ($Drive in $Drives)
{
    $PhysicalDrive = @{   
        NodeID = $CheckNode
        VolumeType = "Fixed Disk"
        DeviceId = $Drive.DeviceID
        VolumeTypeID = "4"
        Icon = "FixedDisk.gif"
        NextRediscovery = (Get-Date (Get-Date -Format "MM.dd.yyy h:mm:ss tt")).AddSeconds(30)
        nextpoll = (Get-Date (Get-Date -Format "MM.dd.yyy h:mm:ss tt")).AddSeconds(30)
        VolumeIndex = [Int]$VolumeIndex
        Caption = $Drive.DeviceID + "\ Label: " + $Drive.VolumeName + $Drive.VolumeSerialNumber
        VolumeDescription = $Drive.DeviceID + "\ Label: " + $Drive.VolumeName + "Serial Number " + $Drive.VolumeSerialNumber
        FullName = $Drive.PSComputerName + "-" + $Drive.DeviceID + "\ Label: " + $Drive.VolumeName + $Drive.VolumeSerialNumber
        PollInterval="120"
        StatCollection="15"
        RediscoveryInterval="30"
    }

    #Create new object with properties from above
    $NewPhysicalDriveURI = New-swisobject $swis -EntityType "Orion.volumes" -properties $PhysicalDrive

    #Get new URI Properties
    $PhysicalDriveProps = Get-SwisObject $swis -uri $NewPhysicalDriveURI

    #Register Pollers
    $PhysicalDrivePoller = @{
        NetObject = "V:" + $PhysicalDriveProps["VolumeID"]
        NetObjectType = "V"
        NetObjectID = $PhysicalDriveProps["VolumeID"]
    }; 

    #Details
    $PhysicalDrivePoller["PollerType"] = "V.Details.WMI.Windows"; 
    $PhysicalDriveURI = New-SwisObject $swis -EntityType "Orion.Pollers" -Properties $PhysicalDrivePoller  

    #Statistics
    $PhysicalDrivePoller["PollerType"] = "V.Statistics.WMI.Windows";
    $PhysicalDriveURI = New-SwisObject $swis -EntityType "Orion.Pollers" -Properties $PhysicalDrivePoller  

    #Status
    $PhysicalDrivePoller["PollerType"] = "V.Status.WMI.Windows";
    $PhysicalDriveURI = New-SwisObject $swis -EntityType "Orion.Pollers" -Properties $PhysicalDrivePoller

    #Poll changes
    Invoke-SwisVerb $Swis "Orion.Nodes" PollNow @("V:" + $PhysicalDriveProps["VolumeID"])

    #Increment the volume index if we have multiple fixed drives
    $VolumeIndex = $VolumeIndex + 1
}

  • I was able to see this behavior as well with using your method to add a volume to a node, and got it working by changing the "VolumeIndex" to 1. What I don't understand is exactly what affect that may have, as there's both a "VolumeIndex" field and an "Index" field. Potentially they're the same data and just ones an older property name.

    That said, I was testing on a node with no volumes being monitored. Perhaps there's some logic around this to be required in various scenarios.

    Also you may want to look to add .ToUniversalTime() to the end of lines 17 and 18, the variables for NextPoll and NextRediscovery, as the DB will expect UTC.

    Hope this helps.

  • Thank you for replying. I tried changing that value and re-adding the volume, but unfortunately that change didn't make any difference. I'm trying to navigate and look at different values within our Solarwinds server using the Database Manager tool as well as SWQL to see if I can spot anything. So far unfortunately no luck. I'm open to any other suggestions.

    Let me ask a different question, but similar to this topic... is there a way to preconfigure a "template" that every new server build follows the same guidelines outside of some minor changes such as IP, servername, etc. If I were to add a server node manually we follow the same "configuration" rinse & repeat, so if there is a way to preconfigure the template to always select the options I have in my post above (including the volume) that's another option for me.

    Here is a copy of the changes I made

    foreach ($Drive in $Drives)
    {
        $PhysicalDriveProps = @{
            NodeID = $NodeID
            Icon = "FixedDisk.gif"
            Index = 1
            VolumeIndex = 1
            Caption = $Drive.DeviceID + "\ Label: " + $Drive.VolumeName + $Drive.VolumeSerialNumber
            VolumeType = "Fixed Disk"
            Size = $SourceVolume.Size
            Responding = $SourceVolume.Responding
            FullName = $Drive.PSComputerName + "-" + $Drive.DeviceID + "\ Label: " + $Drive.VolumeName + $Drive.VolumeSerialNumber
            VolumePercentUsed = $SourceVolume.VolumePercentUsed
            VolumeAllocationFailuresThisHour = $SourceVolume.VolumeAllocationFailuresThisHour
            VolumeDescription = $Drive.DeviceID + "\ Label: " + $Drive.VolumeName + "Serial Number " + $Drive.VolumeSerialNumber
            VolumeSpaceUsed = $SourceVolume.VolumeSpaceUsed
            VolumeAllocationFailuresToday = $SourceVolume.VolumeAllocationFailuresToday
            VolumeSpaceAvailable = $SourceVolume.VolumeSpaceAvailable
            VolumeTypeID = "4"
            DeviceId = $Drive.DeviceID
            NextRediscovery = (Get-Date (Get-Date -Format "MM.dd.yyy h:mm:ss tt")).AddSeconds(30).ToUniversalTime()
            nextpoll = (Get-Date (Get-Date -Format "MM.dd.yyy h:mm:ss tt")).AddSeconds(30).ToUniversalTime()
            PollInterval="120"
            StatCollection="15"
            RediscoveryInterval="30"
        }
    
        #Create new object with properties from above
        $NewPhysicalDriveURI = New-swisobject $swis -EntityType "Orion.volumes" -properties $PhysicalDriveProps
    
        #Get new URI Properties
        $NewPhysicalDriveProps = Get-SwisObject $swis -uri $NewPhysicalDriveURI
    
        foreach ($volPollerType in $SourceVolPollerTypes) 
        {
            $volPoller = @{
                PollerType = "$volPollerType";
                NetObject = "V:"+$NewPhysicalDriveProps.VolumeID;
                NetObjectType = "V";
                NetObjectID = $NewPhysicalDriveProps.VolumeID;
            }
    
            New-SwisObject $swis -EntityType "Orion.Pollers" -Properties $volPoller | Out-Null
        }
    
        #Poll changes
        Invoke-SwisVerb $Swis "Orion.Nodes" PollNow @("V:" + $NewPhysicalDriveProps["VolumeID"])
    }

    Thank you!

  • So I looked at my lab and the volumeIndex and Index are always the same in my environment, but it doesn't look like you can get away with just hard coding it as 1.  In my environment Index 1 for windows servers always appears to be RAM, 2 is Virtual Memory, and the C: drive is usually 3 or 4, but even in my small lab it was not always true so I would not be willing to chance it and just randomly guess at this if I was setting this kind of workflow up in my environment.

    Getting to your question about setting up templates, I've talking to various SW PM's over the years about wanting to get this idea in the product natively but it hasnt made the cut yet.  In the mean time I just settled on building that logic on my own with a combination of Powershell and SQL.  I had scripts that build complete discoveries every day against all currently monitored nodes.  The discovery job had some limited amount of filtering that I was able to implement directly in the discovery, but it wasnt really good enough for a variety of reasons so I added an extra step where it would rip through the discovery results tables and remove anything we didnt want imported.  Once that was done it would execute the command to import anything that's left over.  It was a pretty tedious process of trial and error to get it all working but eventually I got it all dialed in and working pretty much on auto pilot for my previous job with ~10k nodes in the environment. I'd automatically bring known objects in from GCP/AWS/CMDB so the monitoring stayed pretty current to what was deployed

  • Yes, in our environment it's the same. 1 = physical memory, 2 = virtual memory, and 3+ = fixed disk (depending on how many drives the server has)

    You wouldn't by chance still have any of those scripts handy and willing to share would you? I pretty have everything automated the way I like, just this volume checkbox is the only thing holding me back. I thought at 1 point it was working fine for me, but then I noticed it isn't working anymore and I don't think anything changed in our environment.

    EDIT: I made a similar post a few months ago here: Requesting assistance with adding volume via swispowershell

    The last post I made in the link above, I thought it was basically working well and the volumes were good, but I don't think my current code is much different and for some reason the volumes aren't being listed in resources.

  • Look into PSCustomObjects in PowerShell - https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pscustomobject?view=powershell-7.3 and/or switches - https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_switch?view=powershell-7.3. You could create a PSCustomObject with all the predefined data for each, and use a switch to tell it which one to use depending on your condition.

    For the prior issue of it not showing in list resources, try changing your volumeindex to 1 and the below adjustments, it could potentially be comparing the end result of "mashed" data together, and it's not the same, so I looked at the formatting of the volumes when I added them through the UI, and this appears to match it.

    It appears to work for me now.

    Caption = $Drive.DeviceID + "\ Label:" + $Drive.VolumeName + " " + $Drive.VolumeSerialNumber.ToLower()
    VolumeDescription = $Drive.DeviceID + "\ Label:" + $Drive.VolumeName + "  Serial Number " + $Drive.VolumeSerialNumber.ToLower()
    FullName = $Drive.PSComputerName + "-" + $Drive.DeviceID + "\ Label: " + $Drive.VolumeName + $Drive.VolumeSerialNumber.ToLower()
     

    Also these properties are redundant amongst them and only need to define one of them in each:

    [Index, VolumeIndex] 

    [Description, Type, VolumeType]

  • I noticed exactly the same, most C: drives were volumeindex 3. But some were 1 and just couldn't make heads or tails of it to understand why. That's the "Magic sauce"... Stuck out tongue

  • Although speculating here   and  ... I do see some correlation between the polling method. It looks like at least in my environment SNMP nodes use VolumeIndex of 1 to start, and WMI/Agent nodes use VolumeIndex of 3 to start. Maybe that's due to it being Windows, and A: \ B: are reserved? Idk..

    Try taking a look in your environments with this SWQL:

    SELECT
         v.Node.ObjectSubType
        ,v.DeviceId
        ,v.VolumeIndex
        ,COUNT(v.VolumeID) AS [Total]
    FROM Orion.Volumes AS v
    WHERE v.VolumeDescription LIKE 'C:%'
    GROUP BY v.Node.ObjectSubType,v.DeviceId,v.VolumeIndex

  • So looking at that script you posted you just need to do whatever powershell command on the server gets you the disk's Index, but poking at my laptop i can't quite tell what commands will give that.  

  • Thanks to all of you for all these reply. I was off site today so I didn't get a chance to play with this anymore, but I will definitely look into the few things you posted above and see if I can get it working tomorrow. I really appreciate the responses, and I will post back my findings.

  •   
    Here is some additional information that may help.
    1. The nodes I am adding are WMI not SNMP. That being said, when I look at the tables for orion.volume, all of my fixed disks are an index value of 3+.
    So for example if a server has 1 drive then that c:\ drive would be indexed 3, if it has a 2nd drive (say drive D:\) that would be index 4 and so on... 

    So what I initially did was 

    $Drives = Get-CimInstance -ComputerName $node -ClassName Win32_LogicalDisk -Property * | Where-Object { $_.VolumeSerialNumber -ne $NULL }

    What this above code does is it tells me how many drives are on the source node. Then I do a loop through each drive and start with index 3 and then increment by 1 until it goes through all the drives. 

    As far as pscustomobjects go, what I tried doing is instead of prepopulating the data manually, I pull it from a node that actually has the volume listed in the "List Resources" section. For troubleshooting reasons I just populated the mandatory fields. 
     Here is what I came up with:

    #=================
    
    #Node we are creating the volume for
    $node = "Server6789"
    $nodeID = Get-SwisData $swis "SELECT NodeID FROM Orion.Nodes WHERE SysName='$node'"
    
    #Node we are pulling volume information from
    $NodeCopy = "Server6111"
    $nodeCopyID = Get-SwisData $swis "SELECT NodeID FROM Orion.Nodes WHERE SysName='$NodeCopy'"
    #Volume info for the node we're copying
    $NodeCopyVolumeInfo = Get-SwisData $swis "SELECT VolumeID,VolumeTypeID,VolumeIndex,VolumeDescription FROM Orion.volumes WHERE NodeID='$nodeCopyID' AND VolumeType='Fixed Disk'"
    #$Poller info for the volumes we're copying from the node
    $NodeCopyVolumePollers = Get-SwisData $swis "SELECT PollerType FROM Orion.Pollers WHERE NetObject=@netobject" @{ netobject='V:' + $NodeCopyVolumeInfo.VolumeID }
    
    #Populate our new Volume Info
    $PhysicalDrive = @{   
                NodeID = $nodeID
                VolumeTypeID = $NodeCopyVolumeInfo.VolumeTypeID
                VolumeIndex = $NodeCopyVolumeInfo.VolumeIndex
                VolumeDescription = $NodeCopyVolumeInfo.VolumeDescription
    }
    
    #Create the new Volume Object
    $PhysicalDriveURI = New-swisobject $swis -EntityType "Orion.volumes" -properties $PhysicalDrive
    
    #Grab properties for the new Object
    $nodeVolume = Get-SwisObject $swis $PhysicalDriveURI
    
     # Copy the pollers for the new Volume
    foreach ($NodeCopyVolumePoller in $NodeCopyVolumePollers) 
    {
        $volPoller = @{
            PollerType = "$NodeCopyVolumePoller";
            NetObject = "V:"+$nodeVolume.VolumeID;
            NetObjectType = "V";
            NetObjectID = $nodeVolume.VolumeID;
        }
        
        Write-Host "Adding poller $NodeCopyVolumePoller"
        New-SwisObject $swis -EntityType "Orion.Pollers" -Properties $volPoller | Out-Null
    }
    
    New-SwisObject $swis -EntityType "Orion.Pollers" -Properties $volPoller | Out-Null

    Anyway, I'm still stuck on the original issue, because I still can't get the volume to show in List Resources. I don't think changing the index from 3 to 1 would do it for me since as I mentioned these are WMI nodes and from looking at the tables all the servers with fixed drives start at index 3. 

    I also tried triggering a manual poll on my node like this:

    $indicationPropertiesXML = ([xml]"<dictionary xmlns='http://schemas.solarwinds.com/2007/08/informationservice/propertybag' />").DocumentElement
    $sourceInstancePropertiesXML = ([xml]"<dictionary xmlns='http://schemas.solarwinds.com/2007/08/informationservice/propertybag' />").DocumentElement
    
    (Invoke-SwisVerb $swis Orion.Rediscovery ReportIndication $nodeID, $($indicationPropertiesXML.InnerXml), $($sourceInstancePropertiesXML.InnerXml))

    Unfortunately this didn't help either.