PRODUCT DOCUMENTATION
SHARE TO SOCIAL

Cisco UCS X-Series Modular System Monitoring

Last updated - 30 July, 2025

LogicMonitor offers out-of-the-box monitoring for Cisco UCS X-Series Chassis, Servers, and Fabric Interconnects. This package uses the Cisco Intersight Telemetry API to retrieve metrics and inventory data. SNMP and Syslog provide additional layers for Fabric Interconnect monitoring. UCS X-Series Servers can also be monitored using hypervisor-specific modules.

Requirements for Cisco UCS X-Series Modular System Monitoring

To enable Cisco UCS X-Series monitoring, you need the following:

  • Collector version must support LogicMonitor_Collector_Snippets
  • Cisco Intersight API Key (ID and Secret Key or Secret Location)
    For more information, see Creating Intersight API Keys from Cisco. 

Adding Cisco UCS X-Series Resources into Monitoring

You can either add Cisco UCS X-Series resources by running a NetScan or add the resources manually.  For more information, see NetScan Overview.

Recommendation: Using a NetScan to add resources is the preferred method as it creates devices under device groups for each Cisco organization site.

Using Advanced NetScan to add Cisco UCS X-Series Resources

For more information, see Enhanced Script NetScan.

  1. In the LogicMonitor Portal, navigate to Modules > Exchange, and install the Cisco UCS X-Series LogicModules.
  2. Navigate to Resources > Add > Several Devices > Advanced NetScan.
  3. Enter a name for the NetScan (For example, “Cisco UCS X-Series”).
  4. Select the Collector to execute the NetScan.
  5. Choose Enhanced Script NetScan from the Method drop-down menu.
  6. In the Device Credentials field, select Use custom credentials for this scan.
  7. Add the following required and optional properties:
PropertiesValueRequired
cisco.intersight.account.idIntersight Account IDYes
cisco.intersight.key.idAPI Key IDYes
cisco.intersight.secret.keySecret KeyYes*
cisco.intersight.secret.locationPath to secret key fileYes*
lmaccess.id or logicmonitor.access.idLogicMonitor API Access IDYes**
lmaccess.key or logicmonitor.access.keyLogicMonitor API Access KeyYes**
skip.device.dedupeSkips device deduplication checksNo
hostname.sourceDetermines source of hostname to avoid conflictsNo
cisco.ucsx.org.nameOrganization name (default: UCSXOrganization)No
cisco.ucsx.org.folderResource Group name in LogicMonitorNo
cisco.intersight.moidDevice IDNo
cisco.intersight.modelDevice ModelNo
cisco.intersight.serialSerial NumberNo

* Required unless cisco.intersight.secret.location is used.
** Required unless skip.device.dedupe is set.

  1.  Select Embed a Groovy script and embed the following script:

Warning: Do not edit the script. Edited Enhanced Script NetScans are not supported. If the LogicMonitor-provided script is edited, LogicMonitor Support may (at their discretion) require you to overwrite your edits with the supported script if problems arise.

/*******************************************************************************
*  © 2007-2025 - LogicMonitor, Inc. All rights reserved.
 ******************************************************************************/

import com.santaba.agent.groovy.utils.GroovyScriptHelper as GSH
import com.logicmonitor.mod.Snippets
import com.santaba.agent.AgentVersion
import java.text.DecimalFormat

// To run in debug mode, set to true
Boolean debug = false
// To enable logging, set to true
Boolean log = false

// Set props object based on whether or not we are running inside a netscan or debug console
def props
try {
    hostProps.get("system.hostname")
    props = hostProps
    debug = true  // set debug to true so that we can ensure we do not print sensitive properties
}
catch (MissingPropertyException) {
    props = netscanProps
}

def accountId = props.get("cisco.intersight.account.id")
def keyId = props.get("cisco.intersight.key.id")
def secretKey = props.get("cisco.intersight.secret.key")
def secretKeyLocation = props.get("cisco.intersight.secret.location")

if (!accountId) {
    throw new Exception("Must provide cisco.intersight.account.id to run this script.  Verify necessary credentials have been provided in Netscan properties.")
}
if (!keyId) {
    throw new Exception("Must provide cisco.intersight.key.id to run this script.  Verify necessary credentials have been provided in Netscan properties.")
}
if (!secretKey && !secretKeyLocation) {
    throw new Exception("Must provide cisco.intersight.secret.key or cisco.intersight.secret.location to run this script.  Verify necessary credentials have been provided in Netscan properties.")
}

def logCacheContext = "${accountId}:cisco-ucsx"
Boolean skipDeviceDedupe = props.get("skip.device.dedupe", "true").toBoolean()
String hostnameSource    = props.get("hostname.source", "")?.toLowerCase()?.trim()

Integer collectorVersion = AgentVersion.AGENT_VERSION.toInteger()
 
// Bail out early if we don't have the correct minimum collector version to ensure netscan runs properly
if (collectorVersion < 32400) {
    def formattedVer = new DecimalFormat("00.000").format(collectorVersion / 1000)
    throw new Exception("Upgrade collector running netscan to 32.400 or higher to run full featured enhanced netscan. Currently running version ${formattedVer}.")
}

def modLoader = GSH.getInstance(GroovySystem.version).getScript("Snippets", Snippets.getLoader()).withBinding(getBinding())
def emit        = modLoader.load("lm.emit", "1.1")
def lmDebugSnip = modLoader.load("lm.debug", "1")
def lmDebug     = lmDebugSnip.debugSnippetFactory(out, debug, log, logCacheContext)
def httpSnip    = modLoader.load("proto.http", "0")
def http        = httpSnip.httpSnippetFactory(props)

// Only initialize lmApi snippet class if customer has not opted out
def lmApi
if (!skipDeviceDedupe) {
    def lmApiSnippet = modLoader.load("lm.api", "0")
    lmApi = lmApiSnippet.lmApiSnippetFactory(props, http, lmDebug)
}
def ciscoUCSXSnip = modLoader.load("cisco.ucsx", "0")
def ciscoUCSX     = ciscoUCSXSnip.ciscoUCSXSnippetFactory(hostProps, lmDebug, http)

String orgDisplayname       = props.get("cisco.ucsx.org.name") ?: "UCSXOrganization"
String rootFolder           = props.get("cisco.ucsx.org.folder") ? props.get("cisco.ucsx.org.folder") + "/" : ""
String serviceUrl           = props.get("cisco.intersight.url")
def addDeviceApiKey= props.get("cisco.ucsx.key.addToAllDevices") == null ? true : props.get("cisco.ucsx.key.addToAllDevices").toBoolean()

// Get information about devices that already exist in LM portal
List fields = ["name", "currentCollectorId", "displayName"]
Map args = ["size": 1000, "fields": fields.join(",")]
def lmDevices
// But first determine if the portal size is within a range that allows us to get all devices at once
def pathFlag, portalInfo, timeLimitSec, timeLimitMs
if (!skipDeviceDedupe) {
    portalInfo = lmApi.apiCallInfo("Devices", args)
    timeLimitSec = props.get("lmapi.timelimit.sec", "60").toInteger()
    timeLimitMs = (timeLimitSec) ? Math.min(Math.max(timeLimitSec, 30), 120) * 1000 : 60000 // Allow range 30-120 sec if configured; default to 60 sec

    if (portalInfo.timeEstimateMs > timeLimitMs) {
        lmDebug.LMDebugPrint("Estimate indicates LM API calls would take longer than time limit configured.  Proceeding with individual queries by display name for each device to add.")
        lmDebug.LMDebugPrint("\t${portalInfo}\n\tNOTE:  Time limit is set to ${timeLimitSec} seconds.  Adjust this limit by setting the property lmapi.timelimit.sec.  Max 120 seconds, min 30 seconds.")
        pathFlag = "ind"
    }
    else {
        lmDebug.LMDebugPrint("Response time indicates LM API calls will complete in a reasonable time range.  Proceeding to collect info on all devices to cross reference and prevent duplicate device creation.\n\t${portalInfo}")
        pathFlag = "all"
        lmDevices = lmApi.getPortalDevices(args)
    }
}

List<Map> resources = []

def now = new Date()
def dateFormat = "yyyy-MM-dd'T'HH:mm:ss.s z"
TimeZone tz = TimeZone.getDefault()
Map duplicateResources = [
    "date" : now.format(dateFormat, tz),
    "message" : "Duplicate device names and display names, keyed by display name that would be assigned by the netscan, found within LogicMonitor portal.  Refer to documentation for how to resolve name collisions using 'hostname.source' netscan property.",
    "total" : 0,
    "resources" : []
]

def chasses = ciscoUCSX.slurper.parseText(ciscoUCSX.intersightAPISingleGet("equipment/Chasses")).Results
if (!chasses) {
    throw new Exception("Error occurred during GET request to equipment/Chasses")
}

def serverInfo = ciscoUCSX.slurper.parseText(ciscoUCSX.intersightAPISingleGet("compute/PhysicalSummaries")).Results
if (!serverInfo) {
    throw new Exception("Error occurred during GET request to compute/PhysicalSummaries")
}

def fabricInterconnects = ciscoUCSX.slurper.parseText(ciscoUCSX.intersightAPISingleGet("network/Elements")).Results.findAll { it.SwitchType == "FabricInterconnect" }
if (!fabricInterconnects) {
    throw new Exception("Error occurred during GET request to network/Elements filtered for SwitchType=FabricInterconnect")
}

def chassisMoidToName = [:]
chasses.each { chassis ->
    def model = chassis.Model
    if (!model.contains("UCSX")) return

    def name = chassis.Name
    def ip = name
    def moid = chassis.Moid
    def serial = chassis.Serial

    chassisMoidToName.put(moid, name)

    // Skip devices that do not have an IP and name; we must have at least one to create a device
    if (!ip && !name) return

    String displayName = name

    // Check for existing device in LM portal with this displayName; set to false initially and update to true when dupe found
    def deviceMatch = false
    // If customer has opted out of device deduplication checks, we skip the lookups where we determine if a match exists and proceed as false
    if (!skipDeviceDedupe) {
        if (pathFlag == "ind") {
            deviceMatch = lmApi.findPortalDevice(displayName, args)
            if (!deviceMatch) deviceMatch = lmApi.findPortalDeviceByName(ip, args)
        }
        else if (pathFlag == "all") {
            deviceMatch = lmApi.checkExistingDevices(displayName, lmDevices)
            if (!deviceMatch) deviceMatch = lmApi.checkExistingDevicesByName(ip, lmDevices)
        }
    }
    if (deviceMatch) {
        // Log duplicates that would cause additional devices to be created; unless these entries are resolved, they will not be added to resources for netscan output
        def collisionInfo = [
            (displayName) : [
                "Netscan" : [
                    "hostname"    : ip,
                    "displayName" : displayName
                ],
                "LM" : [
                    "hostname"    : deviceMatch.name,
                    "collectorId" : deviceMatch.currentCollectorId,
                    "displayName" : deviceMatch.displayName
                ],
                "Resolved" : false
            ]
        ]

        // If user specified to use LM hostname on display name match, update hostname variable accordingly
        // and flag it as no longer a match since we have resolved the collision with user's input
        if (hostnameSource == "lm" || hostnameSource == "logicmonitor") {
            ip = deviceMatch.name
            deviceMatch = false
            collisionInfo[displayName]["Resolved"] = true
        }
        // If user specified to use netscan data for hostname, update the display name to make it unique
        // and flag it as no longer a match since we have resolved the collision with user's input
        else if (hostnameSource == "netscan") {
            // Update the resolved status before we change the displayName
            collisionInfo[displayName]["Resolved"] = true
            displayName = "${displayName} - ${ip}"
            deviceMatch = false
        }

        duplicateResources["resources"].add(collisionInfo)
    }

    // Verify we have minimum requirements for device creation
    if (ip) {
        def deviceProps = [
            "cisco.intersight.account.id"   : emit.sanitizePropertyValue(accountId),
            "cisco.intersight.moid"         : emit.sanitizePropertyValue(moid),
            "cisco.intersight.model"        : emit.sanitizePropertyValue(model),
            "cisco.intersight.serial"       : emit.sanitizePropertyValue(serial),
            "system.categories"             : "CiscoUSCXChassis,NoPing"
        ]

        if (addDeviceApiKey) {
            deviceProps.put("cisco.intersight.key.id", keyId)
            if (secretKey) deviceProps.put("cisco.intersight.secret.key", keyId)
            if (secretKeyLocation) deviceProps.put("cisco.intersight.secret.location", keyId)
        }

        if (serviceUrl) deviceProps.put("cisco.intersight.url", serviceUrl)

        // Set group and collector ID based on user CSV inputs if provided
        def collectorId = null
        Map resource = [
            "hostname"    : ip,
            "displayname" : name,
            "hostProps"   : deviceProps,
            "groupName"   : ["${rootFolder}${orgDisplayname}/Chasses/${name}"]
        ]

        // Only add the collectorId field to resource map if we found a collector ID above
        if (collectorId) {
            resource["collectorId"] = collectorId
            if (duplicateResources["resources"][displayName]["Netscan"][0]) duplicateResources["resources"][displayName]["Netscan"][0]["collectorId"] = collectorId
        }

        if (!deviceMatch) {
            resources.add(resource)
        }
    }
}

serverInfo.each { server ->
    def model = server.Model
    if (!model.contains("UCSX")) return

    def name = server.Name
    def ip = server.MgmtIpAddress
    def moid = server.Moid
    def serial = server.Serial
    def chassisMoid = server.EquipmentChassis.Moid
    def chassisName = chassisMoidToName.get(chassisMoid)

    // Skip devices that do not have an IP and name; we must have at least one to create a device
    if (!ip && !name) return

    String displayName = name

    // Check for existing device in LM portal with this displayName; set to false initially and update to true when dupe found
    def deviceMatch = false
    // If customer has opted out of device deduplication checks, we skip the lookups where we determine if a match exists and proceed as false
    if (!skipDeviceDedupe) {
        if (pathFlag == "ind") {
            deviceMatch = lmApi.findPortalDevice(displayName, args)
            if (!deviceMatch) deviceMatch = lmApi.findPortalDeviceByName(ip, args)
        }
        else if (pathFlag == "all") {
            deviceMatch = lmApi.checkExistingDevices(displayName, lmDevices)
            if (!deviceMatch) deviceMatch = lmApi.checkExistingDevicesByName(ip, lmDevices)
        }
    }

    if (deviceMatch) {
        // Log duplicates that would cause additional devices to be created; unless these entries are resolved, they will not be added to resources for netscan output
        def collisionInfo = [
            (displayName) : [
                "Netscan" : [
                    "hostname"    : ip,
                    "displayName" : displayName
                ],
                "LM" : [
                    "hostname"    : deviceMatch.name,
                    "collectorId" : deviceMatch.currentCollectorId,
                    "displayName" : deviceMatch.displayName
                ],
                "Resolved" : false
            ]
        ]

        // If user specified to use LM hostname on display name match, update hostname variable accordingly
        // and flag it as no longer a match since we have resolved the collision with user's input
        if (hostnameSource == "lm" || hostnameSource == "logicmonitor") {
            ip = deviceMatch.name
            deviceMatch = false
            collisionInfo[displayName]["Resolved"] = true
        }
        // If user specified to use netscan data for hostname, update the display name to make it unique
        // and flag it as no longer a match since we have resolved the collision with user's input
        else if (hostnameSource == "netscan") {
            // Update the resolved status before we change the displayName
            collisionInfo[displayName]["Resolved"] = true
            displayName = "${displayName} - ${ip}"
            deviceMatch = false
        }

        duplicateResources["resources"].add(collisionInfo)
    }

    // Verify we have minimum requirements for device creation
    if (ip) {
        if (ip == "127.0.0.1") ip = name
        if (!name) name = ip
        def deviceProps = [
            "cisco.intersight.account.id"   : emit.sanitizePropertyValue(accountId),
            "cisco.intersight.moid"         : emit.sanitizePropertyValue(moid),
            "cisco.intersight.chassis.moid" : emit.sanitizePropertyValue(chassisMoid),
            "cisco.intersight.model"        : emit.sanitizePropertyValue(model),
            "netscan.serial"                : emit.sanitizePropertyValue(serial),
            "system.categories"             : "CiscoUSCXServer"
        ]

        if (addDeviceApiKey) {
            deviceProps.put("cisco.intersight.key.id", keyId)
            if (secretKey) deviceProps.put("cisco.intersight.secret.key", keyId)
            if (secretKeyLocation) deviceProps.put("cisco.intersight.secret.location", keyId)
        }

        if (serviceUrl) deviceProps.put("cisco.intersight.url", serviceUrl)

        // Set group and collector ID based on user CSV inputs if provided
        def collectorId = null
        Map resource = [
                "hostname"    : ip,
                "displayname" : name,
                "hostProps"   : deviceProps,
                "groupName"   : ["${rootFolder}${orgDisplayname}/Chasses/${chassisName}/Servers"]
        ]

        // Only add the collectorId field to resource map if we found a collector ID above
        if (collectorId) {
            resource["collectorId"] = collectorId
            if (duplicateResources["resources"][displayName]["Netscan"][0]) duplicateResources["resources"][displayName]["Netscan"][0]["collectorId"] = collectorId
        }

        if (!deviceMatch) {
            resources.add(resource)
        }
    }
}

fabricInterconnects.each { fabricInterconnect ->
    def model = fabricInterconnect.Model
    if (!model.contains("UCSX")) return

    def name = fabricInterconnect.SwitchProfileName.replace("-A", " FI-A").replace("-B", " FI-B")
    def ip = fabricInterconnect.OutOfBandIpAddress
    def moid = fabricInterconnect.Moid
    def serial = fabricInterconnect.Serial

    // Skip devices that do not have an IP and name; we must have at least one to create a device
    if (!ip && !name) return

    String displayName = name

    // Check for existing device in LM portal with this displayName; set to false initially and update to true when dupe found
    def deviceMatch = false
    // If customer has opted out of device deduplication checks, we skip the lookups where we determine if a match exists and proceed as false
    if (!skipDeviceDedupe) {
        if (pathFlag == "ind") {
            deviceMatch = lmApi.findPortalDevice(displayName, args)
            if (!deviceMatch) deviceMatch = lmApi.findPortalDeviceByName(ip, args)
        }
        else if (pathFlag == "all") {
            deviceMatch = lmApi.checkExistingDevices(displayName, lmDevices)
            if (!deviceMatch) deviceMatch = lmApi.checkExistingDevicesByName(ip, lmDevices)
        }
    }
    if (deviceMatch) {
        // Log duplicates that would cause additional devices to be created; unless these entries are resolved, they will not be added to resources for netscan output
        def collisionInfo = [
            (displayName) : [
                "Netscan" : [
                    "hostname"    : ip,
                    "displayName" : displayName
                ],
                "LM" : [
                    "hostname"    : deviceMatch.name,
                    "collectorId" : deviceMatch.currentCollectorId,
                    "displayName" : deviceMatch.displayName
                ],
                "Resolved" : false
            ]
        ]

        // If user specified to use LM hostname on display name match, update hostname variable accordingly
        // and flag it as no longer a match since we have resolved the collision with user's input
        if (hostnameSource == "lm" || hostnameSource == "logicmonitor") {
            ip = deviceMatch.name
            deviceMatch = false
            collisionInfo[displayName]["Resolved"] = true
        }
        // If user specified to use netscan data for hostname, update the display name to make it unique
        // and flag it as no longer a match since we have resolved the collision with user's input
        else if (hostnameSource == "netscan") {
            // Update the resolved status before we change the displayName
            collisionInfo[displayName]["Resolved"] = true
            displayName = "${displayName} - ${ip}"
            deviceMatch = false
        }

        duplicateResources["resources"].add(collisionInfo)
    }

    // Verify we have minimum requirements for device creation
    if (ip) {
        if (ip == "127.0.0.1") ip = name
        if (!name) name = ip
        def deviceProps = [
            "cisco.intersight.account.id" : emit.sanitizePropertyValue(accountId),
            "cisco.intersight.moid"       : emit.sanitizePropertyValue(moid),
            "cisco.intersight.model"      : emit.sanitizePropertyValue(model),
            "netscan.serial"              : emit.sanitizePropertyValue(serial),
            "system.categories"           : "CiscoUSCXFabricInterconnect"
        ]

        if (addDeviceApiKey) {
            deviceProps.put("cisco.intersight.key.id", keyId)
            if (secretKey) deviceProps.put("cisco.intersight.secret.key", keyId)
            if (secretKeyLocation) deviceProps.put("cisco.intersight.secret.location", keyId)
        }

        //if (networksWhitelist != null) deviceProps.put("cisco.ucsx.org.networks", emit.sanitizePropertyValue(networksWhitelist))

        if (serviceUrl) deviceProps.put("cisco.intersight.url", serviceUrl)

        // Set group and collector ID based on user CSV inputs if provided
        def collectorId = null
        Map resource = [
                "hostname"    : ip,
                "displayname" : name,
                "hostProps"   : deviceProps,
                "groupName"   : ["${rootFolder}${orgDisplayname}/Fabric Interconnects"]
        ]

        // Only add the collectorId field to resource map if we found a collector ID above
        if (collectorId) {
            resource["collectorId"] = collectorId
            if (duplicateResources["resources"][displayName]["Netscan"][0]) duplicateResources["resources"][displayName]["Netscan"][0]["collectorId"] = collectorId
        }

        if (!deviceMatch) {
            resources.add(resource)
        }
    }
}

lmDebug.LMDebugPrint("Duplicate Resources:")
duplicateResources.resources.each {
    lmDebug.LMDebugPrint("\t${it}")
}

emit.resource(resources, debug)

return 0
  1.  In the Schedule section, enable the Run this NetScan on a schedule switch. You may run the scan as often as hourly.
  2. Select Save or Save & Run.

Manually Adding Resources 

  1. Create a Cisco UCS X-Series Organization device group. For more information, see Adding Resource Groups.
  2. Add the devices to the group.
  3. Set the following properties on each resource:
PropertyValue
cisco.intersight.account.idAccount ID from Intersight UI
cisco.intersight.key.idIntersight API Key ID
cisco.intersight.secret.keyAPI Secret Key (if no file path used)
cisco.intersight.secret.locationFile path to API Secret Key (if used)

NetScan Troubleshooting

The NetScan for this suite can update existing devices in the portal to add relevant information retrieved from the Cisco UCS X-Series API. It is also possible for the NetScan to create duplicate devices in the portal when a conflict exists where the display name is the same, but the value for system.hostname is different. To ensure devices are updated properly and duplicate devices are not created, this NetScan uses LogicMonitor’s API to query existing devices and report name conflicts discovered. This file can be accessed in the collector logs.

For more information on retrieving collector logs, see Collector Logging – Sending Logs to LogicMonitor.

The devices in this report are not reported to LogicMonitor as part of the NetScan output unless the NetScan has been configured with the property hostname.source. This property allows a user to resolve the name conflicts discovered by selecting the source of the hostname that is used in the NetScan output. Two possible hostname sources are determined by the following values:

  • “lm” or “logicmonitor” Devices with name conflicts use the existing system.hostname in LogicMonitor to ensure a device in the portal is updated using the NetScan. This setting does not create a new device.
  • “netscan” Devices with name conflicts maintain system.hostname determined in the NetScan script and update the display name reported to append – <system.hostname> to ensure it is unique and can be added to the portal. This option is beneficial if you do not have strict naming conventions and have multiple devices with the same display name.

Note: NetScans are not able to update the value of system.hostname. NetScans can update display name, custom properties, and group assignments.

Import LogicModules

Import all Cisco UCS X-Series LogicModules from the LogicMonitor public repository. See the list of LogicModules in Package. If these LogicModules are already present, make sure you have the most recent versions.

Assuming all previous setup requirements have been met, data collection will automatically start once the LogicModules are imported.​ 

LogicModules in Package

LogicMonitor’s package for Cisco UCS X-Series consists of the following LogicModules. For full coverage, make sure that all of these LogicModules are imported into your LogicMonitor platform.

Display NameTypeDescription
addCategory_Cisco_UCSX_DevicePropertySourceAdds Cisco UCS-X system category and properties
UCS X Chassis FansDataSourceMonitors chassis fan performance
UCS X Chassis HealthDataSourceMonitors chassis health and power usage
UCS X Chassis Power SuppliesDataSourceMonitors power supply unit performance
UCS X Fabric Interconnect CPUDataSourceMonitors FI CPU metrics
UCS X Fabric Interconnect FansDataSourceMonitors FI fan modules
UCS X Fabric Interconnect HealthDataSourceMonitors FI health, energy, and power usage
UCS X Fabric Interconnect MemoryDataSourceMonitors FI memory usage
UCS X Fabric Interconnect Power SuppliesDataSourceMonitors FI power supply metrics
UCS X Fabric Interconnect TemperatureDataSourceMonitors FI temperature
UCS X Server HealthDataSourceMonitors server health, energy, and power usage
UCS X Server TemperatureDataSourceMonitors server temperature
addERI_Cisco_UCSX_DevicePropertySourceAdds UCS-X-specific ERI properties
Cisco_UCSX_TopologyTopologySourceMaps UCS X-Series topology

When setting static datapoint thresholds on the various metrics tracked by this package’s DataSources, LogicMonitor follows the technology owner’s best practice KPI recommendations.

Recommendation: If necessary, LogicMonitor encourages you to adjust these predefined thresholds to meet the unique needs of your environment. For more information on tuning datapoint thresholds, see Static Thresholds for Datapoints.