popoto.jsでネットワーク「図」を検索してみよう

## 前置き

せっかく [会社アドカレ](https://qiita.com/advent-calendar/2018/tis) なのでお仕事関連のネタでやろう、Neo4j で最近見てた話でやるかなーと思ってたら 5 日目で ike_dai さんが [システム運用の世界をグラフで表現すると良いことあるかも？Neo4jのメリット感を体験\-パッケージ依存関係管理\- \- Qiita](https://qiita.com/ike_dai/items/5c8d5ae1b41f92861c87) という記事できたじゃないですか。似てる領域をやってるのでまあそういうこともあるよね。

さて。

最近「ネットワーク図」を中心にした運用業務の改善……みたいな話ができないかな、ということを考えています。ネットワーク機器を設定する・操作する、というのはもういろいろできるようになったので、その次のステップですね。ネットワーク(全体)に対する操作それ自体をどう考えるか・どう組み立てるか? ということを考えると、「図」をもとに判断するしていることがいろいろあるはず。でも、ネットワーク図の書き方って人や案件によってまちまちだし、そもそも Visio だったり PowerPoint だったり、アレだと Excel だったり……。図を読み書きする、図を元にやることを考える、みたいなところは、結局は人がやっているのがネックだよね、というのが問題意識です。

そんな感じの話を [Open NetworkIng Conference Japan 2018](http://onic.jp/) でしゃべってきたりしたので詳しくはそちらをみてください。

*  [「ネットワーク図」のモデル化とモデルを起点にした自動化の可能性 / onic2018 \- Speaker Deck](https://speakerdeck.com/corestate55/onic2018)

上の資料にあるように、 [RFC 8345](https://tools.ietf.org/html/rfc8345) を元にいろいろやろうとしています。方向性として「見せ方」と「データモデルやデータの扱い方」とがあるかなと思ってるんですが、ここでは後者の話をします。

## ネットワークトポロジのデータを Neo4j であつかう

[先に挙げた資料](https://speakerdeck.com/corestate55/onic2018) で説明しているのですが、とりあえずお試しで書いてみたネットワーク図と、それを元に起こした json data があるとします。

* [JSON file](https://gist.github.com/corestate55/c98d6e5d902dee0b0f9341f82b3e26cf#file-target3a-json)
  *  [元になるトポロジデータ定義](https://github.com/corestate55/netomox/blob/proto/popoto/vendor/model_defs/target3a.rb)
* https://netoviz.herokuapp.com/ で "L2 Aggr & L35 Model" を選ぶと上の json をレイヤ別に描画します。

これに以下のような relation を設定して Neo4J に登録します。(この辺は省略… [netomox](https://github.com/corestate55/netomox) を使っています)

* "network" は複数の "node" [^node_def] (と "link") で構成されている。
いま、"network" はひとつのネットワークレイヤとして扱っています。
* "node" は複数の "termination point" (ポートと思ってよい)を持つ
* "termination point" は他の "termination point" とつながっている ( "link" に相当…今回は "term point" 間の relation として表現[^relation_note])
* それぞれ "support" で他の "network" (layer) にあるノードをポイントできる。

[^node_def]: 「ノード」が neo4j 用語とネットワークトポロジ用語とで被ってわかりにくいですね…。"node" のようにクォートしているものはネットワークトポロジデータの用語だと思ってください。

[^relation_note]: "node" - "termination-point" の間の関係と "termination-point" 同士の関係のどちらも connected にしてありますが、これはどことどこがつながっているかをたどるときに同じ relation name でたどれた方が楽かな、という発想でこうしてあります。トポロジデータ(元の JSON)では "termination point" は "node" に包含される形だし、 "termination point" 間の接続は "link" として定義されています。

![relation defs](https://qiita-image-store.s3.amazonaws.com/0/154230/07b41acc-a2dc-c954-1169-d974b7de95d6.png)

とりあえず登録したノードを全部出してみるとこんな感じ。

![all nodes](https://qiita-image-store.s3.amazonaws.com/0/154230/a0069d26-51c5-f54e-28df-fe3c7f59b7a2.png)

はい。何が何だかわかりませんね。ここから Cypher query 書いて必要な情報を抽出していくわけです。……が、この辺はそれなりにトレーニングが必要なので私のような初心者にはちょっととっつきにくい。

## popoto.js でインクリメンタルなデータ検索

もうちょっと手軽に(Cypherとかあまりくわしくなくても)・インクリメンタルにデータ見ていくってのができないかな…というところで登場するのが  [Popoto\.js](http://www.popotojs.com/) です。 Neo4j WebUI の Cypher コマンドラインみたいな万能性はないのですが、クリックしながら順に関係性を定義してデータを検索していくことができます。

*  [Home · Nhogs/popoto Wiki](https://github.com/Nhogs/popoto/wiki)  : 画面構成の説明
*  [Basic action · Nhogs/popoto Wiki](https://github.com/Nhogs/popoto/wiki/Basic-action) : データ検索操作の説明

セットアップの方法とかはいったんおいといて、このツールでどんなことができるのか、例を見てみましょう。

### Layer1 で SW1/SW2 の両方につながっている機器を探す

ちょっと冗長ですが順に見ていきましょう。

"node" を探すので、左側の Taxonomy から "node" をクリックします。

![first step](https://qiita-image-store.s3.amazonaws.com/0/154230/97775480-4ec6-787e-4ceb-ed0ad88d1744.png)

[35] は検索結果の数です。このときページ下部、Query/Result で検索結果が出ています。

![result view](https://qiita-image-store.s3.amazonaws.com/0/154230/836ccbbf-5581-104b-da06-e80f5dcbc2fb.png)

以降、クリックして条件をしぼりこむごとに Query/Result が変化していきます。

この 35 件はすべての "network" に含まれる "node" の総数なので、いったん Layer1 にしぼりこみましょう。

![filter by network](https://qiita-image-store.s3.amazonaws.com/0/154230/6f83181d-43ca-11c4-0013-5d524f0aa4b0.png)

constructed_with relation をたどって Layer1 (target-L1) を選択します。

![select network](https://qiita-image-store.s3.amazonaws.com/0/154230/9d7fd3d1-5c3e-f0dd-6b90-d9ce3ef72f7b.png)

選択すると、"node" 検索結果が 7 件になりました。これは Layer1 (target-L1) に含まれる "node" の総数です。

ここから接続しているノードの関係性を指定していきます。まず 「SW1 につながっている」条件を指定します。元のデータ定義から、隣接する "node" の接続は "node" - "term point" - "term point" - "node" になっているというのがわかっているのでそのまま展開していきます。

![nodes connected with SW1](https://qiita-image-store.s3.amazonaws.com/0/154230/2dbb8798-0c00-eb1b-a592-f6f799190d12.png)

右端の SW1 意外、"node", "term point" は特に値を選択していません。接続関係だけを指定しています。SW1と "term point" ("link") を介して直接つながっていること、という条件を追加することで Result は 3 件までしぼりこまれました。

同じ操作をもう一度追加して今度は 「SV2 につながっている」の条件を追加します (AND 条件の指定)。

![nodes connected with SW1 AND SW2](https://qiita-image-store.s3.amazonaws.com/0/154230/b5ba5b1d-833d-3868-49f3-065c058b3a18.png)

Result は最終的に 1件 になりました。 (target-L1/HYP1)

## なにができたのか

popoto.js でグラフ構造クエリをインクリメンタルに実行してみました。クエリ自体としては、単純な例を取り上げたんですが、これ、「図がそのままクエリになる」(あるいは「クエリを図として表現する」) というのが特徴的ですね。[元のグラフトポロジ (Layer1)](http://netoviz.herokuapp.com/) を抜粋してみましょう。

![Layer1 topology](https://qiita-image-store.s3.amazonaws.com/0/154230/21407729-65c1-942b-d0fe-bbca89505bd8.png)

クエリのために作った構造と、実際のトポロジが一致している(赤で囲ったところ)のがわかるかと思います。ある意味、絵で「このパターンでつながっているところ」を描いてトポロジデータを検索したような感じです。「こういう関係性でつながっているもの」みたいにデータを抽出していくにはおもしろいツールだと思います。