The F5 monitoring is quite detailed in the 2020 version of Solarwinds. What is lacking, is a way to look at all the F5 data in the once place, and to search for vIPs, Pool members, and so on.
I have built such a dashboard. I hope to do an export, but for the meantime, below you will find out how to build it yourself.
The main screen is as follows, and has the following widgets:
The second page is more a work in progress. On the left are all the virtual servers. Clicking on the right will show the Netflow conversations data.
How To Build
As you can see, I have build this as a two page, Summary View. To get started, make a blank summary view with a couple of columns. I will show how to create each component in order.
Add this View Limitation by Group of Machine Types. Add All the device types that have "BIG-IP" in the name. This allows us to use some standard widgets - which will be filtered to just our F5s.
F5s
Object Type: Custom Table
Rows Per Page: 5
Custom SWQL Query:
SELECT d.Caption as F5, d.DetailsUrl as _linkfor_F5
, '/Orion/images/StatusIcons/Small-' + n.StatusLED as _iconfor_F5
,ProductVersion + ' (' + ProductBuild + ')' as Version
,FailoverStatusDescription as Failover
,'/Orion/F5/images/F5_' + tostring(d.FailOverStatusColor) + '.png' as _iconfor_Failover
, d.SyncStatusDescription as Sync
,'/Orion/F5/images/F5_' + tostring( d.SyncStatusColor ) + '.png' as _iconfor_Sync
,'' as Maintenance
,case when IsInMaintenanceMode = 'True' then '/Orion/F5/images/Small/Status-Unmanaged.png' else '' end as _iconfor_Maintenance
--,In_Throughput, Out_Throughput, Connections, ConnectionsNew, ConnectionsSSL
,Connections, ConnectionsSSL
,mod.Modules
,VLANs
FROM Orion.F5.System.Device d
inner join orion.Nodes n
on n.nodeID = d.NodeID
inner join (
SELECT NodeID --, Name--, Enabled
,max( case when Name = 'Global Traffic Manager' then 'GTM ' else '' end )
+ max( case when Name = 'Local Traffic Manager' then 'LTM ' else '' end )
+ max( case when Name = 'Advanced Firewall Manager' then 'AFM ' else '' end )
+ max( case when Name = 'Access Policy Manager' then 'APM ' else '' end )
+ max( case when Name = 'Application Security Manager' then 'ASM ' else '' end )
+ max( case when Name = 'Acceleration Manager' then 'AM ' else '' end )
+ max( case when Name = 'Application Visibility and Reporting' then 'AVR ' else '' end )
+ max( case when Name = 'Link Controller' then 'LC ' else '' end )
+ max( case when Name = 'Policy Enforcement Manager' then 'PEM ' else '' end )
+ max( case when Name = 'Fraud Protection Service' then 'FPS ' else '' end )
+ max( case when Name = 'iRules Language Extensions' then 'ILX ' else '' end )
+ max( case when Name = 'Secure Web Gateway' then 'SWG ' else '' end )
+ max( case when Name = 'Virtual CMP' then 'VCMP ' else '' end )
as Modules
FROM Orion.F5.System.Module
group by NodeID
) mod
on mod.NodeID = d.NodeID
inner join (
SELECT NodeID
,max(case when vlanIndex = 1 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 2 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 3 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 4 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 5 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 6 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 7 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 8 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 9 then ShortName else '' end ) + ' '
+ max(case when vlanIndex = 1 then ShortName else '' end )
as VLANs
FROM Orion.F5.System.VLAN
group by NodeID
) vlan
on vlan.NodeID = d.NodeID
Virtual Servers - LTM
Note: I originally planned for these to show LTM and GTM data, but I had problems with the UNION being executed. It is preferred to also have the GTM data, though for my organisation we do not have GTM F5s. You will see there is a Type column, that has 'LTM' in it. I have added the "- LTM" to the end of the heading to as not to mislead.
Adding GTM is an exercise for future improvement - and I will gladly take updates.
Object Type: Custom Table
Rows Per Page: 5
Custom SWQL Query:
SELECT 'LTM' as Type, '/Orion/F5/F5LTMDetails.aspx?NetObject=F5LTM:' + TOSTRING(n.nodeid) as _linkfor_Type
, n.Caption as F5, n.DetailsUrl as _linkfor_F5
, '/Orion/images/StatusIcons/Small-' + n.StatusLED as _iconfor_F5
,vs.ShortName as Virtual_Server
,'/Orion/F5/F5VirtualServerDetails.aspx?NetObject=F5VS:' + TOSTRING( vs.VirtualServerID) as _linkfor_Virtual_Server
,'/Orion/images/StatusIcons/Small-' + case vs.F5Status when 4 then 'UNKNOWN' when 1 then 'UP' when 3 then 'DOWN' end + '.gif' as _iconfor_Virtual_Server
,vs.Port
,case when vs.F5StatusReason <> 'The virtual server is available' then vs.F5statusReason end as Detail
FROM Orion.F5.LTM.VirtualServer vs
inner join Orion.Nodes n
on vs.NodeID = n.NodeID
order by n.Caption
Enable Search: yes
Search SWQL Query:
SELECT 'LTM' as Type, '/Orion/F5/F5LTMDetails.aspx?NetObject=F5LTM:' + TOSTRING(n.nodeid) as _linkfor_Type
, n.Caption as F5, n.DetailsUrl as _linkfor_F5
, '/Orion/images/StatusIcons/Small-' + n.StatusLED as _iconfor_F5
,vs.ShortName as Virtual_Server
,'/Orion/F5/F5VirtualServerDetails.aspx?NetObject=F5VS:' + TOSTRING( vs.VirtualServerID) as _linkfor_Virtual_Server
,'/Orion/images/StatusIcons/Small-' + case vs.F5Status when 4 then 'UNKNOWN' when 1 then 'UP' when 3 then 'DOWN' end + '.gif' as _iconfor_Virtual_Server
,vs.Port
,case when vs.F5StatusReason <> 'The virtual server is available' then vs.F5statusReason end as Detail
FROM Orion.F5.LTM.VirtualServer vs
inner join Orion.Nodes n
on vs.NodeID = n.NodeID
where vs.DisplayName like '%${SEARCH_STRING}%'
or vs.VirtualIPAddress.IPAddress like '%${SEARCH_STRING}%'
order by n.Caption
Pools - LTM
Note the same for this, as the above object.
Object Type: Custom Table
Rows Per Page: 5
Custom SWQL Query:
SELECT
'LTM' as Type, '/Orion/F5/F5LTMDetails.aspx?NetObject=F5LTM:' + TOSTRING(n.nodeid) as _linkfor_Type
, n.Caption as F5, n.DetailsUrl as _linkfor_F5
, '/Orion/images/StatusIcons/Small-' + n.StatusLED as _iconfor_F5
, p.ShortName as Pool_Name
,p.DetailsUrl as _linkfor_Pool_Name
,'/Orion/images/StatusIcons/Small-' + p.OrionStatusDescription + '.GIF' as _iconfor_Pool_Name
,'' as Enabled
,'/Orion/images/StatusIcons/Small-' + case when p.EnabledDescription = 'Enabled' then 'UP' else 'DOWN' END + '.GIF' as _iconfor_Enabled
,p.LBModeDescription as LB_Mode
,p.MemberCountTotal as Members
,p.MemberCountActual as Actual
,case when p.OrionStatus <> 1 then p.F5StatusReason end as Details
FROM Orion.F5.LTM.Pool p
inner join orion.Nodes n
on p.nodeID = n.nodeID
Search SWQL Query:
SELECT
'LTM' as Type, '/Orion/F5/F5LTMDetails.aspx?NetObject=F5LTM:' + TOSTRING(n.nodeid) as _linkfor_Type
, n.Caption as F5, n.DetailsUrl as _linkfor_F5
, '/Orion/images/StatusIcons/Small-' + n.StatusLED as _iconfor_F5
, p.ShortName as Pool_Name
,p.DetailsUrl as _linkfor_Pool_Name
,'/Orion/images/StatusIcons/Small-' + p.OrionStatusDescription + '.GIF' as _iconfor_Pool_Name
,'' as Enabled
,'/Orion/images/StatusIcons/Small-' + case when p.EnabledDescription = 'Enabled' then 'UP' else 'DOWN' END + '.GIF' as _iconfor_Enabled
,p.LBModeDescription as LB_Mode
,p.MemberCountTotal as Members
,p.MemberCountActual as Actual
,case when p.OrionStatus <> 1 then p.F5StatusReason end as Details
FROM Orion.F5.LTM.Pool p
inner join orion.Nodes n
on p.nodeID = n.nodeID
where p.ShortName like '%${SEARCH_STRING}%'
or p.VirtualServer.VirtualIPAddress.IPAddress like '%${SEARCH_STRING}%'
order by n.Caption
Pool Members - LTM
Object Type: Custom Table
Rows Per Page: 5
Custom SWQL Query:
SELECT 'LTM' as Type, '/Orion/F5/F5LTMDetails.aspx?NetObject=F5LTM:' + TOSTRING(n.nodeid) as _linkfor_Type
, n.Caption as F5, n.DetailsUrl as _linkfor_F5
, '/Orion/images/StatusIcons/Small-' + n.StatusLED as _iconfor_F5
, p.ShortName as Pool_Name
,p.DetailsUrl as _linkfor_Pool_Name
,'/Orion/images/StatusIcons/Small-' + p.OrionStatusDescription + '.GIF' as _iconfor_Pool_Name
,substring(pm.ShortName, length( p.ShortName )+2, 999) as Pool_Member
,pm.DetailsUrl as _linkfor_Pool_Member
,'/Orion/images/StatusIcons/Small-' + pm.OrionStatusDescription + '.GIF' as _iconfor_Pool_Member
,case when pm.F5Status <> 1 then pm.F5StatusReason end as Detail
--,pm.Port, pm.Enabled, pm.F5Status, pm.F5StatusReason, pm.OrionStatus, PPS_In, PPS_Out, BPS_In, BPS_Out, Connections, ConnectionsPerSec, RequestsPerSec, Sessions, pm.ShortName, pm.DisplayName, pm.DetailsUrl, pm.Description, pm.F5StatusDescription, pm.OrionStatusDescription, pm.EnabledDescription, pm.DisableReason
FROM Orion.F5.LTM.PoolMember pm
inner join orion.Nodes n
on pm.nodeID = n.nodeID
inner join Orion.F5.LTM.Pool p
on pm.PoolIndex = p.PoolIndex
and pm.NodeID = p.NodeID
order by n.Caption , pm.ShortName
Search SWQL Query:
SELECT 'LTM' as Type, '/Orion/F5/F5LTMDetails.aspx?NetObject=F5LTM:' + TOSTRING(n.nodeid) as _linkfor_Type
,n.Caption as F5, n.DetailsUrl as _linkfor_F5
, '/Orion/images/StatusIcons/Small-' + n.StatusLED as _iconfor_F5
, p.ShortName as Pool_Name
,p.DetailsUrl as _linkfor_Pool_Name
,'/Orion/images/StatusIcons/Small-' + p.OrionStatusDescription + '.GIF' as _iconfor_Pool_Name
,substring(pm.ShortName, length( p.ShortName )+2, 999) as Pool_Member
,pm.DetailsUrl as _linkfor_Pool_Member
,'/Orion/images/StatusIcons/Small-' + pm.OrionStatusDescription + '.GIF' as _iconfor_Pool_Member
,case when pm.F5Status <> 1 then pm.F5StatusReason end as Detail
--,pm.Port, pm.Enabled, pm.F5Status, pm.F5StatusReason, pm.OrionStatus, PPS_In, PPS_Out, BPS_In, BPS_Out, Connections, ConnectionsPerSec, RequestsPerSec, Sessions, pm.ShortName, pm.DisplayName, pm.DetailsUrl, pm.Description, pm.F5StatusDescription, pm.OrionStatusDescription, pm.EnabledDescription, pm.DisableReason
FROM Orion.F5.LTM.PoolMember pm
inner join orion.Nodes n
on pm.nodeID = n.nodeID
inner join Orion.F5.LTM.Pool p
on pm.PoolIndex = p.PoolIndex
and pm.NodeID = p.NodeID
where p.ShortName like '%${SEARCH_STRING}%' or pm.ShortName like '%${SEARCH_STRING}%'
or pm.pool.VirtualServer.VirtualIPAddress.IPAddress like '%${SEARCH_STRING}%'
order by n.Caption , pm.ShortName
Concurrent Connections by Virtual Server
This is a standard widget, for a change.
Object Type: Concurrent Connections By Virtual Server
Maximum Number of Virtual Servers to Display: 10
Amount of historical data to load: Last 7 days
Default Zoom Range: Today
Sample Interval: Every 15 minutes
Concurrent Connections by Virtual Server
Another standard widget.
Object Type: Active Alerts
F5 Audit Events
This is a custom query. Only so that we can do a more compact view of audited changes, and to make it have some interactivity. Note the queries limit the data to the last 100 audit records.
Object Type: Custom Table
Rows Per Page: 5
Custom SWQL Query:
SELECT TOP 100 ObservationTimestamp as Time
, n.Caption as F5
, n.DetailsUrl as _linkfor_F5
, AuditEventMessage as Log_Message
, e.DetailsUrl as _linkfor_Log_Message
FROM Orion.AuditingEvents e
inner join orion.nodes n
on n.nodeID = e.NetworkNode
inner join orion.AuditingActionTypes a
on a.ActionTypeID = e.ActionTypeID
where n.Vendor = 'F5 Networks, Inc.'
order by auditeventid desc
Search SWQL Query:
SELECT TOP 100 ObservationTimestamp as Time
, n.Caption as F5
, n.DetailsUrl as _linkfor_F5
, AuditEventMessage as Log_Message
, e.DetailsUrl as _linkfor_Log_Message
FROM Orion.AuditingEvents e
inner join orion.nodes n
on n.nodeID = e.NetworkNode
inner join orion.AuditingActionTypes a
on a.ActionTypeID = e.ActionTypeID
where n.Vendor = 'F5 Networks, Inc.'
AND (
n.Caption like '%${SEARCH_STRING}%'
or AuditEventMessage like '%${SEARCH_STRING}%'
)
order by auditeventid desc
Last 5 Config Changes
Another standard widget.
Object Type: Last XX Config Changes
Number of configs to display: 5
EXPERIMENTAL - BUT FUN - SECTION
Second Page - Netflow Data
This is a work in progress. Uses an embedded IFRAME, and targetted links. I currently have it filtered to the subset of Virtual Servers that have netflow. If not filtered then there are too many rows of data. Note that I only have Virtual Server IPs. I could also do Pool Member IPs. I should also point out that I have the links loading Conversations. I would like to change this to also have a link for the Applications graph.
I cannot do a search like for other widgets, as I am using SQL so I can retrieve the IP address.
F5 Virtual Servers
This is a complicated query, as I have to do some advanced string handling that is really a bit beyond the SWQL functions. The IP links for IPAM are in the form aaabbbcccdddeeefff (for a.b.c.d IP addresses)
Object Type: Custom Query
Rows Per Page: 5
Data Source: - SWQL
select Distinct Type, _linkfor_Type, F5, _linkfor_F5, _linkfor_Virtual_Server, Virtual_Server, Port, Detail
, '<a href="'
+ '/Orion/DetachResource.aspx?ResourceID=1488&NetObject=NSF%3aT%3aLast+2+Hours%3bFD%3aBoth%3bIPV%3aBoth%3bE%3a'
+ isnull( ip6,
concat( (case length(o1) when 1 then '00' when 2 then '0' else '' end + o1 )
, (case length(o2) when 1 then '00' when 2 then '0' else '' end + o2 )
, (case length(o3) when 1 then '00' when 2 then '0' else '' end + o3 )
, (case length(o4) when 1 then '00' when 2 then '0' else '' end + o4 ) )
)
+ '" target="f5_nta">' + p2.IPAddress + '</a>'
as ParamIP
from (
select Type, _linkfor_Type, F5, _linkfor_F5, _linkfor_Virtual_Server, Virtual_Server, Port, Detail
,IPAddress, IP6
,case when IP6 is null then SUBSTRING(p1.IPAddress, 1, p1.p1-1 ) end as O1
,case when IP6 is null then SUBSTRING(p1.IPAddress, p1.p1+1, (p1.p2-p1.p1-1) ) end as O2
,case when IP6 is null then SUBSTRING(p1.IPAddress, p1.p2+1, (p1.p3-p1.p2-1) ) end as O3
,case when IP6 is null then SUBSTRING(p1.IPAddress, p1.p3+1, 999 ) end as O4
from (
SELECT vs.VirtualIPAddress.IPAddress
,charindex('.', vs.VirtualIPAddress.IPAddress) as p1
,charindex('.', vs.VirtualIPAddress.IPAddress, (charindex('.', vs.VirtualIPAddress.IPAddress)+1) ) as p2
,charindex('.', vs.VirtualIPAddress.IPAddress, charindex('.', vs.VirtualIPAddress.IPAddress, (charindex('.', vs.VirtualIPAddress.IPAddress)+1) )+1 ) as p3
,case when vs.VirtualIPAddress.IPAddress like '%:%' then replace(vs.VirtualIPAddress.IPAddress, ':', '') END as IP6
,'LTM' as Type, '/Orion/F5/F5LTMDetails.aspx?NetObject=F5LTM:' + TOSTRING(n.nodeid) as _linkfor_Type
, n.Caption as F5, n.DetailsUrl as _linkfor_F5
, '/Orion/images/StatusIcons/Small-' + n.StatusLED as _iconfor_F5
,vs.ShortName as Virtual_Server
,'/Orion/F5/F5VirtualServerDetails.aspx?NetObject=F5VS:' + TOSTRING( vs.VirtualServerID) as _linkfor_Virtual_Server
,'/Orion/images/StatusIcons/Small-' + case vs.F5Status when 4 then 'UNKNOWN' when 1 then 'UP' when 3 then 'DOWN' end + '.gif' as _iconfor_Virtual_Server
,vs.Port
,case when vs.F5StatusReason <> 'The virtual server is available' then vs.F5statusReason end as Detail
FROM Orion.F5.LTM.VirtualServer vs
inner join Orion.Nodes n
on vs.NodeID = n.NodeID
where '0.0.0.0' <> vs.VirtualIPAddress.IPAddress and n.Caption like '%APM%'
) as p1
) as p2
Table Layout
Netflow Data
HTML:
<iframe name="f5_nta" style="width:100%;height:750px;" src="/Orion/DetachResource.aspx?ResourceID=1488&NetObject=NSF%3aT%3aLast+2+Hours%3bFD%3aBoth%3bIPV%3aBoth%3bE%3a115178104172"></iframe>
Great piece of work and well written up, double kudos for sharing.
Well done! I've gotten tagged to write some queries for F5 before but this is so much more awesome!
Yes, please do share. I really like what I see here and would like to do something similar.
SolarWinds solutions are rooted in our deep connection to our user base in the THWACK® online community. More than 150,000 members are here to solve problems, share technology and best practices, and directly contribute to our product development process.