Cisco Catalyst SD-WAN モニタリング

最終更新日: 26 年 2024 月 XNUMX 日

免責事項: これらのモジュールは、Cisco Catalyst SD-WAN エッジ ルータ (vEdge および cEdge)、コントローラ (vSmart)、およびバリデータ (vBond) デバイスを個別の LogicMonitor リソースとして監視し、Cisco vManage (レガシー) モジュールへのインプレース アップグレードではありません。 詳細については、「」を参照してください。 Cisco SD-WAN モニタリング (レガシー).

LogicMonitor は、これらの Catalyst SD-WAN モジュールを Cisco vManage (レガシー) モジュール (または Cisco SD-WAN リアルタイム モニタリング API を利用する他のサードパーティ モニタリング) と並行して使用することをサポートしていません。 これを行うと、Cisco vManage のパフォーマンスと信頼性に悪影響が生じ、モジュールとサードパーティの監視ソリューションの両方にデータのギャップが発生する可能性があります。 リスクを軽減するには、組織の変更管理プロセスに従ってください。

LogicMonitor の Cisco Catalyst SD-WAN モニタリング パッケージは、Cisco Catalyst SD-WAN Bulk API を利用して、Catalyst SD-WAN のさまざまな健全性およびパフォーマンス メトリックを取得します。

技術タイプ

ネットワーキングとファイアウォール

技術ノート

これらのモジュールは Cisco Catalyst SD-WAN Bulk API を使用します。 詳細については、「 バルクAPI シスコのドキュメント。

推奨事項: コントローラ、エッジ、または IOS XE リソースに対してシスコが推奨する vManage または IOS のバージョンを使用してください。 詳細については、「 コントローラおよび WAN エッジ ルータ用のシスコ推奨 SD-WAN ソフトウェア バージョン シスコのドキュメント。

互換性

これらのモジュールと完全な互換性を得るには、Cisco Catalyst SD-WAN (vManage) バージョン 20.6.3 以降が必要です。

すべての監視対象リソースには、vManage ホストの Bulk API ポートへの接続と、コレクタからの Bulk API アクセスによる認証情報が必要です。

注: 2023 年 20.6.3 月の時点で、LogicMonitor の Cisco Catalyst SD-WAN パッケージはバージョン 20.10.1 ~ XNUMX と互換性があることが知られています。

セットアップ要件

LogicMonitor_Collector_Snippetsデータソースをインポートして、コレクターがこの監視スイートのコードをサポートしていることを確認するか、EACollector32.100以降に更新します。

依存関係を満たす

資格情報を取得する

LogicMonitor は、状態および統計データを正常に収集するために、Bulk API ユーザー アカウントに属する適切な資格情報を提供する必要があります。 各リソース上で NetScan によって設定された cisco.sdwan.user アカウントは、次の役割権限を持っているか、または次の権限を持つユーザ グループに属している必要があります。

職種説明
デバイス監視シスコでは、このロール タスク機能を「デバイス モニタリング」と定義しており、ユーザが属しているグループに対して読み取りと有効の両方が true である必要があります。詳細については、を参照してください。 ユーザーとグループ シスコのドキュメント。

ポート

8443 は、一括 API アクセスのデフォルト ポートとして設定されます。

モニタリングにリソースを追加する

Cisco API を使用する Advanced NetScan を使用して Cisco Catalyst SD-WAN リソースを追加し、監視対象の Cisco Catalyst SD-WAN リソースごとにリソースを検出および作成できます。 詳細については、「」を参照してください。 ネットスキャンとは.

警告: 超過を避けるために、NetScan を実行する前に、十分な LogicMonitor ライセンスがあることを確認してください。 さらに、NetScan フィルタをテストして、監視したくない Catalyst SD-WAN デバイスを誤って追加しないようにしてください。

Advanced NetScan を使用して Cisco Catalyst SD-WAN リソースを追加する

Advanced NetScan の使用の詳細については、次を参照してください。 強化されたスクリプト ネットスキャン.

  1. あなたの中で ロジックモニターポータル > モジュール > 応募者と、Cisco Catalyst SD-WAN LogicModule をインストールします。
  2. MFAデバイスに移動する  「リソース」 > 「追加」 > 「複数のデバイス」 > 「高度な NetScan」.
      高度な NetScan を追加する ページが表示されます。
  3. この NetScan に関連付ける名前を入力します。 たとえば、「Cisco Catalyst SD-WAN」です。 
  4. NetScan を実行するコレクタを選択します。
    デフォルトでは、NetScan は NetScan を実行しているコレクタに新しいリソースを割り当てます。
  5. 選択 強化されたスクリプト NetScan   方法 ドロップダウンリスト。
  6. 「拡張スクリプト」セクションから、次を選択します。 デバイスの資格情報 > このスキャンにカスタム資格情報を使用する.
  7. NetScan に必要な Cisco API クレデンシャルを提供する次のプロパティを追加し、NetScan がリソースを作成および編成する方法と場所を変更します。
プロパティ必須?
cisco.sdwan.userBulk API へのアクセスに使用される Cisco Catalyst SD-WAN のユーザ名。 見つからない場合、LogicMonitor は vmanage.user の既存の値を使用しようとします(見つかった場合)。 cisco.sdwan.user プロパティは NetScan 出力に必要であり、Cisco Catalyst SD-WAN モジュールの優先ユーザー プロパティです。有り
cisco.sdwan.passBulk API へのアクセスに使用される Cisco Catalyst SDWAN パスワード。 NetScan は、このプロパティの値をマスクします。 見つからない場合、LogicMonitor は、見つかった場合は vmanage.pass の既存の値を使用しようとします。 cisco.sdwan.pass このプロパティは NetScan 出力に必要であり、Cisco Catalyst SDWAN モジュールの推奨パスワード プロパティです。有り
cisco.sdwan.vmanagehostBulk API メトリクスを収集する vmanage ホストのホスト名(たとえば、yourvmanagehostname.cisco.com)。 これは、Bulk API データのキャッシュに使用されるコレクターがアクセスできるホスト名である必要があります。有り
lmaccess.id またはlogicmonitor.access.idポータルにリソースを追加する前に NetScan で重複リソースを検索するための LogicMonitor API アクセス ID。 ポータル監視の詳細については、次を参照してください。 LogicMonitorポータルモニタリング.有り
lmaccess.key またはlogicmonitor.access.keyポータルにリソースを追加する前に NetScan で重複リソースを検索するための LogicMonitor API キー。 ポータル監視の詳細については、次を参照してください。 LogicMonitorポータルモニタリング.有り
ホスト名.ソースNetScan で使用されるホスト名のソースを選択できます。 これは、既存のリソースに競合が見つかった場合に、重複したデバイスの作成を防ぐのに役立ちます。 詳細については、「」を参照してください。 NetScan のトラブルシューティング.いいえ
cisco.sdwan.ポートCisco Catalyst SDWAN API が REST Bulk API を使用してメトリックを公開する TCP ポート。 このポートはカスタマイズできますが、デフォルトでは、Bulk API はポート 8443 を使用します。見つからない場合、LogicMonitor は vmanage.port の既存の値を使用しようとします(見つかった場合)。いいえ
cisco.sdwan.フォルダこの NetScan が作成するか、すでに存在する場合は使用する LogicMonitor リソース グループの名前。 値には、ネストされた子フォルダーを指定できます (例: folder/folder/folder)。デフォルトは「Cisco Catalyst SDWAN」です。動的デバイス グループは NetScans によって追加されないため、これを動的デバイス グループに割り当てないでください。 詳細については、「」を参照してください。 デバイスグループの概要.いいえ
cisco.sdwan.allowedsitesNetScan によって追加されるサイト ID のリスト。 許可されたサイト ID に含まれるどのデバイスが NetScan によってリソースとして追加されるかを指定するには、このリスト形式は 100,102,103、XNUMX、XNUMX である必要があります。 このプロパティが設定されていない場合、NetScan はすべてのサイト ID をリソースとして追加できます。いいえ
cisco.sdwan.manager.namevManage API へのアクセスに使用される vManage の名前ラベル。デフォルトは「Cisco vManage」です。いいえ
cisco.sdwan.statisticslookback統計ベースの API 呼び出しに使用される時間の範囲は 20 ~ 60 分です。 デフォルトは 60 分です。いいえ
cisco.sdwan.sites.csv手動ファイルベースの設定: デフォルトでは、NetScan によって作成された新しいリソースは、NetScan を実行するコレクターに割り当てられます。 これをオーバーライドするオプションとして、このプロパティを使用して、デフォルトの動作をオーバーライドするために作成した CSV ファイルを使用し、サイト ID と LM コレクター名に基づいてデバイスを目的のコレクターに割り当てるように NetScan に指示できます。 CSV ファイルは、NetScan:Linux を実行するコレクターに保存する必要があります。 /usr/local/logicmonitor/agent/binWindows: C:\Program Files\LogicMonitor\Agent\bin ヘッダーには (コレクター ID、リージョン フォルダー、サイト ID、サイト名) が含まれ、ファイル データはヘッダー構造に従った形式である必要があります。いいえ
  1. 選択 Groovyスクリプトを埋め込む 次のスクリプトを埋め込みます。

警告: スクリプトを編集しないでください。 編集された拡張スクリプト NetScan はサポートされていません。 LogicMonitor が提供するスクリプトを編集した場合、問題が発生した場合、LogicMonitor サポートは (独自の裁量により) サポートされているスクリプトで編集内容を上書きするよう要求する場合があります。 拡張スクリプト NetScan は、LM Envision リソースの作成を 600 時間あたり 600 以下に制限します。 XNUMX を超えるリソースを作成するには、すべてのリソースが追加されるまで NetScan を XNUMX 時間ごとに繰り返すようにスケジュールします。

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

import com.logicmonitor.common.sse.utils.GroovyScriptHelper as GSH
import com.logicmonitor.mod.Snippets
import com.santaba.agent.AgentVersion
import java.text.DecimalFormat
import groovy.json.JsonOutput
import groovy.json.JsonSlurper

// To run in debug mode, set to true
def debug = false
// To save collector logs, set to true
Boolean log = false

Integer collectorVersion = AgentVersion.AGENT_VERSION.toInteger()
String vManageHost, vManageName, rootFolder, sites, host, user, pass, csvFile
Integer port


// 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
}

vManageHost = props.get("cisco.sdwan.vmanagehost") // required
def cleanedvManageHost = vManageHost?.replaceAll(":","_") // replace : if found since it's a delimiter
def logCacheContext = "cisco-sdwan" + "_" + cleanedvManageHost// used in keys also

user = props.get("cisco.sdwan.user") // required
pass = props.get("cisco.sdwan.pass") // required

// Check that required properties are present
if (!user || !pass || !vManageHost) {
    throw new Exception("Not all required properties have been configured.  Please update netscan properties to include cisco.sdwan.user, cisco.sdwan.pass, and cisco.sdwan.vmanagehost.")
}

vManageName = props.get("cisco.sdwan.manager.name", "Cisco vManage")
rootFolder = props.get("cisco.sdwan.folder", "Cisco Catalyst SDWAN")
port = (props.get("cisco.sdwan.port", props.get("vmanage.port", "8443"))).toInteger()

// CSV file containing headers "Collector ID", "Region Folder", "Site ID" and "Site Name" to customize collector assignment and group names created
// Save in /usr/local/logicmonitor/agent/bin directory (Linux)
// or C:\Program Files\LogicMonitor\Agent\bin directory (Windows)
csvFile = props.get("cisco.sdwan.sites.csv", null)
String cacheFilename = "Cisco_Catalyst_SDWAN_${vManageHost}_devices"
statisticsLookBack = (props.get("cisco.sdwan.statisticslookback", "60")).toInteger()
String hostnameSource = props.get("hostname.source")?.toLowerCase()?.trim() ?: ""

Map sensitiveProps = [
        "cisco.sdwan.user" : user,
        "cisco.sdwan.pass" : pass,
]

// 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}.")
}

// Convert to map with site ID as key if CSV file was provided
Map siteInfo = (csvFile) ? processCollectorSiteInfoCSV(csvFile) : null

// Configure all required snippets
def modLoader = GSH.getInstance()._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 cacheSnip = modLoader.load("lm.cache", "0")
def cache = cacheSnip.cacheSnippetFactory(lmDebug, logCacheContext)
def httpSnippet = modLoader.load("proto.http", "0")
def http = httpSnippet.httpSnippetFactory(props)
def lmApiSnippet = modLoader.load("lm.api", "0")
def lmApi = lmApiSnippet.lmApiSnippetFactory(props, http, lmDebug)
def ciscoSDWANSnippet = modLoader.load("cisco.sdwan", "0")
def ciscoSDWAN = ciscoSDWANSnippet.ciscoSDWANSnippetFactory(props, lmDebug, cache, http)

def sessionIdKey = "${vManageHost}:sessionId"
def csrfTokenKey = "${vManageHost}:csrfToken"
def response
def testSessionId = ciscoSDWAN.cache.cacheGet(sessionIdKey)
def siteAllowList = props.get("cisco.sdwan.allowedsites", null)?.tokenize(",")?.collect{ it.trim() }

// Get information about devices that already exist in LM portal
List fields = ["name", "currentCollectorId", "displayName"]
Map args = ["size": 1000, "fields": fields.join(",")]
def lmDevices = lmApi.getPortalDevices(args)

if (testSessionId == null) {
    // Since login and logouts can lock a portal we will only do so if we cannot find data for sessionId in cache.
    ciscoSDWAN.sessionId = ciscoSDWAN.login()
    ciscoSDWAN.csrfToken = ciscoSDWAN.getCSRFtoken()
    response = ciscoSDWAN.getDevice()
}
else {
    // Try to do a getDevice with cached sessionId so we don't lock existing resources
    ciscoSDWAN.sessionId = ciscoSDWAN.cache.cacheGet(sessionIdKey)
    ciscoSDWAN.csrfToken = ciscoSDWAN.cache.cacheGet(csrfTokenKey)
    response = ciscoSDWAN.getDevice()
}

if (response) {
    def devices = ciscoSDWAN.slurper.parseText(response)
    // Set variable to store all resources that will be added by netscan
    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 display names found within LogicMonitor portal wherein hostname in LM does not match hostname in Netscan output.  Refer to documentation for how to resolve name collisions using 'hostname.source' netscan property.",
        "total" : 0,
        "resources" : []
    ]

    // Keep track of region devices that have been added including their associated sites
    List seenSites = []

    // Add each device into monitoring 
    devices?.'data'?.each{ it ->
        if ((siteAllowList?.contains(it.'site-id')) || siteAllowList == null) {
            String ip = it.'system-ip'.toString()
            String displayName = it.'host-name'.toString()

            // Check for existing device in LM portal with this displayName
            def deviceMatch = lmApi.checkExistingDevices(displayName, 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
                if (ip != deviceMatch.name) {
                    def collisionInfo = [
                        (displayName) : [
                            "Netscan" : [
                                "hostname"    : ip
                            ],
                            "LM" : [
                                "hostname"    : deviceMatch.name,
                                "collectorId" : deviceMatch.currentCollectorId
                            ],
                            "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)
                }
                // Don't worry about matches where the hostname values are the same
                // These will update via normal netscan processing and should be ignored
                else {
                    deviceMatch = false
                }
            }

            String siteId = it.'site-id'.toString()
            String setCategory = null
            String deviceType = it.'device-type'

            if (deviceType.contains("edge")) {
                setCategory = "CiscoSDWANEdge"
            }
            if (deviceType.contains("smart")) {
                setCategory = "CiscoSDWANSmart"
            }
            if (deviceType.contains("bond")) {
                setCategory = "CiscoSDWANBond"
            }

            Map deviceProps = [
                    "cisco.sdwan.user"               : emit.sanitizePropertyValue(ciscoSDWAN.user),
                    "cisco.sdwan.pass"               : pass,
                    "cisco.sdwan.vmanagehost"        : emit.sanitizePropertyValue(ciscoSDWAN.vManageHost),
                    "cisco.sdwan.port"               : emit.sanitizePropertyValue(ciscoSDWAN.port),
                    "cisco.sdwan.device.type"        : emit.sanitizePropertyValue(it.'device-type'),
                    "cisco.sdwan.device.id"          : emit.sanitizePropertyValue(it.'system-ip'),
                    "cisco.sdwan.site.id"            : emit.sanitizePropertyValue(siteId),
                    "cisco.sdwan.statisticslookback" : emit.sanitizePropertyValue(statisticsLookBack),
                    "system.categories"              : setCategory,
            ]

            // Initialize groupName and collectorId, then assign values based on whether info has been provided via CSV
            String groupName
            Integer collectorId
            if (seenSites.contains(siteId)) {
                // If we have site info from the CSV, we can use that to build the user defined group name
                if (siteInfo) {
                    // When data is provided, we build a nested group with the site folder under the region folder
                    groupName = "${siteInfo[siteId].regionFolder}/${siteInfo[siteId].siteName}"
                    collectorId =  siteInfo[siteId].collectorId.toInteger()
                }
                // If not, we'll simply name it with the site ID and not assign collector ID
                else {
                    groupName = "Site ID: ${siteId}"
                }
            }
            // If we haven't seen any info about this site, we'll also simply name it with the site ID and not assign collector ID
            else {
                groupName = "Site ID: ${siteId}"
            }
            if (!(deviceType.contains("manage"))) {
                Map resource = [
                        "hostname"   : ip,
                        "displayname": displayName,
                        "hostProps"  : deviceProps,
                        "groupName"  : ["${rootFolder}/${groupName}"],
                ]
                // Only add the collectorId field to resource map if we found a collector ID above
                if (collectorId) {
                    resource["collectorId"] = collectorId
                    duplicateResources["resources"][displayName]["Netscan"]["collectorId"] = collectorId
                }
                // Only add devices that have not been flagged as a display name device match
                // Name collisions that have been resolved are updated to remove the device match flag
                if (!deviceMatch) {
                    resources.add(resource)
                }
                else {
                    lmDebug.LMDebug("${displayName} skipped due to unresolved name collison.")
                }
            }
        }
    }

    // After building full map of resources, emit complete JSON of discovered devices
    // Enhanced netscan format (requires collector version 32.400+)
    if (resources) {
        // emit.resource(resources, debug) // when we don't need to limit output this can be used.
        emitWriteJsonResources(emit, "catalyst_devices", resources, lmDebug) // limit output to 600
    }

    // Report devices that already exist in LM via log file named after root folder
    if (duplicateResources["resources"].size() > 0) {
        def netscanDupLog = new File("../logs/NetscanDuplicates/${rootFolder.replaceAll(" ", "_")}.json")
        new File(netscanDupLog.getParent()).mkdirs()
        duplicateResources["total"] = duplicateResources["resources"].size()
        def json = JsonOutput.prettyPrint(JsonOutput.toJson(duplicateResources))
        netscanDupLog.write(json)
        if (hostnameSource) {
            lmDebug.LMDebug("${duplicateResources["resources"].size()} devices found that were resolved with hostname.source=${hostnameSource} in netscan output.  See LogicMonitor/Agent/logs/NetscanDuplicates/${rootFolder.replaceAll(" ", "_")}.json for details.")
        }
        else {
            lmDebug.LMDebug("${duplicateResources["resources"].size()} devices found that were not reported in netscan output.  See LogicMonitor/Agent/logs/NetscanDuplicates/${rootFolder.replaceAll(" ", "_")}.json for details.")
        }
    }
}
else {
    lmDebug.LMDebugLog("NETSCAN: No response from device API call. Credential check likely failed or some other communication error occurred.")
    throw new Exception(" No response data from device. Verify credentials and that we get data back from the device endpoint using them.")
}

return 0


/**
* Helper function to process CSV with collector id, site device name, folder, site id and site name info
* @param String filename Filename of the CSV containing user-defined site info
* @return Map siteInfo with site ID as the key with a Map containing the rest of the info as key value pairs
*/
def processCollectorSiteInfoCSV(String filename) {
    // Read file into memory and split into list of lists
    def csv = newFile(filename, "csv")
    def rows = csv.readLines()*.split(",")
    def siteInfo = [:]

    // Verify whether headers are present and contain expected values
    // Sanitize for casing and extra whitespaces while gathering headers
    def maybeHeaders = rows[0]*.toLowerCase()*.trim()
    if (maybeHeaders.contains("collector id") &&
        maybeHeaders.contains("region folder") &&
        maybeHeaders.contains("site id") &&
        maybeHeaders.contains("site name")) {

        Map headerIndices = [:]
        maybeHeaders.eachWithIndex{ val, i ->
            headerIndices[val] = i
        }
        // Index values for headers to ensure we key the correct index regardless of order
        def ci = headerIndices["collector id"]
        def rf = headerIndices["region folder"]
        def si = headerIndices["site id"]
        def sn = headerIndices["site name"]

        // Remove headers from dataset
        def data = rows[1..-1]

        // Build a map of common site names with site ID as key
        data.each{ entry ->
            siteId = entry[si].trim()
            siteInfo[siteId] = [
                    "collectorId"      : entry[ci].trim(),
                    "regionFolder"     : entry[rf].trim(),
                    "siteName"         : entry[sn].trim(),
            ]
        }
    }
    // Bail out early if we don't have the expected headers in the provided CSV
    else {
        throw new Exception(" Required headers not provided in CSV.  Please provide \"Collector ID\", \"Region Folder\", \"Site ID\", and \"Site Name\" (case insensitive).  Headers provided: \"${rows[0]}\"")
    }

    return siteInfo
}


/**
 * 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)
}


/**
 * 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. の中に スケジュール セクション、選択 このNetScanをスケジュールに従って実行する。 動的環境の場合、NetScan を XNUMX 時間ごとに実行するようにスケジュールできます。

注: 後続の NetScan の実行では、Cisco Catalyst SD-WAN の変更に基づいてリソースまたはリソース グループが追加または移動されます。 ただし、NetScan にはリソースを削除する機能がありません。

  1. 選択 Save or 保存して実行.

NetScan を実行した後、追加されたリソースの数、または NetScan がリソースを作成しない場合はエラー メッセージの履歴を確認します。

リソースを手動で追加する

  1. Cisco Catalyst SDWAN デバイス グループを作成します。
  2. デバイスを Cisco Catalyst SDWAN デバイス グループに追加します。
  3. 次のプロパティを追加または確認します。 cisco.sdwan.device.id Cisco Catalyst SDWAN リソース グループの下のリソースに設定されます。
プロパティ必須
cisco.sdwan.userBulk API へのアクセスに使用される Cisco Catalyst SD-WAN のユーザ名。見つからない場合、LogicMonitor は vmanage.user の既存の値を使用しようとします(見つかった場合)。の cisco.sdwan.user プロパティは NetScan 出力に必要であり、Cisco Catalyst SD-WAN モジュールの優先ユーザー プロパティです。 有り
cisco.sdwan.passBulk API へのアクセスに使用される Cisco Catalyst SDWAN パスワード。 NetScan は、このプロパティの値をマスクします。見つからない場合、LogicMonitor は vmanage.pass の既存の値を使用しようとします(見つかった場合)。の cisco.sdwan.pass このプロパティは NetScan 出力に必要であり、Cisco Catalyst SDWAN モジュールの推奨パスワード プロパティです。有り
cicso.sdwan.vmanagehostBulk API メトリックを収集する vmanageg ホストのホスト名(たとえば、yourvmanagehostname.cisco.com)。これは、Bulk API データのキャッシュに使用されるコレクターがアクセスできるホスト名である必要があります。 有り
  1. 手動で追加する cisco.sdwan.device.id プロパティは各リソースで必要になります。

Note注:cisco.sdwan.device.id は、vmanagehost からの vmanage Web インターフェイスの [デバイス] タブに表示される「システム IP」である必要があります。リソースが割り当てた他の IP アドレスは使用できません。詳細については、Cisco の Web サイトを参照してください。 システムおよびインターフェース構成ガイド.

  1. system.categories がエッジ、スマート、またはスマート デバイスの場合は、デバイス タイプに応じて次のいずれかを使用します。
  • CiscoSDWANEdge
  • CiscoSDWANスマート
  • CiscoSDWANボンド

LogicModulesをインポートする

LogicMonitor パブリック リポジトリから、すべての Cisco Catalyst SDWAN LogicModule をインポートします。 詳細については、「パッケージ内のロジックモジュール」を参照してください。

これらの LogicModule がすでにインポートされている場合は、最新バージョンであることを確認してください。

LogicModule がインポートされると、データ収集が自動的に開始されます。

考慮事項と警告

  • ログイン セッションは 24 時間持続する必要があります。 セッションがアクティブな状態を維持できるように、ログアウト要求を制限する必要があります。
  • Cisco_Catalyst_SDWAN_API は、Cisco Catalyst SDWAN リソースを監視するために必要です。 このモジュールは、バルク API データをキャッシュします。 LogicMonitor は、これらのモジュールでキャッシュ設計を使用して API 呼び出しを制限します。
  • 2800 時間あたり 100 API コールを超えてはなりません。 同時 API コールは XNUMX を超えてはなりません。
    詳細については、以下を参照してください 認証方法 シスコのドキュメント。

トラブルシューティング

トラブルシューティング用の次のデバッグ モードとログ モードは、API 制限に達するのを防ぐために、使用中に一部のエンドポイントでのデータ収集を停止する場合があります。

  • このパッケージのモジュールは、データ収集スクリプトにデバッグ モードが埋め込まれるように設計されています。
    問題が発生した場合は、変数 debug を「true」に設定してデバッグ モードを有効にし、コレクタ デバッグ機能でスクリプトをテストするときに出力で詳細情報を取得します。
    コレクタ デバッグ機能でのスクリプトのテストの詳細については、「コレクタ デバッグ機能」を参照してください。 スクリプトのトラブルシューティング.
  • このパッケージのモジュールは、Active Discovery およびデータ収集スクリプトに組み込まれたログ モードを使用して設計されています。 ログ モードを使用すると、通常のアクティブな検出またはデータ収集の実行中に発生する問題のトラブルシューティングが可能になり、データ ギャップの調査に使用できます。
    問題が発生した場合は、変数 log を「true」に設定してログ モードを有効にし、コレクタ ログで詳細情報を取得します。
    コレクタ ログの取得の詳細については、「」を参照してください。 LogicMonitorへのログの送信 in コレクターロギング.
  • DataSource は、存在する場合、エラー メッセージをコンソールに出力します。 これらのエラーは、データを手動でポーリングするときに (各データソースの [リソース] ページに表示される [未加工データ] タブから) 出力に表示されます。 DataSource はエラーを適切に処理し、エラーが発生した場合でも利用可能なデータを取得しようとするように設計されています。
  • 監視に使用されるユーザーが、デバイス監視が有効になっており、ユーザー設定で設定された一括 API データに対する読み取り権限も有効になっているグループに属していることを確認してください。 cisco.sdwan.user。 詳細については、 ユーザーグループの操作 シスコのドキュメント。

NetScan のトラブルシューティング

このスイートの NetScan は、ポータル内の既存のデバイスを更新して、Cisco API から取得した関連情報を追加できます。 また、表示名は同じでも system.hostname の値が異なるという競合が存在する場合、NetScan がポータル内に重複したデバイスを作成する可能性があります。 デバイスが適切に更新され、重複したデバイスが作成されないように、この NetScan は LogicMonitor の API を使用して既存のデバイスをクエリし、検出された名前の競合を報告します。 このファイルにはコレクター ログからアクセスできます。 コレクタ ログの取得の詳細については、「」を参照してください。 コレクターログ–LogicMonitorへのログの送信.

NetScan がプロパティで構成されていない限り、このレポート内のデバイスは NetScan 出力の一部として LogicMonitor に報告されません。 hostname.source。 このプロパティを使用すると、ユーザーは、NetScan 出力で使用されるホスト名のソースを選択することによって、検出された名前の競合を解決できます。 考えられる XNUMX つのホスト名ソースは、次の値によって決まります。

  • 「lm」または「logicmonitor」 名前が競合しているデバイスは、LogicMonitor の既存の system.hostname を使用して、ポータル内のデバイスが NetScan を使用して更新されるようにします。 この設定では新しいデバイスは作成されません。
  • 「netscan」 名前が競合しているデバイスは、NetScan スクリプトで決定された system.hostname を維持し、追加するように報告された表示名を更新します。 - <system.hostname> 一意であり、ポータルに追加できることを確認するためです。 このオプションは、厳密な命名規則がなく、同じ表示名を持つ複数のデバイスがある場合に役立ちます。

注: NetScan は、system.hostname の値を更新できません。 NetScans は、表示名、カスタム プロパティ、およびグループ割り当てを更新できます。

レガシーLogicModulesからの移行

2023 年 20.4 月の時点で、LogicMonitor は Cisco Catalyst SD-WAN モジュールの新しいスイートをリリースしました。 新しい DataSource は Cisco Catalyst SD-WAN Bulk API にデータをクエリしますが、Cisco vManage の LogicMonitor モジュールはリアルタイムおよびデバイスごとの API 呼び出しに依存しており、vManage バージョン XNUMX.x 以降をサポートしていません。 Bulk API を使用してメトリクスを収集すると、次の利点があります。

  • より多くのデータへのアクセス
  • リアルタイム API ではなくバルク API およびデバイスごとの呼び出しを使用した継続的なモニタリングには、シスコが推奨する方法を使用します。
  • リアルタイム API を直接使用してクエリされたリソースの CPU 使用率が削減される
  • ネットワークと相互接続のリソース使用量が減少するため、データソースはより少ない API 呼び出しでデータを収集でき、レート制限のリスクが軽減されます。
  • NetScan を使用したセットアップと構成
  • Bulk API データの一元的なキャッシュ

免責事項: これらのモジュールは、Cisco Catalyst SDWAN デバイスを個別の LogicMonitor リソースとして監視し、Cisco vManage モジュールへのインプレース アップグレードではありません。 詳細については、「」を参照してください。 CiscoSD-WANモニタリング.

推奨事項: これらのモジュールを LogicMonitor Cisco vManage モジュール (または他のサードパーティ監視ソリューション) と並行して使用しないでください。 これにより、Cisco vManage API 接続エラーや、モジュールとサードパーティ監視ソリューションの両方でデータ ギャップが発生する可能性があります。 リスクを軽減するには、組織の変更管理プロセスに従ってください。

現在、これらのレガシー DataSource のいずれかを使用して Cisco vManage デバイスを監視している場合、新しい DataSource をインポートするときにデータが失われることはありません。 モジュールの上書きを排除するために、DataSource 名が変更されます。 両方のデータソース セットがアクティブである限り、重複データを収集し、重複アラートを受信します。 

推奨事項: 新しい DataSource セットをインポートした後、従来の DataSource を無効にし、それらが環境で意図したとおりに動作していることを確認します。

DataSource が無効になると、ホストへのクエリとアラートの生成が停止されますが、すべての履歴データは維持されます。 従来のデータソースを完全に削除することもできますが、すべての履歴データが失われるため、この移行は慎重に検討してください。 データソースの無効化の詳細については、次を参照してください。 データソースまたはインスタンスの監視を無効にする.

パッケージ内のLogicModules

Cisco Catalyst SDWAN 用の LogicMonitor パッケージは、次の LogicModule で構成されています。 完全にカバーするには、次のすべての LogicModule を LogicMonitor プラットフォームにインポートします。

表示名タイプ説明
Catalyst SDWAN APIデータソースCisco Catalyst SDWAN パッケージのデータ収集を制御し、API の使用状況を監視します。
Catalyst SDWAN 制御接続データソース個々の制御接続の状態を監視します。
Catalyst SDWAN コントローラ インターフェイスデータソースコントローラーインターフェイスのステータスを監視します。
Catalyst SDWAN デバイスの健全性データソースデバイスの健全性とシステム ステータスの状態メトリックを収集します。
Catalyst SDWAN ネットワーク インターフェイスデータソースCisco Catalyst SDWAN ネットワーク インターフェイス統計を監視します。
Catalyst SDWAN のパフォーマンスデータソースCisco Catalyst SDWAN リソースのストレージ、メモリ、CPU パフォーマンスを監視します。
Catalyst SDWAN トンネルデータソーススループット データ、ジッター、損失、遅延、vQoE、および状態に関するトンネルごとの概要データ。
Cisco_Catalyst_SDWAN_トポロジートポロジーソースvManage API からのデータに基づいて Cisco Catalyst SD-WAN トポロジを生成します。
addCategory_Cisco_Catalyst_SDWANプロパティソース提供された資格情報を使用してログインを試行することにより、Cisco Catalyst SDWAN デバイスを識別します。 システム カテゴリ、およびバージョン番号 (バージョン番号が使用可能な場合) や CSRF トークンが必要かどうかを示すフラグなどの自動プロパティを設定します。
addERI_Cisco_Catalyst_SDWANプロパティソースCisco Catalyst SDWAN リソースの ERI を検出して追加します。

このパッケージの DataSources によって追跡されるさまざまなメトリックに静的なデータポイントのしきい値を設定する場合、LogicMonitor はテクノロジ所有者のベスト プラクティス KPI の推奨事項に従います。 必要に応じて、これらの定義済みのしきい値を調整して、環境固有のニーズに合わせてください。 データポイントのしきい値の調整の詳細については、次を参照してください。 データポイントの静的しきい値の調整.

記事上で