キャンセル
次の結果を表示 
次の代わりに検索 
もしかして: 
cancel
294
閲覧回数
1
いいね!
0
コメント
takasano
Cisco Employee
Cisco Employee

はじめに

以前、CLICommandCollector App が別のドキュメントで紹介されました。
この App は APIC GUI から User が複数の Node で CLI コマンド出力を並行して収集する機能を提供しています。
しかし、GUI を使用せずに直接 Web API を利用して App の機能にアクセスし、各種コマンドを収集したいという要望がありました。
そこで本稿では CLICommandCollector の API を直接利用してコマンドを取得する方法を紹介します。

注意点

本稿で用いる CLICommandCollector は本来 GUI による利用を前提とした App です。
API を直接実行する場合、GUI では決して入ることのない入力を与えることもできます。
そうした様々なケースに対して十分な試験は実施されていません。
そのため、不適切な入力を行うとコマンドの取得に失敗したり App がハングする可能性があります。
自然に回復しない場合には App の Disable/Enable を行って回復させる必要があります。

前提

続く内容は下記の全ての条件を満たしていることが前提となっています。

  • APIC に CLICommandCollector がインストールされている
  • CLICommandCollector が APIC GUI の Apps > Installed Apps から Enable にされている
  • CLICommandCollector の Settings タブでコマンド取得に利用できる Username/Password が適切に設定されている

本稿は下記の環境での実行結果に基づいて作成されています。

  • APIC-SERVER-L3 (Version: 6.0(6c))
  • CLICommandCollector (Version: 1.2)
  • Ubuntu 22.04.4 LTS (WSL 環境)
  • curl 7.81.0

 

取得方法

1. Token の取得

ここでは続く API 実行に必要な Token を取得します。
同様の内容は「Cisco ACI : ACI における REST API 利用のためのログイン認証」でも紹介しています。
Token の取得のため、下記のコマンドを実行します。
なお、<Username> は「ログインに使用するUsername」、<Password> は「ログインに使用するUserのPassword」、<APIC IP address> は「アクセスする APIC の Management IP Address」をそれぞれ表しています。
また、Current Directory に取得した Token 入りの Cookie を cookie.txt として保存しています。

curl -X POST -d '{"aaaUser":{"attributes":{"name":"<Username>","pwd":"<Password>"}}}' -k https://<APIC IP Address>/api/aaaLogin.json -c cookie.txt

成功すると、HTTP 200 OK を受け取ります。

2. App Token の取得

ここでは App の API 実行に必要な App Token を取得します。
App Token 取得のために下記のコマンドを実行を実行します。

curl -k -X POST -d '{"aaaAppToken": {"attributes": {"appName": "cisco_CLICommandCollector"}}}' -b cookie.txt https://<APIC IP Address>/api/requestAppToken.json

ここで HTTP 200 OK と共に下記のような Response を受け取ります。
なお、XXXXXXXXXXXXXXXXXX の部分が App Token であり、実際には遥かに長い複雑な文字列です。

{
    "totalCount": "1",
    "imdata": [
        {
            "aaaLogin": {
                "attributes": {
                    "token": "XXXXXXXXXXXXXXXXXX",   ######  これが App Token
                    "siteFingerprint": "zc3hrz4ucaaaaaaaaaaaa4c8fbpywb",
                    "refreshTimeoutSeconds": "600",
<snip>
                }
            }
        }
    ]
}

 

3. App Token を用いたコマンドの取得

ここでは App Token を用いて、実際にコマンドの取得を行う result.json の実行をします。
取得した App Token を Header に入れるため、下記の内容のテキストファイル「header.txt」を Current Directory に作成します。

Cookie: app_cisco_CLICommandCollector_token=XXXXXXXXXXXXXXXXXX
Devcookie: XXXXXXXXXXXXXXXXXX
Content-Type: application/json

次に Current Directory に取得するコマンドをまとめた JSON ファイル「payload.json」を作成します。
ここでは apic1 で「acidiag version」を取得します。

[
    {
        "id": "1",
        "name": "apic1",
        "state": "in-service",
        "cmds": [
            {
                "type": "acidiag",
                "cmd": "acidiag version"
            }
        ]
    }
]

ここで下記のコマンドで result.json を実行します。

curl -k -X POST -H @headers.txt -d @payload.json https://<APIC IP Address>/appcenter/cisco/CLICommandCollector/result.json

コマンド取得のためにしばらく待つと、取得に成功した場合 HTTP 200 OK と共に下記のような Reponse を受け取ります。
なお、「show clock」の取得は指示していませんがコマンドを取得する前後で各機器で自動的に実行するようになっています。

[
    {
        "devs": {
            "id": "1",
            "name": "apic1"
        },
        "result": [
            {
                "cmd": "show clock",
                "output": "Time : 20:57:53.122 UTC+09:00 Fri Aug 23 2024\n%                                                                                                                                                                                                      \n \n"
            },
            {
                "cmd": "acidiag version",
                "output": "6.0.6c\n%                                                                                                                                                                                                      \n \n"
            },
            {
                "cmd": "show clock",
                "output": "Time : 20:57:54.534 UTC+09:00 Fri Aug 23 2024\n%                                                                                                                                                                                                      \n \n"
            }
        ]
    }
]

確かに実行している Version である「6.0.6c」が返ってきています。

result.json 実行時の Payload の書式

ここでは result.json を実行する際の Payload の書式を説明します。
書式全体は下記の形式になっています。
ここで「string」はその Key の Value が文字列であることを、「number」はその Key の Value が整数型の数値であることを、「?」はその Key が必須ではなく特定の場合にのみ必要であることを、「[]」はそれが付いている Object が複数格納された配列になっていることをそれぞれ意味しています。

{
    "id":  string,
    "name": string,
    "state": string,
    "lc"?: number[],
    "cmds": {
        "type": string,
        "cmd": string
    }[]
}[]

ここからは各 Key がどのような文字列や値を持つべきであるかを説明します。

id

「id」はコマンドを取得したい機器の node-id を意味しています。
これは APIC で「acidiag avread」、「acidiag fnvread」や「show switch」を実行した際に表示される ID と同じです。
例えば、node-id が 1101 番の機器で取得する場合には下記のようになります。

"id": "1101"

 

name

「name」は機器の名前です。
これは当該機器に SSH でログインした時にプロンプトに表示されるものです。
これは APIC で「acidiag fnvread」や「moquery -c topSystem」を実行した時に表示される Name や name の項目に表示されるものです。
例えば、取得したい機器のプロンプトが「leaf1#」であれば、「name」は下記のようになります。

"name": "leaf1"


state

「state」は機器の状態を表しています。
ただ、普通コマンドを取得したい機器は起動状態にあるため、この項目には原則「in-service」以外のものが指定されることはありません
そのため、いつも下記のように指定してください。

"state": "in-service"

 
lc

「lc」はコマンドを取得したい Line Card と Fabric Module の番号を意味しています。
この項目はコマンドを取得したい機器が Chassis 型の Spine である時のみ使用します。
それ以外の場合には含めないでください。
例えば、Chassis 型 Spine の 1,22,23,24,26 番のモジュールで取得したい場合には下記のように指定してください。

"lc": [1,22,23,24,26]


cmds

「cmds」はその機器で取得したいコマンドを表す配列です。
その配列の各要素は「type」と「cmd」という Key を持っています。
各 Key が表す具体的な内容は次で解説します。

type

「type」は取得するコマンドの種類やコマンドを取得する Shell を表します。
必ず取得する機器の種類やコマンドに応じた適切な内容を指定してください。
例えば、Box 型 Switch で vsh_lc_fc を使用するような不適切な指定をしないでください。
「type」にはコマンドに応じて以下のいずれかを指定します。

  • moquery: APIC でのみ使用します。moquery コマンドを取得する際に使用します。
  • show: APIC でのみ使用します。APIC で show コマンドを取得する際に使用します。
  • acidiag: APIC でのみ使用します。APICで acidiag コマンドを取得する際に使用します。
  • ish: Switch でのみ使用します。通常、ユーザーがログインした際に標準で使用する ishell でコマンドを取得する際にしようします。Switch の大抵の show コマンドはこれで取得します。
  • vsh: Switch でのみ使用します。Debug 用の Shell である Supervisor 側の vshell でコマンドを取得する場合に使用します。
  • vsh_lc: Box 型 Switch でのみ使用します。Debug 用の Shell である Line Card 側の vshell でコマンドを取得する際に使用します。
  • vsh_lc_lc: Chassis 型 Spine でのみ使用します。Debug 用の Shell である Line Card 側の vshell でコマンドを取得する際に使用します。これを指定する際には取得したい Line Card を「lc」に必ず含めてください。
  • vsh_lc_fc: Chassis 型 Spine でのみ使用します。Debug 用の Shell である Fabric Module 側の vshell でコマンドを取得する際に使用します。これを指定する際には取得したい Fabric Module を「lc」に必ず含めてください。

例えば、Chassis 型 Spine であるコマンドを Fabric Module の vshell で取得したい場合には下記のように指定します。

"type": "vsh_lc_fc"


cmd

「cmd」は取得する具体的なコマンドを表します。
例えば、取得したいコマンドが「show module」の場合は下記のように指定してください。

"cmd": "show module"

 

 

例えば、下記のような要件でコマンドを取得したいとします。

  • apic1 で「moquery -c topInfo」を取得する
  • spine1 の Line Card で「show copyright」を、Fabric Module で「show system uptime」を取得する。(この Chassis 型 Spine には 1 番の Module に Line Card が、22, 23, 24, 26 番の Module に Fabric Module が搭載されているとします。)
  • leaf1 の ishell で「show switchname」を取得する。

すると、result.json を叩く際の Payload は次のようになります。

[
    {
        "id": "1",
        "name": "apic1",
        "state": "in-service",
        "cmds": [
            {
                "type": "moquery",
                "cmd": "moquery -c topInfo"
            }
        ]
    },
    {
        "id": "201",
        "name": "leaf1",
        "state": "in-service",
        "cmds": [
            {
                "type": "ish",
                "cmd": "show switchname"
            }
        ]
    },
    {
        "id": "101",
        "name": "spine1",
        "state": "in-service",
        "lc": [
            22,
            23,
            24,
            26,
            1
        ],
        "cmds": [
            {
                "type": "vsh_lc_fc",
                "cmd": "show system uptime"
            },
            {
                "type": "vsh_lc_lc",
                "cmd": "show copyright "
            }
        ]
    }
]

これを実行すると下記のような Response を得ます。

[
    {
        "devs": {
            "id": "201",
            "name": "leaf1"
        },
        "result": [
            {
                "cmd": "show clock",
                "output": "10:42:13.247639 JST Tue Aug 27 2024\n"
            },
            {
                "cmd": "show switchname",
                "output": "leaf1\n"
            },
            {
                "cmd": "show clock",
                "output": "10:42:15.068102 JST Tue Aug 27 2024\n"
            }
        ]
    },
    {
        "devs": {
            "id": "1",
            "name": "apic1"
        },
        "result": [
            {
                "cmd": "show clock",
                "output": "Time : 10:42:13.759 UTC+09:00 Tue Aug 27 2024\n%                                                                                                                                                                                                      \n \n"
            },
            {
                "cmd": "moquery -c topInfo",
                "output": "Total Objects shown: 1\n# top.Info\nchildAction  : \ncurrentTime  : 2024-08-27T10:42:14.410+09:00\ndn           : info\nid           : 1\nmodTs        : never\npodId        : 1\nrn           : info\nrole         : controller\nstatus       : \n%                                                                                                                                                                                                      \n \n"
            },
            {
                "cmd": "show clock",
                "output": "Time : 10:42:15.097 UTC+09:00 Tue Aug 27 2024\n%                                                                                                                                                                                                      \n \n"
            }
        ]
    },
    {
        "devs": {
            "id": "101",
            "name": "spine1"
        },
        "result": [
            {
                "cmd": "show clock",
                "output": "10:42:13.025531 JST Tue Aug 27 2024\n"
            },
            {
                "lc": 22,
                "cmd": "show system uptime",
                "output": "No remote directory.\nSystem start time:          Wed Aug 21 14:38:22 2024\nSystem uptime:              5 days, 20 hours, 4 minutes, 3 seconds\nKernel uptime:              5 days, 20 hours, 8 minutes, 3 seconds\n"
            },
            {
                "lc": 23,
                "cmd": "show system uptime",
                "output": "No remote directory.\nSystem start time:          Wed Aug 21 14:34:43 2024\nSystem uptime:              5 days, 20 hours, 7 minutes, 44 seconds\nKernel uptime:              5 days, 20 hours, 11 minutes, 34 seconds\n"
            },
            {
                "lc": 24,
                "cmd": "show system uptime",
                "output": "No remote directory.\nSystem start time:          Wed Aug 21 14:39:53 2024\nSystem uptime:              5 days, 20 hours, 2 minutes, 39 seconds\nKernel uptime:              5 days, 20 hours, 5 minutes, 52 seconds\n"
            },
            {
                "lc": 26,
                "cmd": "show system uptime",
                "output": "No remote directory.\nSystem start time:          Wed Aug 21 14:34:27 2024\nSystem uptime:              5 days, 20 hours, 7 minutes, 59 seconds\nKernel uptime:              5 days, 20 hours, 12 minutes, 15 seconds\n"
            },
            {
                "lc": 1,
                "cmd": "show copyright ",
                "output": "No remote directory.\nCisco Nexus Operating System (NX-OS) Software\nTAC support: http://www.cisco.com/tac\nCopyright (c) 2002-2020, Cisco Systems, Inc. All rights reserved.\nThe copyrights to certain works contained in this software are\nowned by other third parties and used and distributed under\nlicense. Certain components of this software are licensed under\nthe GNU General Public License (GPL) version 2.0 or the GNU\nLesser General Public License (LGPL) Version 2.1. A copy of each\nsuch license is available at\nhttp://www.opensource.org/licenses/gpl-2.0.php and\nhttp://www.opensource.org/licenses/lgpl-2.1.php\n"
            },
            {
                "cmd": "show clock",
                "output": "10:42:31.095265 JST Tue Aug 27 2024\n"
            }
        ]
    }
]

 

手動での Payload の作成が大変、あるいは難しい方へ

ここまでの内容で Web API を利用して各種コマンドを取得することが出来るようになります。
ただ、複数の機器での複雑なコマンド取得のための JSON を手動で書くことが大変な場合があります。
また、上記の仕様を確認して手動で Payload を作成するのが面倒な場合もあります。
ここでは APIC GUI を使用してそうした内容を作成出来る方法を紹介します。

スクリーンショット 2024-08-24 171321.png

そもそも、result.json は CLICommandCollector の「Command Selection」で取得したい機器とコマンドを選択して、上記の画面で「Submit」を押下した時に実行されます。
このとき、Payload に含まれる内容に従って各機器でコマンドが取得されます。
言い換えると、本稿で紹介した内容は APIC GUI を用いずに手動で Payload の内容を作成して result.json を叩いてコマンドを取得する方法でした。
ブラウザに搭載されている Developer Tool (例えば、Windows の Google Chrome では Ctrl + Shift + I で開く) を開いて、APIC GUI の CLICommandCollector で取得したい機器とコマンドを選択して「Submit」を押下します。
そして、result.json を実行している際の Payload の内容をそのまま本稿で紹介した方法で使用すれば、同等の取得を行うことが出来ます。

 

本稿は以上です。

参考文献

ACI App:CLICommandCollector の紹介(複数 ACI ノードの CLI コマンド出力を同時に取得)
Cisco ACI : ACI における REST API 利用のためのログイン認証
Cisco ACI How To

Getting Started

検索バーにキーワード、フレーズ、または質問を入力し、お探しのものを見つけましょう

シスコ コミュニティをいち早く使いこなしていただけるよう役立つリンクをまとめました。みなさんのジャーニーがより良いものとなるようお手伝いします