VMware vSphere Monitoring

Last updated on 30 October, 2023

LogicMonitor offers out-of-the-box monitoring for the VMware vSphere. This monitoring suite leverages the vSphere Web Services and Automation APIs to monitor VMware vCenter Server Appliances (VCSA), VMware ESXi hosts, and Virtual Machines:

Compatibility

As of July 2023, LogicMonitor’s VMware vSphere package is known to be compatible with:

  • VMware vCenter Server Appliance 6.7 through vCenter Server 8.0.x
  • VMware ESXi 6.5 GA through ESXi 8.0.x

Setup Requirements

  • VMware vSphere LogicModules
  • LogicMonitor_Collector_Snippets DataSource
  • Collector 32.400 or later
  • vCenter and ESXi Read-Only User credentials
  • VMWare Tools
    You can download VMware Tools from VMWare Customer Connect.

Note: vSphere performance counters must be enabled and configured with the default settings (counter level and interval). Using a non-default configuration can potentially cause some datapoints to not properly report data.

Creating or Selecting a Read-Only User

The process of creating a read-only user varies if you monitor standalone ESXi hosts or a vCenter server.

  • ESXi Host: For more information, see the following:
  • vCenter Server:
    • If vCenter is integrated with Active Directory (AD), a group in vCenter that has a corresponding group in AD. Create a user with read-only permissions for your vCenter environment in AD and add it to the corresponding AD group. Your credentials for vCenter will be in the format of username@domain ([email protected]) with its password.
    • If vCenter is not integrated with AD, you will have to create a new read-only using a process similar to that for creating an ESXi host user. However, it’s important to note that a key difference between ESXi host and vCenter is that vCenter credentials are formatted as [email protected] (e.g. [email protected]) with password.

Adding VMware vSphere Resources

Recommendation: To add VMware vSphere resources, use the Enhanced Script Netscan method with the Groovy script, property, and filter settings. For more information, see Enhanced Script Netscan. Alternatively, see “Manually Assigning Properties to Resources”.

For a given VMware vCenter, the Enhanced Script Netscan creates a Resource Group with nested Resource Groups and Resources to match your vCenter Organizational Structure of Datacenters, Clusters, Resource Pools, User-Defined vCenter Folders, ESXi Hosts, and Virtual Machines. The NetScan properties and filters allows you to control what Resource Groups are created and what ESXi Hosts and Virtual Machines are added to LogicMonitor as Resources.

Warning: If you do not configure the LogicMonitor recommended filters (listed), the NetScan attempts to add all ESXi Hosts and Virtual Machines defined in the target vCenter environment as discrete LogicMonitor resources.

  1. In your LogicMonitor Portal > Modules > Exchange, install the VMware vSphere LogicModules.
  2. Navigate to Resources > Add > Several Devices > Advanced NetScan.
    The Add Advanced NetScan page is displayed
  3. Enter a name that you want to associate with this NetScan. For example, “VMware vCenter” or “VMware vSphere”. 
  4. Select the Collector to execute the NetScan.
    By default, the NetScan assigns new resources to the collector executing the NetScan
  5. Select Enhanced Script NetScan from the Method drop-down list.
  6. From the Enhanced Script section, select Device Credentials > Use custom credentials for this scan.
  7. Add the following properties that provide the NetScan with the required VMware API credentials and change how and where the NetScan creates and organizes resources.
PropertyValueExampleRequired
vcenter.uservCenter read-only user[email protected]Yes
vcenter.passvCenter read-only password************Yes
vcenter.hostnameHostname for the vCenter

If a vcenter.url is not set, this value will be used to attempt to connect to the vCenter.
IP Address or FQDNYes
vcenter.displaynameDisplay Name for the vCenter Server Appliancevcenter01Yes
vcenter.urlURL to access the VCSAhttps://<vcenter.hostname>/sdkNo
esx.userCredential to use for connecting to the ESXi host

The same credential is used for every ESXi host. If the property is not set, then the credentials specified for the vCenter are used. If you are unable to connect to the host with the provided credentials, the device is still discovered, and the credentials must be manually set on the ESXi Host Resources or parent Resource Groups.
readonly_userNo
esx.passCredential to use for connecting to the ESXi host.************No
rootFolderRoot folder where all discovered devices are placed in LogicMonitor. Value can be nested. If the Resource Group does not exist, the NetScan creates it.Customer01/VMware vSphere/vCenter01/No
discover.esxiWhen true, LogicMonitor adds esxi Hosts.
Note: This property has no impact on virtual machine discovery, these properties can be individually toggled.
true, false (default is true)No
discover.vmWhen true, LogicMonitor discovers the VMs.

Note: This property has no impact on ESXi discovery, these properties can be individually toggled.


true, false (default is true)
No
view.hostAndClusterToggle to create the host and cluster inventory view:
Datacenter > Cluster > Host > Resource pool > VM

When true, LogicMonitor recreates this folder structure.
true, false (default is true)No
view.vmsAndTemplatesToggle to create the VM and templates inventory view:
Datacenter > Cluster > Folder > VM

LogicMonitor recreates this folder structure.
Note: Regardless of the option, VM templates are not discovered.
true, false (default is true)No
view.standaloneVmToggle when the host and cluster view is used, and when VMs that are not in a resource pool are placed into a default folder called Standalone VMs.

LogicMonitor recreates this folder structure. 
true, false (default is true)No
  1. In the Filters section, use the following filter properties to omit specific Resources (Virtual Machines, ESXi Hosts) from discovery.
    These filters behave the same way as Active Discovery filters. The following device level properties are automatically discovered and can be filtered on. Available filter operations include: Equal, NotEqual, GreaterThan, GreaterEqual, LessThan, LessEqual, Contain, NotContain, Exist, NotExist, RegexMatch, RegexNotMatch
    The following list provides examples on how to use these filters. 

Recommendation: With large vCenter environments, you can incrementally change the filter operations or values to onboard monitored resources in stages. For example, you can configure the filters to only discover or import one datacenter at a time, or a few clusters at a time, so an Autobalanced Collector Group has time to distribute the monitoring workload. 

Warning: If you do not configure the listed filter properties, NetScan attempts to add all ESXi Hosts and Virtual Machines defined in the target vCenter environment.

PropertyOperationValueExampleRequired
netscan.foundDNSEqualNetScan was able to discover the Virtual Machine’s DNS name (true or false)TrueNo
netscan.powerstateEqualPower state at the time that the netscan was run. Used for filtering powered off Virtual Machines from discovery.poweredOnNo
vcenter.datacenterEqualUsed to filter out all VMs in a specific folder/resource pool/etc. One value per filter entry.DataCenter01No
NotEqualDataCenter02No
vcenter.clusterEqualvSphere Clusters whose resources you wish to discover/exclude. The default behavior is to discover/import all clusters for the targeted vCenter. One value per filter entry.Cluster01, Cluster02No
NotEqualDev,
Test
No
vcenter.resourcepoolEqualResource pools, whose resources you wish to discover/exclude.The Default behavior discovers/imports all vCenter Resource Pools as Resource Groups and all VMs as Resources. One value per filter entry.Prod, MissionCritical
vcenter.folderNotEqualvCenter Folders, whose resources you wish to discover/exclude. The Default behavior discovers/imports all vCenter Folders as Resource Groups and all VMs as Resources. One value per filter entry.vCLSNo
EqualMaryVMs, JosephsVMsNo
vcenter.hostnameRegexNotMatchESXi Hosts or Virtual Machines you want to discover or exclude. The Default behavior discovers or imports all vCenter ESXi Hosts and VMs as Resources. One value per filter entry..*[Tt]est.*No
vcenter.tagsNotEqualResources you want to discover or exclude based on tags of format category.tag.  The Default behavior ignores the values of VM tags. One value per filter entry.dev, test,  nomonitoringNo
  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. The Enhanced Script NetScan limits LM Envision Resource creation to <= 600 per hour. To create more than 600 Resources, schedule the NetScan to recur each hour until all resources are added.

/*******************************************************************************
 * © 2007-2023 - LogicMonitor, Inc. All rights reserved.
 ******************************************************************************/
 
import com.logicmonitor.common.sse.utils.GroovyScriptHelper
import com.logicmonitor.mod.Snippets
import com.santaba.agent.AgentVersion
import java.text.DecimalFormat
import com.vmware.vim25.InvalidLoginFaultMsg
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
 
def debug = false
def log = false
 
// Bail out early if we don't have the correct minimum collector version to ensure netscan runs properly
if (AgentVersion.AGENT_VERSION.toInteger() < 32400) {
    throw new Exception("Upgrade collector running netscan to 32.400 or higher to run full featured enhanced netscan. Currently running version ${new DecimalFormat('00.000').format(collectorVersion / 1000)}.")
}
 
// Set props object based on whether or not we are running inside a netscan or debug console
def props
// Required properties
def host, displayName
try {
    host = hostProps.get('system.hostname') // This is the vCenter
    props = hostProps
    displayName = props.get('system.displayname')
    debug = true  // Set debug to true to ensure we do not output sensitive properties
}
catch (MissingPropertyException) {
    props = netscanProps
    host = props.get('vcenter.hostname')
    displayName = props.get('vcenter.displayname') ?: host
}
 
// Required properties
def user = props.get('vcenter.user') ?: props.get('vcsa.user') ?: props.get('esx.user')
def pass = props.get('vcenter.pass') ?: props.get('vcsa.pass') ?: props.get('esx.pass')
def addr = props.get('vcenter.url')  ?: props.get('vcsa.url')  ?: props.get('esx.url') ?: "https://${host}/sdk"
 
// Optional properties
def eUser = props.get('esx.user') // Additional credentials for a standalone host
def ePass = props.get('esx.pass')
 
def rootFolder = props.get('rootFolder') // Root folder can be nested, i.e. 'site1/subfolder1'
 
// Default to true
def includeVMs                  = (props.get('discover.vm')                                                   ?: true).toBoolean() // Toggle if we want to discover VMs, true = discover
def includeESXiHosts            = (props.get('discover.esxi',        props.get('filter.esxiHosts'))           ?: true).toBoolean() // Toggle if we want to discover ESXi hosts, true = discover
def includeHostsAndClustersView = (props.get('view.hostandcluster',  props.get('filter.hostandclusterview'))  ?: true).toBoolean() // Toggle for if we want to create the Host and Cluster view, true = create
def includeVMsAndTemplatesView  = (props.get('view.vmsandtemplates', props.get('filter.vmsandtemplatesview')) ?: true).toBoolean() // Toggle for if we want to create the VM and templates view (only VMs will be discovered), true = create
def includeStandaloneVM         = (props.get('view.standaloneVm',    props.get('filter.standaloneVm'))        ?: true).toBoolean() // Toggle for if we want to create the standalone VM folder, true = create
binding.setProperty('includeStandaloneVM', includeStandaloneVM) // Make it global
 
// Default to false
def applyVCenterCredentialsToESXHost = (props.get('esx.vcentercredentials') ?: false).toBoolean() // Toggle for if we want standalone ESXi hosts to also get vcenter.user/pass credentials. Note the ESXi modules only care about the ESX credentials.
 
 
modLoader = GroovyScriptHelper.getInstance()._getScript('Snippets', Snippets.getLoader()).withBinding(getBinding())
def emit      = modLoader.load("lm.emit", "1.1")
def debugSnip = modLoader.load("lm.debug", "1.0")
def lmDebug   = debugSnip.debugSnippetFactory(out, debug, log, "VMware_vSphere_ESN")
def lmvSphere = modLoader.load("vmware.vsphere", "1.0")
def vSphere   = lmvSphere.vSphereWebServicesAPIFactory(addr, user, pass, lmDebug)
 
String cacheFilename = "VMware_${host}_devices"
Map sensitiveProps = [
    "vcenter.pass" : pass,
    "vcsa.pass"    : pass,
    "esx.pass"     : ePass,
]
 
// Determine whether there are devices cached on disk that still need to be added from previous netscan runs
if (processResourcesJson(emit, cacheFilename, sensitiveProps, lmDebug)) return 0
 
List<Map> resources = []
Map<String, String> ilpCredentials = [:]
Map tags
// Determine the vSphere host that we are making API queries to
Map<String, Integer> productType = ['vpx' :   0, 'embeddedEsx' : 1]
def productId = productType[vSphere.getAbout().productLineId]
switch (productId) {
    case 0: // vCenter
        ilpCredentials['vcenter.user'] = user
        ilpCredentials['vcenter.pass'] = pass
        ilpCredentials['vcenter.addr'] = addr
        tags = lmvSphere.vSphereAutomationAPIFactory(host, user, pass).withCloseable(){ it.getTagMap() } // Get all vCenter tags
        lmDebug.LMDebugPrint( "DEBUG: vCenter tags found: ${tags}" )
        break
    case 1: // ESXi
        ilpCredentials['esx.user'] = user
        ilpCredentials['esx.pass'] = pass
        ilpCredentials['esx.addr'] = addr
        break
        // gsx(VMware_Server) and esx(VMware_ESX) are not supported
}
 
def vms = vSphere.getMOs('VirtualMachine').each{ vSphere.updateEntityLineage(it) }
def hosts = vSphere.getMOs('HostSystem').each{ vSphere.updateEntityLineage(it) }
// Discover each VM
if (includeVMs) {
    vms.each { _vm ->
        Map device = [:]
 
        def MOR = _vm.MOR
        if (!MOR) {
            lmDebug.LMDebugPrint("DEBUG: MOR not found for ${_vm}, skipping")
            return
        }
 
        def compLine = vSphere.getComputeLineage(MOR?.val)
        def vmLine = vSphere.getVmLineage(MOR?.val)
        def compFolder = (includeHostsAndClustersView) ? folderFormatter(compLine, rootFolder) : null
        def vmFolder   = (includeVMsAndTemplatesView)  ? folderFormatter(vmLine,   rootFolder) : null
 
        if (!compFolder && !vmFolder) {
            lmDebug.LMDebugPrint("DEBUG: VM ${_vm.name} skipped due to no containing folder determined. This could be due to different filters being set.")
            return
        }
 
        def guest = _vm.guest
        def ips = []
 
        guest?.net?.eachWithIndex { nic, number -> ips << nic?.ipAddress }
        def hostname = ips.flatten().findAll { it.contains('.') }
 
        def foundDNS = true
        if (!hostname) { // Couldn't find any IPs
            lmDebug.LMDebugPrint("No IPs could not be found for VM: ${_vm.name}")
            if (guest?.hostName) {
                hostname[0] = guest?.hostName
            } else {
                hostname[0] = _vm.name
                foundDNS = false
            }
        }
 
        if (productId == 0 && hostname?.contains(host)) { // This is the vCenter VM
            def baseFolder = (vmFolder ?: folderFormatter(vmLine, rootFolder))?.split('/')[0]
            // Rely on the vmFolder here. If customer is not including standalone VMs, but the vCenter is a standalone VM, discover it anyway
            device = [
                    'hostname'   : "${host}",
                    'displayname': "${displayName}",
                    'hostProps'  : [
                            'system.categories': 'VMware_vCenter,VMware_VM'
                    ],
                    'groupName'  : [baseFolder, compFolder, vmFolder].minus(null)
            ]
        } else {
            device = [
                    'hostname'   : hostname[0],
                    'displayname': _vm.name,
                    'hostProps'  : [
                            'system.categories': 'VMware_VM'
                    ],
                    'groupName'  : [compFolder, vmFolder].minus(null)
            ]
        }
 
        // If the netscan is running on a vCenter device
        if (productId == 0) {
            // Add vCenter tags
            def tagP = tags[MOR?.value as String]?.values.collect { k, v ->
                v.collect { "${k}.${it}" }
            }.flatten().join(",")
            device.hostProps.'vcenter.tags' = tagP
 
            // Add all parent entities as device properties
            def lineage = lineageParser(compLine + vmLine)
            lineage.each { k, v -> device.hostProps?."vcenter.${k.toLowerCase()}" = v.join(',') }
        }
 
        device.hostProps.'netscan.powerstate' = _vm.runtime.powerState // Add power state for filtering
        device.hostProps.'netscan.foundDNS' = foundDNS as String
        device.hostProps += ilpCredentials
 
        resources.add(device)
    }
}
 
if (includeESXiHosts) {
    hosts.each{ _host ->
        Map device = [:]
 
        def MOR = _host.MOR
        if (!MOR) {
            lmDebug.LMDebugPrint( "DEBUG: MOR not found for ${_host}, skipping" )
            return
        }
 
        def compLine = vSphere.getComputeLineage(_host.MOR?.val)
        def compFolder = folderFormatter(compLine, rootFolder)
 
        def vSphere1
        lmDebug.LMDebugPrint( "DEBUG: Attempting to login to the ESX host ${_host}" )
 
        def addr1 = "https://${_host.name}/sdk"
        def user1 = eUser ?: user
        def pass1 = ePass ?: pass
        try {
            vSphere1 = lmvSphere.vSphereWebServicesAPIFactory(addr1, user1, pass1, 10, 10)
        } catch (InvalidLoginFaultMsg e) {
            lmDebug.LMDebugPrint( "DEBUG: Unable to login to ESXi host ${_host} at ${addr1}, skipping..." )
        }
        if (!vSphere1) {
            lmDebug.LMDebugPrint( "DEBUG: Unable to connect to ESXi host ${_host.name} with the provided credentials" )
 
            // We were unable to connect to the ESXi host directly, just add it as a standard device
            device = [
                    'hostname'   : _host.name,
                    'displayname': _host.name,
                    'hostProps'  : [:], // Do not set the system category 'VMware_ESXi' since we can't actually use this as an ESXi device
                    'groupName'  : ["${compFolder}/ESXi hosts"].minus(null)
            ]
        } else {
            lmDebug.LMDebugPrint( "DEBUG: Successful connection to ESXi host ${_host.name}" )
            def esxHost = vSphere1.getMOs('HostSystem')[0]
            device = [
                    'hostname'   : esxHost.name,
                    'displayname': esxHost.name,
                    'hostProps'  : [
                        'esx.user'         : user1,
                        'esx.pass'         : pass1,
                        'esx.addr'         : addr1,
                        'system.categories': 'VMware_ESXi'
                    ],
                    'groupName'  : ["${compFolder}/ESXi hosts"].minus(null)
            ]
        }
 
        device.hostProps.'vcenter.hostname' = host
        if (applyVCenterCredentialsToESXHost) { device.hostProps += ilpCredentials }
 
        // If the netscan is running on a vCenter device
        if (productId == 0) {
            // Add vCenter tags
            def tagP = tags[MOR?.value as String]?.values.collect{ k, v ->
                v.collect{ "${k}.${it}" }
            }.flatten().join(",")
            device.hostProps.'vcenter.tags' = tagP
 
            // Add all parent entities as device properties
            def lineage = lineageParser(compLine)
            lineage.each{ k, v -> device.hostProps?."vcenter.${k.toLowerCase()}" = v.join(',') }
        }
 
        resources.add(device)
    }
}
 
emitWriteJsonResources(emit, cacheFilename, resources, lmDebug)
 
return 0
 
 
/**
 * Function for transforming the inventory view/device lineage -> formatted LM group structure
 *
 * @param lineage Lineage generated from vSphere.getComputeLineage/vSphere.getVMLineage functions
 * @param rootFolder optional property to set the root folder for the vSphere that all other folders will be nested in
 * @return String of the formatted folder for netscan groupName parameter
 */
String folderFormatter(List<Map> lineage, String rootFolder = '') {
    if (lineage.size() > 1) {
        def folder = lineage.collect{
            switch (it.type.toUpperCase()) {
                case 'FOLDER' :
                    if (it.parent[0] == null) { // This is the parent folder
                        return ((rootFolder) ?: "VMware - ${it.name}")
                    } else if (it.name == 'vm') {
                        return 'VMs' // VMs and templates folder
                    } else {
                        return it.name
                    }
                    break
                case 'DATACENTER' :
                    return "Datacenter - ${it.name}"
                    break
                case 'CLUSTERCOMPUTERESOURCE' :
                    return "Cluster - ${it.name}"
                    break
                case 'RESOURCEPOOL' :
                    return "Resource Pool - ${it.name}"
                    break
                case 'VIRTUALMACHINE' :
                case 'HOSTSYSTEM' :
                    // The devices we want to discover
                    return it.name
                    break
                case 'COMPUTERESOURCE' :
                    return 'Standalone ESXi hosts'
                default:
                    return it.name
            }
            // Don't put the device in a folder named after it
        }[0..-2]
 
        if (lineage.size() >= 2) {
            // Check for standalone VMs that are not in a resourcePool, and put them in their own standalone folder
            if ( lineage[-1].type == 'VIRTUALMACHINE' && (lineage[-2].type != 'RESOURCEPOOL' && lineage[-2].type != 'FOLDER')) {
                if (includeStandaloneVM) {
                    folder << 'Standalone VMs'
                } else {
                    // This is a standalone, and if we don't want to include it, return nothing
                    return null
                }
            }
        }
        return folder.join('/')
    } else {
        return
    }
}
 
 
/**
 * Determines which nested folders/datacenter/cluster/resourcepool/etc. that an object belongs to.
 * Ignores the auto-generated folders that all VMs exist in. These folders are not visible in the VM, but do exist in the backend
 *
 * @param lineage Lineage generated from vSphere.getComputeLineage/vSphere.getVMLineage functions
 * @return Map of the folders/datacenter/cluster/resourcepool/etc. that are provided from the lineage
 */
Map<String, List<String>> lineageParser(List<Map> lineage) {
    Map<String, List<String>> out = [:].withDefault{[]}
 
    lineage.each{ out[it?.type] << it?.name }
    out.collectEntries{ k, v ->
        v.unique()
        switch (k.toUpperCase()) {
            case 'CLUSTERCOMPUTERESOURCE':
                k = 'CLUSTER'
                break
            case 'FOLDER':
                v.remove('vm') // Autogenerated folders
                v.remove('Datacenters')
                break
        }
        _out = [k, v]
    }
}
 
 
/**
 * Sanitizes filepath and instantiates File object
 *
 * @param filename String
 * @param fileExtension String
 * @return File object using sanitized relative filepath
*/
File newFile(String filename, String fileExtension) {
    // Ensure relative filepath is complete with extension type
    def filepath
    if (!filename.startsWith("./")) {
        filepath = "./${filename}"
    }
    if (!filepath.endsWith(".${fileExtension}")) {
        filepath = "${filepath}.${fileExtension}"
    }
 
    return new File(filepath)
}
 
 
/**
 * Replaces cached props stored with bogus values with their correct values
 *
 * @param cachedProps Map of hostProps values stored in file cache
 * @param sensitiveProps Map of sensitive properties configured in the netscan to use for updating cachedProps values
 * @return completeHostProps Map updated hostProps with no bogus values
*/
Map processCachedHostProps(Map cachedProps, Map sensitiveProps) {
    Map completeHostProps = cachedProps.collectEntries{ k, v ->
                                if (sensitiveProps.containsKey(k)) {
                                    return [k as String, sensitiveProps[k]]
                                }
                                else {
                                    return [k as String, v as String]
                                }
                            }
    // Verify that we do not have any remaining properties with fake values; stop the show if we do
    def missingKeys = completeHostProps.findAll{ k,v -> v == "***" }
    if (missingKeys) {
        throw new Exception(" Unable to update all cached sensitive properties with appropriate values.  Check Netscan properties and ensure the following keys have been added with values other than ***:\n\t${missingKeys.keySet().join(",")}")
    }
    return completeHostProps
}
 
 
/**
 * Processes a JSON file representing resources cached to disk on the collector
 *
 * @param emit Snippet object for lm.emit (requires version 1.0)
 * @param filename String
 * @param sensitiveProps Map of sensitive properties configured in the netscan to use for updating cachedProps values
 * @param lmDebug Snippet object class instantiation of lm.debug (requires version 1.0)
 * @return Boolean indicator of whether processing was successful
*/
Boolean processResourcesJson(emit, String filename, Map sensitiveProps, lmDebug) {
    File cacheFile = newFile(filename, "json")
    def cachedDevices
    try {
        cachedDevices = new JsonSlurper().parse(cacheFile)
    }
    catch (JsonException) {
        lmDebug.LMDebugPrint("No file found under ${cacheFile.name}; proceeding with API calls to retrieve devices.\n")
        return false
    }
 
    if (!cachedDevices) {
        lmDebug.LMDebugPrint("No cached devices found in ${cacheFile.name}; proceeding with API calls to retrieve devices.\n")
        return false
    }
    lmDebug.LMDebugPrint("${cachedDevices.size()} devices retrieved from cache file ${cacheFile.name}")
 
    // Updated cached devices to include proper values for sensitive properties stored in cache
    cachedDevices.each{ device ->
        if (device["hostProps"]) device["hostProps"] = processCachedHostProps(device["hostProps"], sensitiveProps)
    }
 
    emitWriteJsonResources(emit, filename, cachedDevices, lmDebug)
    return true
}
 
 
/**
 * Output resources to stdout and cache any remainders to JSON file on collector disk
 *
 * @param emit Snippet object for lm.emit (requires version 1.0)
 * @param filename String
 * @param resources List<Map> resources to be added from netscan
 * @param lmDebug Snippet object class instantiation of lm.debug (requires version 1.0)
*/
def emitWriteJsonResources(emit, String filename, List<Map> resources, lmDebug) {
    def chunkSize = 600
    def chunk = Math.min(resources.size(), chunkSize)
    lmDebug.LMDebugPrint("Adding ${chunk} devices.")
    // Output resources in chunk size deemed safe by platform team
    emit.resource(resources[0..chunk-1], lmDebug.debug)
 
    File cacheFile = newFile(filename, "json")
    // If the number of resources is less than or equal to our chunk size, our batching is complete and we can delete the file and exit
    if (resources.size() <= chunk) {
        cacheFile.delete()
        lmDebug.LMDebugPrint("All known devices have been reported.")
        return
    }
    // Remove sensitive properties prior to storing data in cache file; hardcode to true to ensure props are masked regardless of debug mode
    def remainingResources = emit.sanitizeResourceSensitiveProperties(resources, true)
    remainingResources = remainingResources[chunk..-1]
    def jsonRR = JsonOutput.toJson(remainingResources)
    // println JsonOutput.prettyPrint(jsonRR) // Uncomment for debugging purposes if needed
 
    lmDebug.LMDebug("Caching ${remainingResources.size()} devices to disk to add to portal in upcoming netscan executions.")
    cacheFile.write(jsonRR)
    return
}
  1. In the Schedule section, select Run this NetScan on a schedule. For dynamic environments, you can schedule the NetScan to run as frequently as hourly.

Note: Subsequent NetScan runs will add or move resources or resource groups based on changes in VMware vCenter. However, the NetScan does not have the ability to delete resources.

  1. Select Save or Save & Run.

After running the NetScan, review the history for the number of resources added, or for error messages if the NetScan does not create any resources. As needed, create Dynamic Resource Groups to organize Resources by business need and to apply workload-specific monitoring credentials. 

Manually Assigning Properties to Resources

If you add hosts through an Advanced Netscan, then the relevant properties and credentials are discovered and assigned to the hosts automatically. If the hosts are added manually into LogicMonitor, use the following properties. For more information on manually adding resources into monitoring, see Adding Devices.

ESXi Host

PropertyValueRequired
esx.user ESXi read-only userYes
esx.passESXi read-only passwordYes
esx.urlURL to access the ESXi
Default value is https://<host>/sdk
No

vCenter Server Appliance Host Properties

PropertyValueRequired
vcenter.uservCenter read-only userYes
vcenter.passvCenter read-only passwordYes
vcenter.urlURL to access the VCSA
Default value is https://<host>/sdk
No

Note: For backwards compatibility with older generations of vCenter modules, if the credentials are not set, the follwoing vCenter User Properties are used. However, it is recommended to use the preceding vCenter Server Appliance Host Properties vcenter prefix when configuring devices.

vCenter User Properties

PropertyValue
vcsa.uservCenter read-only user
vcsa.passvCenter read-only password
esx.uservCenter read-only user
esx.passvCenter read-only password

Note: In vSphere, there are no API-only users. By default, the created read-only user can access the host’s web interface. If it is unable to, this could indicate a configuration issue for the user/role. For vCenter monitoring, the VAMI interface (default access on port 5480) must be accessible.

API Port or URL

If your vCenter or ESXi hosts are configured to expose their API on nonstandard ports, you can set the properties vcenter.url or esx.url with an appropriate URL (e.g. https://192.168.1.100:8443/sdk).

Troubleshooting

  • If data can be collected from the VMware_vSphere modules but issues are encountered with the VMware_vCenterAppliance modules it could be due to a permission issue. The default read-only vSphere role should provide adequate permissions for LogicMonitor, however if a custom role is assigned, ensure that the option to “propagate to children” is enabled for the role. The role can be verified if it has adequate permissions by logging into the VAMI interface (https://<HOST>:5480) and verifying that the monitoring tab can be viewed.
  • Large queries to clusters may place an excessive load on internal DB, resulting in data collection issues. To mitigate this issue, see the Performance charts are empty and displays the error: Request processing is restricted by administrator (2107096) documentation from VMware.
  • You must ensure your vCenter server is sized appropriately for the numbers of hosts and VMs it is managing. See VMware’s documentation for size requirements. The vCenter database requirements must be added to the vCenter server requirements if they are on the same machine.
    If vCenter does not have enough resources, it may refuse some connections to the API (HTTPS) port (easily seen in the HTTPS- DataSource in LogicMonitor), or it may report a value of “-1” to some performance queries. Both of these situations will cause gaps in graphs. This is not an issue with LogicMonitor.
  • If your vCenter 5-minute Statistics Collection Level is set to “Level 1”, some datapoints may not return data. To access all of the necessary counters monitored, you must set your vCenter Statistics Collection Level to “Level 2.” This can be done within your vSphere Web Client (you must use the ‘flex’or ‘flash’ interface (not HTML5)) by doing the following:
    1. Select your vCenter instance in tree.
    2. Open the Configure tab.
    3. Select General > Statistics > Edit.
    4. From the dropdown in the Statistics Level column, select “Level 2” for the first item listed in the table.

VMware vSphere LogicModules in Package

VMware vSphere modules are organized into three distinct categories based on the components that are being monitored.

VMware ESXi modules provide availability, performance, and hardware sensor monitoring for VMware ESXi hosts and Virtual Machine monitoring for Standalone ESXi hosts not managed by vCenter.

Display NameTypeDescriptionReplaces
VMware_ESXi_CPUDataSourceTracks the utilization of host’s CPUs.VMware_ESXi_Resources
VMware_ESXi_HostPerformance
VMware_ESXi_DatastoreThroughputDataSourceMonitors vSphere / vCenter host performance metrics.VMware_ESXi_DatastorePerformance
VMware_ESXi_DatastoreUsageDataSourceMonitors storage capacity of ESXi datastores. Data is only valid if datastore is accessible.VMware_ESXi_DatastoreCapacity
VMware_ESXi_DisksDataSourceMonitors disk usage of the ESXi host.VMware_ESXi_HostPerformance
VMware_ESXi_HardwareHealthSensorDataSourceMonitors hardware health sensors as reported by ESXi. Sensors monitored are the hardware health sensors located in the Storage / Memory / Processor monitoring tabs and are separate from the system sensors which are reported on by VMware_ESXi_SystemHealthSensor. Sensors with an unknown or grey status are filtered from active discovery.VMware_ESXi_HardwareHealthSensors
VMware_ESXi_HardwareSensorFans
VMware_ESXi_HardwareSensorPower
VMware_ESXi_HardwareSensors

VMware_ESXi_LogicalProcessorsDataSourceTracks the utilization of the ESXi host CPUs’ logical processors.VMware_ESXi_HostCPUCores
VMware_ESXi_MemoryDataSourceMonitors the memory available to the ESXi host.VMware_ESXi_HostPerformance
VMware_ESXi_NetworkInterfacesDataSourceMonitors the bandwidth of the ESXi host network interfaces.VMware_ESXi_HostInterfaces
VMware_ESXi_NetworkStateDataSourceMonitors the statuses of ESX host’s networks and distributed port groups.VMware_ESXi_NetworkStatus
VMware_ESXi_PowerDataSourceMonitors the power usage of the ESXi host.N/A
VMware_ESXi_SystemHealthSensorDataSourceMonitors the hardware health system sensors on an ESXi host as reported by VMware. The system sensors being monitored are separate from the additional storage, memory, and CPU sensors hardware sensors.N/A
VMware_ESXi_VirtualMachineDiskCapacityDataSourceMonitors virtual disk storage capacity metrics on individual virtual machines.VMware_vSphere_vDiskCapacity
VMware_ESXi_VirtualMachinePerformanceDataSourceMonitors the CPU, disk, and memory, & network performance metrics for ESXi virtual machines.VMware_vSphere_VMperformance
VMware_ESXi_VirtualMachineSnapshotsDataSourceMonitors ages of snapshots on individual virtual machines.VMware_vSphere_VMsnapshots
VMware_ESXi_VirtualMachineStatusDataSourceTracks power, heartbeat, fault tolerance, guest tools states, as well as time since last power-on on individual virtual machines.VMware_vSphere_VMstatus
VMware_vSphere_Network_TopologyTopologySourceGenerate VMware network topologies based on data from vCenter.VMware_vCenter_Network_Topology
VMware_vSphere_VirtualMachine_TopologyTopologySourceGenerate VMware virtual machine topologies based on data from vCenter.VMware_vCenter_VM_Topology
addERI_ESXiPropertySourceSets device External Resource IDs (ERIs) for VMware ESXi hosts for topology mapping, including host UUID, MAC addresses, IQN, and WWN. Sets ERI Type (ERT) to “HyperVisor”.N/A
VMware_vSphere_InfoPropertySourceProvides additional info for the vSphere host.VMware_ESXi_ObjectCount
VMware_vCenter_ObjectCount
VMware_LM_TroubleshooterDataSourceChecks various settings to make sure that ESXi/vCenter collection will work properly. Will direct the user on how to fix any discovered issues.N/A

VMware vCenterAppliance modules provide data on availability and performance Monitoring of VMware vCenter Server Appliances.

Display NameTypeDescriptionReplaces
VMware_vCenterAppliance_BackupDataSourceCollects recovery backup information from the most recent backup occurrence.VMware_VCSA_Backups
VMware_vCenterAppliance_CPUDataSourceMonitors the vCenter host’s CPU information.VMware_VCSA_CPU
VMware_vCenterAppliance_DiskPerformanceDataSourceMonitors the vCenter host’s disk performance.VMware_VCSA_DiskPerformance
VMware_vCenterAppliance_FileSystemPartitionsDataSourceMonitors the utilization of vCenter host’s filesystem partitions.VMware_VCSA_FilesystemCapacity
VMware_vCenterAppliance_FileSystemSwapDataSourceMonitors the utilization of vCenter host’s disk swap.VMware_VCSA_Swap
VMware_vCenterAppliance_HealthStatusDataSourceMonitors the vCenter host’s health status of various system services such as applmgmt, database-storage, load, memory, software-packages, storage, swap, and system.VMware_VCSA_HealthStatus
VMware_vCenterAppliance_HighAvailabilityDataSourceMonitors the status of vCenter HA (VCHA).VMware_vCenter_AdmissionControl
VMware_vCenter_HANodeHealth
VMware_vCenter_HAStatus
VMware_vCenterAppliance_MemoryDataSourceMonitors the vCenter host’s memory information.VMware_VCSA_Memory
VMware_vCenterAppliance_NetworkInterfacesDataSourceMonitors the vCenter host’s network connection.VMware_VCSA_Network
VMware_vCenterAppliance_PowerDataSourceMonitors the total power usage of the vCenter environment.N/A
VMware_vCenterAppliance_ServicesDataSourceMonitors the vCenter host’s services’ runtime state.VMware_VCSA_Services
addCategory_vCenterPropertySourceSets categories for optional additional vCenter monitoring services, if they are in use, including vCenter clusters with HA (VCHA) and VCSA backups.addCategory_vCenterHA
VMware_vSphere_InfoPropertySourceProvides additional info for the vSphere host.VMware_ESXi_ObjectCount
VMware_vCenter_ObjectCount
VMware_LM_TroubleshooterDataSourceChecks various settings to make sure that ESXi/vCenter collection will work properly. Will direct the user on how to fix any discovered issues.N/A

VMware vSphere modules provide availability and performance monitoring for the vSphere environment (virtual machines, clusters, resource pools, datastores, etc.).

Display NameTypeDescriptionReplaces
VMware_vSphere_ClustersDataSourceMonitors ESX host clusters’ CPU and Memory metrics on vCenter devices.VMware_vCenter_ClusterPerformance
VMware_vSphere_DatastoreClustersDataSourceMonitors storage usage of vCenter datastore clusters.VMware_vCenter_DatastoreClusters
VMware_vSphere_DatastoreStatusDataSourceMonitors operating status of vSphere datastore.VMware_vCenter_DatastoreStatus
VMware_vSphere_DatastoreThroughputDataSourceMonitors vSphere / vCenter host performance metrics.VMware_vCenter_DatastorePerformance
VMware_vSphere_DatastoreUsageDataSourceMonitors storage usage of vCenter datastores. Data is only valid if datastore is accessible.VMware_vCenter_DatastoreCapacity
VMware_vSphere_HighAvailabilityDataSourceMonitors vSphere High Availability (vSphere HA) and admission control, including resources available for HA and if any vSphere HA agent (FDM) is experiencing issues.VMware_vCenter_AdmissionControl
VMware_vSphere_HostStatusDataSourceMonitors the state of the vCenter ESXi hosts.VMware_vCenter_HostStatus
VMware_vSphere_NetworkStateDataSourceMonitors the status of vCenter networks and distributed virtual port groups.VMware_vCenter_NetworkStatus
VMware_vSphere_ResourcePoolsDataSourceMonitors resource pools’ CPU and Memory metrics on vCenter devices.VMware_vCenter_ResourcePools
VMware_vSphere_VirtualMachineDiskCapacityDataSourceMonitors virtual disk storage capacity metrics on individual virtual machines.VMware_vCenter_VMDiskCapacity
VMware_vSphere_VirtualMachineNetworkInterfaceDataSourceMonitors virtual machine interface data throughput and packet transmission.VMware_vCenter_VMInterface
VMware_vSphere_VirtualMachinePerformanceDataSourceMonitors the CPU, disk, memory and network performance metrics on individual virtual machines.VMware_vCenter_VMPerformance
VMware_vSphere_VirtualMachineSnapshotsDataSourceMonitors ages of snapshots on individual virtual machines.VMware_vCenter_VMSnapshots
VMware_vSphere_VirtualMachineStatusDataSourceTracks power, heartbeat, fault tolerance, guest tools states, as well as time since last power-on on individual virtual machines.VMware_vCenter_VMStatus
VMware_vCenter_Cluster_TopologyTopologySourceGenerate VMware cluster topologies based on data from vCenter.VMware_ESXi_Topology
VMware_vCenter_Datastore_TopologyTopologySourceGenerate VMware datastore topologies based on data from vCenter.VMware_ESXi_Topology
VMware_vSphere_Network_TopologyTopologySourceGenerate VMware network topologies based on data from vCenter.VMware_vCenter_Network_Topology
VMware_vSphere_VirtualMachine_TopologyTopologySourceGenerate VMware virtual machine topologies based on data from vCenter.VMware_vCenter_VM_Topology
addERI_vCenterPropertySourceSets device External Resource IDs (ERIs) for VMware ESX vCenters for topology mapping, including UUID. Sets ERI Type (ERT) to “PhysicalServer”.N/A
addCategory_vCenterPropertySourceSets categories for optional additional vCenter monitoring services, if they are in use, including vCenter clusters with HA (VCHA) and VCSA backups.addCategory_vCenterHA
VMware_vSphere_InfoPropertySourceProvides additional info for the vSphere host.VMware_ESXi_ObjectCount
VMware_vCenter_ObjectCount
VMware_LM_TroubleshooterDataSourceChecks various settings to make sure that ESXi/vCenter collection will work properly. Will direct the user on how to fix any discovered issues.N/A

When setting static datapoint thresholds on the various metrics tracked by this package’s modules, LogicMonitor follows the technology owner’s best practice KPI recommendations. If necessary, we encourage you to adjust these predefined thresholds to meet the unique needs of your environment. For more information on tuning datapoint thresholds, see Tuning Static Thresholds for Datapoints.

Migration from Legacy Modules

If you are currently monitoring VMware devices using any of these legacy modules, you will not experience data loss upon importing the new modules. This is because module names have been changed to eliminate module overwriting. For more information, see Deprecated LogicModules.

However, you will collect duplicate data and receive duplicate alerts for as long as both sets of modules are active. For this reason and to avoid adding unnecessary additional load to vCenter Servers, you should disable the above-listed modules after importing the new set of modules and confirm they are working as intended in your environment.

When a DataSource is disabled, it stops querying the host and generating alerts, but maintains all historical data. You may want to delete the legacy modules altogether, but consider this move carefully as all historical data will be lost at deletion. For more information on disabling modules, see Disabling Monitoring for a DataSource or Instance.

In This Article