Cisco Network Services Orchestrator (NSO) ができること

#Cisco Network Services Orchestrator

Cisco Network Services Orchestrator は、ネットワーク機器を含む各種デバイスを、クライアントへ抽象化して見せる事が出来ます。コントローラとして動作するだけでなく内部にデータベースを保持する事で、それら各種デバイスの設定情報や、アプリケーション固有の情報を効率的に活用することが出来るようになっており、システム（ソリューション）を完成させるためのフレームワークとして、それに組み込んで使用出来ることが大きな特徴です。

#動作概要

![NSO_overview.png](https://qiita-image-store.s3.amazonaws.com/0/140504/3df1903b-d9d0-3da1-d764-c684e5681698.png)

コントローラ(NSO)から見て、クライアント側を Northbound　(赤矢印)、機器側を Southbound (青矢印) と呼びます。
Northboundに位置するクライアントは、実際のユーザがブラウザから操作しているかもしれませんし、NMS 等上位コントローラとして動作するアプリケーションかもしれません。
Southboundとして接続する機器は、Network Element Driver (NED) によって抽象化されるため、あらゆる機器へ接続することが出来ます。ほとんどのネットワーク機器のNEDは製品として提供されており、すぐに使用可能です。また未知の機器に対しては、NEDを自作することも可能です。


# NSO のアーキテクチャ

NSOは、以下のように複数のコンポーネントが動作しています。

![NSO_architecture.png](https://qiita-image-store.s3.amazonaws.com/0/140504/e7b313f3-f1b1-1c33-62d4-ef64573db820.png)

その中でも、中央に位置している CDB (Configuration Database) は、もっとも重要なものの一つです。

# Configuration Database (CDB) - 内部データベース

Cisco NSO は、独自の XML データベースを内蔵しています。Southbound機器の接続情報やそのConfig、サービスインスタンスの設定情報の他、NSOのシステムとしての設定やローカル認証情報等が保存されます。

CDB の状態の例

```
<data>
  <aaa> ... </aaa>
  <nacm> ... </nacm>
  <devices>
    <device>
      <name>CSR1006-1</name>
      <address>10.1.1.1</address>
      <port>22</port>
      <config>
        <hostname>CSR1006</hostname>
        ...
      </config>
    </device>
    <device>
      <name>ASR9001-1</name>
      <address>10.1.1.2</address>
      <port>22</port>
      <config>
        <hostname>ASR9006</hostname>
        ...
      </config>
      ...
    </device>
  <devices>
  <vpn>
    <pair-name>CompanyA-vpn1</pair-name>
    <location1>Tokyo</location1>
    <location2>Osaka</location2>
  <vpn>
</data>
```
(*) NACM = Netconf Configuration Protocol Access Control Model (RFC 6536)
XMLノードへのアクセスについての権限を詳細に設定を行う。

XML では、XPath を使用してノードの表現を行います。

これらノードや配下のノードは、登録されているSouthbound機器の設定、及びそのConfig情報です。
/data/devices/device[name='CSR1006-1']
/data/devices/device[name='ASR9006']

これはサービスインスタンスです。この投稿で使用している例では、vpn サービスを定義しています。
/data/vpn[pair-name='CompanyA-vpn1']


CDBの操作（データの編集）は、Northboundインターフェースを使用して行います。特定のノードを Subscribe し、変化があれば登録したコールバックを動作させるといったことも出来ますので、柔軟に他のアプリケーションとの連携も可能です。ネットワークエンジニアの皆様は、Cisco IOS-XR の sysdb のような動作という言い方がわかりやすいかもしれません。

デバイスモデルやサービスモデルは、それぞれのインスタンスが CDB 上に作成されると、当該部分は特殊な意味を持ちます。

NSO では、全ての config 変更は CDB 上で行われ、CDBのデータ変更をトリガとして種々の動作を行います。CDB上のデバイスモデルがマッピングされている部分が変更されると、NED を通じて当該機器へ Config 変更が行われます。なお、機器上での設定に何らかのエラーが発生した場合は、CDB上の設定はロールバックされます。

その為、CDB上の Southbound 機器の Config は、それぞれ常に同期している必要があります。ルータのConfigを "sync-from" によってCDBへ取り込みますと、その機器についてCDBは "in-sync" 状態となります。その状態で、実機で Config を行いますと、それをNSOは知りませんので、NSO の CDB は "out-of-sync" 状態となります。その場合は、再度 "sync-from" を行い、再同期する必要があります。このような、out-of-band 作業は出来るだけ避ける必要があります。

CLI から、機器の hostname を変更している例

```
admin@ncs# conf
Entering configuration mode terminal
admin@ncs(config)# devices device CSR1006-1 config
admin@ncs(config-config)# ios:hostname new-hostname
admin@ncs(config-config)# commit
Commit complete.
admin@ncs(config-config)#
```

#Northboundからの要求

クライアントが要求する内容は、例えば以下の様なものがあるでしょう。

- 拠点Aから拠点BまでのVPN設定をしたい
- WebサーバをOpenstack上に作成し、プールから使用可能なIPアドレスをアサインし、ファイアウォールも設定したい
- サーバを Amazon.co.jp で購入し、届いたら Linuxをインストールしたい
- Playstation 4 を Amazon.co.jp で購入し、届いたら Linux をインストールしたい (ん？笑

どれも、Southbound側の詳細については要求には入っていません。拠点Aを管理するPEルータは何か、IPアドレスを管理しているプールのデータベースへのアクセスの方法、Amazon Pay API の使用方法など、要求を達成するために必要なものは、全てクライアントに対しては隠れています。

クライアントは概要のみをNSOへ要求するだけで、目的を達成することが出来るようになります。

なお、その時に使用されるプロトコルは、以下のものがサポートされています。

- CLI
- NETCONF
- REST
- RESTCONF
- JSON-RPC
- Python/Java API による、NSOへの直接命令

#Southboundとのやりとり

NSOにとって、Southbound機器とはルータやスイッチだけでなく、あらゆるものが対象となり得ます。機器との通信方法は、大きくわけて、以下の4つが存在します。

- CLI (telnet, ssh)
- NETCONF
- Generic
- SNMP

## CLI NED

CLI とは、ルータ、スイッチ等へ接続する際に使用されるものです。プロトコルとして telnet や ssh 等が使用され、機器の設定を行うことが出来ます。NSO は設定したい内容、実行したい内容を CLI NED へ渡すと、CLI NED は接続機器の仕様に合わせて telnet や ssh でログインし、"config terminal" を送ったりして機器を設定します。

## NETCONF NED

RFC 6241 で標準化されているプロトコルで、TCP上でXMLメッセージを交換します。昨今の機器では、NETCONF対応のものが増えてきており、機器操作の上で今後ますます重要となってきます。NETCONF対応機器内では、設定情報が XML データベースとして管理されています。NSOのデータベース(CDB) 上でもそのままマップされるため、基本的には機器ベンダが提供する yang ファイルがあれば、操作することが可能です。

## Generic NED

機器のよっては CLI や NETCONF ではなく、独自プロトコルでの設定のみとなっているものがあります。
例えば、Cisco ACI の APIC は REST が唯一の構成変更の窓口ですので、NSOでは Generic NED として、Cisco ACIの APIC 用 NED を提供しています。

他にも、F5社 BIG-IP 等では、ssh を使用して CLI 上で設定を行いますが、show running-config で表示される Config のままコマンドを入力するのではなく、create/modify/delete 等のコマンドを使用して設定を変更する必要があります。そのため、Ciscoでは、F5社 BIG-IP 用 NED は、Generic NEDとして提供しています。

上記例で、Amazon Pay APIを例に出しましたが、これも REST を使用しています。Cisco ではこのプロトコルを使用するNEDを提供していませんが、ユーザは自由に作成し使用することが可能です。（テクニカルサポートの観点では、非サポートです)

# サービスモデル

Northbound で受け付ける要求は、フリーフォーマットのテキストよりも、APIとして定義したフォーマットに沿っているべきです。NSOでは、これをサービスモデルとして Yang で定義します。先の VPN の例では、以下のようなものが考えられます。

```
list vpn {
  key pair-name
  leaf pair-name {
    type string;
  }
  leaf location1 {
    type string;
  }
  leaf location2 {
    type string;
  }
}
```
vpn というリストがあり、VPN を新たに設定する場合、2つの拠点情報が必要です。またその VPN には何らかの名前が付けられる必要があるでしょう。このモデルを使用して、要求の例を JSON で書くと以下のようになります。

```
{
  "vpn" : {
    "pair-name" : "CompanyA-vpn1",
    "location1" : "Tokyo",
    "location2" : "Osaka"
  }
}
```
このサービスプロバイダでは、各市に一つのPOPとしてPEが配置されているとした場合、"Tokyo" から設定が必要なルータが特定出来ます。ビジネスロジック上ではこれを受けて、実際のPEルータ名に変換し、デバイスモデルに従って必要なConfigを作成します。NSOでは、この変換ロジックを FastMap アルゴリズムと呼んでいます。

# デバイスモデル

デバイスモデルは、Southbound機器の設定をモデル化したものです。NETCONF 対応機器では、NETCONF で使用するモデルが各機器ベンダーから提供されます。Cisco IOS 機器など、NETCONF 対応機器でありながら、従来の CLI も同時に使用可能な場合、NETCONF 用のモデルと CLI のモデルは違い、またそのモデルは提供されない場合が多いです。これは、CLIを作成した時に、Yangを意識して作成していないため、ベンダーもYangファイルを用意していないためです。

Cisco NSO では、そう言った機器に対して独自にConfigのモデル化をし、CLI NED として提供しています。全てのConfigをカバーすることは不可能なため、お客様で必要な部分を随時追加していくという方法をとっています。


例えば、Cisco ルータのインターフェースの設定では、以下の様な Config があります。インターフェース FastEthernet1/1 に対して、各項目を設定するものです。

```
interface FastEthernet1/1
 description test1
 ip address 192.168.1.1 255.255.255.0
 duplex full
 speed 1000
```
これをYangでモデル化すると、以下のようなものを作ることが出来ます。
(Cisco NSO では、cisco-ios NED として IOSのモデルを提供していますが、それと以下のモデルとは違っています。これは説明のために簡易的なもので、実際にはこのモデルでは IOS で使用されるConfigがカバーされていません。)

```
container interface {
  list FastEthernet {
    list name {
      key name;
      leaf name {
        type string;
        pattern '[0-9]+/[0-9]+'
      }
      leaf description {
        type string;
      }
      container ip {
        leaf address {
         type inet:ipv4-address;
        }
        leaf mask {
         type inet:ipv4-address;
        }
      }
    }
    ....
```




# パッケージ (ユーザアプリケーション)

NSOのユーザは、独自のアプリケーションを開発することが出来ます。サービスモデルを定義し、その要求をデバイスモデルへマッピングするためのロジックを、FastMap アルゴリズムとして作成することが主な役割です。NSOで使用するパッケージの開発言語としては、以下をサポートしています。

- Java
- Python
- C
- Erlang

作成するアプリケーションは、NSOのライブラリを使用した、通常のアプリケーションですので、ソケット通信やファイルアクセス等は自由に可能です。FastMap ロジック上、必要なデータを外部データベースから取得、外部データベースへ出力することも必要に応じて行います。上記デバイスモデルでの例では、機器に設定する IP アドレスを決定する必要がありますが、IPアドレスプールのデータベースから、一つIPアドレスを取得するといった動作が必要でしょう。

アプリケーションによっては、定期的な処理をさせる必要があるかもしれません。その場合は別のアプリケーションスレッドを作成し、Northboundからの要求とは関係なく、動作させることもできます。

また、最新のNSOバージョンでは、WebアプリケーションとしてGUIのコンポーネントをパッケージに格納できます。これにより、Northboundとしての要求を Javascript で作成し、Ajax で NSO へ送ることも出来ます。


# サービスインスタンス

サービスモデルが完成し、先程の例の VPN サービス要求に対して Config 変換ができるようになったとします。例えば、以下のようなサービス要求があった場合はどのように動作するべきでしょうか。

- サービス要求1 (サービスインスタンス 1)

```
{
  "vpn" : {
    "pair-name" : "CompanyA-vpn1",
    "location1" : "Tokyo",
    "location2" : "Osaka"
  }
}
```

- サービス要求2 (サービスインスタンス 2)

```
{
  "vpn" : {
    "pair-name" : "CompanyA-vpn2",
    "location1" : "Tokyo",
    "location2" : "Sapporo"
  }
}
```
つまり、一つの会社 CompanyA が、3拠点での VPN を作成したいという状態です。Tokyo 拠点では、一つの PE ルータにどちらの要求でも同じ Config (RT 等) が設定される必要があります。(話の都合上、L3VPN とします)

NSOはサービス要求2 を受信して処理する場合、FastMap計算の結果がユーザのロジックから返された際に、Tokyo の PE には既に設定がされていることを認識しているため、内部データベース (CDB) 上の当該Config部分の、Reference Counter を一つ増加させるのみで、Tokyo の PE への Config 送信は行いません。

また、2つのサービスインスタンスが設定されている状態で、Tokyo-OsakaのVPNサービス(サービスインスタンス 1)が解約された場合はどうでしょうか。サービスインスタンスの削除が行われると、FastMap計算で作られたConfigの逆を行い、Southbound 機器からConfigを削除を行います。Osaka の PE ルータからは設定を削除する必要がありますが、Tokyo の PE ルータでは、当該設定がサービスインスタンス 2 が使用しており、削除することは出来ません。この場合は、Reference Counter を一つ減少させ、Tokyo の PE への Config 変更は行いません。その後に、サービスインスタンス2 が削除された場合には、Reference Counter が 0 となるため、Tokyo の PE ルータからも Config が削除されることになります。

# ロールバック

CDB への変更は、ロールバックが可能です。CDB上にマッピングされたデバイスモデル部分に対するロールバックが必要な場合は、Southbound 機器に対して、設定変更が同時に行われます。

サービスインスタンスに対する変更のロールバックでは、自動的にFastMapアルゴリズムの結果を逆計算し、それをSouthbound機器に対して適用します。

これにより、ロールバック機能がない IOS 機器などにおいても、Config ロールバックが行えるようになります。

# まとめ

NSO は、単純に機器を操作するためだけではなく、データベースを内蔵したソリューション完成のためのフレームワークとも言えます。提供されているNEDは100を超え、また自作することも可能なため、あらゆる機器を使用した堅牢なシステムを容易に作ることが出来ます。

オープンソースの世界では、Ansible や Python ライブラリを使用した、デバイス操作についてが話される事が多いと思います。
NSOももちろん NED を使用してデバイス操作が可能ですが、その機能だけを使用するのは非常にもったいない、と思います。
独自パッケージ、独自アプリケーションを作成することで、 NSOの使用方法は何倍にもなっていきます。

NSOを既にお持ちの方は、パッケージ作成にも手を出してみて下さい。多くのサンプルが内蔵されています。
NSOを検討される方は、NEDを使用したデバイス操作（Ansible の Network モジュールの代替）機能で機器管理環境の構築だけではなく、業務自体の自動化も是非考えてみて下さい。