らくがきちょう

なんとなく ~所属組織/団体とは無関係であり、個人の見解です~

Rocky Linux8 へ NSO 5.5 評価版をシステムインストールする

Cisco NSO を使うと自動化を行うことが出来ます。 NSO は商用製品ですが、Cisco DevNet で 90 日間有効な評価版も公開されています。 今回は Rocky Linux8 へ NSO 5.5 評価版をインストールする手順をメモしておきます。 後述しますが、NSO のインストール方法は「ローカルインストール」と「システムインストール」がありますが、このメモではシステムインストールを行います。 NSO のシステムインストール手順は NSO System Install に記載されています。

NSO のインストール方法

NSO には 2 つのインストール方法があります。

  1. ローカルインストール (デフォルト)
    • (サービスとしてでは無く) ローカルアプリケーションとして NSO をインストールする
    • 複数バージョンの NSO を混在させることが出来る
    • サービスでは無い為、基本的には手動で起動する必要がある
  2. システムインストール
    • サービスとして NSO をインストールする
    • 特定バージョンの NSO のみ、インストール可能
    • サービスなので OS の起動と共に、自動的に起動させることが出来る

開発環境であれば複数バージョンを混在させやすいローカルインストールで、本番環境であればサービスとして動作させるシステムインストールで構築するのが好ましいと考えられます。

ディレクトリ構成

Download Your NSO Free Trial Installer and Cisco NEDs から NSO の評価版をダウンロードしておきます。 ダウンロードしたファイルは以下のディレクトリ構成下に配置しました。

# tree ~/tmp/
/root/tmp/
├── ned
│   └── ncs-5.5-cisco-ios-6.69.1.signed.bin
└── nso
    └── nso-5.5.linux.x86_64.signed.bin

2 directories, 2 files

依存パッケージのインストール

NSO のインストール方法は Installation で説明されています。 このドキュメントによると、下記を事前にインストールしておくように記載されています。

これらをインストールします。 JDK のバージョンは Ensure that Java JDK-8.x or 11.x is installed. と書かれていますが、今回は JDK 8 系をインストールしました。

dnf -y install ant java-1.8.0-openjdk libxml2

Python のインストール

Python 2.7.4 以降がインストールされていないと NSOインストーラでエラーが発生します。

# sh nso-5.5.linux.x86_64.signed.bin
Unpacking...
Verifying signature...
nso-5.5.linux.x86_64.signed.bin: line 81: python: command not found
nso-5.5.linux.x86_64.signed.bin: line 90: python: command not found
ERROR
ERROR Failed to perform signature verification.
ERROR Verification requires Python version 2.7.4 or later.
ERROR

ですので予め Python をインストールしておきます。

dnf install -y python39

今回はバージョン 3.9.6 がインストールされました。

# python3 --version
Python 3.9.6

(python39 では無く) pythonPython を実行出来るように alternatives を実行しておきます。

alternatives --set python /usr/bin/python3.9

NSO のインストール

NSO のバイナリを実行すると展開出来ます。 バイナリを展開する際、ネットワークへ通信をしてパッケージの妥当性を検証します。 ネットワークに接続されていないオフライン環境で実行するには --skip-verification オプションを指定します。

# cd ~/tmp/nso/
# sh nso-5.5.linux.x86_64.signed.bin
Unpacking...
Verifying signature...
Retrieving CA certificate from http://www.cisco.com/security/pki/certs/crcam2.cer ...
Successfully retrieved and verified crcam2.cer.
Retrieving SubCA certificate from http://www.cisco.com/security/pki/certs/innerspace.cer ...
Successfully retrieved and verified innerspace.cer.
Successfully verified root, subca and end-entity certificate chain.
Successfully fetched a public key from tailf.cer.
Successfully verified the signature of nso-5.5.linux.x86_64.installer.bin using tailf.cer

展開が終わったらインストールします。 --system-install を指定することでシステムインストールすることが可能です。 このオプションを省略するか、または明示的に --local-install を指定するとローカルインストールすることが出来ます。

sh nso-5.5.linux.x86_64.installer.bin --system-install

以下はシステムインストール例です。

# sh nso-5.5.linux.x86_64.installer.bin --system-install
INFO  Using temporary directory /tmp/ncs_installer.2011 to stage NCS installation bundle
INFO  Using /opt/ncs/ncs-5.5 for static files
INFO  Using /etc/ncs for configuration files
INFO  Using /var/opt/ncs for run-time state files
INFO  Using /var/log/ncs for log files
INFO  Unpacked ncs-5.5 in /opt/ncs/ncs-5.5
INFO  Found and unpacked corresponding DOCUMENTATION_PACKAGE
INFO  Found and unpacked corresponding EXAMPLE_PACKAGE
INFO  Found and unpacked corresponding JAVA_PACKAGE
INFO  Generating default SSH hostkey (this may take some time)
INFO  SSH hostkey generated
INFO  Environment set-up generated in /opt/ncs/ncs-5.5/ncsrc
INFO  NSO installation script finished
INFO  Found and unpacked corresponding NETSIM_PACKAGE
INFO  Generating keys for encrypted-strings
INFO  Configuring installation for PAM authentication
INFO  Using PAM service system-auth for authentication
INFO  Generating self-signed certificates for HTTPS
INFO  Installed init script /etc/init.d/ncs
INFO  Installed user profile script ncs.sh in /etc/profile.d
INFO  Installed user profile script ncs.csh in /etc/profile.d
INFO  Installed 'logrotate' configuration file ncs in /etc/logrotate.d

INFO  The installation has been configured for PAM authentication,
INFO  with group assignment based on the OS group database
INFO  (e.g. /etc/group file). Users that need access to NCS must
INFO  belong to either the 'ncsadmin' group (for unlimited access
INFO  rights) or the 'ncsoper' group (for minimal access rights).
INFO  To create the 'ncsadmin' group, use OS shell command:

  groupadd ncsadmin

INFO  To create the 'ncsoper' group, use OS shell command:

  groupadd ncsoper

INFO  To add an existing user to one of these groups, use OS shell command:

  usermod -a -G <groupname> <username>

INFO  NCS installation complete

NED のインストール

Package Overview にはシステムインストール時のパッケージ配置について下記の記載があります。

In a "system install" of NSO, packages are always installed (normally by means of symbolic links) in the packages subdirectory of the "run directory", i.e. by default /var/opt/ncs/packages, and the private directory tree is created in the state subdirectory, i.e. by default /var/opt/ncs/state.

NED のインストールも基本的な進め方は NSO と同様です。 NSO 同様、オフライン環境で展開するには --skip-verification オプションを指定します。

# cd ~/tmp/ned/
# sh ncs-5.5-cisco-ios-6.69.1.signed.bin
# cp ncs-5.5-cisco-ios-6.69.1.tar.gz /var/opt/ncs/packages/

設定ファイルの修正

NSO の設定ファイルは /etc/ncs/ncs.conf です。 デフォルトでは WebUI 自体は有効に設定されているのですが、実際の利用ポートが無効になっており、結局 WebUI を利用することが出来ません。 そこで ncs.conf の 288 行目以降の enabled 設定を falsetrue へ変更します。

変更前

  <webui>
    <enabled>true</enabled>
    <transport>
      <tcp>
        <enabled>false</enabled>
        <ip>0.0.0.0</ip>
        <port>8080</port>
      </tcp>
      <ssl>
        <enabled>false</enabled>
        <ip>0.0.0.0</ip>
        <port>8888</port>
        <key-file>${NCS_CONFIG_DIR}/ssl/cert/host.key</key-file>
        <cert-file>${NCS_CONFIG_DIR}/ssl/cert/host.cert</cert-file>
      </ssl>
    </transport>

変更後

  <webui>
    <enabled>true</enabled>
    <transport>
      <tcp>
        <enabled>true</enabled>
        <ip>0.0.0.0</ip>
        <port>8080</port>
      </tcp>
      <ssl>
        <enabled>true</enabled>
        <ip>0.0.0.0</ip>
        <port>8888</port>
        <key-file>${NCS_CONFIG_DIR}/ssl/cert/host.key</key-file>
        <cert-file>${NCS_CONFIG_DIR}/ssl/cert/host.cert</cert-file>
      </ssl>
    </transport>

ユーザとグループの作成

ローカルインストールした場合は admin ユーザが作成されますが、システムインストールした場合は PAM での認証設定が行われているようです。 NSO インストール時のログにも表示されるのですが、Linux ユーザを ncsadmin グループ、または ncsoper へ追加することで、これらのユーザが NSO を利用出来るようになるようです。 今回は以下の 2 ユーザを定義しました。

ユーザ名 パスワード 所属グループ
ncsadmin ncsadmin ncsadmin
ncsoper ncsoper ncsoper

ncsadmin ユーザの追加手順は以下です。

groupadd ncsadmin
useradd -g ncsadmin ncsadmin
echo ncsadmin | passwd --stdin ncsadmin

ncsoper ユーザの追加手順は以下です。

groupadd ncsoper
useradd -g ncsoper ncsoper
echo ncsoper | passwd --stdin ncsoper

OOM Killer の無効化

Installation の Note には下記の記載があります。

If the Linux kernel allows overcommit of memory (this is the default), it introduces an unexpected and unreliable environment for NSO, since the “OOM killer” may terminate NSO in such a way that it is not restarted. Thus it is strongly recommended that overcommit is disabled.

上記の記載に従ってメモリのオーバーコミットを無効化しておきます。

echo "vm.overcommit_memory = 2" >> /etc/sysctl.conf

設定を反映する為に OS を再起動します。

reboot

オーバーコミットの設定値は /proc/sys/vm/overcommit_memory で確認することが出来ます。 値は以下の意味を持ちます。

オーバーコミットの有効/無効 意味
0 有効 実メモリサイズまで割り当てる
1 有効 実メモリサイズ以上に割り当てる
2 無効 オーバーコミットを行わない
# cat /proc/sys/vm/overcommit_memory
2

NSO サービスの開始

ここまでの手順が完了したら、いよいよ NSO サービスを開始します。

systemctl start ncs
systemctl enable ncs

WebUI へのログイン

ここまでの手順が正しく設定されていれば以下、いずれかの URL から NSO の WebUI へアクセス出来るはずです。

  • http://ADDRESS:8080
  • https://ADDRESS:8888

f:id:sig9:20211204224518p:plain

ここでは先の手順で設定したユーザ ncsadmin (パスワードも ncsadmin) でログインしてみます。 正しくログイン出来れば以下のような画面が表示されるはずです。

f:id:sig9:20211204224521p:plain

参考

/opt/ncs/current/packages/neds/ の内容

# tree -L 1 /opt/ncs/current/packages/neds/
/opt/ncs/current/packages/neds/
├── a10-acos-cli-3.0
├── alu-sr-cli-3.4
├── cisco-asa-cli-6.6
├── cisco-ios-cli-3.0
├── cisco-ios-cli-3.8
├── cisco-iosxr-cli-3.0
├── cisco-iosxr-cli-3.5
├── cisco-nx-cli-3.0
├── dell-ftos-cli-3.0
└── juniper-junos-nc-3.0

10 directories, 0 files

ncs_cli のヘルプ

# ncs_cli --help
Usage: ncs_cli [options] [file]
Options:
  --help, -h            display this help
  --host, -H <host>     current host name (used in prompt)
  --address, -A <addr>  cli address to connect to
  --port, -P <port>     cli port to connect to
  --cwd,  -c <dir>      current working directory
  --proto, -p <proto>   type of connection (tcp, ssh, console)
  --verbose, -v         verbose output
  --ip, -i              clients source ip[/port]
  --interactive, -n     force interactive mode
  --escape-char, -E <C> brute force shutdown when user enters ASCII C
  -J                    Juniper style CLI
  -C                    Cisco XR style CLI
  --user, -u <user>     clients user name
  --uid, -U <uid>       clients user id
  --groups, -g <groups> clients group list
  --gids, -D <gids>     clients group id list
  --gid, -G <gid>       clients group id
  --noaaa               disable AAA
  --opaque, -O <opaque> pass opaque info
  --stop-on-error, -s   stop on error

/etc/rc.d/init.d/ncs

#!/bin/bash
#
# Redhat Startup script for NCS
#
# chkconfig: 2345 95 05
# description: NCS - Network Control System
#
### BEGIN INIT INFO
# Provides:          ncs
# Required-Start:    $local_fs $network $syslog
# Required-Stop:
# X-Start-Before:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: NCS
# Description: NCS - Network Control System
### END INIT INFO

ncsdir=/opt/ncs/current
confdir=/etc/ncs
rundir=/var/opt/ncs
logdir=/var/log/ncs

ncs=${ncsdir}/bin/ncs
prog=ncs
conf="-c ${confdir}/ncs.conf"
heart="--heart"

# When systemd is used, the sourcing of /etc/rc.d/init.d/functions
# below will actually use systemctl to tell systemd to do the
# start/stop/etc when the script is invoked by a user, and only
# when systemd in turn invokes the script will it actually do the
# requested action. Thus we must pass info about package reload
# from the first to the second invocation, via a "flag file".

package_reload_file="$rundir/state/do_package_reload"
package_reload_file_force="$rundir/state/do_package_reload_force"

case "$1" in
    *start*)
        if [ "x$NCS_RELOAD_PACKAGES" = "xtrue" ]; then
            touch $package_reload_file
        elif [ "x$NCS_RELOAD_PACKAGES" = "xforce" ]; then
            touch $package_reload_file_force
        fi
        ;;
esac

. /etc/rc.d/init.d/functions

case "$1" in
    *start*)
        if [ -f $package_reload_file ]; then
            rm -f $package_reload_file
            export NCS_RELOAD_PACKAGES=true
        elif [ -f $package_reload_file_force ]; then
            rm -f $package_reload_file_force
            export NCS_RELOAD_PACKAGES=force
        fi
        ;;
esac

start() {
        echo -n $"Starting $prog: "
        . $ncsdir/ncsrc
        NCS_CONFIG_DIR=${confdir}
        NCS_RUN_DIR=${rundir}
        NCS_LOG_DIR=${logdir}
        export NCS_CONFIG_DIR NCS_RUN_DIR NCS_LOG_DIR
        $ncs --cd ${rundir}  ${heart} ${conf}
        RETVAL=$?
        echo
        # [ $RETVAL = 0 ] && touch /var/lock/subsys/ncs
        return $RETVAL
}

stop() {
        echo -n $"Stopping $prog: "
        $ncs --stop
        if [ "$?" = 0 ]; then
            echo_success
            RETVAL=0
        else
            echo_failure
            RETVAL=1
        fi
        echo
        rm -f /var/lock/subsys/ncs
        return $RETVAL
}


reload() {
        echo -n $"Reloading $prog: "
        r=`$ncs --reload`
        RETVAL=$?
        echo $r
}

usage() {
    cat <<EOF
"Usage: $prog {start | stop | restart | reload | status |
               start-with-package-reload |
               restart-with-package-reload |
               start-with-package-reload-force |
               restart-with-package-reload-force |
               help}"

 start
     Start the NCS daemon via systemctl.

 stop
     Stop the NCS daemon via systemctl.

 restart
     Restart the running NCS service via systemctl.

 reload
     Reload the NCS configuration via systemctl.

 status
     Print status about the NCS daemon.

 start-with-package-reload
     Start the NCS daemon via systemctl and reload all packages.

 restart-with-package-reload
     Restart the running NCS daemon via systemctl and reload all packages.

 start-with-package-reload-force
     Start the NCS daemon via systemctl and reload all packages
     in an unsage manner and override warnings if any.

 restart-with-package-reload-force
     Restart the running NCS daemon via systemctl and reload all packages
     in an unsage manner and override warnings if any.

EOF
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        start
        ;;
  reload)
        reload
        ;;
  status)
        $ncs --status
        RETVAL=$?
        ;;
  start-with-package-reload)
        # Start NCS and attempt an NCS package code reload
        # This will not be redirected to systemd by default, need
        # to make it happen or systemd will be confused
        NCS_RELOAD_PACKAGES=true exec $0 start
        ;;
  restart-with-package-reload)
        # Restart NCS and attempt an NCS package code reload
        # This will not be redirected to systemd by default, need
        # to make it happen or systemd will be confused
        NCS_RELOAD_PACKAGES=true exec $0 restart
        ;;
  start-with-package-reload-force)
        # Start NCS and reload all packages in an unsafe manner
        # and override warnings if any.
        # This will not be redirected to systemd by default, need
        # to make it happen or systemd will be confused
        NCS_RELOAD_PACKAGES=force exec $0 start
        ;;
  restart-with-package-reload-force)
        # Start NCS and reload all packages in an unsafe manner
        # and override warnings if any.
        # This will not be redirected to systemd by default, need
        # to make it happen or systemd will be confused
        NCS_RELOAD_PACKAGES=force exec $0 restart
        ;;

  help)
        $ncs --help
        ;;
  *)
        usage
        exit 1
esac

exit $RETVAL