この記事はシスコの有志による Cisco Systems Japan Advent Calendar 2025 の 11 日目として投稿しています。
過去のアドベントカレンダーも是非覗いてみてください。
2024年版: https://qiita.com/advent-calendar/2024/cisco
2023年版: https://qiita.com/advent-calendar/2023/cisco
2022年版: https://qiita.com/advent-calendar/2022/cisco
2021年版: https://qiita.com/advent-calendar/2021/cisco
2020年版: https://qiita.com/advent-calendar/2020/cisco
2019年版: https://qiita.com/advent-calendar/2019/cisco
はじめに
「バイブコーディング」 という言葉をご存知でしょうか?
2025年、AI コーディングアシスタントの進化により、「コードを書く」から「AI と対話してコードを生み出す」時代へと変わりつつあります。バイブコーディングとは、まさにその流れを象徴する言葉で、AI とのやり取りの「雰囲気(vibe)」でコードが生まれていく開発スタイルです。
今回は、Windsurf という AI コーディングエディタを使って、実際に pyATS の CML2 プラグイン を半日で開発してみた体験記をお届けします。
pyATS(Python Automated Test System)は、Cisco が提供するネットワークテスト自動化フレームワークです。詳しくは私の過去記事をご参照ください。
今回作ったもの:CML2 プラグイン
CML2 とは?
CML2(Cisco Modeling Labs 2) は、Cisco のネットワークシミュレーション環境です。仮想ルーター、スイッチ、ファイアウォールなどを GUI 上でドラッグ&ドロップで配置し、本番さながらのネットワークトポロジーをオンデマンドで構築できます。
何を作りたかったのか
pyATS でテストを実行する際、テスト対象のネットワーク環境が必要です。通常は既存の機器に接続しますが、「pyATS の testbed ファイルから CML2 上にトポロジーを自動で展開し、テスト完了後に自動で片付ける」 ことができれば、オンデマンドでテスト環境を用意できます。
これにより:
- 🎯 テストのたびに手動で CML2 ラボを作成する必要がない
- 🎯 テスト完了後の後片付けも自動
- 🎯 CI/CD パイプラインへの組み込みが容易に
完成したもの
上記のように、pyATS の testbed.yaml から自動的に CML2 上にトポロジーが展開されます。
開発環境
| 項目 | 詳細 |
|---|---|
| エディタ | Windsurf 1.12.39 |
| AI モデル | Claude Opus 4.5 (Thinking) |
| 開発期間 | 約半日 |
| プロンプト数 | 約 50+ |
最終的には virl2-client を使っています。
バイブコーディング実践記
ステップ1: まずは AI に理解してもらう(コードは書かせない!)
バイブコーディングで最も重要なのは、最初に AI にコンテキストをしっかり理解してもらうことです。
私の最初のプロンプトはこうでした:
CML2 MCP サーバを使って、pyATS testbed yaml の情報からトポロジーをCML2上に作成し、起動させて、起動完了を確認して、pyATS Testbed object を上書きし、CML2 上のトポロジーに対して pyATS script を実行する pyATS plugin を作りたいです。まずは下記の pyATS plugin のドキュメント理解してください。まだコードは生成しないでください。
ポイントは 「まだコードは生成しないでください」 という一文。これを入れないと、AI は理解が不十分なまま勝手にコードを書き始めてしまいます。
AI コーディングアシスタントは「すぐにコードを書きたがる」傾向があります。複雑なタスクでは、まず理解を確認してから進めることで、手戻りを大幅に減らせます。
ステップ2: 既存コードを参考資料として提供
pyATS には既に Ansible 用のプラグインが存在していたため、そのコードを参考にしてもらいました:
下記コードは pyATS の Ansible Plugin です。これをベースに、上記の理解を元に CML2 plugin の骨組みとなるベースを作ってください。
既存の動作するコードを見せることで、AI はプロジェクトのコーディングスタイルや構造を理解できます。これは ゼロから作るより圧倒的に品質が上がる テクニックです。
ステップ3: 選択肢を提示して方向性を確認
開発中、AI には不明な点は必ず確認を取るようにお願いしました。そのため、AI が「どうしましょうか?」と聞いてくることがあります。そんな時は番号付きの選択肢を提示してもらい、シンプルに回答しました:
AI の提案:
- デバッグログを追加して原因を調査
- 別のアプローチで認証情報を設定
私の回答:
1で進めてください
これにより、長い説明なしに迅速に方向性を決められます。
開発中のハプニング集 🎭
バイブコーディングは順調に見えて、実は色々なハプニングがありました。ここからが本記事の本題(?)です。
ハプニング1: 「tahigash って誰だよ!」問題 😱
CML2 ラボが起動し、いざデバイスに接続!...と思ったら、ログにこんな表示が:
inserthostname-here login: tahigash
Password:
Login incorrect
User Access Verification
login: tahigash
Password:
Login incorrect
tahigash...それ、私のユーザー名です!!
CML2 デバイスのデフォルト認証情報(cisco/cisco や admin/cisco)を設定したはずなのに、なぜか私のシステムユーザー名が使われていました。
原因究明の旅
AI とのデバッグ対話が始まりました:
私: ログを見ると、まだ tahigash を使っています。なぜ?
AI: デバッグログを追加して確認します...
Set CML2 credentials for csr1000v: username=cisco
Verified: cisco
認証情報は正しく設定されています!
私: 設定されてるのに使われてない...?
ここから原因究明の旅が始まりました。結局、原因は 3 段階 ありました:
-
プラットフォーム推論の問題: デバイスの
platform属性がrouterやswitchという汎用的な値で、CML2 のノード定義(csr1000v,nxosv9000)とマッチしなかった -
認証情報の設定方法:
device.credentials.default.username = "cisco"と属性で設定していたが、内部の辞書データが更新されていなかった -
Genie testbed.load() の罠: テストスクリプトで
genie.testbed.load(testbed)を呼ぶと、新しい Testbed オブジェクトが作られ、せっかく設定した認証情報が引き継がれなかった!
解決策
最終的に、認証情報をデバイスオブジェクトと接続オブジェクトの両方に設定することで解決しました:
# デバイスに認証情報を設定
orig_device.credentials = Credentials(creds_dict)
# 接続オブジェクトにも設定(これが重要!)
for conn_name, conn in orig_device.connections.items():
conn["credentials"] = creds_dict
この問題だけで 10 回以上 のプロンプトを費やしました...バイブコーディングも万能ではありません!
ハプニング2: node.state() が呼べない問題
トポロジーサマリーを表示する機能を追加した時のこと:
TypeError: 'str' object is not callable
原因は node.state() というコード。virl2-client ライブラリで state がメソッドなのかプロパティなのか、バージョンによって異なっていました。
AI の修正提案:
# Before
node_state = node.state()
# After(メソッドかプロパティか判定)
node_state = node.state() if callable(node.state) else node.state
こういう細かいバグも、AI は瞬時に修正案を出してくれます。
ハプニング3: NX-OS のパスワードが違う!
CML2 のデフォルト認証情報をコード内に定義していたのですが:
CML2_DEFAULT_CREDENTIALS = {
"csr1000v": {"username": "cisco", "password": "cisco"},
"nxosv9000": {"username": "admin", "password": "Admin123"}, # ← 間違い!
...
}
実際の NX-OSv9000 のデフォルトパスワードは cisco でした。私は CML2 ノードのデフォルトパスワードが記載されているドキュメントページを AI に提供したのですが、そのページには NX-OSv9000 のパスワードが含まれていませんでした。にもかかわらず、AI は確認を取らずに勝手に Admin123 と推測して コードを生成していました。
AI は「分からない」と言わずに、それっぽい値を勝手に補完することがあります。AI の出力を鵜呑みにせず、必ず確認しましょう。
完成した CML2 プラグインの機能
紆余曲折を経て、以下の機能を持つプラグインが完成しました:
主な機能
1. 自動ラボ作成
pyATS testbed.yaml からCML2ラボを自動生成:
- デバイスの作成(プラットフォーム自動推論)
- インターフェースの作成
- リンクの作成
2. ライフサイクル管理
- ラボの起動と収束待機
- テスト完了後の自動クリーンアップ
-
--cml2-keep-labオプションでラボを残すことも可能
3. 認証情報の自動設定
CML2 デバイスのデフォルト認証情報を自動で設定:
| ノード定義 | ユーザー名 | パスワード |
|---|---|---|
| csr1000v | cisco | cisco |
| nxosv9000 | admin | cisco |
| iosxrv9000 | cisco | cisco |
| asav | admin | Admin123 |
4. トポロジー検証
期待されるリンクが CML2 ラボに存在するか検証し、問題があればエラーを報告。
5. トポロジーサマリー表示
ラボ起動後に詳細なトポロジー情報をログに出力。
+------------------------------------------------------------------------------+
| CML2 Topology Summary |
+------------------------------------------------------------------------------+
Lab Name: devnet_always_on_sandbox
Lab ID: c8b7cb98-0c16-403a-bd90-d2175efc9253
Lab URL: https://10.1.1.1/lab/c8b7cb98-0c16-403a-bd90-d2175efc9253
================================================================================
DEVICES
================================================================================
Name Platform State Console Port
--------------------------------------------------------------------------------
csr1000v csr1000v BOOTED N/A
sbx-n9kv-ao nxosv9000 BOOTED N/A
================================================================================
CONNECTIONS
================================================================================
Device Connection Host Port
--------------------------------------------------------------------------------
csr1000v console N/A N/A
csr1000v defaults N/A N/A
sbx-n9kv-ao console N/A N/A
sbx-n9kv-ao defaults N/A N/A
================================================================================
LINKS
================================================================================
Link Device A Interface A Device B Interface B
-------------------------------------------------------------------------------------
1 csr1000v GigabitEthernet2 sbx-n9kv-ao Ethernet1/1
================================================================================
使い方
pyats run job my_job.py \
--testbed-file testbed.yaml \
--cml2-enable \
--cml2-url https://cml2-server/ \
--cml2-username <cml2 username> \
--cml2-password <cml2 password> \
--cml2-keep-lab # オプション:ラボを残す
バイブコーディングで学んだこと
良かった点 ✅
- 開発速度: 半日で機能的なプラグインが完成
- ボイラープレートの自動生成: 繰り返しコードは AI に任せられる
- デバッグ支援: エラーメッセージを貼り付けるだけで原因と解決策を提案
- ドキュメント理解: 公式ドキュメントを読ませて要約してもらえる
注意点 ⚠️
- 最初のコンテキスト設定が重要: 理解を確認してからコードを書かせる
- AI を過信しない: 生成されたコードは必ずレビューする
- デバッグは根気よく: 複雑な問題は複数回のやり取りが必要
- 正確な情報を与える: 間違った前提 → 間違ったコード
プロンプトのコツ
| テクニック | 説明 |
|---|---|
| 段階的に進める | 「まだコードは書かないで」で理解を先に確認 |
| 既存コードを参考に | 「このコードをベースに」で品質向上 |
| 選択肢で回答 | 「1で進めてください」で迅速な意思決定 |
| ログを貼り付ける | デバッグ時はエラーログをそのまま共有 |
今後のロードマップ
このプラグインは現在も開発中です。今後の予定:
- 特定イメージの指定: ノード定義だけでなく、特定のソフトウェアイメージを指定可能に
- pyATS Clean ファイル対応: CML2 向けの Clean ステージを追加
- より柔軟なトポロジー定義: 複雑なトポロジーのサポート強化
ソースコード
本記事執筆時点のコードは以下の PR で確認できます:
記事執筆後もコードの更新が行われている可能性があります。最新のコードは PR またはマージ後のリポジトリをご確認ください。
まとめ
バイブコーディングで pyATS プラグインを開発してみた結果:
- ✅ 半日で機能的なプラグインが完成
- ✅ AI との対話でデバッグも効率化
- ⚠️ ただし AI を過信せず、コードレビューは必須
- 💡 最初のコンテキスト設定が成功の鍵
AI コーディングアシスタントの進化により、pyATS のようなフレームワークへのコントリビュートがより身近になっています。「コードを書くのが苦手」という方も、バイブコーディングなら挑戦できるかもしれません。
皆さんもぜひ、AI と一緒にコーディングしてみてください!🚀
参考リンク
- pyATS Documentation
- Genie Documentation
- CML2 Documentation
- virl2-client (PyPI)
- Windsurf Editor
- pyATS.contrib GitHub
免責事項
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。

