Cisco覚書_Pythonでconfig投入

###Cisco機器上のPythonプロンプトからconfig投入

IOS-XEのファームは`16.XX～17.XX`と`3.X.X`の2種類あり、guestshellやpythonの機能が使えるのは`16.XX～17.XX`のみ。
JUNIPERもCISCOもPythonが標準具備になってきていているらしい。
EEM(event)をトリガーにスクリプトを自動実行させるようなprogramableなネットワークの実装が可能。
Junosでは昔からshellモードがあり運用者が間違えて入ると危険という意味でユーザ権限無効にしていた。
CiscoのTCLも障害対応のワークアラウンドで埋め込んだことはあるが運用側でメンテはハードルが高い。
大人気のPython、NW運用でも活用できるかな。。。とにかく簡単で安全じゃないと使ってもらえないから、、まずは試してみる。

#####豆知識
IOS-XE搭載のCatalyst3850/3650では
`16.XX`のファームウェアのコードネームは、頭文字のアルファベット順で山の名前が付けられている。
16.2 – 16.3  は Denali
16.6 – 16.7 は Everest
16.8 – 16.9 は Fuji
16.10 – 16.12 は Gibraltar

Catalyst9000シリーズでは17.XXでFujiの後は頭文字AのAmsterdamがリリース（次は何の名シリーズ、、、？）
Cisco IOS XE Amsterdam 17.2.x 30/Mar/2020



####準備

#####バージョン確認
16.6.5  Everestで対応OK

```cosco:cisco
iso-sw#show version
---snip---
Switch Ports Model              SW Version        SW Image              Mode
------ ----- -----              ----------        ----------            ----
*    1 56    WS-C3850-48T       16.6.5            CAT3K_CAA-UNIVERSALK9 INSTALL
```
#####guestshellとPython初期設定
**iox**を有効にする
CiscoIOS上でLinuxのオープンソース ツールを使ってCisco機器上でアプリ開発を可能にするような機能らしい。

```cisco:cisco

isp-sw(config)#iox
```
**ip http server** を有効にする

```cisco:cisco
isp-sw(config)#ip http server
```


#####初期設定確認
RunningになっていればOK

```cisco:cisco
isp-sw#show iox-service
IOx Infrastructure Summary:
---------------------------
IOx service (CAF)    : Running
IOx service (HA)     : Running
IOx service (IOxman) : Running
Libvirtd             : Running

isp-sw#show app-hosting list
App id                           State
------------------------------------------------------
guestshell                       RUNNING
```

#####特権モードからguestshellに移動
bashプロンプトになる
userはguestshell

```shell:cisco→shell
isp-sw#guestshell
[guestshell@guestshell ~]$ echo $SHELL
/bin/bash
[guestshell@guestshell ~]$ whoami
guestshell
[guestshell@guestshell ~]$ uname -a
Linux guestshell 3.10.101-rt110 #1 SMP Sat Oct 13 11:07:11 PDT 2018 mips64 GNU/Linux

```


#####特権モードからpythonに移動
※いったんExitでguestshellを抜けてから
guestshell入って続けてpythonプロンプトになる

```python:cisco→guestshell→python
isp-sw#guestshell run python
Python 2.7.11 (default, May 17 2017, 05:17:57)
[GCC 5.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
```
---
#####CiscoのPythonモジュールimport
**import cli**で
まず、コマンドを使うためのモジュールをimport
このモジュールではpythonからEXECコマンドや設定コマンドを実行することができる
help(XXXX) コマンドを入力するとpythonコマンドの使い方が表示される

以下**cli.configure**のhelp表示例

```python:python
isp-sw#guestshell run python
Python 2.7.11 (default, May 17 2017, 05:17:57)
[GCC 5.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import cli     ###  モジュールをimport
>>>
>>> help(configure)         ### configureの使い方が表示される
Help on function configure in module cli:

configure(configuration)
    Apply a configuration (set of Cisco IOS CLI config-mode commands) to the device
    and return a list of results.

    configuration = '''interface gigabitEthernet 0/0
                         no shutdown'''

    # push it through the Cisco IOS CLI.
    try:
        results = cli.configure(configuration)
        print "Success!"
    except CLIConfigurationError as e:
        print "Failed configurations:"
        for failure in e.failed:
            print failure

    Args:
        configuration (str or iterable): Configuration commands, separated by newlines.

    Returns:
        list(ConfigResult): A list of results, one for each line.

    Raises:
        CLISyntaxError: If there is a syntax error in the configuration.
>>>
```
####pythonコマンドで設定

#####**configure**と**configurep**コマンド確認
configureコマンドでIF設定しshut実行
Ciscoの設定モードで設定するのと同じconfigを一行ずつ”,”で区切って並べたリストで投入。コマンドが横に長くなるが複数行設定可能

```python:python
>>> cli.configure(["interface GigabitEthernet1/0/7", "shutdown","interface GigabitEthernet1/0/5", "shutdown"]) 
[ConfigResult(success=True, command='interface GigabitEthernet1/0/7', line=1, output='', notes=None), ConfigResult(success=True, command='shutdown', line=2, output='', notes=None), ConfigResult(success=True, command='interface GigabitEthernet1/0/5', line=3, output='', notes=None), ConfigResult(success=True, command='shutdown', line=4, output='', notes=None)]
>>> 
''
```
ターミナルログで実機設定確認
設定できた

```cisco:cisco
isp-sw#ter monitor 
Mar 26 08:42:50.264 JST: %LINK-5-CHANGED: Interface GigabitEthernet1/0/7, changed state to administratively down
Mar 26 08:42:50.270 JST: %LINK-5-CHANGED: Interface GigabitEthernet1/0/5, changed state to administratively down
```

次にconfigurepコマンドでIF設定しshut実行
pがついてるだけで設定動作は同じで実行後結果の出力に違いがある
スクリプト実行結果を次の処理に渡すときに使うのか

```python:python
>>> cli.configurep(["interface GigabitEthernet1/0/7", "shutdown","interface GigabitEthernet1/0/5", "shutdown"]) 
Line 1 SUCCESS: interface GigabitEthernet1/0/7
Line 2 SUCCESS: shutdown
Line 3 SUCCESS: interface GigabitEthernet1/0/5
Line 4 SUCCESS: shutdown
>>> 
```
ターミナルログで実機設定確認

```cisco:cisco
isp-sw#ter monitor 
Mar 26 08:50:18.152 JST: %LINK-5-CHANGED: Interface GigabitEthernet1/0/7, changed state to administratively down
Mar 26 08:50:18.156 JST: %LINK-5-CHANGED: Interface GigabitEthernet1/0/5, changed state to administratively down
```



#####**execute**tと**executep**コマンドを確認

CiscoのEXECコマンドを**1つ**実行できる
こちらも設定後の出力コード形式に差

```python:python
>>> cli.execute("sh system mtu") 
'Global Ethernet MTU is 1500 bytes.'
>>> 
>>> cli.executep("sh system mtu") 
Global Ethernet MTU is 1500 bytes.
>>> 
```
ターミナルログで実機設定確認

```cisco:cisco
isp-sw#ter monitor 
Mar 26 07:47:09.399 JST: %LINEPROTO-5-UPDOWN: Line protocol on Interface Loopback11, changed state to up
Mar 26 07:47:09.400 JST: %LINK-3-UPDOWN: Interface Loopback11, changed state to up
May 26 07:47:09.409 JST: %LINEPROTO-5-UPDOWN: Line protocol on Interface Loopback13, changed state to up
Mar 26 07:47:09.410 JST: %LINK-3-UPDOWN: Interface Loopback13, changed state to up
```
---
#####**clip**と**cli**コマンドを確認
EXECモードからCiscoのconfigをそのまま投入できる。
こちらも設定後の出力コード形式に差があるだけ。

```python:python
>>> cli.clip('show clock')  
21:06:06.846 JST Mon Mar 25 2020
>>> 
>>> cli.cli('show clock')  
'\n21:06:12.672 JST Mon Mar 25 2020\n'
>>>
```
**cli**コマンドで設定確認
cilコマンドで2つのLoアドレスを設定してみた。EXECモードからの設定になる。no shut実行。configを一行ずつ;で区切って並べるだけ。

```python:python
>>> cli.cli('configure terminal; interface loopback 11; ip address 10.11.11.11 255.255.255.255; no shutdown ;interface loopback 13; ip address 10.13.13.13 255.255.255.255; no shutdown ')  
''
```
ターミナルログで実機設定確認

```cisco:cisco
isp-sw#ter monitor 
Mar 26 07:47:09.399 JST: %LINEPROTO-5-UPDOWN: Line protocol on Interface Loopback11, changed state to up
Mar 26 07:47:09.400 JST: %LINK-3-UPDOWN: Interface Loopback11, changed state to up
May 26 07:47:09.409 JST: %LINEPROTO-5-UPDOWN: Line protocol on Interface Loopback13, changed state to up
Mar 26 07:47:09.410 JST: %LINK-3-UPDOWN: Interface Loopback13, changed state to up
```
---
####まとめ
Cisco機器上でPythonモジュールを使って定コマンドとEXECコマンドを実行できた。
次は[EEMでPythonスクリプトを実行](https://qiita.com/drafts/f7081a0c613ebd66491a)で応用する

####確認機種とバージョン
機種:Catalyst3850
Ver:Cisco IOS XE　16.06.05　Everest

---
####参考リンク
[Programmability Configuration Guide, Cisco IOS XE Everest 16.6.x](https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/prog/configuration/166/b_166_programmability_cg/eem_python_module.html#id_46478)