CML でノードの起動時間を取得する
Cisco CML で「一定時間以上、起動しているラボは停止する」という処理を実装しようと思ったのですが、ラボには「作成時間」や「起動時間」というプロパティが存在しないようです。 代替手段として「機器へ TELNET / SSH して uptime を取得する」という方法もあるかもしれませんが、イマイチです。 ラボそのものには「起動時間」のプロパティが無いものの、ノードには「起動時間を示すプロパティ」があるようです。 今回はその値を取得する Python のサンプルプログラムをメモしておきます。
検証環境¶
| 対象 | バージョン |
|---|---|
| CML | 2.6.1 |
| macOS | 14.4 |
| Python | 3.12.2 |
ノードの起動時間は BOOTED プロパティで取得出来る¶
結論から述べると「ノードの起動時間」は Labs にある /labs/{lab_id}/simulation_stats API の結果に含まれる BOOTED という値として取得出来ました。 「ノードの起動時間」ということで Nodes の API で取得出来そうな気がするのですが、こちらでは取得出来ませんでした。

実際に /labs/{lab_id}/simulation_stats API を実行した結果例は以下の通りです。 テストした対象ラボは 2 ノード存在する為、「2 ノード分の実行結果」を取得しています。
{
"links": {},
"nodes": {
"18c1ac79-64f7-4cc4-b55f-fd07c4d31f3e": {
"block0_rd_bytes": 1571173888,
"block0_wr_bytes": 608583680,
"cpu_usage": 45.81,
"times": {
"BOOTED": 614,
"QUEUED": 11,
"STARTED": 730
}
},
"d5cb4984-d086-441f-981c-da0fd7bbbef5": {
"block0_rd_bytes": 1569957376,
"block0_wr_bytes": 339341312,
"cpu_usage": 46.77,
"times": {
"BOOTED": 620,
"QUEUED": 4,
"STARTED": 737
}
}
}
}
BOOTED と STARTED の値がありますが、これらはおそらく以下の意味だと思われます。
| 項目 | 意味 |
|---|---|
STARTED |
ノードが開始されてから経過した秒数 |
BOOTED |
ノードが「起動した」と認識されてから経過した秒数 |
ノードを「起動した」と判定するロジックは CML の Node Definition 中で定義されています。
サンプルプログラム¶
BOOTED の値に加え、STARTED も取得しています。 BOOTED の値を取得するだけであれば不要ですが、ソート等が楽なので pandas を利用しています。
#!/usr/bin/env python3
import http.client
import json
import ssl
import pandas
address = "10.0.0.1"
username = "admin"
password = "password"
def authenticate(conn, username, password):
payload = json.dumps({"username": username, "password": password})
headers = {"Content-Type": "application/json"}
conn.request("POST", "/api/v0/authenticate", payload, headers)
res = conn.getresponse()
data = res.read()
return data.decode("utf-8").replace('"', "")
def get_json(conn: http.client.HTTPSConnection, token: str, url: str):
payload = ""
headers = {"Authorization": "Bearer " + token}
conn.request("GET", url, payload, headers)
return json.loads(conn.getresponse().read().decode("utf-8"))
def get_lab(conn: http.client.HTTPSConnection, token: str, lab_id: str):
return get_json(conn, token, f"/api/v0/labs/{lab_id}")
def get_labs(conn: http.client.HTTPSConnection, token: str):
return get_json(conn, token, "/api/v0/labs")
def get_node(conn: http.client.HTTPSConnection, token: str, lab_id: str, node_id: str):
return get_json(conn, token, f"/api/v0/labs/{lab_id}/nodes/{node_id}")
def get_stats(conn: http.client.HTTPSConnection, token: str, lab_id: str):
return get_json(conn, token, f"/api/v0/labs/{lab_id}/simulation_stats")
def main():
conn = http.client.HTTPSConnection(
address, context=ssl._create_unverified_context()
)
token = authenticate(conn, username, password)
labs = get_labs(conn, token)
values = []
for lab in labs:
lab_title = get_lab(conn, token, lab)["lab_title"]
stats = get_stats(conn, token, lab)
for node in stats["nodes"]:
n = get_node(conn, token, lab, node)
booted = stats["nodes"][node]["times"]["BOOTED"]
started = stats["nodes"][node]["times"]["STARTED"]
values.append([lab_title, n["label"], booted, started])
df = pandas.DataFrame(
columns=["lab_title", "label", "BOOTED", "STARTED"], data=values
)
print(df.sort_values(["lab_title", "label"]).to_string(index=False))
if __name__ == "__main__":
main()
実行結果¶
実行例は以下の通りです。