CCIE lab対策(6.2. Network Automation)その3

前回は登録したデバイスに対して、通常のCLI操作と同じことをNSOから操作する検証をしました。今回は、サービス作成とサービスデプロイの検証をします。

1. サービス自動化の流れ

NSOにはテンプレートベースでサービスを作成し、そのサービスを実行することで自動化を実現することができます。 以下のリンク先に関連する内容があります。 community.cisco.com


かいつまんでまとめると、NSOでサービスを自動化する流れは以下のようになります。
f:id:chimay_wh:20220325201101p:plain
例として作成するサービスはデバイス(IOS-XR:N1)にloopbackインターフェースを作成する内容です。

2. サービススケルトン作成

NSOをインストールしたOS(Linux:Ubuntu)で、"ncs-make-package"コマンドを実行します。
大事なことは、カレントディレクトリに一連のディレクトリ・ファイルが生成されるということです。ここでは例として、OS(Linux:Ubuntu)の/root/WORKにLOOPBACKというサービス名で作成します。

ncs-make-package --service-skeleton template 【サービス名】
root@chas4:~/WORK# ncs-make-package --service-skeleton template LOOPBACK
root@chas4:~/WORK#

② カレントディレクトリに一連のディレクトリ・ファイル(以後、サービスパッケージ若しくはパッケージと省略します。)が生成されます。
以降は生成されたパッケージを編集していきます。ディレクトリ階層は以下のようになっております。パッケージ開発で編集する対象は赤枠内にある2つのファイルのみです。
f:id:chimay_wh:20220326102715p:plain

3. サービスパッケージ開発

3.1 サービステンプレート

サービスパッケージの開発ではサービステンプレートの作成とサービスモデルの作成を行います。サービステンプレートを作成するにあたり、NSOのconfig modeでサンプルコンフィグを作成します。

① デバイス(IOS-XR:N1)でloopbackインターフェースを作成します。 ただしcommitはしません。

admin@ncs# config
Entering configuration mode terminal
admin@ncs(config)# devices device N1 config
admin@ncs(config-config)# interface Loopback 1
admin@ncs(config-if)# ipv4 address 10.0.0.1 255.255.255.255
admin@ncs(config-if)#

② 仮にcommitした場合のconfigをXML形式で表示します。

commit dry-run outformat xml
admin@ncs(config-if)# commit dry-run outformat xml
result-xml {
    local-node {
        data <devices xmlns="http://tail-f.com/ns/ncs">
               <device>
                 <name>N1</name>
                 <config>
                   <interface xmlns="http://tail-f.com/ned/cisco-ios-xr">
                     <Loopback>
                       <id>1</id>
                       <ipv4>
                         <address>
                           <ip>10.0.0.1</ip>
                           <mask>255.255.255.255</mask>
                         </address>
                       </ipv4>
                     </Loopback>
                   </interface>
                 </config>
               </device>
             </devices>
    }
}
admin@ncs(config-if)#

今回作成するサービスは、loopbackインターフェースを作成するものです。具体的に言うと...
Interface Loopback100-199 この範囲で100種類作れるようにします。
かつIPアドレスは、10.100.x.x/32~10.199.x.x/32 に設定するというものです。

③ 出力したXMLファイルを見ると変動する値と固定の値の2種類があります。
f:id:chimay_wh:20220326095023p:plain
この赤と青を変数扱いにすれば、テンプレートとして使えることが何となく想像できると思います。変数はサービス利用時に利用者が指定することを想定しています。

④ サービステンプレートを作成します。サービステンプレートは、OS(Linux:Ubuntu)で編集します。以下は、変更前のサービステンプレート(LOOPBACK-template.xml)です。

<config-template xmlns="http://tail-f.com/ns/config/1.0"
                 servicepoint="LOOPBACK">
  <devices xmlns="http://tail-f.com/ns/ncs">
    <device>
      <!--
          Select the devices from some data structure in the service
          model. In this skeleton the devices are specified in a leaf-list.
          Select all devices in that leaf-list:
      -->
      <name>{/device}</name>
      <config>
        <!--
            Add device-specific parameters here.
            In this skeleton the service has a leaf "dummy"; use that
            to set something on the device e.g.:
            <ip-address-on-device>{/dummy}</ip-address-on-device>
        -->
      </config>
    </device>
  </devices>
</config-template>

英語のコメント通りです。" Add device-specific parameters here."の箇所を編集します。編集内容は、③の太字部分をコピー&ペーストして、変数を特定の文字列に置き換えます。
変数(1)ループバックインターフェース名:LOOPBACK-INTF
変数(2)IPアドレス:IP-ADDRESS
f:id:chimay_wh:20220325203123p:plain

参考までに完成したサービステンプレートを以下に示します。

<config-template xmlns="http://tail-f.com/ns/config/1.0"
                 servicepoint="LOOPBACK">
  <devices xmlns="http://tail-f.com/ns/ncs">
    <device>
      <!--
          Select the devices from some data structure in the service
          model. In this skeleton the devices are specified in a leaf-list.
          Select all devices in that leaf-list:
      -->
      <name>{/device}</name>
    <config>
        <interface xmlns="http://tail-f.com/ned/cisco-ios-xr">
         <Loopback>
          <id>{LOOPBACK-INTF}</id>
           <ipv4>
            <address>
             <ip>{IP-ADDRESS}</ip>
            <mask>255.255.255.255</mask>
           </address>
          </ipv4>
         </Loopback>
        </interface>
       </config>
    </device>
  </devices>
</config-template>

3.2 サービスモデル

① サービスモデルを作成します。サービスモデルも、OS(Linux:Ubuntu)で編集します。
以下は、変更前のサービスモデル(LOOPBACK.yang)です。

module LOOPBACK {
  namespace "http://com/example/LOOPBACK";
  prefix LOOPBACK;

  import ietf-inet-types {
    prefix inet;
  }
  import tailf-ncs {
    prefix ncs;
  }

  list LOOPBACK {
    key name;

    uses ncs:service-data;
    ncs:servicepoint "LOOPBACK";

    leaf name {
      type string;
    }

    // may replace this with other ways of refering to the devices.
    leaf-list device {
      type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
      }
    }

    // replace with your own stuff here
    leaf dummy {
      type inet:ipv4-address;
    }
  }
}

② 今回の編集ポイントは大きく6つあります。
a) インポートするモジュールの名前をimportステートメントで、インポートする名前とprefixを宣言します。

import tailf-common { prefix tailf; }

b) augmentステートメントで、サービスを宣言します。

augment /ncs:services {

c) 定義が分からなくならないようにコメントを挿入します。

tailf:info “【コメント文】”;
    leaf name {
      tailf:info “Service Instance Name”;
      type string;
    }

d) デバイスleaf-listではなくleafに変更します。かつサービス利用時に入力必須項目1にします。

    leaf-list device {
      tailf:info “Router Name”;
      mandatory true;
      type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
      }
    }

e) 変数(1)ループバックインターフェース名:LOOPBACK-INTF を記述します。
typeは符号なし整数を指定します。かつサービス利用時に入力必須項目にします。

    leaf LOOPBACK-INTF {
      tailf:info “Loopback Interface Number from 100 to 199”;
      mandatory true;
      type uint32{
       range “100..199”;
      }
    }

f) 変数(2)IPアドレス:IP-ADDRESS を記述します。
かつサービス利用時に入力必須項目にします。ここで敢えて間違えた記述(pattern)をします。後でコンパイルエラーを修正したいからという理由です。

    leaf IP-ADDRESS{
      tailf:info "Valid IP range from 10.100.x.x to 10.199.x.x";
      mandatory true;      
      type inet:ipve-address{
       pattern “10\.1[0-9][0-9]\.[0-9]+\.[0-9]+”;
      }
    }

4. パッケージのコンパイル

Makefile が配置されている”LOOPBACK/src”ディレクトリに移動して、makeコマンドを実行してサービスコードをコンパイルします。

cd ~/WORK/LOOPBACK/src
make
/nso-5.7//bin/ncsc `ls LOOPBACK-ann.yang  > /dev/null 2>&1 && echo "-a LOOPBACK-ann.yang"` \
        --fail-on-warnings \
         \
        -c -o ../load-dir/LOOPBACK.fxs yang/LOOPBACK.yang
yang/LOOPBACK.yang:37:19: error: illegal character after \
yang/LOOPBACK.yang:37:32: error: illegal character after \
yang/LOOPBACK.yang:37:40: error: illegal character after \
Makefile:26: recipe for target '../load-dir/LOOPBACK.fxs' failed
make: *** [../load-dir/LOOPBACK.fxs] Error 1
root@chas4:~/WORK/LOOPBACK/src#

コンパイルしてエラーがある場合は、XX行目にエラーがあると通知してくれます。タイポだったり構文エラーだったり理由は様々です。
f:id:chimay_wh:20220325204436p:plain

② YANGファイルで間違えた記述を修正します。"."までを一つの区切りとするように()で括り、全体をシングルクォーテーションで囲みました。

    leaf IP-ADDRESS{
      tailf:info "Valid IP range from 10.100.x.x to 10.199.x.x";
      type inet:ipve-address{
       pattern '(10\.)(1[0-9][0-9]\.)([0-9]+\.)([0-9]+)';
      }
    }

f:id:chimay_wh:20220326093214p:plain

③ 再度コンパイルします。

cd ~/WORK/LOOPBACK/src
make
root@chas4:~/WORK/LOOPBACK/src/yang# cd ../
root@chas4:~/WORK/LOOPBACK/src# make
/nso-5.7//bin/ncsc `ls LOOPBACK-ann.yang  > /dev/null 2>&1 && echo "-a LOOPBACK-ann.yang"` \
        --fail-on-warnings \
         \
        -c -o ../load-dir/LOOPBACK.fxs yang/LOOPBACK.yang
root@chas4:~/WORK/LOOPBACK/src#

このようにエラーが無くなればOKです!

④ 作成したパッケージ格納ディレクトリへのシンボリックリンクを、NSOのランタイムディレクト2のpackagesディレクトリ配下に作成します。

ln -s 【パッケージ格納ディレクトリ】【NSOランタイムディレクトリ】/packages
root@chas4:~/WORK/LOOPBACK/src# ln -s ~/WORK/LOOPBACK/ /nso-5.7/ncsrun/packages/
root@chas4:~/WORK/LOOPBACK/src# ls -l /nso-5.7/ncsrun/packages/
total 117548
lrwxrwxrwx 1 root root       20 Mar 25 09:28 LOOPBACK -> /root/WORK/LOOPBACK/
-rw-r--r-- 1 root root  6899909 Jan 12 02:56 ncs-5.7-cisco-asa-6.13.12.tar.gz
-rw-r--r-- 1 root root 61131311 Jan 22 08:48 ncs-5.7-cisco-ios-6.77.10.tar.gz
-rw-r--r-- 1 root root 42440773 Jan 21 19:09 ncs-5.7-cisco-iosxr-7.38.3.tar.gz
-rw-r--r-- 1 root root  9891157 Jan 12 12:44 ncs-5.7-cisco-nx-5.22.8.tar.gz
root@chas4:~/WORK/LOOPBACK/src#

参考までにシンボリックリンクを削除する場合は、unlinkコマンドを使います。

unlink 【シンボリックリンクのパス】
root@chas4:~/WORK/LOOPBACK/src# unlink /nso-5.7/ncsrun/packages/LOOPBACK
root@chas4:~/WORK/LOOPBACK/src#
root@chas4:~/WORK/LOOPBACK/src# ls -l /nso-5.7/ncsrun/packages/
total 117548
-rw-r--r-- 1 root root  6899909 Jan 12 02:56 ncs-5.7-cisco-asa-6.13.12.tar.gz
-rw-r--r-- 1 root root 61131311 Jan 22 08:48 ncs-5.7-cisco-ios-6.77.10.tar.gz
-rw-r--r-- 1 root root 42440773 Jan 21 19:09 ncs-5.7-cisco-iosxr-7.38.3.tar.gz
-rw-r--r-- 1 root root  9891157 Jan 12 12:44 ncs-5.7-cisco-nx-5.22.8.tar.gz
root@chas4:~/WORK/LOOPBACK/src#

重要なのはコンパイルに成功してからシンボリックリンクを作成することです。

参考までに完成したサービスモデルを以下に示します。

module LOOPBACK {
  namespace "http://com/example/LOOPBACK";
  prefix LOOPBACK;

  import ietf-inet-types { prefix inet; }
  import tailf-ncs { prefix ncs; }
  import tailf-common { prefix tailf; }
  
  augment /ncs:services {
  list LOOPBACK {
    key name;

    uses ncs:service-data;
    ncs:servicepoint "LOOPBACK";

    leaf name {
    tailf:info “Service Instance Name”;
      type string;
    }

    leaf device {
      tailf:info “Router Name”;
      mandatory true;
      type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
      }
    }

    leaf LOOPBACK-INTF {
      tailf:info “Loopback Interface Number from 100 to 199”;
      mandatory true;
      type uint32 {
       range “100..199”;
      }
    }

    leaf IP-ADDRESS {
      tailf:info "Valid IP range from 10.100.x.x to 10.199.x.x";
      mandatory true;
      type inet:ipve-address {
       pattern '(10\.)(1[0-9][0-9]\.)([0-9]+\.)([0-9]+)';
      }
    }
   }
  }
}

5. パッケージをNSOにロード

① パッケージのロードはNSO CLIで行います。

ncs_cli -u admin -C
root@chas4:~/WORK/LOOPBACK/src# ncs_cli -u admin -C

User admin last logged in 2022-03-25T08:09:39.475876+00:00, to chas4, from 127.0.0.1 using cli-console
admin connected from 127.0.0.1 using console on chas4
admin@ncs#

② パッケージをロードします。少し時間がかかります。"result true"と表示すれば成功です!

packages reload
admin@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 LOOPBACK
    result true
}
reload-result {
    package cisco-asa-cli-6.13
    result true
}
reload-result {
    package cisco-ios-cli-6.77
    result true
}
reload-result {
    package cisco-iosxr-cli-7.38
    result true
}
reload-result {
    package cisco-nx-cli-5.22
    result true
}
admin@ncs# 
System message at 2022-03-17 02:54:36...
    Subsystem stopped: ncs-dp-8-cisco-ios-cli-6.77:IOSDp
admin@ncs# 
System message at 2022-03-17 02:54:36...
    Subsystem stopped: ncs-dp-9-cisco-nx-cli-5.22:NexusDp
admin@ncs# 
System message at 2022-03-17 02:54:36...
    Subsystem stopped: ncs-dp-7-cisco-asa-cli-6.13:ASADp
admin@ncs# 
System message at 2022-03-17 02:54:36...
    Subsystem started: ncs-dp-10-cisco-asa-cli-6.13:ASADp
admin@ncs# 
System message at 2022-03-17 02:54:36...
    Subsystem started: ncs-dp-11-cisco-ios-cli-6.77:IOSDp
admin@ncs# 
System message at 2022-03-17 02:54:36...
    Subsystem started: ncs-dp-12-cisco-nx-cli-5.22:NexusDp
admin@ncs# 

いよいよ、サービスの実行です。

6. NSOでサービス実行

今回作成するサービスは、loopbackインターフェースを作成するものです。具体的に言うと...
Interface Loopback100-199 この範囲で100種類作れるようにします。
かつIPアドレスは、10.100.x.x/32~10.199.x.x/32 に設定するというものです。

① sync-fromを実行し、NSOのCDBを最新化します。"result true"と表示すれば成功です!
sync-fromを実行せずにサービスを実行すると途中でエラーを表示してしまいます。

devices sync-from device 【デバイス名】
admin@ncs# devices sync-from device N1
sync-result {
    device N1
    result true
}
admin@ncs#

② サービスの実行は、config modeで行います。

config
admin@ncs# config
Entering configuration mode terminal
admin@ncs(config)#

③ サービスを実行します。サービス名は"LOOPBACK"です。識別文字列は数字だけでも良いです。

services 【サービス名】【識別文字列】
admin@ncs(config)# services LOOPBACK TEST_OF_LOOPBACK100

④ サービスを実行するデバイスの入力が求められます。今回は登録している”N1”を入力します。

N1
Value for 'device' [N1]: N1

入力候補が複数ある場合は、その旨表示されます。利用者に優しいです。

e.g.
 Value for 'device' [N1,N2,N3,N4,...]:

⑤ ループバックインターフェース名を入力します。今回は、”100”を入力します。

100
Value for 'LOOPBACK-INTF' (<unsignedInt, 100 .. 199>): 100

サービステンプレート、サービスモデルで指定した"LOOPBACK-INTF"と範囲を表示します。

⑥ ループバックインターフェースのIPアドレスを入力します。今回は、”10.100.1.100”を入力します。

10.100.1.100
Value for 'IP-ADDRESS' (<IPv4 address>): 10.100.1.100
admin@ncs(config-LOOPBACK-TEST_OF_LOOPBACK100)#

⑦ commitするとどうなるのかを確認します。

commit dry-run
admin@ncs(config-LOOPBACK-TEST_OF_LOOPBACK100)# commit dry-run
cli {
    local-node {
        data  devices {
                  device N1 {
                      config {
                          interface {
             +                Loopback 100 {
             +                    ipv4 {
             +                        address {
             +                            ip 10.100.1.100;
             +                            mask 255.255.255.255;
             +                        }
             +                    }
             +                }
                          }
                      }
                  }
              }
              services {
             +    LOOPBACK TEST_OF_LOOPBACK100 {
             +        device N1;
             +        LOOPBACK-INTF 100;
             +        IP-ADDRESS 10.100.1.100;
             +    }
              }
    }
}
admin@ncs(config-LOOPBACK-TEST_OF_LOOPBACK100)#

⑧ 定義に問題がないことを確認したら、commitします。もしこの時点で入力し直したい場合は、サービスを強制終了します。

abort
admin@ncs(config-LOOPBACK-TEST_OF_LOOPBACK100)# abort
admin@ncs#

サービスを強制終了したら、②からやり直します。

⑨ 仮に⑦で問題ないことを確認したとしてcommitします。

commit
admin@ncs(config-LOOPBACK-TEST_OF_LOOPBACK100)# commit
Commit complete.
admin@ncs(config-LOOPBACK-TEST_OF_LOOPBACK100)#

⑩ デバイスのshowコマンドでループバックの定義状況を確認します。

do devices device N1 live-status exec show ip int lo100
admin@ncs(config)# do devices device N1 live-status exec show ip int lo100
result
Fri Mar 25 10:19:54.453 UTC
Loopback100 is Up, ipv4 protocol is Up
  Vrf is default (vrfid 0x60000000)
  Internet address is 10.100.1.100/32
  MTU is 1500 (1500 is available to IP)
  Helper address is not set
  Directed broadcast forwarding is disabled
  Outgoing access list is not set
  Inbound  common access list is not set, access list is not set
  Proxy ARP is disabled
  ICMP redirects are never sent
  ICMP unreachables are always sent
  ICMP mask replies are never sent
  Table Id is 0xe0000000
RP/0/RP0/CPU0:N1#
admin@ncs(config)#

これで、オペレータが”デバイス”と”インターフェース名”と”IPアドレス”を入力するだけでループバックインターフェースの設定をすることができました。

参考までに②~⑥で誤った入力をするとどうなるかを紹介します。
サービス実行対象を間違えた場合

admin@ncs(config)# services LOOPBACK 101
Value for 'device' [N1]: N2
The value must be one of:
  N1

"N1"だけが入力できる旨が通知されます。デバイス名を正しく入力して、インターフェース名を間違えた場合

Value for 'device' [N1]: N1
Value for 'LOOPBACK-INTF' (<unsignedInt, 100 .. 199>): 200
Error: bad value: "200" is out of range.

200は間違いである旨が通知されます。インターフェース名を正しく入力して、IPアドレスを間違えた場合

Value for 'LOOPBACK-INTF' (<unsignedInt, 100 .. 199>): 101
Value for 'IP-ADDRESS' (<IPv4 address>): 1.1.1.1
Error: bad value: "1.1.1.1" is an invalid value.

1.1.1.1は間違いである旨が通知されます。IPアドレスを正しく入力して、定義の内容を確認します。

Value for 'IP-ADDRESS' (<IPv4 address>): 10.101.101.101
admin@ncs(config-LOOPBACK-101)# commit dry-run
cli {
    local-node {
        data  devices {
                  device N1 {
                      config {
                          interface {
             +                Loopback 101 {
             +                    ipv4 {
             +                        address {
             +                            ip 10.101.101.101;
             +                            mask 255.255.255.255;
             +                        }
             +                    }
             +                }
                          }
                      }
                  }
              }
              services {
             +    LOOPBACK 101 {
             +        device N1;
             +        LOOPBACK-INTF 101;
             +        IP-ADDRESS 10.101.101.101;
             +    }
              }
    }
}
admin@ncs(config-LOOPBACK-101)#

仮にオペレータが間違えた入力をしてもコマンドが受け付けられないようになっています。フールプルーフ3が備わっているのは素敵です。

次回はデバイス(IOS-XR)にSegment Routingを自動設定するサービスの作成とデプロイの検証をします。

最後までお読みいただきありがとうございました!


  1. 入力必須項目にするには、”mandatory true;”と記述します。

  2. NSOインストールディレクトリの直下のプロジェクトディレクトリのことをランタイムディレクトリと言います。CCIE lab対策(6.2. Network Automation)その1では、/nso-5.7/ncsrunのことを指しています。

  3. 人間がミスをしようとしてもできないようにする工夫のことをフールプルーフと言います。