There were two articles that I've read recently that helped me create a solution to a question that my boss want answered.

Basically, she wants our team, the Monitoring Support team, to be able to offer a SW page where any person can check & search for which types of data are being collected by our NPM and SAM modules from each machine/node.

One article is from adatole where he posted a custom SQL query that exactly does this. His article can be found here -> 4 Inevitable Questions When Joining a Monitoring Group, Pt.3 - Packet Pushers -


I used the custom SQL query mentioned in the article and have put it into a "Custom Table" custom resource, selecting Advanced SQL.

We have around 2,500 nodes and we have around 100,000 component monitors. These are distributed in 14 polling engines.

The query is taking a lot of time as it attempts to load a lot of stuff.


Then I came across another article, this time from antonis.athanasiou about leveraging the "Custom Query" custom resource in using its pagination and search features. His article can be found here -> SolarWinds Orion Custom Query Resource - A Hidden Gem!


The problem I then encountered is that the Custom Query resource does not accept SQL. It only accepts SWQL.

I took the time & converted the SQL query from adatole's article to SWQL. The SWQL version of the query is then used inside Custom Query resource, all the while leveraging its 'Enable Search' option.


** Notes **

  1. The "SELECT TOP 2500" part was what I've decided to use in my environment. You can change this to what you want or what works for you.
  2. Since the 'Enable Search' option relies on the ${SEARCH_STRING} macro, I've utilized it in the final WHERE clause so that the Search box of the Custom Query resource can look things up either for a node's node name, DNS name, Sys name, IP Address, vendor or machine type.
  3. Initially when you've finished configuring this resource, it will load empty. The only time that it will spit out data is after you've used the search box to look up either a node's node name, DNS name, Sys name, IP Address, vendor or machine type.


Here's the result of the conversion:


    nodes.StatusLed AS [icmpStatus],

    nodes.caption AS [NodeName],


    s1.elementtype AS [ElementType],

    s1.element AS [Element],

    s1.LED AS [ElementStatus],

    s1.Description AS [ElementDescr],

    s1.capacity AS [ElementCapacity],

    s1.threshold_value AS [threshold_for],

    s1.warn AS [warningLevel],

    s1.crit AS [criticalLevel]


    orion.nodes AS nodes

        LEFT JOIN



                    '01' as elementorder,

                    'CPU' as elementtype,


                    'Up.gif' as LED,

                    'CPU Count:' as element,

                    TOSTRING(COUNT(c1.CPUIndex)) as description,

                    '' as capacity,

                    'CPU Utilization' as threshold_value,

                    TOSTRING(t1.Level1Value) as warn,

                    TOSTRING(t1.Level2Value) as crit



                        SELECT DISTINCT CPUMultiLoad.NodeID, CPUMultiLoad.CPUIndex from Orion.CPUMultiLoad

                    ) AS c1

                        join Orion.CpuLoadThreshold t1 on c1.nodeID = t1.InstanceId

                GROUP BY

                    c1.NodeID, t1.Level1Value, t1.Level2Value

                    -- 01 conversion from sql to swql = successful


                UNION ALL (



                    '02' as elementorder,

                    'RAM' as elementtype,


                    'Up.gif' as LED,

                    'Total RAM' as element,

                    '' as description,

                    TOSTRING(ROUND(((nodes.TotalMemory/1048576)/1024),2)) + ' Gigabytes' as capacity,

                    'RAM Utilization' as threshold_value,

                    TOSTRING(NodesPercentMemoryUsedThreshold.Level1Value) as warn,

                    TOSTRING(NodesPercentMemoryUsedThreshold.Level2Value) as crit

                FROM Orion.nodes AS Nodes

                    JOIN Orion.PercentMemoryUsedThreshold AS NodesPercentMemoryUsedThreshold on nodes.nodeid = NodesPercentMemoryUsedThreshold.InstanceId

                    -- 02 conversion from sql to swql = successful



                UNION ALL (



                    '95' as elementorder,

                    'HW' as elementtype,


                    APM_HardwareAlertData.StatusLED as LED,

                    APM_HardwareAlertData.Description as element,

                    APM_HardwareAlertData.CategoriesWithStatus as description,

                    '' as capacity,

                    '' as threshold_value,

                    '' as warn,

                    '' as crit

                FROM Orion.HardwareHealth.HardwareInfo as APM_HardwareAlertData

                    -- 95 conversion from sql to swql = successful



                UNION ALL (



                    '03' as elementorder,

                    'NIC' as elementtype,

                    interfaces.nodeid as NodeID,

                    interfaces.statusled as LED,

                    interfaces.InterfaceName + ' @ifIndex ' + TOSTRING(interfaces.InterfaceIndex) as element,

                    interfaces.InterfaceTypeDescription as Description,

                    TOSTRING(interfaces.InterfaceSpeed) as capacity,

                    'bandwidth in/out' as threshold_value,

                    TOSTRING(i1.Level1Value)+'/'+TOSTRING(i2.level1value) as warn,

                    TOSTRING(i1.Level2Value)+'/'+TOSTRING(i2.level2value) as crit

                FROM Orion.NPM.Interfaces as interfaces

                    JOIN (

                            SELECT InterfacesThresholds.instanceid, InterfacesThresholds.level1value , InterfacesThresholds.level2value

                            FROM Orion.NPM.InPercentUtilizationThreshold AS InterfacesThresholds

                            WHERE = 'NPM.Interfaces.Stats.InPercentUtilization'

                        ) AS i1 on interfaces.interfaceid = i1.InstanceId

                    JOIN (

                            SELECT InterfacesThresholds.instanceid, InterfacesThresholds.Level1Value, InterfacesThresholds.level2value

                            FROM Orion.NPM.OutPercentUtilizationThreshold AS InterfacesThresholds

                            WHERE = 'NPM.Interfaces.Stats.OutPercentUtilization'

                    ) AS i2 on interfaces.interfaceid = i2.InstanceId

                        -- 03 conversion from sql to swql = successful



                UNION ALL (



                    '04' as elementorder,

                    'DISK' as elementtype,

                    volumes.nodeid as NodeID,

                    volumes.statusled as LED,

                    volumes.caption as element,

                    volumes.VolumeType as description,

                    TOSTRING(ROUND(((volumes.VolumeSize/1048576)/1024),2)) + ' Gigabytes' as capacity,

                    '' as threshold_value,

                    '' as warn,

                    '' as crit

                FROM Orion.volumes AS volumes

                    -- 04 conversion from sql to swql = successful



                UNION ALL (



                    '05' AS elementorder,

                    'APP component' AS elementtype,

                    cs.NodeID AS NodeID,

                    si.ShortDescription + '.gif' AS LED,

                    cs.ComponentName AS element,

           AS description,

                    '' AS capacity,

                    'CPU ; PhyMem ; VirtMem ; Stat ; RespTime' as threshold_value,

                    ISNULL(TOSTRING(cat.ThresholdCPUWarning),'no_data') + ' ; ' +  ISNULL(TOSTRING(cat.ThresholdPhysicalMemoryWarning),'no_data') + ' ; ' +  ISNULL(TOSTRING(cat.ThresholdVirtualMemoryWarning),'no_data') + ' ; ' +  ISNULL(TOSTRING(cat.ThresholdStatisticWarning),'no_data') + ' ; ' +  ISNULL(TOSTRING(cat.ThresholdResponseTimeWarning),'no_data') + ' ; ' AS warn,

                    ISNULL(TOSTRING(cat.ThresholdCPUCritical),'no_data') + ' ; ' +  ISNULL(TOSTRING(cat.ThresholdPhysicalMemoryCritical),'no_data') + ' ; ' +  ISNULL(TOSTRING(cat.ThresholdVirtualMemoryCritical),'no_data') + ' ; ' +  ISNULL(TOSTRING(cat.ThresholdStatisticCritical),'no_data') + ' ; ' +  ISNULL(TOSTRING(cat.ThresholdResponseTimeCritical),'no_data') + ' ; ' AS crit


                    Orion.APM.CurrentStatistics AS cs

                        INNER JOIN Orion.APM.ComponentAlertThresholds AS cat ON cs.ComponentID = cat.ComponentID

                        INNER JOIN Orion.APM.Component AS c ON cs.ComponentID = c.ComponentID

                        INNER JOIN Orion.StatusInfo AS si ON cs.ComponentAvailability = si.StatusID

                    -- 05 conversion from sql to swql = successful



                UNION ALL (



                    '06' as elementorder,

                    'POLLER' as elementtype,


                    'up.gif' as LED,

                    CustomPollerAssignmentView.CustomPollerName as element,

                    CustomPollerAssignmentView.CustomPollerDescription as description,

                    '' as capacity,

                    '' as threshold_value,

                    '' as warn,

                    '' as crit

                FROM (


                        AncestorDetailsUrls, AncestorDisplayNames, AssignmentName, CurrentValue, CustomPollerAssignmentID,

                        CustomPollerDescription, CustomPollerID, CustomPollerMIB, CustomPollerName, CustomPollerOid,

                        Description, DetailsUrl, DisplayName, ID, Image, InstanceSiteId, InstanceType,

                        InterfaceID, NodeID, Status, StatusDescription, StatusIconHint, StatusLED, UnManaged, UnManageFrom, UnManageUntil, Uri

                    FROM Orion.NPM.CustomPollerAssignmentOnNode


                    UNION ALL (



                                AncestorDetailsUrls, AncestorDisplayNames, AssignmentName, CurrentValue, CustomPollerAssignmentID,

                                CustomPollerDescription, CustomPollerID, CustomPollerMIB, CustomPollerName, CustomPollerOid,

                                Description, DetailsUrl, DisplayName, ID, Image, InstanceSiteId, InstanceType,

                                InterfaceID, NodeID, Status, StatusDescription, StatusIconHint, StatusLED, UnManaged, UnManageFrom, UnManageUntil, Uri

                            FROM Orion.NPM.CustomPollerAssignmentOnInterface


                    ) AS CustomPollerAssignmentView

                    -- 06 conversion from sql to swql = successful


        ) AS s1 ON nodes.nodeid = s1.NodeID


Nodes.Caption LIKE '%${SEARCH_STRING}%' OR


Nodes.Sysname LIKE '%${SEARCH_STRING}%' OR

Nodes.IP_Address LIKE '%${SEARCH_STRING}%'   OR

Nodes.Vendor LIKE '%${SEARCH_STRING}%' OR

Nodes.MachineType LIKE '%${SEARCH_STRING}%'


    nodes.nodeid, s1.elementtype



Here are some screenshots of how it looks like on my end.


Am Montag morgen kommt ein Prio 1 + Ticket rein, direkt vom Vorstand. Die weltwichtigste Videokonferenz von Europa nach Amerika funktioniert nicht. Im Ticket steht " bitte das gesamte Netzwerk neu starten".

Solche oder so ähnliche Anfragen sind immer eine Herausforderung. Man muss unter Zeitdruck schnell herausfinden was das eigentliche Problem ist.

Einige Probleme können einfach gelöst werden, wenn man direkt herausbekommt wo die Ursache liegt. Seit langer Zeit ist ping und traceroute eines der meistbenutzten Werkzeuge des Administrators.

Es ist überall verfügbar und bietet direkt eine Aussage über Erreichbarkeit und RoundTripTimes.

Wenn es aber dazu kommt, wie im oben beschriebenen Beispiel mit der Videokonferenz, dass die erste Analyse mit ping und traceroute keine Probleme aufzeigt, wird es meistens zeitintensiver den Fehler zu finden.

In Zeiten von Overlays, SDN und MPLS ist es komplexer geworden eine Fehlersuche durchzuführen. Hier kann es passieren, dass unsere alten Werkzeuge ping und traceroute sich als falsche Freunde erweisen.

Wenn unsere Testwerkzeuge einen anderen Weg durch das Netzwerk gehen als die gestörte Applikation wie die Pakete der Videokonferenz, werden wir bei der Fehlersuche in die falsche Richtung gelenkt.

Auch von der Provider Seite bekommt man oft nur nichtssagende Port Uplink Statistiken des eigenen Anschlusses geliefert, wenn man ein Ticket dort eröffnet. Nicht sehr hilfreich, wenn die Statistik vom eigenen

Asnchluss OK ist mit 10% Auslastung, der Uplink des Providers aber 100% Auslastung durch einen anderen Kunden hat.

Auch beim Provider sind die Uplinks geshared für alle angeschlossenen Endkunden. Teure, gemietete MPLS, private WAN Verbindungen des Providers stellen sich als Wolke dar, die für den Endkunden keinerlei oder

nur sehr eingeschränkte Möglichkeiten bieten was Monitoring und Verfügbarkeit angeht.


Wenn man sich nur auf seinen Provider verlässt, ist man oft verlassen. Hier hilft es sehr, wenn man in diesem

Bereich ausserhalb der eigenen Infrastruktur mehr Informationen bekommt.

Die angesprochenen Probleme werden von SolarWinds NetPath addressiert. Mit NetPath kann man einfach

Ende zu Ende Messungen durch komplexe Netzwerke durchführen, egal ob diese zur eigenen Netzwerk

Infrastruktur oder der des Providers gehört.


Das Prinzip ist einfach und genial. Es wird der Netpath discovered und danach eine permanente Ende zu Ende

Messung durchgeführt. Man kann in NetPath Traffic auf beliebigen Ports generieren um z.B. Video oder

Voice Traffic zu emulieren. Dadurch erhält man eine detaillierte Grafik über alle Komponenten im "NetPath"

der Kommunikation darstellt.

Neben dem Dokumentation Aspekt hat man auch sofort Hop-by-Hop live Daten aus der Messung und kann schnell

Flaschenhälse identifiezieren. Gerade in Situationen, in denen man keine aktuelle Dokumentation verfügbar hat,

ist dies sehr hilfreich. Die Dokumentation zu erstellen während der Fehlersuche ist nicht gerade ideal. Dazu ist die automatisiert ausgelesene Topologie aktuell und man sucht keine Phantomkomponenten aus der

Dokumentation, die vielleicht schon gar nicht mehr exsistieren.


Ist der Netpath einmal generiert, bekommt man sofort aus der live Messung Updates sobald sich etwas ändert. Gerade diese kontinuierliche Überwachung lässt uns besser die eigentlichen Probleme verstehen. Um das Bild

zu vervollständigen hat SolarWinds auch noch eine Integration des traditionellen Monitorings in NetPath. Wenn man z.B. eine hohe Latenz auf einem Link sieht und diese sofort

in Kontext mit Paketverlusten auf einem Interface bringen kann, ist die Fehlersuche schnell erfolgreich. Wenn die Videokonferenz wieder läuft kann man sich entspannt dem nächsten Ticket zuwenden.

Hallo Zusammen!


Knapp zwei Monate nach wannacry und wir spüren immer noch die Nachbeben.
Ich erspare uns das nochmalige Nachbeten der Details – die gibt es ohnehin hier


Wir wissen ja, dass Maschinen hauptsächlich durch das Fehlen eines vorab veröffentlichten Sicherheitspatches infiziert worden sind. Somit wäre der Großteil des Desasters vermeidbar gewesen.

Warum wird Patching so stiefmütterlich behandelt? Darüber könnten wir einen ganzen Tag diskutieren.
Aber erstellen wir eine Kette um einen der Hauptgründe zu identifizieren:

1. Es muss sichergestellt werden, dass Unternehmenssoftware auch nach dem Einspielen von Patches noch läuft und keine Probleme zu erwarten sid

2. Administratoren brauchen Kontrolle über den Patchprozess, um dies sicherzustellen

3. Administratoren brauchen Zeit, um die obige Kontrolle auszuüben

4. Zeit ist richtig teuer und, ich erinnere mich an BWL, ein „knappes Gut“


Also: Keine Zeit = kein Patch


Wo kommt jetzt Solarwinds ins Spiel? Das Beste wäre natürlich dieses neue Produkt auf das alle warten, GITDLM – GetIntoTheDeLoreanManager - um in der Zeit zu reisen, aber das steckt aus unbekannten Gründen im QA Prozess fest. Seit Jahren!

Hier ist das einzige existierende Foto der Betaversion:





Also schauen wir uns einmal den Patch Manager an.
Dies ist hier das erste von zwei Blogeinträgen und ich will den Hintergrund sowie den Installationprozess erklären.

Patch Manager, oder auch SPM, setzt auf bestehende Microsoft Infrastruktur auf und nutzt den WindowsUpdateAgent um nicht-MSFT Updates zu verteilen, und benötigt eine WSUS oder SCCM Umgebung.
SPM wird meist auf der gleichen Box installiert auf der der WSUS läuft und benötigt eine SQL DB im Hintergrund.

Da die Menge an Daten üblicherweise ziemlich gering ist, kann die SQL Express Version tatsächlich ausreichend sein.

Bedient wird SPM innerhalb einer MMC und diese kann problemlos auf einer Workstation installiert werden. Ebenso gibt es eine Komponente die SPM in ein bestehendes Orion System integrieren kann.


Aber mal von Anfang an!


Hier die Auswahl der Optionen, wir folgen dem Standard:


Dann klicke ich auf Express



Express installiert einen WSUS sowie eine SQL Express lokal und stellt keine dummen Fragen
Für einen Produktivbetrieb würde ich natürlich die zweite Variante auswählen und meinen eigenen WSUS einhängen, sowie optional auf eine dedizierte SQL verweisen.


Das hier dauert ein Weilchen:



Dieses Fenster kommt beim Starten:




Dann wird ein Benutzer angelegt, dies sollte ein lokaler Admin sein:




Okay das hier klingt verlockend, aber ich gehe die Schritte manuell mit euch durch damit ihr wisst, was passiert. Also bitte die Box abwählen und das Fenster schliessen:




In der MMC links oben klickt auf Enterprise --> Update Services und überprüft ob der WSUS da ist:




Schaut vielleicht auch einmal unter Patch Manager System Config --> Security and User --> Credential Ring und klickt auf Default, dann „next“.
Es sollte etwa so aussehen:



Hier kann man später bei einem Produktivsystem verschiedene Benutzerkonten zuweisen.
Wenn alles passt, cancel und tschüss.


An dieser Stelle würde man jetzt den WSUS einrichten. Das kann man entweder in der WSUS Konsole selbst erledigen oder aber im Patch Manager beim Klick auf den WSUS ganz rechts die folgenden Optionen:




Das Auswählen der Produkte (Windows/Exchange etc) und setzen weiterer WSUS-spezifischer Optionen erkläre ich an dieser Stelle nicht und verweise faul auf die Suchmaschine eurer Wahl.
Gehen wir davon aus, dass WSUS eingerichtet ist und ein paar Clients dranhängen, und machen weiter.


Wechselt zu Patch Manager System Config --> Management Groups --> Managed Enterprise und klickt auf den Server, dann rechts auf „Schedule Inventory“


Setzt die Frequenz etc wie es passt, hier ein Beispiel:




Ein paar Auswahlmöglichkeiten – beim Klick auf eine Zeile sieht man eine Erklärung




Wir haben gerade unsere erste Aufgabe angelegt!
Verifiziert schnell unter Administration and Reporting --> Scheduled Tasks:



Wenn die SPM Maschine in einer Domain sitzt, kann man über den Management Group Wizard den DC hinzufügen.
Es sieht dann so aus (Screenshots kommen von einem anderen System):




Beim Klicken auf den DC habe ich rechts eine weitere Inventarisierungsfunktion:



Dort wählt ihr aus was interessant ist und setzt direkt eine zweite Aufgabe an.



Mittels rechter Maustaste kann ich diese Aufgaben adhoc starten, damit ich auch vor dem eigentlichen Startzeitpunkt Resultate bekomme.

SPM ist jetzt einsatzbereit und kann schon benutzt werden, aber wir müssen ja noch mit den Clients kommunizieren.


Klicken wir einmal auf Administration and Reporting à Software Publishing, dann ganz rechts auf Server Publishing Wizard und wählen den WSUS aus.

Es sollte wie folgt aussehen:



Kickt auf next. Und next. Und…wartet. Dann auf Finish!




Wir haben jetzt ein Zertifikat aber das reicht noch nicht. Leider wird es jetzt kompliziert.
Ich erklär es daher g-a-n-z l-a-n-g-s-a-m.


Klickt rechts auf Client Publishing Setup Wizard. Wählt den WSUS aus und klickt Distribute:




Hier wählen wir die Zielsysteme aus, z.B. über Browse Computers und Update Services Servers, gefolgt von einer Gruppe, oder einem einzelnen System.

Im nächsten Fenster lasse ich alles bei den Standards und klicke direkt auf Finish.

Das Resultat ist höchstwahrscheinlich eine Warnung:




Ok, dann aber ignorieren wir das Fenster und machen etwas Anderes.

Geht ganz hoch zu Enterprise --> Update Services und klickt einmal auf den WSUS, dann ganz rechts etwas weiter unten auf Software Publishing Certificate.
Dort dann bitte rechts auf die drei Punkte:



Details, copy to file



DER passt, klickt next und legt es irgendwo hin. Nur nicht unter den Tannenbaum!


Nun brauchen wir den Group Policy Editor, entweder direkt auf dem DC oder aber in einer Remote-Konsole.

Wie man mit dem Ding umgeht ist auch wieder ausserhalb des Umfangs dieses Blogposts, in meinem Beispiel schnappe ich mir einfach die ganz normale Domain-Policy und editiere.


Wir gehen zu Computer Configuration --> Policies --> Windows Settings --> Security Settings --> Public Key Policies --> Trusted Root, rechtsklicken dann irgendwo und importieren die DER Datei.

Das gleiche dann noch einmal für die Trusted Publisher. Erledigt? Gut.


Jetzt zu Computer Configuration --> Administrative Templates --> Windows Components --> Windows Update und sucht nach “Allow signed updates from an intranet Microsoft update service location” oder dem Deutschen Äquivalent bei Deutschem OS.
Aktiviert die Einstellung. Perfekt.


Das System ist jetzt komplett einsatzbereit und ich könnte entweder auf das hervorragende Rezept für Tiramisu hinweisen, das ich am Freitag ausprobiert habe, oder einfach das Posting beenden und mit der Arbeit an den nächsten Schritten – dem Patchen – beginnen.

Nach kurzer Überlegung entscheide ich mich für letzteres da ich gerade von einer Fliege angegriffen werde und fliehen muss:

Greetings fellow THWACK® comrades!

In a slight deviation from my usual PowerShell® posts, I wanted to share a sneak peek of some of the work that is going on behind the scenes at the Cork office for next week’s SolarWinds® Partner Bootcamp EMEA.

If you’re not familiar with our SolarWinds Partner Bootcamp, it’s a multi-day event in Cork, where SolarWinds technical and sales staff host a series of product workshops with our channel partners from across Europe, the Middle East, and Africa. During these face-to-face sessions, we’re able to cover advanced topics, provide technical training, and receive feedback directly from our partners in the field.

Expect another post in the near future, but in the meantime, here’s a little teaser of some of the welcome kit items our attendees might expect!



SolarWinds uses cookies on its websites to make your online experience easier and better. By using our website, you consent to our use of cookies. For more information on cookies, see our cookie policy.