IOS-XRv Vagrantを試してみた

[NetOpsCoding Advent Clender](http://qiita.com/advent-calendar/2016/netopscoding) 12日目です。

12/5の@taijijiji さんのアドベントカレンダーでこんな投稿がありました。
[Vagrantでfireflyを動かしたら自動化開発が捗った話](http://qiita.com/taijijiji/items/501a4d671106240fbd2c)

今回はそれのCisco IOS-XRバージョンを試してみたので共有します。
**尚、この手法については下記記事で既に公開されてるものを試した、という投稿になります。
内容も下記ブログのチュートリアルをなぞっただけで、出来ました！というものです。
また、本手法はPrivate beta時点のものであり、今後どうなるかは分かりません。**

- [XR toolbox, Part 1 : IOS-XR Vagrant Quick Start](https://xrdocs.github.io/application-hosting/tutorials/iosxr-vagrant-quickstart)

# :zero: 動作環境
 - MacBook Pro (13-inch, Mid 2014)
    - MacOS Sierra
    - 2.8 GHz Intel Core i5
    - 8 GB 1600 MHz DDR3
 - vagrant 1.9.0
 - virtualbox 5.0.2

# :one:Cisco CCO IDの登録
IOS-XRvのvagrant Box取得には、Cisco公式のIDが必要です。
取得していない方は取得しましょう。
https://idreg.cloudapps.cisco.com/idreg/register.do

# :two:Vagrant boxを取得するための申請
今回やってみたこのIOS-XRvに関しては**Private Betaバージョン**です。
boxのダウンロードには、CCO IDを持つ、かつIOS-XRv vagrant boxをダウンロードするためのAPI Keyが必須となります。
URLを参考に、API Keyを取得するためのサイトへのアクセス許可を受けます。
(私は2,3日くらいしたら、許可されたことを通知するメールが来ました)
その後、API Keyを取得するためのWebページでAPI Keyを入手します。

具体的な手順については、下記で画像付きで解説してくれているので、すぐに分かるかと思います。
https://xrdocs.github.io/getting-started/steps-download-iosxr-vagrant

# :three:IOS-XRvのVagrantで起動して確認してみる
Keyを入手したら、もう夢のIOS-XRのvagrant利用は目の前です:relaxed:
さっき入手したAPI KeyとCCO IDを利用してCurlでダンロードします。
YOUR-CCO-ID:YOUR-API-KEYのとこは取得した自分のIDとkeyを入れて下さい。

*ちなみに、IOS-XRvを起動すると約4Gくらいのメモリを消費します。開発要サーバーとしてのubuntuも立ち上げると更に1Gちょっと消費するので、それに耐えうるPCでなければ少し厳しいかもしれません*

```
% mkdir ~/ios-xr-vagrant
% cd ios-xr-vagrant
% BOXURL="https://devhub.cisco.com/artifactory/appdevci-release/XRv64/latest/iosxrv-fullk9-x64.box"
% curl -u YOUR-CCO-ID:YOUR-API-KEY $BOXURL --output ~/iosxrv-fullk9-x64.box
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1690M  100 1690M    0     0  2748k      0  0:10:29  0:10:29 --:--:-- 4876k
```
ダウンロード後はVagrantの流れに則り、box add , vagrant initします。

```
% vagrant box add IOS-XRv ./iosxrv-fullk9-x64.box
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'IOS-XRv' (v0) for provider:
    box: Unpacking necessary files from: file:///****/iosxrv-fullk9-x64.box
==> box: Successfully added box 'IOS-XRv' (v0) for 'virtualbox'!

% vagrant init IOS-XRv
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

[mabuchi@Mabuchi-no-MacBook-Pro] ~/ios-xr-vagrant
% vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
...
    default: 57722 (guest) => 2222 (host) (adapter 1)
    default: 22 (guest) => 2223 (host) (adapter 1)
...
==> default:     Welcome to the IOS XRv (64-bit) VirtualBox.
==> default:     To connect to the XR Linux shell, use: 'vagrant ssh'.
==> default:     To ssh to the XR Console, use: 'vagrant port' (vagrant version > 1.8)
==> default:     to determine the port that maps to guestport 22,
==> default:     then: 'ssh vagrant@localhost -p <forwarded port>'
==> default:
==> default:     IMPORTANT:  READ CAREFULLY
==> default:     The Software is subject to and governed by the terms and conditions
==> default:     of the End User License Agreement and the Supplemental End User
==> default:     License Agreement accompanying the product, made available at the
==> default:     time of your order, or posted on the Cisco website at
==> default:     www.cisco.com/go/terms (collectively, the 'Agreement').
==> default:     As set forth more fully in the Agreement, use of the Software is
==> default:     strictly limited to internal use in a non-production environment
==> default:     solely for demonstration and evaluation purposes. Downloading,
==> default:     installing, or using the Software constitutes acceptance of the
==> default:     Agreement, and you are binding yourself and the business entity
==> default:     that you represent to the Agreement. If you do not agree to all
==> default:     of the terms of the Agreement, then Cisco is unwilling to license
==> default:     the Software to you and (a) you may not download, install or use the
==> default:     Software, and (b) you may return the Software as more fully set forth
==> default:     in the Agreement.
```
ログインして確認します。

```
[mabuchi@Mabuchi-no-MacBook-Pro] ~/ios-xr-vagrant
% vagrant ssh
host:~$
host:~$ exit
logout
Connection to 127.0.0.1 closed.
```
接続してもLINUXなシェルです。
記事によれば、`vagrant ssh`では、IOS-XRのLINUX SHELLに接続されるようにデフォルトで設定されているようです。(2222ポートをIOS-XRの57722にフォワードする設定にデフォルトでなっていて、57722ポートでのSSHがSHELLとなるような仕様の模様です。)
理由としては、AnsibleやChef等でVagrantのプロビジョニングをする時にはCLIな感じではなくサーバーとおなじシェルのほうがいいから、だそうです。

お馴染みのcliにログインするには、2223ポートへログインします。
初期のパスワードは`vagrant`です。

```
% ssh -p 2223 vagrant@localhost
The authenticity of host '[localhost]:2223 ([127.0.0.1]:2223)' can't be established.
RSA key fingerprint is SHA256:WNLFNqU/Q1oZA0TmoBGfYUzTc4uSa7aSjrl/SnOToSc.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[localhost]:2223' (RSA) to the list of known hosts.
Password:
RP/0/RP0/CPU0:ios#
RP/0/RP0/CPU0:ios#
RP/0/RP0/CPU0:ios#show ver
Thu Dec  8 04:32:15.374 UTC

Cisco IOS XR Software, Version 6.2.1.23I
Copyright (c) 2013-2016 by Cisco Systems, Inc.

Build Information:
 Built By     : jwu
 Built On     : Mon Nov 21 00:33:58 PST 2016
 Build Host   : iox-ucs-005
 Workspace    : /auto/iox-ucs-005-san1/nightly/xr-dev_16.11.20C/iosxrv-x64
 Version      : 6.2.1.23I
 Location     : /opt/cisco/XR/packages/

cisco IOS XRv x64 () processor
System uptime is 2 minutes
```

# :four: Interfaceを設定して開発サーバーと疎通を取れるようにする
今回配布されているIOS-XRvでは、vagrant上でのFireflyと違い、`Vagrantfile`に直接IPを書いても反映されません。エラーが出ます。

下記に初期プロビジョニングに必要なshellスクリプトやサンプルが置かれています
https://github.com/ios-xr/vagrant-xrdocs
数ケースかに分けておいてくれてありますが、今回は `vagrant-xrdocs/lxc-app-topo-bootstrap/scripts`を使ってます。

`node.vm.network :private_network, virtualbox__intnet: "link1", auto_config: false`
でとりあえずInterfaceは作成できるので、IPアドレス等はProvisioning用のSHELLスクリプトと投入Configを指定して設定します。
Vagrantfileは下記です。gitのものとほぼ違いはありません。
IOS-XRを起動するついでに、開発用のサーバーも立ち上げてます。
通信できるように、`link1`に同じセグメントのIPを振って繋げてます。

```ruby:Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  
   config.vm.define "iosxr" do |node|
      node.vm.box =  "IOS-XRv"

      node.vm.network :private_network, virtualbox__intnet: "link1", auto_config: false
      node.vm.provision "file", source: "configs/xrconf.txt", destination: "/home/vagrant/xrconf.txt"

      node.vm.provision "shell" do |s|
          s.path =  "./scripts/apply_config.sh"
          s.args = ["/home/vagrant/xrconfig"]
      end
    end

   config.vm.define "dev_ubuntu" do |node|
     node.vm.box =  "ubuntu/trusty64"
     node.vm.network :private_network, virtualbox__intnet: "link1", ip: "192.168.44.2"
   end

end
```
流れとしてはこんな感じです。

- `node.vm.network`でInterfaceを作る
- `node.vm.provision`でios-xrvのconfigファイルを`/home/vagrant/`ディレクトリに設置
- `apply_config.sh`がIOS-XRv内部の`/pkg/bin/ztp_helper.sh`を呼び出してconfigを反映

apply_configは弄らずにgithubのものを利用すればOKです。
中身を見ればわかりますが、内容の大半は適用失敗時のエラーを出すためのスクリプトです。

```apply_config.sh
#!/bin/bash

source /pkg/bin/ztp_helper.sh

function configure_xr() 
{
   ## Apply a blind config 
   xrapply $1
   if [ $? -ne 0 ]; then
       echo "xrapply failed to run"
   fi
   xrcmd "show config failed" > /home/vagrant/config_failed_check
}

config_file=$1
configure_xr $config_file

cat /home/vagrant/config_failed_check
grep -q "ERROR" /home/vagrant/config_failed_check
 
if [ $? -ne 0 ]; then
    echo "Configuration was successful!"
    echo "Last applied configuration was:"
    xrcmd "show configuration commit changes last 1"
else
    echo "Configuration Failed. Check /home/vagrant/config_failed on the router for logs"
    xrcmd "show configuration failed" > /home/vagrant/config_failed
    exit 1
fi
```

IOS-XRのconfigは、外向けInterfaceとsnmpだけ設定してます。

```configs/xrconf.txt
hostname iosxrv1
!
interface GigabitEthernet0/0/0/0
ip address 192.168.44.1/24
no shutdown
!
snmp-server ifindex persist
snmp-server community ios-xr RO SystemOwner
end
```
Vagrantのディレクトリに`scripts/apply_config.sh`と`configs/xr-config`を設置したら、再度`vagrant up`してみます。
立ち上がった後、ubuntu側から疎通が取れるか試してみます。

```:ping-result
vagrant@vagrant-ubuntu-trusty-64:~$ ping 192.168.44.1
PING 192.168.44.1 (192.168.44.1) 56(84) bytes of data.
64 bytes from 192.168.44.1: icmp_seq=1 ttl=255 time=25.8 ms
64 bytes from 192.168.44.1: icmp_seq=2 ttl=255 time=8.60 ms
64 bytes from 192.168.44.1: icmp_seq=3 ttl=255 time=2.62 ms
64 bytes from 192.168.44.1: icmp_seq=4 ttl=255 time=1.91 ms
```

SNMPも試しておきます。

```
vagrant@vagrant-ubuntu-trusty-64:~$ snmpwalk -v2c -c ios-xr 192.168.44.1 .1.3.6.1.2.1.2.2.1.2
iso.3.6.1.2.1.2.2.1.2.2 = STRING: "Null0"
iso.3.6.1.2.1.2.2.1.2.3 = STRING: "MgmtEth0/RP0/CPU0/0"
iso.3.6.1.2.1.2.2.1.2.4 = STRING: "GigabitEthernet0/0/0/0"
```

開発用のサーバーからsshする場合は、vagrantを経由するわけではないため
ポートフォワードの事は感がなくてOKです。
CLIには`22`でs、シェルには`57722`です:v:

```:CLIログイン
vagrant@vagrant-ubuntu-trusty-64:~$ ssh vagrant@192.168.44.1
Password:
RP/0/RP0/CPU0:iosxrv1#
RP/0/RP0/CPU0:iosxrv1#
```


```:SHELL
vagrant@vagrant-ubuntu-trusty-64:~$ ssh -p 57722 vagrant@192.168.44.1
vagrant@192.168.44.1's password:
iosxrv1:~$
iosxrv1:~$
```

# :five: 最後に
今まで、ネットワークの自動化は、開発するための環境を手元に構築するのが大変という非常に大きなデメリットがありました。
しかし、今回のIOS-XRのvagrantや、Fireflyのvagrant等を利用することによって、**自分のPC1台でマルチベンダーの環境すらも再現が可能**となり、その上vagrantを使っての環境構築が非常にお手軽な時代になりました。
次はこの環境でtelemetryやgrpcの通信について試してみたいと思います。

# :six: 参考リンク
XR toolbox, Part 1 : IOS-XR Vagrant Quick Start
https://xrdocs.github.io/application-hosting/tutorials/iosxr-vagrant-quickstart
(かなり丁寧に解説されてます)