概要
Juniper MistのAPを大量に登録・設定する場合、GUI操作では手間と時間がかかりますね。
MistはActivation Codeで一括登録出来ますが、「ホスト名を自由につけたい」とか、「分割して登録していきたい」等の場合、どうしても手作業が発生しているかと思います。
そこで本記事では、皆様からご質問の多い「Mist APをCSVで一括登録できるのか?」について
Mist APIを用いて以下の処理を自動化するPythonスクリプトを作成してみましたのでご紹介します。
本スクリプトで出来ることは以下の内容です:
- ClaimコードによるAP登録(インベントリへの追加)
- サイトへの割り当て(AP毎に指定可能)
- ホスト名(デバイス名)の設定
これらの情報をCSVファイルにまとめ、複数のAPを一括して処理できます。
利用対象
このスクリプトは以下のような場面で活用できます。
- 複数台のAPを一括でサイトに登録したい場合
- 一括登録しつつ、複数のサイトにホスト名を設定して登録したい場合
- Mist APIを使ってセットアップを自動化したいネットワークエンジニア
前提条件
以下の環境が必要です:
- Juniper MistのAPIトークンを取得済み
- 管理対象のOrg IDおよびSite IDを把握している
- Python 3.7以降が利用可能なLinux/Windows/macOS環境
- pandas と requests ライブラリがインストールされていること
インストール例:
pip install pandas requests
入力CSVファイルの例
ap_list.csv という名前のCSVファイルを作成します。
claim_code,site_id,hostname ABC12345,9a3b5c2d-1234-4abc-99aa-1234567890ab,AP-MeetingRoom-1 XYZ67890,9a3b5c2d-1234-4abc-99aa-1234567890ab,AP-Lobby-2
スクリプト(device-claim.py)
以下がサンプルスクリプトです。ファイル名は device-claim.py です。
# device-claim.py
import pandas as pd
import requests
import time
TOKEN = 'YOUR_API_TOKEN_HERE'
ORG_ID = 'YOUR_ORG_ID_HERE'
BASE_URL = 'https://api.mist.com/api/v1'
headers = {
'Authorization': f'Token {TOKEN}',
'Content-Type': 'application/json'
}
def claim_ap(claim_code):
url = f"{BASE_URL}/orgs/{ORG_ID}/inventory"
payload = [claim_code]
resp = requests.post(url, headers=headers, json=payload)
print("CLAIM RESPONSE:", resp.status_code, resp.text)
if resp.status_code == 200:
result = resp.json()
if result.get('inventory_added'):
item = result['inventory_added'][0]
return item.get('mac'), item.get('serial')
elif result.get('inventory_duplicated'):
item = result['inventory_duplicated'][0]
return item.get('mac'), item.get('serial')
else:
print(f"[ERROR] Unexpected result: {result}")
return None, None
else:
print(f"[ERROR] Claim failed: {resp.text}")
return None, None
def assign_site(mac, site_id):
url = f"{BASE_URL}/orgs/{ORG_ID}/inventory"
payload = {"op": "assign", "site_id": site_id, "macs": [mac]}
resp = requests.put(url, headers=headers, json=payload)
if resp.status_code == 200:
print(f"Assigned MAC={mac} to SiteID={site_id}")
return True
elif resp.status_code == 400 and "already assigned" in resp.text:
print(f"[WARN] Already assigned.")
return True
else:
print(f"[ERROR] Assign failed: {resp.text}")
return False
def set_hostname(site_id, mac, hostname):
mac_nocolon = mac.replace(":", "").lower()
device_id = f"00000000-0000-0000-1000-{mac_nocolon}"
url = f"{BASE_URL}/sites/{site_id}/devices/{device_id}"
payload = {"name": hostname}
resp = requests.put(url, headers=headers, json=payload)
if resp.status_code in [200, 204]:
print(f"Hostname set: {hostname}")
return True
else:
print(f"[ERROR] Hostname set failed: {resp.text}")
return False
def main():
df = pd.read_csv('ap_list.csv')
for _, row in df.iterrows():
claim_code = row['claim_code']
site_id = row['site_id']
hostname = row['hostname']
print(f"\nProcessing {claim_code} / {site_id} / {hostname}")
mac, _ = claim_ap(claim_code)
if not mac:
continue
if not assign_site(mac, site_id):
continue
set_hostname(site_id, mac, hostname)
time.sleep(1)
if __name__ == "__main__":
main()※ 注意事項
- TOKEN と ORG_ID はご自身の環境に合わせて書き換えてください。
- BASE_URL は、ご利用のCloudリージョンに合わせる必要があります。
使用方法
python3 device-claim.py
最後に
いかがでしたでしょうか?
実はこのスクリプトですが、勉強会の途中でご質問として頂いた内容を元に、休憩時間の間にChatGPTを使って作成しました。API プログラミングというと、敷居が高いと感じてしまいますが身近に来ていることを実感出来ます。
注意事項(免責)
本スクリプトの作成は、デモ用途としてOpenAIのChatGPTを使用しております。
商用利用や本番環境での利用を前提としたものではございません。
本スクリプトの使用により発生した損害・不具合について、Juniper Networks およびOpenAIは一切責任を負いません。ご利用は自己責任にてお願いいたします。