CSR1000vのREST API

先日とある勉強会でCisco社の仮想ルータCSR1000vでREST APIが使えるよ話をしたのですが、実際どうやるの？というのをちらほら聞かれたのでまとめてみました。

#前準備
##ルータ設定
ドキュメントが公開されています
configuration
http://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/configuration/csr1000Vswcfg/RESTAPI.html


実際試してうまくいかなかったかたがいますが、
http://kashigeru.hatenablog.com/entry/2014/07/03/215132

```
router(config)# remote-management
router(cfg-remote-mgmt)# default restful-api
```
を追加して、urlをhttps://～:55433/とポートを指定します。

ポート番号を変更したいときは
```
router(cfg-remote-mgmt)# restful-api local-port portNumber
```
と指定してください。

`$ openssl s_client -connect ipaddress:port`
で繋がれば前準備は完了してます。


コマンド中のipaddress, port, user, passwordは各自が設定したものを指定して下さい。
***


#REST APIでのアクセス
##１．ファイル作成
curlコマンドでアクセスします。引数にずらずら書いてもいいんですが、入力・修正が大変なので一旦ファイルに書いておきます。

Sub IFの設定を想定して以下のファイルを作成します。

```ifset.json
{
  "subinterface-vlan":{
    "vlan-id":23,
    "encap-type":"DOT1Q"
  },
  "if-name":"GigabitEthernet3.23",
  "subnet-mask":"255.255.255.0",
  "ip-address":"172.16.23.1",
  "type":"ethernet"
}
```

※Management IFにぶつからないよう適宜読み替えて下さい




取得・設定のメソッドとリソースは公開されています。
http://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/restapi/restapi.html



***
##２．セッション開始
```
$ curl -k -X POST https://ipaddress:port/api/v1/auth/token-services -H "Accept:application/json" -u "user:password" |  python -mjson.tool
{
    "expiry-time": "Mon Jul  6 09:45:43 2015",
    "kind": "object#auth-token",
    "link": "https://ipaddress:port/api/v1/auth/token-services/6434994524",
    "token-id": "B2iL/rpn+aMJwcpFbv+vCut3bBVLWBJqAYQEC3UlWsc="
}
```
※パイプ先のpythonはjsonの整形のためだけなので特に必要ありません

設定・取得にはこのtoken-idが必要になりますのでヘッダに含めます。

***
##３．Interfaceリストの取得
```
$ curl -k -X GET https://ipaddress:port/api/v1/interfaces -H "Accept:application/json" -H 'X-auth-token:B2iL/rpn+aMJwcpFbv+vCut3bBVLWBJqAYQEC3UlWsc=' -u "user:password" | python -mjson.tool

{
    "items": [
        {
            "description": "",
            "icmp-redirects": true,
            "icmp-unreachable": true,
            "if-name": "GigabitEthernet2.98",
            "ip-address": "22.10.10.23",
            "ipv6-enable": false,
            "kind": "object#interface",
            "mac-address": "0050.5683.1b10",
            "nat-direction": "",
            "proxy-arp": true,
            "subinterface-vlan": {
                "encap-type": "DOT1Q",
                "vlan-id": 98
            },
            "subnet-mask": "255.255.255.0",
            "type": "ethernet",
            "verify-unicast-source": false
        },
        {
            "description": "",
・・・・・
```


***
##４．カウンタ情報
```
$ curl -k -X GET https://ipaddress:port/api/v1/interfaces/GigabitEthernet3/statistics -H "Accept:application/json" -H "X-auth-token:B2iL/rpn+aMJwcpFbv+vCut3bBVLWBJqAYQEC3UlWsc=" -u "user:password" | python -mjson.tool
{
    "if-name": "GigabitEthernet3",
    "in-errors": 0,
    "in-packet-drops": 0,
    "in-packet-rate-bps": 250,
    "in-packet-rate-pps": 3,
    "in-total-packets": 10750,
    "kind": "object#interface-statistics",
    "out-errors": 0,
    "out-packet-drops": 0,
    "out-packet-rate-bps": 0,
    "out-packet-rate-pps": 0,
    "out-total-packets": 5
}
```
微妙にSNMPで得られるカウンタと違います:-|

***
##５．IF設定
```
$ curl -k -X POST https://ipaddress:port/api/v1/interfaces -H "Accept:application/json" -H "X-auth-token:B2iL/rpn+aMJwcpFbv+vCut3bBVLWBJqAYQEC3UlWsc=" -u "user:password" -H "Content-Type: application/json" -d @ifset.json

```
POSTの中身がJSONなのでHTTPヘッダに
`Content-Type: application/json`
を追加します。

***
##６．確認
```
$ curl -k -X GET https://ipaddress:port/api/v1/interfaces/GigabitEthernet3.23 -H "Accept:application/json" -H "X-auth-token:B2iL/rpn+aMJwcpFbv+vCut3bBVLWBJqAYQEC3UlWsc=" -u "user:password" | python -mjson.tool

{
    "description": "",
    "icmp-redirects": true,
    "icmp-unreachable": true,
    "if-name": "GigabitEthernet3.23",
    "ip-address": "172.16.23.1",
    "ipv6-enable": false,
    "kind": "object#interface",
    "mac-address": "0050.5683.368e",
    "nat-direction": "",
    "proxy-arp": true,
    "subinterface-vlan": {
        "encap-type": "DOT1Q",
        "vlan-id": 23
    },
    "subnet-mask": "255.255.255.0",
    "type": "ethernet",
    "verify-unicast-source": false
}
```

***
##７．Config確認
```
$ ssh csr1000v show config

・・・・
interface GigabitEthernet3
 no ip address
 negotiation auto
!
interface GigabitEthernet3.23
 encapsulation dot1Q 23
 ip address 172.16.23.1 255.255.255.0
!
!
・・・・
```

***
##８．Sub IF削除
```
$ curl -k -X DELETE https://ipaddress:port/api/v1/interfaces/GigabitEthernet3.23  -H 'Accept:application/json' -H 'X-auth-token:B2iL/rpn+aMJwcpFbv+vCut3bBVLWBJqAYQEC3UlWsc=' -u "user:password"
```

***
##９．確認
```
$ curl -k -X GET https://ipaddress:port/api/v1/interfaces/GigabitEthernet3.23 -H "Accept:application/json" -H "X-auth-token:B2iL/rpn+aMJwcpFbv+vCut3bBVLWBJqAYQEC3UlWsc=" -u "user:password" | python -mjson.tool
{
    "detail": " ",
    "error-code": -1,
    "error-message": "Invalid interface GigabitEthernet3.23"
}
```

***
##１０．Config確認
```
$ ssh csr1000v show config
・・・・・
interface GigabitEthernet3
 no ip address
 negotiation auto
!
!
virtual-service csr_mgmt
```

***

##１１．セッション終了
２．でのlinkにDELETEメソッドでアクセスします

```
$ curl -k -X DELETE https://ipaddress:port/api/v1/auth/token-services/6434994524 -H "Accept:application/json" -H "X-auth-token:B2iL/rpn+aMJwcpFbv+vCut3bBVLWBJqAYQEC3UlWsc=" -u "user:password"
```

***

イマドキのプロダクトらしく真っ当にREST APIを実装してます。
ルータだけでなくL2/L3スイッチでも対応機種が増えるといいですね～