model driven programmability advancement OSPF configuration using NETCONF 2

# 前回の取得データ
前回取得し変更したXMLはこちら

```xml:ios-xe1.xml
<config>
    <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
        <interface>
            <GigabitEthernet>
                    <name>2</name>
                    <description>connect to IOS-XE2</description>
                    <ip>
                            <address>
                                    <primary>
                                            <address>12.0.0.1</address>
                                            <mask>255.255.255.0</mask>
                                    </primary>
                            </address>
                            <ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
                                    <process-id>
                                            <id>1</id>
                                            <area>0</area>
                                    </process-id>
                                    <network>point-to-point</network>
                            </ospf>
                    </ip>
                    <mop>
                            <enabled>false</enabled>
                            <sysid>false</sysid>
                    </mop>
                    <negotiation xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ethernet">
                            <auto>true</auto>
                    </negotiation>
            </GigabitEthernet>
            <GigabitEthernet>
                    <name>3</name>
                    <description>connect to IOS-XE3</description>
                    <ip>
                            <address>
                                    <primary>
                                            <address>13.0.0.1</address>
                                            <mask>255.255.255.0</mask>
                                    </primary>
                            </address>
                            <ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
                                    <process-id>
                                            <id>1</id>
                                            <area>0</area>
                                    </process-id>
                                    <network>point-to-point</network>
                            </ospf>
                    </ip>
                    <mop>
                            <enabled>false</enabled>
                            <sysid>false</sysid>
                    </mop>
                    <negotiation xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ethernet">
                            <auto>true</auto>
                    </negotiation>
            </GigabitEthernet>
            <GigabitEthernet>
                    <name>4</name>
                    <description>connect to IOS-XE4</description>
                    <ip>
                            <address>
                                    <primary>
                                            <address>14.0.0.1</address>
                                            <mask>255.255.255.0</mask>
                                    </primary>
                            </address>
                            <ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
                                    <process-id>
                                            <id>1</id>
                                            <area>0</area>
                                    </process-id>
                                    <network>point-to-point</network>
                            </ospf>
                    </ip>
                    <mop>
                            <enabled>false</enabled>
                            <sysid>false</sysid>
                    </mop>
                    <negotiation xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ethernet">
                            <auto>true</auto>
                    </negotiation>
            </GigabitEthernet>
        </interface>
        <router>
                <ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
                        <id>1</id>
                        <router-id>1.1.1.1</router-id>
                </ospf>
        </router>
    </native>
</config>
```


```xml:ios-xe2.xml
<config>
    <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
        <interface>
            <GigabitEthernet>
                    <name>2</name>
                    <description>connect to IOS-XE1</description>
                    <ip>
                            <address>
                                    <primary>
                                            <address>12.0.0.2</address>
                                            <mask>255.255.255.0</mask>
                                    </primary>
                            </address>
                            <ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
                                    <process-id>
                                            <id>1</id>
                                            <area>0</area>
                                    </process-id>
                                    <network>point-to-point</network>
                            </ospf>
                    </ip>
                    <mop>
                            <enabled>false</enabled>
                            <sysid>false</sysid>
                    </mop>
                    <negotiation xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ethernet">
                            <auto>true</auto>
                    </negotiation>
            </GigabitEthernet>
            <GigabitEthernet>
                    <name>3</name>
                    <description>connect to IOS-XE4</description>
                    <ip>
                            <address>
                                    <primary>
                                            <address>24.0.0.2</address>
                                            <mask>255.255.255.0</mask>
                                    </primary>
                            </address>
                            <ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
                                    <process-id>
                                            <id>1</id>
                                            <area>0</area>
                                    </process-id>
                                    <network>point-to-point</network>
                            </ospf>
                    </ip>
                    <mop>
                            <enabled>false</enabled>
                            <sysid>false</sysid>
                    </mop>
                    <negotiation xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ethernet">
                            <auto>true</auto>
                    </negotiation>
            </GigabitEthernet>
            <GigabitEthernet>
                    <name>4</name>
                    <description>connect to IOS-XE3</description>
                    <ip>
                            <address>
                                    <primary>
                                            <address>23.0.0.2</address>
                                            <mask>255.255.255.0</mask>
                                    </primary>
                            </address>
                            <ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
                                    <process-id>
                                            <id>1</id>
                                            <area>0</area>
                                    </process-id>
                                    <network>point-to-point</network>
                            </ospf>
                    </ip>
                    <mop>
                            <enabled>false</enabled>
                            <sysid>false</sysid>
                    </mop>
                    <negotiation xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ethernet">
                            <auto>true</auto>
                    </negotiation>
            </GigabitEthernet>
        </interface>
        <router>
                <ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
                        <id>1</id>
                        <router-id>2.2.2.2</router-id>
                </ospf>
        </router>
    </native>
</config>

```


# 取得したデータをPythonで送信。

device-templates
++ios-xe1.xml
++ios-xe2.xml
deploy_ospf_netconf.py
.envrc

.envrcについては以前使ったユーザーネームとパスワードのファイル

```python:deploy_opsf_netconf.py
import os
from ncclient import manager

def import_template(template_name: str) -> bool:
    try:
        with open(f"./device-templates/{template_name}") as fd:
            payload = fd.read()
    except:
        print(f"Failed to open ./device-templates/{template_name} file")
        return False
    
    if not payload.strip().startswith("<config"):
        print(f"Template {template_name} content must begin with <config> tag.")
        return False
    
    device_name = template_name.strip(".xml")
    print(f"\nDeploying template configuration to {device_name}...\n")
    
    with manager.connect(
        host = device_name,
        port = "830",
        username = os.environ["ROUTER_USERNAME"],
        password = os.environ["ROUTER_PASSWORD"],
        hostkey_verify = False
    ) as m:
        try:
            m.edit_config(config=payload,target="running")
            print(f"\nOSPF Configuration Deployed to {device_name} Successfully")
        except Exception as e:
            print(e)
            print(f"\nFailed to deploy OSPF Configuration{device_name}")
    
    return True
            
def main() -> None:
    
    result = True
    
    with os.scandir("./device-templates") as pd:
        for entry in pd:
            if entry.is_file() and entry.name.endswith(".xml"):
                result &=  import_template(template_name=entry.name)
            
    if not result:
        exit(1)

if __name__ =="__main__":
    main()
```


# 実行
ローカルの名前解決に名前を登録してから実行する。
```shell:/etc/hosts
#下記を追加
10.255.101 ios-xe1
10.255.102 ios-xe2
```

```shell-session
#source .envrc
#python deploy_ospf_netconf.py 

Deploying templae configuration to ios-xe2...


OSPF Configuration Deployed to ios-xe2 Successfully

Deploying templae configuration to ios-xe1...


OSPF Configuration Deployed to ios-xe1 Successfully
```

```cisco_ios
IOS-XE1#sh ip ospf neighbor 
IOS-XE1#
*Nov 25 18:33:42.064: %SEC_LOGIN-5-LOGIN_SUCCESS: Login Success [user: admin] [Source: 10.255.1.51] [localp
ort: 22] at 18:33:42 UTC Mon Nov 25 2024
*Nov 25 18:33:53.549: %SYS-6-LOGOUT: User admin has exited tty session 1(10.255.1.51)
*Nov 25 18:36:18.103: %DMI-5-AUTH_PASSED: R0/0: dmiauthd: User 'admin' authenticated successfully from 10.2
55.1.51:34774 and was authorized for netconf over ssh. External groups: PRIV15
*Nov 25 18:36:25.329: %OSPF-6-DFT_OPT: Protocol timers for fast convergence are Enabled.
*Nov 25 18:36:26.209: %OSPF-5-ADJCHG: Process 1, Nbr 3.3.3.3 on GigabitEthernet3 from LOADING to FULL, Load
ing Done
*Nov 25 18:36:26.210: %OSPF-5-ADJCHG: Process 1, Nbr 4.4.4.4 on GigabitEthernet4 from LOADING to FULL, Load
ing Done
*Nov 25 18:36:26.047: %DMI-5-CONFIG_I: R0/0: nesd: Configured from NETCONF/RESTCONF by admin, transaction-i
d 59
*Nov 25 18:36:33.117: %OSPF-5-ADJCHG: Process 1, Nbr 2.2.2.2 on GigabitEthernet2 from LOADING to FULL, Load
ing Done
IOS-XE1#sh ip ospf neighbor 

Neighbor ID     Pri   State           Dead Time   Address         Interface
2.2.2.2           0   FULL/  -        00:00:31    12.0.0.2        GigabitEthernet2
3.3.3.3           0   FULL/  -        00:00:38    13.0.0.3        GigabitEthernet3
4.4.4.4           0   FULL/  -        00:00:38    14.0.0.4        GigabitEthernet4
IOS-XE1#
```
```cisco_ios
IOS-XE2#sh ip ospf neighbor 
IOS-XE2#
*Nov 25 18:35:20.778: %SEC_LOGIN-5-LOGIN_SUCCESS: Login Success [user: admin] [Source: 10.255.1.51] [localp
ort: 22] at 18:35:20 UTC Mon Nov 25 2024
*Nov 25 18:35:24.340: %SYS-6-LOGOUT: User admin has exited tty session 1(10.255.1.51)
*Nov 25 18:35:59.236: %DMI-5-AUTH_PASSED: R0/0: dmiauthd: User 'admin' authenticated successfully from 10.2
55.1.51:59034 and was authorized for netconf over ssh. External groups: PRIV15
*Nov 25 18:36:04.672: %OSPF-6-DFT_OPT: Protocol timers for fast convergence are Enabled.
*Nov 25 18:36:05.344: %DMI-5-CONFIG_I: R0/0: nesd: Configured from NETCONF/RESTCONF by admin, transaction-i
d 39
*Nov 25 18:36:09.776: %OSPF-5-ADJCHG: Process 1, Nbr 4.4.4.4 on GigabitEthernet3 from LOADING to FULL, Load
ing Done
*Nov 25 18:36:10.046: %OSPF-5-ADJCHG: Process 1, Nbr 3.3.3.3 on GigabitEthernet4 from LOADING to FULL, Load
ing Done
*Nov 25 18:36:33.366: %OSPF-5-ADJCHG: Process 1, Nbr 1.1.1.1 on GigabitEthernet2 from LOADING to FULL, Load
ing Donesh ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
3.3.3.3           0   FULL/  -        00:00:36    23.0.0.3        GigabitEthernet4
4.4.4.4           0   FULL/  -        00:00:32    24.0.0.4        GigabitEthernet3
1.1.1.1           0   FULL/  -        00:00:38    12.0.0.1        GigabitEthernet2
IOS-XE2#
```


:::note info
まとめ
・XML記法は独自性が高いので覚えるのは大変。ルーターを設定してそこから取ってきた方がいいかも。
・ダイアグラムの対称性がずれてるのには注意。
・TryのErrorはExceptionで常にひろう。
:::