はじめに
Cisco VIRL(Virtual Internet Routing Lab)とは、Ciscoや他ベンダの仮想プラットフォームやサーバを、仮想環境内で互いに接続したり、外部の物理環境と接続したりできるシミュレーターです。
具体的には、IOSv、IOSv Layer-2、IOS-XRv、NX-OSv、CSR1000v、ASAvのようなCisco OSを使用可能です。
以前の記事で、virlutilsというCLIのユーティリティを使い、VIRLファイルから環境構築を行いました。
virlutilsを使ってCisco VIRLをCLIで構築してみた
VIRLはREST APIも提供しており、HTTP GET/PUT/POST/DELETEで環境の作成、削除、確認が可能です。
API一覧は、UWM(VIRLサーバ)上のメニュ「Documentation > STD API > simengine」で確認可能です。
VIRL API Details
今回はAnsibleを使って、シミュレーションの作成から終了までの基本操作を行ってみました。
用意した環境
-
VIRLサーバ
Cisco DevNet Sandbox上のVIRLを使用しました。 -
Ansible
ローカル環境のCentOSにインストールした2.8.3を使用しました。Sandbox上のDevBox(Linux)のAnsibleでも問題ないと思います。
Inventory
virl_host
、virl_username
、virl_password
でVIRLサーバのログイン情報を定義しています。
virl_file
で、環境構築に必要なトポロジーやConfigが定義されたVIRLファイルのパスを指定します。今回はGitHub virlfilesで公開されているvirlfiles/2-ios-router(2台のIOSvが相互接続された構成)を、topology.virl
というファイル名でローカル環境に格納し、フルパスで指定しています。
session
で、起動するシミュレーションの名前を指定します。今回はtest01
としました。
[cisco]
VIRL virl_host=[VIRLサーバのIPアドレス]
[cisco:vars]
virl_username=[VIRLサーバのユーザ名]
virl_password=[VIRLサーバのパスワード]
virl_file=/home/centos/venv/ansible/topology.virl
session=test01
Playbook①: 起動しているシミュレーションの確認
まず始めに、現在起動中のシミュレーションを確認します。HTTP GETメソッドで、URL~/list
を送信することで一覧を取得できます。
以前の記事でご紹介したvirl ls --all
に相当するAPIです。
---
- hosts: cisco
gather_facts: no
connection: local
tasks:
- name: Get the list of running simulations
uri:
url: "http://{{ virl_host }}:19399/simengine/rest/list"
user: "{{ virl_username }}"
password: "{{ virl_password }}"
method: GET
register: result_list
- name: Display running simulations
debug:
msg: "{{ result_list.json['simulations'] }}"
出力結果①: 起動しているシミュレーションの確認
~jumphost
というシミュレーションが起動しています。デフォルトで作成されるものなので、そのままにして次に移ります。
$ ansible-playbook -i inventory_virl playbook_virl_list.yml
PLAY [cisco] ****************************************************************************************************************
TASK [Get the list of running simulations] **********************************************************************************
ok: [VIRL]
TASK [Display running simulations] ******************************************************************************************
ok: [VIRL] => {
"msg": {
"~jumphost": {
"expires": null,
"launched": "2018-08-02T19:21:08.764190",
"status": "ACTIVE"
}
}
}
PLAY RECAP ******************************************************************************************************************
VIRL : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Playbook②: シミュレーションの開始
シミュレーションtest01
を開始します。HTTP POSTメソッドを使い、URL~/launch
の中でパラメータsession
をtest01
に指定しています。指定しない場合は勝手に名前が付けられます。
また、BodyにVIRLファイルの中身を指定しています。
リクエストに失敗した場合に備え、GitHub - CiscoDevNet/ansible-virlを参考にリトライ処理も加えています。
以前の記事でご紹介したvirl up
に相当するAPIです。
---
- hosts: cisco
gather_facts: no
connection: local
tasks:
- name: Launch the simulation {{ session }}
uri:
url: "http://{{ virl_host }}:19399/simengine/rest/launch?session={{ session }}"
user: "{{ virl_username }}"
password: "{{ virl_password }}"
method: POST
headers:
Content-Type: "text/xml;charset=UTF-8"
body: "{{ lookup('file', '{{ virl_file }}') }}"
register: result_launch
until: result_launch['status']|default(0) < 300
retries: 60
delay: 10
- name: Display the launch result
debug:
msg: "{{ result_launch }}"
出力結果②: シミュレーションの開始
"status": 200
と表示されているので、リクエストに成功したようです。
$ ansible-playbook -i inventory_virl playbook_virl_launch.yml
PLAY [cisco] ****************************************************************************************************************
TASK [Launch the simulation test01] *****************************************************************************************
ok: [VIRL]
TASK [Display the launch result] ********************************************************************************************
ok: [VIRL] => {
"msg": {
"access_control_allow_origin": "*",
"attempts": 1,
"changed": false,
"connection": "close",
"content_length": "6",
"content_type": "text/plain",
"cookies": {},
"cookies_string": "",
"elapsed": 3,
"failed": false,
"msg": "OK (6 bytes)",
"redirected": false,
"server": "virl_std_server/0.10.37.23",
"status": 200,
"url": "http://10.10.20.160:19399/simengine/rest/launch?session=test01"
}
}
PLAY RECAP ******************************************************************************************************************
VIRL : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
VIRLサーバの画面を見ると、シミュレーションtest01
が作成され、router1、router2が起動していました。
Playbook③: シミュレーション内のノード確認
念のためAPI経由でも、シミュレーションtest01
内のノード名やステータスを確認してみます。
---
- hosts: cisco
gather_facts: no
connection: local
tasks:
- name: Get the list of nodes in simulation {{ session }}
uri:
url: "http://{{ virl_host }}:19399/simengine/rest/nodes/{{ session }}"
user: "{{ virl_username }}"
password: "{{ virl_password }}"
method: GET
register: result_nodes
- name: Display the node list
debug:
msg: "{{ result_nodes.json }}"
出力結果③: シミュレーション内のノード確認
②のGUIと同様の情報が表示されました。
$ ansible-playbook -i inventory_virl playbook_virl_nodes.yml
PLAY [cisco] ****************************************************************************************************************
TASK [Get the list of nodes in simulation test01] ***************************************************************************
ok: [VIRL]
TASK [Display the node list] ************************************************************************************************
ok: [VIRL] => {
"msg": {
"test01": {
"router1": {
"management-protocol": "telnet",
"management-proxy": "jumphost",
"reachable": true,
"serial-ports": 2,
"state": "ACTIVE",
"subtype": "IOSv",
"vnc-console": false
},
"router2": {
"management-protocol": "telnet",
"management-proxy": "jumphost",
"reachable": true,
"serial-ports": 2,
"state": "ACTIVE",
"subtype": "IOSv",
"vnc-console": false
}
}
}
}
PLAY RECAP ******************************************************************************************************************
VIRL : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Playbook④: シミュレーションの停止
VIRLは起動台数の上限があるため、使わない時は停止しておくケースが多いと思います。これもHTTP PUTメソッドでURL~/update/{シミュレーション名}/stop
を送信すれば停止可能です。
逆に、起動する時はURL~/update/{シミュレーション名}/start
で起動できます。
---
- hosts: cisco
gather_facts: no
connection: local
tasks:
- name: Stop the simulation {{ session }}
uri:
url: "http://{{ virl_host }}:19399/simengine/rest/update/{{ session }}/stop"
user: "{{ virl_username }}"
password: "{{ virl_password }}"
method: PUT
headers:
Content-Type: "text/xml;charset=UTF-8"
register: result_stop
- name: Display the stop result
debug:
msg: "{{ result_stop }}"
出力結果④: シミュレーションの停止
jsonの結果が"stopped": "~~==\"a|u|t|o\"==~~"
となっています。
$ ansible-playbook -i inventory_virl playbook_virl_stop.yml
PLAY [cisco] ****************************************************************************************************************
TASK [Stop the simulation test01] *******************************************************************************************
ok: [VIRL]
TASK [Display the stop result] **********************************************************************************************
ok: [VIRL] => {
"msg": {
"access_control_allow_origin": "*",
"changed": false,
"connection": "close",
"content_length": "34",
"content_type": "application/json",
"cookies": {},
"cookies_string": "",
"elapsed": 2,
"failed": false,
"json": {
"stopped": "~~==\"a|u|t|o\"==~~"
},
"msg": "OK (34 bytes)",
"redirected": false,
"server": "virl_std_server/0.10.37.23",
"status": 200,
"url": "http://10.10.20.160:19399/simengine/rest/update/test01/stop"
}
}
PLAY RECAP ******************************************************************************************************************
VIRL : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
VIRLサーバの画面でも、各ノードのStateがABSENTになっています。
Playbook⑤: シミュレーションの終了(完全停止)
不要になったシミュレーションは、完全に停止し、VIRLサーバ上から削除します。この場合はHTTP GETメソッドでURL/stop/{シミュレーション名}
を送信します。
前回の記事でご紹介したvirl down --sim-name {シミュレーション名}
に相当するAPIです。
---
- hosts: cisco
gather_facts: no
connection: local
tasks:
- name: Completely stop the simulation {{ session }}
uri:
url: "http://{{ virl_host }}:19399/simengine/rest/stop/{{ session }}"
user: "{{ virl_username }}"
password: "{{ virl_password }}"
method: GET
register: result_termination
- name: Display the termination result
debug:
msg: "{{ result_termination }}"
出力結果⑤: シミュレーションの終了(完全停止)
問題なく"status": 200
が返ってきました。
$ ansible-playbook -i inventory_virl playbook_virl_termination.yml
PLAY [cisco] ****************************************************************************************************************
TASK [Completely stop the simulation test01] ********************************************************************************
ok: [VIRL]
TASK [Display the termination result] ***************************************************************************************
ok: [VIRL] => {
"msg": {
"access_control_allow_origin": "*",
"changed": false,
"connection": "close",
"content_length": "7",
"content_type": "text/plain",
"cookies": {},
"cookies_string": "",
"elapsed": 2,
"failed": false,
"msg": "OK (7 bytes)",
"redirected": false,
"server": "virl_std_server/0.10.37.23",
"status": 200,
"url": "http://10.10.20.160:19399/simengine/rest/stop/test01"
}
}
PLAY RECAP ******************************************************************************************************************
VIRL : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
最後に
今回は完成しているVIRLファイルを使いましたが、Inventoryで指定したパラメータとJinja2テンプレートと組み合わせて、動的にConfig、シミュレーションを作成することもできます。
また作成時、マネジメントネットワーク経由でSSHアクセスする設定を入れておけば、その後の設定変更やshowコマンド確認をAnsibleのxxx_config
やxxx_command
モジュールで行うこともできます。この辺は、今後別の記事でご紹介したいと思います。