#初めに
YANGはネットワークデバイスのコンフィグをモデル化するのに適した言語とされてますが、CLIに慣れているので私には取っつきにくいものでした。NSOのサービスパッケージを作成する過程でYANGモデルを自作すれば理解しやすかったので、備忘録的に記事に残そうと思いました。
2部構成で1部(YANGの概要、説明)はこちらです。
YANGモデルの理解のためのNSOカスタムサービスパッケージの追加デモ(1/2)
DevNetのLearning Moduleの「NSO Basics for Network Automation」を見ればもっと詳しく記載されてます。
-NSO Basics for Network Automation
#NSOにおけるYANG
NSOの概要については、Qiitaにも大変参考になる記事がたくさんあるので割愛します。
NSOには、デバイスマネージャーとサービスマネージャーという2つの主要コンポーネントがあります。デバイスマネージャは、Interfaceや、OSPF、VLANなど個々のネットワークデバイスの設定を管理し、サービスマネージャは、MP-BGPや、Layer 3 MPLS VPNなど、ネットワーク全体のフィーチャーを抽象化し管理します。
このデバイスマネージャーとサービスマネージャーがYANGデータモデリングに大きく依存しています。
その他にも、NSOサーバー構成、ユーザーが追加するカスタムデータ、さらにはシステムアラームなど、NSOはシステム内のすべてのデータをYANGでモデル化しており、CDBのデータにアクセスし保存する方法が統一されています。
#デモの目的、概要、手順
今回は、YANGモデルの構成を理解することを目的として、NSOにカスタムサービスパッケージを追加していきたいと思います。
- デモ環境
- DevNet Sandbox 『Cisco Network Services Orchestrator』
- 内容
- Sandbox内のCML2で構築したL3VPN(SR-MPLS)に新たなサイトを追加するカスタムサービスパッケージを追加し、サイト追加に必要なコンフィグデータをYANGでモデリング
(参考)CML2 core-rtr01へのL3VPN(SR-MPLS)追加コンフィグ
vrf A
address-family ipv4 unicast
import route-target
65432:111
!
export route-target
65432:111
!
!
!
vrf B
address-family ipv4 unicast
import route-target
65432:222
!
export route-target
65432:222
!
!
!
interface loopback0
ipv4 address 172.16.252.101 255.255.255.255
no shutdown
!
interface Loopback111
vrf A
ipv4 address 1.1.1.1 255.255.255.255
no shutdown
!
interface Loopback222
vrf B
ipv4 address 2.2.2.1 255.255.255.255
no shutdown
!
router bgp 65432
bgp router-id 172.16.252.101
bgp log neighbor changes detail
address-family vpnv4 unicast
!
neighbor 172.16.252.102
remote-as 65432
update-source Loopback0
address-family vpnv4 unicast
!
!
vrf A
rd 65432:111
address-family ipv4 unicast
!
redistribute connected
!
!
vrf B
rd 65432:222
address-family ipv4 unicast
!
redistribute connected
!
!
!
segment-routing
global-block 16000 18000
!
router ospf 1
segment-routing mpls
area 0
segment-routing mpls
interface Loopback0
prefix-sid index 111
(参考)CML2 core-rtr02へのL3VPN(SR-MPLS)追加コンフィグ
vrf A
address-family ipv4 unicast
import route-target
65432:111
!
export route-target
65432:111
!
!
!
vrf B
address-family ipv4 unicast
import route-target
65432:222
!
export route-target
65432:222
!
!
!
interface loopback0
ipv4 address 172.16.252.102 255.255.255.255
no shutdown
!
interface Loopback111
vrf A
ipv4 address 1.1.1.2 255.255.255.255
no shutdown
!
interface Loopback222
vrf B
ipv4 address 2.2.2.2 255.255.255.255
no shutdown
!
router bgp 65432
bgp router-id 172.16.252.102
bgp log neighbor changes detail
address-family vpnv4 unicast
!
neighbor 172.16.252.101
remote-as 65432
update-source Loopback0
address-family vpnv4 unicast
!
!
vrf A
rd 65432:111
address-family ipv4 unicast
!
redistribute connected
!
!
vrf B
rd 65432:222
address-family ipv4 unicast
!
redistribute connected
!
!
!
segment-routing
global-block 16000 18000
!
router ospf 1
segment-routing mpls
area 0
segment-routing mpls
interface Loopback0
prefix-sid index 222
今回はCML2の仮想デバイスに設定を反映するところまではいきませんが、新たなサイトを追加する設定項目の参考までに、CML2でL3VPN(SR-MPLS)を構築するためのコンフィグを掲載しました。
- 手順
- ⓪事前準備
①サービスパッケージの作成
②moduleの定義
③leaf、leaf-list、の定義
④containerの定義
⑤listの定義
#事前準備
- 1. デザイン
- 新たなサイトを追加するには、①設定を追加するデバイス、②VRFの追加、③VRFに所属するLoopbackアドレスの追加、④その他、が必要になります。
①設定を追加するデバイス
Config | Node | Node Name | Type |
---|---|---|---|
device | 値は一つなのでleaf | device | NSOに登録したデバイスから参照するleafref |
②VRFの追加
VRFの追加については同じ性質なので、containerにまとめます。
必要なconfigの設定値を適切なnodeに定義します。
Config | Node | Node Name | type |
---|---|---|---|
- | container | vrf | - |
vrf-definition | 値は一つなのでleaf | vrf-name | string |
route-distinguisher | 値は一つなのでleaf | rd | regexでパターンを制限したstring |
route-target export | 値は一つなのでleaf | route-target-export | regexでパターンを制限したstring |
route-target import | 値が複数の可能性もあるので leaf-list |
route-target-import | regexでパターンを制限したstring |
③VRFに所属するLoopbackアドレスの追加
Loopbackの追加については同じ性質なので、containerにまとめます。
必要なconfigの設定値を適切なnodeに定義します。
Config | Node | Node Name | Type |
---|---|---|---|
- | container | loopabck | - |
Loopback番号 | 値は一つなのでleaf | loopback-number | uint16 |
Loopbackアドレス | 値は一つなのでleaf | loopback-ip | ietf-inet-typesからインポートしたipv4-address |
④その他
全てのnodeをまとめるため、__container__を作成します。
deviceごとにpolicyを作って設定を反映させたいので、keyとなるpolicy名のleafと、__list__を定義し、インスタンスができるようにします。
Config | Node | Node Name | Type |
---|---|---|---|
- | container | vpn | - |
- | list | vpn-policy | - |
listのキーとなるPolicy名 | 値は一つなのでleaf | policy-name | string |
Policyの説明 | 値は一つなのでleaf | description | lengthで長さ、regexでパターンを制限したstring |
保守担当者 Maintainer |
値が複数の可能性もあるのでleaf-list | maintainer-members | 他で定義したidentity値を参照するためのidentityref |
- 2. DevNet Sandbox を予約
- 『Cisco Network Services Orchestrator』を予約します。Sandboxの予約の仕方については、下記の記事が大変参考になります。
- 『DevNet Sandbox を使って pyATS/XPRESSO を CML2 と始めよう』
Sandboxで『Cisco Network Services Orchestrator』がアクティブになれば環境の準備は完了です。
#サービスパッケージの作成
今回はNSOのインスタンスが起動済みで、CML2内の仮装デバイスを全て登録しコンフィグもsync済みのNSOを利用します。
NSO(10.10.20.49)にSSHで接続します。usernameはdeveloper
、passwordはC1sco12345
でログインできます。
アウトプット
(py3venv) [developer@devbox ~]$ ssh -l developer 10.10.20.49
Warning: Permanently added '10.10.20.49' (ECDSA) to the list of known hosts.
developer@10.10.20.49's password:
Last login: Thu Oct 14 22:34:04 2021 from 192.168.254.11
[developer@nso ~]$
NSOはYANGファイルをそのままの形式では使用できないため、最初にコンパイルする必要があります。コンパイルにはMakefileなどが必要になるので、YANGモデルを作成する前に、テンプレートとなるYANGファイルや、コンパイルに必要なファイルを含んだサービスパッケージをncs-make-package
コマンドで作成する必要があります。
サービスパッケージは所定のディレクトリに展開する必要があるので、コマンドは/var/opt/ncs/packages/
に移動してから入力します。
アウトプット
[developer@nso ~]$ cd /var/opt/ncs/packages/
[developer@nso packages]$ ncs-make-package --service-skeleton template add-vpn-service
ncs-make-package
コマンドによって、add-vpn-service/
ディレクトリが作成されました。
add-vpn-service/src/
ディレクトリにコンパイルが必要なすべてのファイルとMakefileが配置されています。 Makefileは、make
コマンドによってソースファイルをビルドする時に必要となります。./src/yang/
配下にあるすべてのYANGファイルを検索し、それらをNSO互換(バイナリ)形式にコンパイルされます。
add-vpn-service/src/yang
ディレクトリにテンプレートとなるYANGファイルが作成されますが、今回は自作するので削除します。
また、add-vpn-service/templates/
ディレクトリにあるコンフィグテンプレートXMLファイルも削除します。
アウトプット
[developer@nso packages]$ rm add-vpn-service/src/yang/add-vpn-service.yang
[developer@nso packages]$ rm add-vpn-service/templates/add-vpn-service-template.xml
これでYANGファイルの作成の準備ができました。
#moduleの定義
YANGモmoduleには色々なルールがありますが、今回は最小限のmoduleを定義します。
まず、touch
でYANGファイルを作成し、それにvimでmoduleを記述します。
アウトプット
[developer@nso packages]$ cd add-vpn-service/src/yang/
[developer@nso yang]$ touch add-vpn-service.yang
[developer@nso yang]$ vim add-vpn-service.yang
module add-vpn-service {
namespace "http://example.com/ns/yang/add-vpn-service";
prefix vpn;
}
セミコロン(";") はその時点でステートメントを完了しますが、中括弧("{" and "}")を使用すると、このステートメントにサブステートメントを追加できます。 この例では、
namespace
とprefix
はmoduleのサブステートメントです。namespace
とprefix
はこのmoduleを一意に識別するもので、必須です。namespace
はURI(Uniform Resource Identifier)であり、XML形式でデータをエンコードするときに使用されますが、prefix
はYANGからこのmoduleを参照するために使用できます。
pyang
コマンドを使えばYANGの構文が正しいかどうか確かめることができます。
アウトプット
[developer@nso yang]$ pyang --strict add-vpn-service.yang
[developer@nso yang]$
何もエラーが出なければ正しいです。
moduleには下記のようなステートメントを追加できます。
organization
"EXAMPLE SYSTEMS";
contact
"EXAMPLE SYSTEMS
Customer Service
E-mail: example@example.com";
description
"L3VPN YANG Model.";
revision 2021-10-15 {
description
"Initial revision";
}
organization
:moduleを作成した組織
-
contact
:module担当の連絡先 -
description
:moduleの説明文 -
revision
:バージョン管理
YANGにおいては、改行はステートメントを終了しません。あくまでも、セミコロン(";")か、中括弧("{" and "}")で終了します。
add-vpn-service.yang - クリック
module add-vpn-service {
namespace "http://example.com/ns/yang/add-vpn-service";
prefix vpn;
organization
"EXAMPLE SYSTEMS";
contact
"EXAMPLE SYSTEMS
Customer Service
E-mail: example@example.com";
description
"L3VPN YANG Model.";
revision 2021-10-15 {
description
"Initial revision";
}
}
moduleを定義できたので、make
でコンパイルします。
アウトプット
[developer@nso yang]$ make -C ../
make: ディレクトリ `/var/opt/ncs/packages/add-vpn-service/src' に入ります
mkdir -p ../load-dir
/opt/ncs/current/bin/ncsc `ls add-vpn-service-ann.yang > /dev/null 2>&1 && echo "-a add-vpn-service-ann.yang"` \
-c -o ../load-dir/add-vpn-service.fxs yang/add-vpn-service.yang
make: ディレクトリ `/var/opt/ncs/packages/add-vpn-service/src' から出ます
[developer@nso yang]$
エラーが出なければコンパイルは成功です。
#leaf、leaf-listの定義
まず、先ほどのYANGファイルの続きにleaf、leaf-listを定義します。
####leaf device
module add-vpn-service {
namespace "http://example.com/ns/yang/add-vpn-service";
prefix vpn;
import tailf-ncs {
prefix ncs;
}
・・・
leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
description "Configured Device Name";
}
__type__は
leafref
でNSOのCDBに登録されたデバイスリストから選択できるようにします。このように他のYANGモジュールで定義された__type__や、__node__をインポートすることができます。import
ステートメントでインポートするモジュールの名前と、prefix
を定義します。import
ステートメントはmodule
の最初に定義します。
__device__は任意につけたleafの名前です。
全てのnodeにdescription
を記述することが望ましいです。
####leaf vrf-name
leaf vrf-name {
type string;
description "VRF Name";
}
__type__は
string
にします。
####leaf rd、leaf route-target-export
leaf rd {
type union {
type string {
pattern "[0-9]{1,5}:[0-9]{1,5}";
}
type enumeration {
enum "65432:111";
enum "65432:222";
}
}
description "Route Distinguisher and Route target";
}
leaf route-target-export {
type union {
type string {
pattern "[0-9]{1,5}:[0-9]{1,5}";
}
type enumeration {
enum "65432:111";
enum "65432:222";
}
}
description "Route Target Export";
}
__type__を
string
にし、regexでpattern
を指定します。leaf rd、leaf route-target-export__どちらも、nnnnn:nnnnnにしたいので、pattern "[0-9]{1,5}:[0-9]{1,5}"
とします。また、既にデバイスに設定されている"65432:111"と、"65432:222"__を入力不要で選択できるようにしたいので、__type__のenumeration
も適用します。このように2つの__type__を適用するには、typeunion
でグルーピングします。
leaf rd、__leaf route-target-export__を作成しましたが、どちらもビルトインの__type__そのままではなく、カスタマイズした同じ__type__を適用しています。後に出てくる__leaf route-target-import__も同じ__type__を適用するので、revision
の直下にtypedef
としてあらかじめ定義しておき、nodeから参照できるようにします。
・・・
revision 2021-10-15 {
description
"Initial revision";
}
typedef rdrt-type {
type union {
type string {
pattern "[0-9]{1,5}:[0-9]{1,5}";
}
type enumeration {
enum "65432:111";
enum "65432:222";
}
}
}
・・・
leaf rd {
type rdrt-type;
description "Route Distinguisher and Route target";
}
leaf route-target-export {
type rdrt-type;
description "Route Target Export";
}
####leaf-list route-target-import
leaf-list route-target-import {
type rdrt-type;
description "Route Target Export";
}
type__は__leaf rd、__leaf route-target-export__と同じなので、
typedef
で定義したrdrt-type
にを参照します。route-target-importは複数の可能性があるので、__leaf-list__で定義します。
####leaf loopback-number
leaf loopback-number {
type uint16;
description "Loopback Interface Number";
}
__type__は
uint16
にします。
####leaf loopback-ip
module add-vpn-service {
namespace "http://example.com/ns/yang/add-vpn-service";
prefix vpn;
import ietf-inet-types {
prefix inet;
}
・・・
leaf loopback-ip {
type inet:ipv4-address;
description "Loopback IPv4 Address.";
}
__type__は、ietfで定義されたietf-inet-typesモジュールをインポートして、その中で定義されているipv4-addressタイプを使用します。ietf-inet-typesには、アドレスやその他のインターネット関連のオブジェクトや機能について、YANGデータタイプのグループが事前定義されています。
####leaf maintainer-members
・・・
import maintainers-base {
prefix maintainers;
}
・・・
identity IETSUNA {
base maintainers:base-maintainers;
description "The Member of Maintainers";
}
identity TSUNATOSHI {
base maintainers:base-maintainers;
description "The Member of Maintainers";
}
・・・
leaf-list maintainer-members {
type identityref {
base maintainers:base-maintainers;
}
description "Maintainers of Customer";
}
__maintainer-members__は、このVPNサービスの保守担当者のリストです。保守担当者は他のモジュールでも参照される共通のものなので、独立したモジュールで定義してそれをインポートすることにします。
identityref
ステートメントを使えば、他のモジュールで定義したidentityをインポートすることができます。また、identity
ステートメントでローカルモジュールにidentityを追加することもできます。今回は、IEYASU、HIDETADA、IEMITSUを__maintainers-base.yang__で定義しておき、IETSUNA、TSUNATOSHIを__ローカル__で追加しています。
__identity__は__enumeration__のように入力できるオプションを制限することができます。
インポートされる__identity__を定義するモジュール「maintainers-base.yang」を「add-vpn-service.yang」と同じディレクトリに作成します。
maintainers-base.yang - クリック
module maintainers-base {
namespace "http://example.com/us/yang/maintainers-base";
prefix base;
description "The Base Modele For The maintainers.";
identity base-maintainers {
description "Cutom identity for the base protocol";
}
identity IEYASU {
base base-maintainers;
description "The Member of Maintainers";
}
identity HIDETADA {
base base-maintainers;
description "The Member of Maintainers";
}
identity IEMITSU {
base base-maintainers;
description "The Member of Maintainers";
}
}
add-vpn-service.yang - クリック
module add-vpn-service {
namespace "http://example.com/ns/yang/add-vpn-service";
prefix vpn;
import ietf-inet-types {
prefix inet;
}
import tailf-ncs {
prefix ncs;
}
import maintainers-base {
prefix maintainers;
}
organization
"EXAMPLE SYSTEMS";
contact
"EXAMPLE SYSTEMS
Customer Service
E-mail: example@example.com";
description
"L3VPN YANG Model.";
revision 2021-10-15 {
description
"Initial revision";
}
typedef rdrt-type {
type union {
type string {
pattern "[0-9]{1,5}:[0-9]{1,5}";
}
type enumeration {
enum "65432:111";
enum "65432:222";
}
}
}
identity IETSUNA {
base maintainers:base-maintainers;
description "The Member of Maintainers";
}
identity TSUNATOSHI {
base maintainers:base-maintainers;
description "The Member of Maintainers";
}
leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
description "Configured Device Name";
}
leaf vrf-name {
type string;
description "VRF Name";
}
leaf rd {
type rdrt-type;
description "Route Distinguisher and Route target";
}
leaf route-target-export {
type rdrt-type;
description "Route Target Export";
}
leaf-list route-target-import {
type rdrt-type;
description "Route Target Export";
}
leaf loopback-number {
type uint16;
description "Loopback Interface Number";
}
leaf loopback-ip {
type inet:ipv4-address;
description "Loopback IPv4 Address.";
}
leaf-list maintainer-members {
type identityref {
base maintainers:base-maintainers;
}
description "Maintainers of Customer";
}
}
leaf、leaf-listを定義できたので、make
でコンパイルします。
アウトプット
[developer@nso yang]$ YANGPATH="./yang" make -C ../
make: ディレクトリ `/var/opt/ncs/packages/add-vpn-service/src' に入ります
/opt/ncs/current/bin/ncsc `ls add-vpn-service-ann.yang > /dev/null 2>&1 && echo "-a add-vpn-service-ann.yang"` \
--yangpath ./yang -c -o ../load-dir/add-vpn-service.fxs yang/add-vpn-service.yang
/opt/ncs/current/bin/ncsc `ls maintainers-base-ann.yang > /dev/null 2>&1 && echo "-a maintainers-base-ann.yang"` \
--yangpath ./yang -c -o ../load-dir/maintainers-base.fxs yang/maintainers-base.yang
make: ディレクトリ `/var/opt/ncs/packages/add-vpn-service/src' から出ます
[developer@nso yang]$
YANGPATH = "./yang"の部分は、必要なモジュールがないかYANGフォルダーも検索するようにビルドシステムに指示します。これがないと、システムがモジュールmaintainers-baseを見つけられないというエラーが発生する場合があります。
NSO cliにdeveloperユーザーで接続します。
アウトプット
[developer@nso src]$ ncs_cli -C -u developer
User developer last logged in 2021-10-17T20:50:34.086471-00:00, to nso, from 10.10.20.49 using rest-https
developer connected from 192.168.254.11 using ssh on nso
developer@ncs#
一つのパッケージに変更を適用した後でも、オペレーションモードのpackages reload
コマンドですべてのパッケージをリロードする必要があります。
アウトプット
developer@ncs# packages reload
>>> System upgrade is starting.
>>> Sessions in configure mode must exit to operational mode.
>>> No configuration changes can be performed until upgrade has completed.
>>> System upgrade has completed successfully.
reload-result {
package add-vpn-service
result true
}
reload-result {
package cisco-asa-cli-6.12
result true
}
reload-result {
package cisco-ios-cli-6.67
result true
}
reload-result {
package cisco-iosxr-cli-7.32
result true
}
reload-result {
package cisco-nx-cli-5.20
result true
}
reload-result {
package resource-manager
result true
}
reload-result {
package selftest
result true
}
reload-result {
package svi_verify_example
result true
}
developer@ncs#
System message at 2021-10-18 03:33:40...
Subsystem stopped: ncs-dp-10-cisco-ios-cli-6.67:IOSDp
developer@ncs#
System message at 2021-10-18 03:33:40...
Subsystem stopped: ncs-dp-11-cisco-nx-cli-5.20:NexusDp
developer@ncs#
System message at 2021-10-18 03:33:40...
Subsystem stopped: ncs-dp-12-resource-manager:AddressallocationIPvalidation
developer@ncs#
System message at 2021-10-18 03:33:40...
Subsystem stopped: ncs-dp-9-cisco-asa-cli-6.12:ASADp
developer@ncs#
System message at 2021-10-18 03:33:40...
Subsystem started: ncs-dp-13-cisco-asa-cli-6.12:ASADp
developer@ncs#
System message at 2021-10-18 03:33:40...
Subsystem started: ncs-dp-14-cisco-ios-cli-6.67:IOSDp
developer@ncs#
System message at 2021-10-18 03:33:40...
Subsystem started: ncs-dp-15-cisco-nx-cli-5.20:NexusDp
developer@ncs#
System message at 2021-10-18 03:33:40...
Subsystem started: ncs-dp-16-resource-manager:AddressallocationIPvalidation
developer@ncs#
コンフィギュレーションモードで?
をタイプします。
アウトプット
developer@ncs#
developer@ncs# config t
Entering configuration mode terminal
developer@ncs(config)# ?
Possible completions:
aaa AAA management
alarms Alarm management
alias Create command alias.
cluster Cluster configuration
compliance Compliance reporting
customers Customers using services
device
devices The managed devices and device communication settings
high-availability Configuration, status and actions concerning NSO Built-in HA
java-vm Control of the NCS Java VM
loopback-ip
loopback-number
maintainer-members
nacm Access control
ncs-state NCS status information
packages Installed packages
policy Configuration policies
python-vm Control of the NCS Python VM
rd
resource-pools
route-target-export
route-target-import
scheduler Time-based job scheduler suitable for scheduling periodic background work.
selftest
service-progress-monitoring Service Progress Monitoring policies
services The services managed by NCS
session Global default CLI session parameters
side-effect-queue
smart-license
snmp Top-level container for SNMP related configuration and status objects.
snmp-notification-receiver Configure reception of SNMP notifications
software Software management
ssh Global SSH connection configuration
svi_verify_example
tls Global TLS keystore configuration
user User specific command aliases and default CLI session parameters
vrf-name
webui Web UI specific configuration
zombies Container for deleted Nano Services that still perform staged deletes.
---
abort Abort configuration session
activate Activate a statement
annotate Add a comment to a statement
clear Remove all configuration changes
commit Commit current set of changes
compare Compare configuration
copy Copy a list entry
deactivate Deactivate a statement
describe Display transparent command information
do Run an operational-mode command
end Terminate configuration session
exit Exit from current mode
help Provide help information
insert Insert a parameter
load Load configuration from an ASCII file or from terminal
move Move a parameter
no Negate a command or set its defaults
pwd Display current mode path
rename Rename an identifier
resolved Conflicts have been resolved
revert Copy configuration from running
rload Load configuration from an ASCII file or from terminal, relative to current location
rollback Roll back database to last committed version
save Save configuration to an ASCII file
save-device-cfg save device settings
service Modify use of network based services
show Show a parameter
switch Change CLI style
tag Manipulate statement tags
top Exit to top level and optionally run command
validate Validate current configuration
developer@ncs(config)#
__leaf__や、__leaf-list__など定義した__node__がコマンドで設定できるようになりましたが、整理されておらず、いろんなコマンドと一緒に出てくるので煩雑です。
そこで、__container__を利用します。
#containerの定義
container__を定義します。まず、全体をvpn
という__container__でグループ化し、vrf設定関連をvrf
という__container、VRFに所属するLoopbackアドレス設定関連をloopback
という__container__にグループ化します。
module add-vpn-service {
namespace "http://example.com/ns/yang/add-vpn-service";
prefix vpn;
import ietf-inet-types {
prefix inet;
}
import tailf-ncs {
prefix ncs;
}
import maintainers-base {
prefix maintainers;
}
organization
"EXAMPLE SYSTEMS";
contact
"EXAMPLE SYSTEMS
Customer Service
E-mail: example@example.com";
description
"L3VPN YANG Model.";
revision 2021-10-15 {
description
"Initial revision";
}
typedef rdrt-type {
type union {
type string {
pattern "[0-9]{1,5}:[0-9]{1,5}";
}
type enumeration {
enum "65432:111";
enum "65432:222";
}
}
}
identity IETSUNA {
base maintainers:base-maintainers;
description "The Member of Maintainers";
}
identity TSUNATOSHI {
base maintainers:base-maintainers;
description "The Member of Maintainers";
}
container vpn {
description "L3vpn vrf";
leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
description "Configured Device Name";
}
leaf-list maintainer-members {
type identityref {
base maintainers:base-maintainers;
}
description "Maintainers of Customer";
}
container vrf {
description "Vrf container";
leaf vrf-name {
type string;
description "VRF Name";
}
leaf rd {
type rdrt-type;
description "Route Distinguisher and Route target";
}
leaf route-target-export {
type rdrt-type;
description "Route Target Export";
}
leaf-list route-target-import {
type rdrt-type;
description "Route Target Export";
}
}
container loopback {
description "Loopback container";
leaf loopback-number {
type uint16;
description "Loopback Interface Number";
}
leaf loopback-ip {
type inet:ipv4-address;
description "Loopback IPv4 Address.";
}
}
}
}
add-vpn-service.yangを更新して、make
、packages reload
します。
アウトプット
[developer@nso yang]$ YANGPATH="./yang" make -C ../
make: ディレクトリ `/var/opt/ncs/packages/add-vpn-service/src' に入ります
/opt/ncs/current/bin/ncsc `ls add-vpn-service-ann.yang > /dev/null 2>&1 && echo "-a add-vpn-service-ann.yang"` \
--yangpath ./yang -c -o ../load-dir/add-vpn-service.fxs yang/add-vpn-service.yang
make: ディレクトリ `/var/opt/ncs/packages/add-vpn-service/src' から出ます
[developer@nso yang]$
[developer@nso yang]$
[developer@nso yang]$ ncs_cli -C -u developer
User developer last logged in 2021-10-18T03:31:49.65825-07:00, to nso, from 192.168.254.11 using cli-ssh
developer connected from 192.168.254.11 using ssh on nso
developer@ncs#
developer@ncs# packages reload
>>> System upgrade is starting.
>>> Sessions in configure mode must exit to operational mode.
>>> No configuration changes can be performed until upgrade has completed.
>>> System upgrade has completed successfully.
reload-result {
package add-vpn-service
result true
}
reload-result {
package cisco-asa-cli-6.12
result true
}
reload-result {
package cisco-ios-cli-6.67
result true
}
reload-result {
package cisco-iosxr-cli-7.32
result true
}
reload-result {
package cisco-nx-cli-5.20
result true
}
reload-result {
package resource-manager
result true
}
reload-result {
package selftest
result true
}
reload-result {
package svi_verify_example
result true
}
developer@ncs#
System message at 2021-10-18 04:09:06...
Subsystem stopped: ncs-dp-14-cisco-ios-cli-6.67:IOSDp
developer@ncs#
System message at 2021-10-18 04:09:06...
Subsystem stopped: ncs-dp-15-cisco-nx-cli-5.20:NexusDp
developer@ncs#
System message at 2021-10-18 04:09:06...
Subsystem stopped: ncs-dp-16-resource-manager:AddressallocationIPvalidation
developer@ncs#
System message at 2021-10-18 04:09:06...
Subsystem stopped: ncs-dp-13-cisco-asa-cli-6.12:ASADp
developer@ncs#
System message at 2021-10-18 04:09:06...
Subsystem started: ncs-dp-17-cisco-asa-cli-6.12:ASADp
developer@ncs#
System message at 2021-10-18 04:09:06...
Subsystem started: ncs-dp-18-cisco-ios-cli-6.67:IOSDp
developer@ncs#
System message at 2021-10-18 04:09:06...
Subsystem started: ncs-dp-19-cisco-nx-cli-5.20:NexusDp
developer@ncs#
System message at 2021-10-18 04:09:06...
Subsystem started: ncs-dp-20-resource-manager:AddressallocationIPvalidation
developer@ncs#
コンフィギュレーションモードで?
をタイプします。
アウトプット
developer@ncs# config t
Entering configuration mode terminal
developer@ncs(config)# ?
Possible completions:
aaa AAA management
alarms Alarm management
alias Create command alias.
cluster Cluster configuration
compliance Compliance reporting
customers Customers using services
devices The managed devices and device communication settings
high-availability Configuration, status and actions concerning NSO Built-in HA
java-vm Control of the NCS Java VM
nacm Access control
ncs-state NCS status information
packages Installed packages
policy Configuration policies
python-vm Control of the NCS Python VM
resource-pools
scheduler Time-based job scheduler suitable for scheduling periodic background work.
selftest
service-progress-monitoring Service Progress Monitoring policies
services The services managed by NCS
session Global default CLI session parameters
side-effect-queue
smart-license
snmp Top-level container for SNMP related configuration and status objects.
snmp-notification-receiver Configure reception of SNMP notifications
software Software management
ssh Global SSH connection configuration
svi_verify_example
tls Global TLS keystore configuration
user User specific command aliases and default CLI session parameters
vpn
webui Web UI specific configuration
zombies Container for deleted Nano Services that still perform staged deletes.
---
abort Abort configuration session
activate Activate a statement
annotate Add a comment to a statement
clear Remove all configuration changes
commit Commit current set of changes
compare Compare configuration
copy Copy a list entry
deactivate Deactivate a statement
describe Display transparent command information
do Run an operational-mode command
end Terminate configuration session
exit Exit from current mode
help Provide help information
insert Insert a parameter
load Load configuration from an ASCII file or from terminal
move Move a parameter
no Negate a command or set its defaults
pwd Display current mode path
rename Rename an identifier
resolved Conflicts have been resolved
revert Copy configuration from running
rload Load configuration from an ASCII file or from terminal, relative to current location
rollback Roll back database to last committed version
save Save configuration to an ASCII file
save-device-cfg save device settings
service Modify use of network based services
show Show a parameter
switch Change CLI style
tag Manipulate statement tags
top Exit to top level and optionally run command
validate Validate current configuration
developer@ncs(config)#
__container vpn__のおかげで
vpn
にまとめられました。
vpn
で?
をタイプします。
アウトプット
developer@ncs(config)# vpn ?
Possible completions:
device loopback maintainer-members vrf
developer@ncs(config)# vpn
では、実際に設定し、NSOのCDBへ反映してみましょう。
アウトプット
developer@ncs# config t
Entering configuration mode terminal
developer@ncs(config)# vpn ?
Possible completions:
device loopback maintainer-members vrf
developer@ncs(config)# vpn device ?
Possible completions:
core-rtr01 core-rtr02 dist-rtr01 dist-rtr02 dist-sw01 dist-sw02 edge-firewall01 edge-sw01 internet-rtr01
developer@ncs(config)# vpn device core-rtr01
developer@ncs(config)#
developer@ncs(config)#
developer@ncs(config)# vpn maintainer-members ?
Possible completions:
HIDETADA IEMITSU IETSUNA IEYASU TSUNATOSHI [
developer@ncs(config)# vpn maintainer-members HIDETADA
developer@ncs(config)# vpn maintainer-members IEYASU
developer@ncs(config)#
developer@ncs(config)#
developer@ncs(config)# vpn vrf ?
Possible completions:
rd route-target-export route-target-import vrf-name
developer@ncs(config)# vpn vrf vrf-name C
developer@ncs(config)#
developer@ncs(config)#
developer@ncs(config)# vpn vrf rd ?
Possible completions:
<string> 65432:111 65432:222
developer@ncs(config)# vpn vrf rd 65432:333
developer@ncs(config)#
developer@ncs(config)#
developer@ncs(config)# vpn vrf route-target-export ?
Possible completions:
<string> 65432:111 65432:222
developer@ncs(config)# vpn vrf route-target-export 65432:333
developer@ncs(config)#
developer@ncs(config)#
developer@ncs(config)# vpn vrf route-target-import ?
Possible completions:
<string> 65432:111 65432:222 [
developer@ncs(config)# vpn vrf route-target-import 65432:111
developer@ncs(config)# vpn vrf route-target-import 65432:222
developer@ncs(config)# vpn vrf route-target-import 65432:333
developer@ncs(config)#
developer@ncs(config)#
developer@ncs(config)# vpn loopback ?
Possible completions:
loopback-ip loopback-number
developer@ncs(config)# vpn loopback loopback-number ?
Possible completions:
<unsignedShort>
developer@ncs(config)# vpn loopback loopback-number 333
developer@ncs(config)#
developer@ncs(config)#
developer@ncs(config)# vpn loopback loopback-ip ?
Possible completions:
<IPv4 address>
developer@ncs(config)# vpn loopback loopback-ip 3.3.3.1
developer@ncs(config)#
developer@ncs(config)#
developer@ncs(config)# show configuration
vpn device core-rtr01
vpn maintainer-members [ HIDETADA IEYASU ]
vpn vrf vrf-name C
vpn vrf rd 65432:333
vpn vrf route-target-export 65432:333
vpn vrf route-target-import [ 65432:111 65432:222 65432:333 ]
vpn loopback loopback-number 333
vpn loopback loopback-ip 3.3.3.1
commit
し、show running-config vpn
を見てみます。
アウトプット
developer@ncs(config)# commit
Commit complete.
developer@ncs(config)# end
developer@ncs# show running-config vpn
vpn device core-rtr01
vpn maintainer-members [ HIDETADA IEYASU ]
vpn vrf vrf-name C
vpn vrf rd 65432:333
vpn vrf route-target-export 65432:333
vpn vrf route-target-import [ 65432:111 65432:222 65432:333 ]
vpn loopback loopback-number 333
vpn loopback loopback-ip 3.3.3.1
developer@ncs#
別のデバイスへもコンフィグを追加する場合を想定して、今度は違う設定を投入してみます。
アウトプット
developer@ncs(config)# vpn device core-rtr02
developer@ncs(config)# vpn maintainer-members HIDETADA
developer@ncs(config)# vpn maintainer-members IETSUNA
developer@ncs(config)# vpn maintainer-members TSUNATOSHI
developer@ncs(config)# vpn vrf vrf-name D
developer@ncs(config)# vpn vrf rd 65432:444
developer@ncs(config)# vpn vrf route-target-export 65432:444
developer@ncs(config)# vpn vrf route-target-import 65432:444
developer@ncs(config)# vpn loopback loopback-number 444
developer@ncs(config)# vpn loopback loopback-ip 4.4.4.1
developer@ncs(config)# show configuration
vpn device core-rtr02
vpn maintainer-members [ IETSUNA TSUNATOSHI HIDETADA IEYASU ]
vpn vrf vrf-name D
vpn vrf rd 65432:444
vpn vrf route-target-export 65432:444
vpn vrf route-target-import [ 65432:111 65432:222 65432:333 65432:444 ]
vpn loopback loopback-number 444
vpn loopback loopback-ip 4.4.4.1
developer@ncs(config)# commit
Commit complete.
developer@ncs(config)# end
developer@ncs# show running-config vpn
vpn device core-rtr02
vpn maintainer-members [ IETSUNA TSUNATOSHI HIDETADA IEYASU ]
vpn vrf vrf-name D
vpn vrf rd 65432:444
vpn vrf route-target-export 65432:444
vpn vrf route-target-import [ 65432:111 65432:222 65432:333 65432:444 ]
vpn loopback loopback-number 444
vpn loopback loopback-ip 4.4.4.1
developer@ncs#
#listの定義
listを使えばいくつでもインスタンスを作れるので、設定が必要なnodeを全て包含するようにvpn-policy
というlistを定義します。
module add-vpn-service {
namespace "http://example.com/ns/yang/add-vpn-service";
prefix vpn;
import ietf-inet-types {
prefix inet;
}
import tailf-ncs {
prefix ncs;
}
import maintainers-base {
prefix maintainers;
}
organization
"EXAMPLE SYSTEMS";
contact
"EXAMPLE SYSTEMS
Customer Service
E-mail: example@example.com";
description
"L3VPN YANG Model.";
revision 2021-10-15 {
description
"Initial revision";
}
typedef rdrt-type {
type union {
type string {
pattern "[0-9]{1,5}:[0-9]{1,5}";
}
type enumeration {
enum "65432:111";
enum "65432:222";
}
}
}
identity IETSUNA {
base maintainers:base-maintainers;
description "The Member of Maintainers";
}
identity TSUNATOSHI {
base maintainers:base-maintainers;
description "The Member of Maintainers";
}
container vpn {
description "L3vpn vrf";
list vpn-policy {
key "policy-name";
description "VRF Configured Policy";
leaf policy-name {
type string;
}
leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
description "Configured Device Name";
}
leaf-list maintainer-members {
type identityref {
base maintainers:base-maintainers;
}
description "Maintainers of Customer";
}
container vrf {
description "Vrf container";
leaf vrf-name {
type string;
description "VRF Name";
}
leaf rd {
type rdrt-type;
description "Route Distinguisher and Route target";
}
leaf route-target-export {
type rdrt-type;
description "Route Target Export";
}
leaf-list route-target-import {
type rdrt-type;
description "Route Target Export";
}
}
container loopback {
description "Loopback container";
leaf loopback-number {
type uint16;
description "Loopback Interface Number";
}
leaf loopback-ip {
type inet:ipv4-address;
description "Loopback IPv4 Address.";
}
}
}
}
}
__list__を使えばいくつでもインスタンスを作ることができますが、それぞれのインスタンスを区別するためにユニークな値を持たせる必要があります。今回は
leaf policy-name
を定義してそれぞれのインスタンスにポリシー名を設定するようにしました。
add-vpn-service.yangを更新して、make
、packages reload
して、再度設定を投入してみます。
アウトプット
developer@ncs(config)# vpn ?
Possible completions:
vpn-policy
developer@ncs(config)# vpn vpn-policy CORE-RTR01_VRF_C
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# ?
Possible completions:
device
loopback
maintainer-members
vrf
---
commit Commit current set of changes
describe Display transparent command information
exit Exit from current mode
help Provide help information
no Negate a command or set its defaults
pwd Display current mode path
rload Load configuration from an ASCII file or from terminal, relative to current location
top Exit to top level and optionally run command
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# device core-rtr01
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# maintainer-members HIDETADA
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# maintainer-members IEYASU
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# vrf vrf-name C
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# vrf rd 65432:333
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# vrf route-target-export 65432:333
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# vrf route-target-import 65432:333
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# loopback loopback-number 333
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# loopback loopback-ip 3.3.3.1
developer@ncs(config-vpn-policy-CORE-RTR01_VRF_C)# top
developer@ncs(config)# show configuration
vpn vpn-policy CORE-RTR01_VRF_C
device core-rtr01
maintainer-members [ HIDETADA IEYASU ]
vrf vrf-name C
vrf rd 65432:333
vrf route-target-export 65432:333
vrf route-target-import [ 65432:333 ]
loopback loopback-number 333
loopback loopback-ip 3.3.3.1
!
developer@ncs(config)# commit
Commit complete.
developer@ncs(config)#
developer@ncs(config)# vpn vpn-policy CORE-RTR02_VRF_C
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# device core-rtr02
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# maintainer-members HIDETADA
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# maintainer-members IETSUNA
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# maintainer-members TSUNATOSHI
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# vrf vrf-name C
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# vrf rd 65432:333
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# vrf route-target-export 65432:333
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# vrf route-target-import 65432:333
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# loopback loopback-number 333
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# loopback loopback-ip 3.3.3.2
developer@ncs(config-vpn-policy-CORE-RTR02_VRF_C)# top
developer@ncs(config)# show configuration
vpn vpn-policy CORE-RTR02_VRF_C
device core-rtr02
maintainer-members [ IETSUNA TSUNATOSHI HIDETADA ]
vrf vrf-name C
vrf rd 65432:333
vrf route-target-export 65432:333
vrf route-target-import [ 65432:333 ]
loopback loopback-number 333
loopback loopback-ip 3.3.3.2
!
developer@ncs(config)# commit
Commit complete.
developer@ncs(config)#
show running-config vpn
を見てみます。
アウトプット
developer@ncs# show running-config vpn
vpn vpn-policy CORE-RTR01_VRF_C
device core-rtr01
maintainer-members [ HIDETADA IEYASU ]
vrf vrf-name C
vrf rd 65432:333
vrf route-target-export 65432:333
vrf route-target-import [ 65432:333 ]
loopback loopback-number 333
loopback loopback-ip 3.3.3.1
!
vpn vpn-policy CORE-RTR02_VRF_C
device core-rtr02
maintainer-members [ IETSUNA TSUNATOSHI HIDETADA ]
vrf vrf-name C
vrf rd 65432:333
vrf route-target-export 65432:333
vrf route-target-import [ 65432:333 ]
loopback loopback-number 333
loopback loopback-ip 3.3.3.2
!
#まとめ
YANGでサービスパッケージのモデルを作成しNSOのCDBに登録することができました。デバイスへ設定を反映させるためにはXMLテンプレートにYANGで定義したnodeをマッピングしますが、その方法については次回まとめたいと思います。YANGは強力なデータモデリング言語であり、ニーズに合わせて単純なモジュールから複雑なモジュールまで作成できるので、マルチベンダーネットワークにとっては非常に有効な言語であると思います。
#参考リンク