✅ cURLワンライナー(外部ファイルなし・1台だけ変更)
置換:
TOKEN=$(curl -sk -X POST "https://<XIQC_IP>:5825/management/v1/oauth2/token" \
-H "Content-Type: application/json" -d '{"username":"<USER>","password":"<PASS>"}' \
| jq -r .access_token); \
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://<XIQC_IP>:5825/management/v1/aps/<AP_SERIAL>" \
| jq '.hostname="<NEW_HOSTNAME>" | .name="<NEW_HOSTNAME>"' \
| curl -sk -X PUT "https://<XIQC_IP>:5825/management/v1/aps/<AP_SERIAL>" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d @-
ポイント:GETの応答(JSON)をそのまま加工してPUT(記事の解決策どおり)。
Extreme Networks
画面上の表示名も揃えるなら .name も同時に差し替え(不要なら .name=... を削ってOK)。
自己署名証明書の環境を想定して -k を入れています。
🐍 Python(1台だけ変更・requests)
import requests, urllib3
urllib3.disable_warnings()
BASE = "https://<XIQC_IP>:5825"
USER = "<USER>"
PASS = "<PASS>"
SERIAL = "<AP_SERIAL>"
NEW = "<NEW_HOSTNAME>"
def token():
r = requests.post(f"{BASE}/management/v1/oauth2/token",
json={"username": USER, "password": PASS},
verify=False)
r.raise_for_status()
return r.json()["access_token"]
tok = token()
hdr = {"Authorization": f"Bearer {tok}"}
# GET(全項目取得)
ap = requests.get(f"{BASE}/management/v1/aps/{SERIAL}", headers=hdr, verify=False).json()
# 変更箇所だけ上書き(必要なら name も)
ap["hostname"] = NEW
ap["name"] = NEW # 表示名も合わせたい場合
# 丸ごとPUT(全項目を返す)
r = requests.put(f"{BASE}/management/v1/aps/{SERIAL}",
headers={**hdr, "Content-Type": "application/json"},
json=ap, verify=False)
print("OK" if r.ok else f"NG {r.status_code}: {r.text}")
運用メモ
重要:PUTはGETで返ってきた全プロパティを含めるのがコツ(単一フィールドだけ送るとエラー)。これは公式KBの解決策として明記されています。
Extreme Networks
認証は /management/v1/oauth2/token のOAuth2で取得したaccess_tokenをBearerで送ります。
Extreme Networks Documentation
もしあなたの環境で/management/v1/aps/のGETが既に通っているなら、PUTも同じURIで動きます(同一リソースの更新)。
やっていることはシンプルに言うと「トークン取得 → AP設定をGET → hostname/nameを書き換え → 同じURIにPUT」です。各パートを順に分解して解説します。
全体の流れ(ワンライナーの意図)
OAuth2でアクセストークンを取りに行く
そのトークンで /management/v1/aps/ を GET(=APの“完全な”現在設定)
jq で hostname と name を置換(他の項目は触らない)
置換後の完全オブジェクトを PUT(=“丸ごと返す”)
XIQ-Cは「フィールドだけPUT/PATCH」は通らず、GETした完全JSONを丸ごとPUTするのが正解です。
コードを部品ごとに解説
TOKEN=$(curl -sk -X POST "https://<XIQC_IP>:5825/management/v1/oauth2/token" \
-H "Content-Type: application/json" -d '{"username":"<USER>","password":"<PASS>"}' \
| jq -r .access_token); \
curl -s: 進捗などを黙らせる(静かに)
-k: サーバ証明書の検証を無効化(自己署名などの環境向け)
※本番はCAを正しく入れて -k を外すのが安全
-X POST: POSTメソッド
-H "Content-Type: application/json": ボディがJSON
-d '{...}': ユーザ/パスをJSONで送る
| jq -r .access_token: JSON応答から access_token を生値で抽出(-r はダブルクォートを外す)
$( ... ): コマンド置換でTOKEN変数に代入
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://<XIQC_IP>:5825/management/v1/aps/<AP_SERIAL>" \
ここでAPの現在設定をGET(JSON一式)
Authorization: Bearer $TOKEN: さきほどのトークンで認可
| jq '.hostname="<NEW_HOSTNAME>" | .name="<NEW_HOSTNAME>"' \
受け取ったJSONに対して変換:
.hostname="" → hostname を上書き
| .name="" → 続けて name も上書き(GUIの表示名を揃えたいとき)
hostname や name が無ければ 新規に追加 されます
それ以外のフィールドは全部温存(丸ごとPUTに必要)
| curl -sk -X PUT "https://<XIQC_IP>:5825/management/v1/aps/<AP_SERIAL>" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d @-
-X PUT: 更新
-d @-: 標準入力から受け取ったJSONをそのままボディに(jq の出力をそのままPUT)
つまり 「GETの中身」+「hostname/nameの差分」=完全オブジェクトを返している
何が良いのか(この形の狙い)
完全オブジェクトPUTなので、XIQ-Cの仕様(部分更新不可)を満たす
他の設定は一切壊さない(GETした内容をそのまま返す)
jq で差分だけ操作できるので、安全に1項目だけ変えたい要件に合う
ありがちな落とし穴と対策
GETが失敗してもパイプが続いてしまう
→ curl に -f(fail)を付ける/set -euo pipefail を使う/jq -e でJSONでない入力をエラーに
set -euo pipefail
TOKEN=$(curl -fsSk ... | jq -r .access_token)
curl -fsSk -H "Authorization: Bearer $TOKEN" "https://.../aps/<AP_SERIAL>" \
| jq -e '.hostname="<NEW_HOSTNAME>" | .name="<NEW_HOSTNAME>"' \
| curl -fsSk -X PUT "https://.../aps/<AP_SERIAL>" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d @-
-k の常用は危険(MITM耐性が落ちる)
→ 可能ならコントローラの証明書を信頼させ、-k を外す
ホスト名のルール
→ 一般にRFC 1123準拠(英数字・ハイフン、63文字/ラベル等)が無難。環境で制約があれば従う
name を揃えたくない場合
→ jq '.hostname=""' だけにする
URLに特殊文字(シリアルに / 等)はほぼ無いが、もし必要ならURLエンコードを
トークン期限
→ このワンショットでは問題になりにくいが、バッチで長く回すなら適宜再取得を
Windowsの改行
→ PowerShell/WSLでのコピペ時に改行・クォートが崩れないよう注意(WSL推奨)
動作確認(検証の仕方)
変更後に再GETして一致を確認:
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://<XIQC_IP>:5825/management/v1/aps/<AP_SERIAL>" \
| jq -r '.hostname,.name'
想定どおり NEW_HOSTNAME が出ればOK。
HTTPコードを最後に出す(デバッグ時):
... | curl -sk -X PUT "https://.../aps/<AP_SERIAL>" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d @- \
-w "\nHTTP_STATUS:%{http_code}\n"
応用(必要に応じて)
name は触らず hostname だけ更新:
... | jq '.hostname="<NEW_HOSTNAME>"' | curl ... -d @-
Diffを見てからPUT(ドライラン):
curl -sk -H "Authorization: Bearer $TOKEN" "https://.../aps/<AP_SERIAL>" \
| jq --arg hn "<NEW_HOSTNAME>" 'select(.hostname!=$hn) | .hostname=$hn | .name=$hn'
# 出力が空なら変更不要。出力があれば、そのままPUTに流す。
バッチ処理(CSVで複数台)
すでにPython版をお渡しした通り、serial,hostname のCSVを読み、GET→書換→PUTをループすればOK。Bashでも while IFS=, read ... で同様に回せます(スロットルに sleep 0.2 など)。
TOKEN=$(curl -sk -X POST "https://<XIQC_IP>:5825/management/v1/oauth2/token" \
-H "Content-Type: application/json" \
-d '{"username":"<USER>","password":"<PASS>"}' | jq -r .access_token); \
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://<XIQC_IP>:5825/management/v1/aps/<AP_SERIAL>" \
| jq --arg hn "<NEW_HOSTNAME>" '.hostname=$hn | .apName=$hn' \
| curl -sk -X PUT "https://<XIQC_IP>:5825/management/v1/aps/<AP_SERIAL>" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d @-
反映確認
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://<XIQC_IP>:5825/management/v1/aps/<AP_SERIAL>" \
| jq -r '[.apName?, .name?, .hostname] | @tsv'