- RSS フィードを購読する
- 新着としてマーク
- 既読としてマーク
- ブックマーク
- 購読
- 印刷用ページ
- 不適切なコンテンツを報告
2017-04-29
03:01 PM
- 最終編集日:
2017-09-20
11:02 AM
、編集者:
Hiromasa Kakehashi
- JSON-RPCとは
- NSOにおけるJSON-RPC
- WebUI
- JSON-RPCの使用例
- session 作成 (login)
- トランザクションの開始 (new_trans)
- config の取得 (show_config)
- リストキーの取得 (get_list_keys)
- /aaa/authentication/users/user{test} の作成 (create)
- /aaa/authentication/users/user{test}/uid 等 leaf への値設定 (set_value / set_values)
- 変更の実施 (validate_commit / commit)
- 値の取得 (get_value / get_values)
- /aaa/authentication/users/user{test} の削除 (delete)
- action の実行 (run_action)
- スキーマ(モデル) の取得 (get_schema)
JSON-RPCとは
JSON-RPC は、NSO がサポートする Northbound APIs の一つで、クライアントはHTTP(S) を使用して、NSOを操作することが出来ます。REST API と違い、一つのセッション(或いは、トランザクション) 内で複数のコマンドを実行することが可能です。
Remote Procedure Call (RPC) としては、歴史的に多くの方法が使用されてきました。XML-RPCが1990年代後半に使用され始め、その拡張としてSOAPが存在します。JSON-RPC は 2000年半ばに使われ始め、これら他のRPCと考え方は同じです。
JSON-RPC は、現在その仕様は バージョン 2.0 が最新となっています。詳細については、以下をご確認ください。
NSOにおけるJSON-RPC
JSON-RPC では、その Transport 層の仕様については定められていません。NSOで使用する JSON-RPC では、多くの実装でも使用されているように、HTTP(S) 上でPayloadの送受信が行います。
Payloadの中身は、一般的な JSON-RPC と同様、以下の様になります。
リクエスト:
{
"jsonrpc": "2.0",
"method": "XXXXX",
"params": {
"param1": XXXXX,
"param2": XXXXX
},
"id": XXXXX
}
レスポンス(正常時):
{
"jsonrpc": "2.0",
"result": XXXXX,
"id": XXXXX
}
レスポンス(エラー):
{
"jsonrpc": "2.0",
"error": {
"code": XXXXX,
"message": XXXXX,
"data": XXXXX,
"type": XXXXX
},
"id": XXXXX
}
type フィールドは、NSOが独自に決めたアプリケーションエラー(code = -32000) 発生時付加され、エラーの内容が含まれます。
WebUI
NSO はGUIからの操作を可能にするため、WebUIが実装されています。JSON-RPCを使用しているため、動作例として確認する場合には、ブラウザの開発機能を使用し動作を観察することも可能です。
JSON-RPCの使用例
あらゆるJSON-RPCリクエストに対しては、ユーザ認証されている必要があります。ただし、login method のみ認証されていない場合でもリクエストする事が可能で、それを実行することで、HTTP Cookie を受信し、以後のリクエストに使用します。
その後、NSOへのログインユーザの追加、削除を行います。また、action の実行方法についても説明しています。
session 作成 (login)
login method をNSOに対して実行し、ログインします。その際、HTTP Header にSet-Cookie が含まれますので、それに含まれる sessionid_[ポート番号] を以後のリクエストではCookieに含めて使用します。curl を使用する場合は、-i オプションを使用することで、それを確認できます。
$ curl -i -c cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"login",
"params":{
"user":"admin",
"passwd":"admin"
}
}'
HTTP/1.1 200 OK
Server:
Date: Sat, 29 Apr 2017 03:56:28 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Content-Length: 36
Content-Type: application/json
Set-Cookie: sessionid_8080=sessjZtwG0ekhzDUZXwvrkW2rw==; path=/; HttpOnly
Vary: Accept-Encoding
{"jsonrpc":"2.0","result":{},"id":1}
なお、curl コマンドでは、取得した cookie を -c オプションで保存し、-b オプションで使用することが可能です。これにより、自動でセッション情報を継続して使用することが出来ます。
トランザクションの開始 (new_trans)
CDBへの操作など、データの取得・変更などを行う場合は、トランザクションの中で行います。ログイン直後は、有効なトランザクションが無いため、新たに開始します。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"new_trans",
"params":{
"db": "running",
"mode": "read"
}
}'
{"jsonrpc":"2.0","result":{"th":1},"id":1}
$
mode には read または、read_write を指定出来ます。ここでは、read を指定して、読み取り専用のトランザクションが開始されました。トランザクションハンドル(th) =1 がアサインされていることがわかります。念のため、get_trans メソッドで確認してみます。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"get_trans",
"params":{}
}'
{"jsonrpc":"2.0","result":{"trans":[{"th":1,"db":"running","mode":"read"}]},"id":1}
$
th=1 として、トランザクションが一つある事が確認出来ました。
config の取得 (show_config)
CLI 上での "show running" コマンドに相当するRPCです。show_config メソッドを使用します。以下では、"/aaa" を取得しています。これは、CLI上での "show running-config aaa" 相当です。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"show_config",
"params":{
"th":1,
"path":"/aaa"
}
}'
{"jsonrpc":"2.0","result":{"config":"aaa {\n authentication {\n users {\n user admin {\n uid 65534;\n gid 65534;\n password $6$EOlKr.zRujz34uPj$hHyfbMtbvcQWPwvwsmJ8VRaLn1mu/fdZAYKDRkHaL7UEm.WOxPafGr807a2hulfeJwrDSdr4YqLo/Kvg8KOrG0;\n ssh_keydir /var/ncs/homes/admin/.ssh;\n homedir /var/ncs/homes/admin;\n }\n user oper {\n uid 65534;\n gid 65534;\n password $6$7kfOoClUgxfsrRyl$DBpyWaMkBzPQ2njtxfj9ysaSA7WeabDWaW9EfaaokpNGsSiGuu.Ek6VH12EzEiJghl7aCEFy9Sj24eAPxOcBP/;\n ssh_keydir /var/ncs/homes/oper/.ssh;\n homedir /var/ncs/homes/oper;\n }\n user private {\n uid 65534;\n gid 65534;\n password $6$;\n ssh_keydir /var/ncs/homes/private/.ssh;\n homedir /var/ncs/homes/private;\n }\n user public {\n uid 65534;\n gid 65534;\n password $6$;\n ssh_keydir /var/ncs/homes/public/.ssh;\n homedir /var/ncs/homes/public;\n }\n }\n }\n}\n"},"id":1}
$
"show running-config aaa" の結果がテキストで返って来ています。実際にこの形式でアプリケーションから使用する為には、これをparse する必要があり、プログラマビリティとしては、良いものではありません。具体的に、/aaa/authentication/users/user リストを取得してみます。
リストキーの取得 (get_list_keys)
/aaa/authentication/users/user はリストです。get_list_keys メソッドを使用して、このリストのキーを取得してみます。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"get_list_keys",
"params":{
"th":1,
"path":"/aaa/authentication/users/user"
}
}'
{"jsonrpc":"2.0","result":{"keys":[["admin"],["oper"],["private"],["public"]],"total_count":4,"lh":-1},"id":1}
$
admin / oper / private / public の4ユーザが、このNSOには登録されている事がわかりました。
/aaa/authentication/users/user{test} の作成 (create)
JSON-RPC を使用して、ユーザ "test" を追加してみます。
これまでに使用してきたトランザクションは、読み取り専用でした。これでは、書き込みが出来ませんので、新たに、読み書き可能なトランザクションを作成します。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"new_trans",
"params":{
"db": "running",
"mode": "read_write"
}
}'
{"jsonrpc":"2.0","result":{"th":2},"id":1}
$
th=2 のトランザクションが作成されました。これを使用して、ユーザの追加をしましょう。
user リストへ test ユーザを作成します。リストへ新しいエントリーを作成する場合は、create メソッドを使用します。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"create",
"params":{
"th": 2,
"path": "/aaa/authentication/users/user{test}"
}
}'
{"jsonrpc":"2.0","result":{},"id":1}
$
これは、CLI 上で以下を行ったことと同等です。
admin@ncs# conf
admin@ncs(config)# aaa authentication users user test
user リストでは、uid / gid / password / ssh_keydir / homedir を同時に定義する必要がありますので、これらも設定します。
/aaa/authentication/users/user{test}/uid 等 leaf への値設定 (set_value / set_values)
以下の leaf に対して、設定を実施します。複数の leaf への設定を、それぞれの HTTP リクエストで行うことも可能ですが、ここでは Batch 機能を使用し、まとめて設定します。
また、uid/gid leaf は integer ですが、文字列を指定していることに注意して下さい。set_value が value として設定可能な値は、string または 配列です。(null を設定すると、当該 leaf を削除します)
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
[{
"jsonrpc":"2.0",
"id":1,
"method":"set_value",
"params":{
"th": 2,
"path": "/aaa/authentication/users/user{test}/uid",
"value": "0"
}
},
{
"jsonrpc":"2.0",
"id":1,
"method":"set_value",
"params":{
"th": 2,
"path": "/aaa/authentication/users/user{test}/gid",
"value": "0"
}
},
{
"jsonrpc":"2.0",
"id":1,
"method":"set_value",
"params":{
"th": 2,
"path": "/aaa/authentication/users/user{test}/password",
"value": "cisco"
}
},
{
"jsonrpc":"2.0",
"id":1,
"method":"set_value",
"params":{
"th": 2,
"path": "/aaa/authentication/users/user{test}/ssh_keydir",
"value": "/home/test/.ssh"
}
},
{
"jsonrpc":"2.0",
"id":1,
"method":"set_value",
"params":{
"th": 2,
"path": "/aaa/authentication/users/user{test}/homedir",
"value": "/home/test"
}
}]'
[{"jsonrpc":"2.0","result":{},"id":1},{"jsonrpc":"2.0","result":{},"id":1},{"jsonrpc":"2.0","result":{},"id":1},{"jsonrpc":"2.0","result":{},"id":1},{"jsonrpc":"2.0","result":{},"id":1}]
変更の実施 (validate_commit / commit)
これまでに、変更に必要なデータは全てトランザクション内に入りました。後は、CLIと同様、commit が必要です。
その際に、CLI では自動で行われますが、commit 前に、validate_commit を行う必要があります。これは、入力値のチェックを行い、不正があればエラーを表示します。validate されていないトランザクションは、commit する事が出来ません。
validate_commit
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"validate_commit",
"params":{
"th": 2
}
}'
{"jsonrpc":"2.0","result":{},"id":1}
$
以下は validate_commit に失敗した例です。user リストのエントリ作成では、homedir の設定が必須ですが、それをしていない場合には、以下の様なエラーが戻ります。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"validate_commit",
"params":{
"th": 2
}
}'
{"jsonrpc":"2.0","error":{"type":"trans.validation_failed","code":-32000,"message":"Validation failed","data":{"errors":[{"reason":"is not configured","paths":["/aaa:aaa/authentication/users/user{test}/homedir"],"path":"/aaa:aaa/authentication/users/user{test}/homedir"}]}},"id":1}
$
commit
flags パラメータはオプションです。必要に応じて、dry-run=native, no-networking などを指定します。
例: flags = ["dry-run=native", "no-networking"]
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"commit",
"params":{
"th": 2,
"flags" : []
}
}'
{"jsonrpc":"2.0","result":{},"id":1}
値の取得 (get_value / get_values)
commit が完了しましたので、値を取得し、正しく commit が完了した事を確認します。また、get_list_keys を使用して、test が user リストに追加された事も確認します。
get_value は特定の leaf の値を取得します。複数のleaf の値をまとめて取得する get_values もありますので、以下例を示します。
test ユーザが追加された事を確認 (get_list_keys)
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"get_list_keys",
"params":{
"th":1,
"path":"/aaa/authentication/users/user"
}
}'
{"jsonrpc":"2.0","result":{"keys":[["admin"],["oper"],["private"],["public"],["test"]],"total_count":5,"lh":-1},"id":1}
user {test} / ssh_keydir を確認 (get_value)
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"get_value",
"params":{
"th": 1,
"path": "/aaa/authentication/users/user{test}/ssh_keydir"
}
}'
{"jsonrpc":"2.0","result":{"value":"/home/test/.ssh"},"id":1}
user {test} に設定された値をまとめて確認 (get_values)
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"get_values",
"params":{
"th": 1,
"path": "/aaa/authentication/users/user{test}",
"leafs": ["uid", "gid", "password", "ssh_keydir", "homedir"]
}
}'
{"jsonrpc":"2.0","result":{"values":[{"value":"0","access":{"read":true,"write":true}},{"value":"0","access":{"read":true,"write":true}},{"value":"$6$hXtiNxdt6ngFWZCO$MdOQfIe4cHEnzsZnVMkMIOH4eJ7ZGZEmNSUCYPO68SEHs2L/V9tZ1KbCIFFUfV52kl88JKbWmFCn2vrZNVuxA.","access":{"read":true,"write":true}},{"value":"/home/test/.ssh","access":{"read":true,"write":true}},{"value":"/home/test","access":{"read":true,"write":true}}]},"id":1}
/aaa/authentication/users/user{test} の削除 (delete)
作成した test ユーザを削除します。リストからエントリを削除するには、delete メソッドを使用します。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"delete",
"params":{
"th": 2,
"path": "/aaa/authentication/users/user{test}"
}
}'
{"jsonrpc":"2.0","result":{},"id":1}
action の実行 (run_action)
アクションは、yang 上で定義された rpc です。当該ノードを「実行」することで、何らかの動作がNSO上で発生します。JSON-RPC では、run_action メソッドを実行する事で、NSO上でアクションを実行出来ます。
以下では、/devices/sync-from アクションを実施しています。このNSOでは、c0/c1 という二つのデバイスが登録されています。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"run_action",
"params":{
"th": 1,
"path": "/devices/sync-from"
}
}'
{"jsonrpc":"2.0","result":[{"name":"sync-result/device","value":"c0"},{"name":"sync-result/result","value":"true"},{"name":"sync-result/device","value":"c1"},{"name":"sync-result/result","value":"true"}],"id":1}
スキーマ(モデル) の取得 (get_schema)
上記例では、/aaa 以下のモデルを既に知っていることから、user はリストであり、それ以下には pid, gid 等の leaf が存在している事がわかり、get_value 等を実行出来ました。しかしながら、知らない場合には、get_value 等でpath を指定することが出来ません。
一般のアプリケーションであれば、通常モデルを確認した上で作成するため、これは問題にはなりません。もし、ツリーを walk する様なアプリケーションを作成したい場合は、事前にモデルを知り得ませんので、get_value のようなことは出来ません。
JSON-RPCでは、get_schema メソッドによりモデルを取得出来ますので、そういったダイナミックなアプリケーションを作成することも可能です。
$ curl -b cookie -X POST http://localhost:8080/jsonrpc -H 'Content-Type: application/json' -d '
{
"jsonrpc":"2.0",
"id":1,
"method":"get_schema",
"params":{
"th": 1,
"path": "/aaa/authentication/users/user"
}
}'
{"jsonrpc":"2.0","result":{"meta":{"namespace":"http://tail-f.com/ns/aaa/1.1","keypath":"/aaa:aaa/authentication/users/user","prefix":"aaa","types":{"http://tail-f.com/ns/aaa/1.1:passwdStr":[{"name":"http://tail-f.com/ns/aaa/1.1:passwdStr"},
<< 出力が非常に長いため、省略しています >>