model driven programmability advancement OSPF configuration using RESTCONF 1

# RESTCONFを使ってOSPFを行う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943132/e77ad1c2-754d-a14b-a4ce-73486fd55fe6.png)

ルーターのL3IPは事前に設定済み
R3とR4はすでに設定済みでOSPFが稼働済み
PythonプログラムでCSR1とCSR2を設定する
デバイス名.jsonファイルを使う
プログラム実行時にCSR1とCSR2はすべてのルーターとOSPFを形成

NETCONFの時とほとんど変わらないがJSONを使ったり若干変更になってる。

device-templates
++ios-xe1.json
++ios-xe2.json
restconf_deploy.py
.envrc

ルーター設定
設定もRESTCONF向けに一部変更になってる
```cisco_ios:IOS-XE1
hostname IOS-XE1
ip domain-name abc.com
crypto key generate rsa module 1024
ip ssh version 2
username admin privilege 15 password cisco
ip http server
ip http secure-server
restconf
line vty 0 4
login local
transport input all
int gi1
ip address 10.255.1.101 255.255.255.0
description Connect to MGMT
no shut
int gi2
ip address 12.0.0.1 255.255.255.0
description Connect to IOS-XE2
no shut
int gi3
ip address 13.0.0.1 255.255.255.0
description Connect to IOS3
no shut
int gi4
ip address 14.0.0.1 255.255.255.0
description Connect to IOS4
no shut
```

```cisco_ios:IOS-XE2
hostname IOS-XE2
ip domain-name abc.com
crypto key generate rsa module 1024
ip ssh version 2
username admin privilege 15 password cisco
ip http server
ip http secure-server
restconf
line vty 0 4
login local
transport input all
int gi1
ip address 10.255.1.102 255.255.255.0
description Connect to MGMT
no shut
int gi2
ip address 12.0.0.2 255.255.255.0
description Connect to IOS-XE1
no shut
int gi3
ip address 24.0.0.2 255.255.255.0
description Connect to IOS4
no shut
int gi4
ip address 23.0.0.2 255.255.255.0
description Connect to IOS3
no shut
```

```cisco_ios:IOS3
hostname IOS3
int gi0/1
ip address 13.0.0.3 255.255.255.0
description connected to IOS-XE1
no shut
int gi0/2
ip address 23.0.0.3 255.255.255.0
description connected to IOS-XE2
no shut
router ospf 1
router-id 3.3.3.3
interface range gi0/1-2
ip ospf 1 area 0
ip ospf network point-to-point
```

```cisco_ios:IOS4
hostname IOS4
int gi0/1
ip address 14.0.0.4 255.255.255.0
description connected to IOS-XE1
no shut
int gi0/2
ip address 24.0.0.4 255.255.255.0
description connected to IOS-XE2
no shut
router ospf 1
router-id 4.4.4.4
interface range gi0/1-2
ip ospf 1 area 0
ip ospf network point-to-point
```

#方針
Jsonの設定ファイルを作ってそれを投げる。今回はそのまま投げる模様。

```json:ios-xe1.json
{
    "Cisco-IOS-XE-native:native": {
        "interface": {
            "GigabitEthernet": [
                {
                    "name":"2",
                    "ip": {
                        "Cisco-IOS-XE-ospf:ospf": {
                            "process-id": {
                                "id": "1",
                                "area": "0"
                            },
                            "network": "point-to-point"
                        }
                    }
                },
                {
                    "name":"3",
                    "ip": {
                        "Cisco-IOS-XE-ospf:ospf": {
                            "process-id": {
                                "id": "1",
                                "area": "0"
                            },
                            "network": "point-to-point"
                        }
                    }
                },
                {
                    "name":"4",
                    "ip": {
                        "Cisco-IOS-XE-ospf:ospf": {
                            "process-id": {
                                "id": "1",
                                "area": "0"
                            },
                            "network": "point-to-point"
                        }
                    }
                }
            ]
        },
        "router": {
            "Cisco-IOS-XE-ospf:ospf": {
                "id":"1",
                "router-id":"1.1.1.1"
            }
        }
    }
}

```


```json:ios-xe2.json
{
    "Cisco-IOS-XE-native:native": {
        "interface": {
            "GigabitEthernet": [
                {
                    "name":"2",
                    "ip": {
                        "Cisco-IOS-XE-ospf:ospf": {
                            "process-id": {
                                "id": "1",
                                "area": "0"
                            },
                            "network": "point-to-point"
                        }
                    }
                },
                {
                    "name":"3",
                    "ip": {
                        "Cisco-IOS-XE-ospf:ospf": {
                            "process-id": {
                                "id": "1",
                                "area": "0"
                            },
                            "network": "point-to-point"
                        }
                    }
                },
                {
                    "name":"4",
                    "ip": {
                        "Cisco-IOS-XE-ospf:ospf": {
                            "process-id": {
                                "id": "1",
                                "area": "0"
                            },
                            "network": "point-to-point"
                        }
                    }
                }
            ]
        },
        "router": {
            "Cisco-IOS-XE-ospf:ospf": {
                "id":"1",
                "router-id":"2.2.2.2"
            }
        }
    }
}

```

```python:restconf-deploy.py
import requests
from requests.auth import HTTPBasicAuth
from urllib3 import disable_warnings
import os
import logging

#Set logging level
logging.basicConfig(level=logging.INFO)

#Disable SSL Warnings
disable_warnings()

def process_template(template_name: str) -> bool:
    try:
        with open(f"./device-templates/{template_name}") as fd:
            payload = fd.read()
    except OSError:
        logging.exception("Failed to open ./device-templates/{template_name}")
        return False
    
    device_name = template_name.rstrip("json")
    
    logging.info(f"Deploying Template Configuration to {device_name}")
    
    url = f"https://{device_name}/restconf/data/Cisco-IOS-XE-native:native"
    creds = HTTPBasicAuth(
        username = os.environ["DEVICE_USERNAME"],
        password = os.environ["DEVICE_PASSWORD"]
    )
    
    headers = {
        "Content-Type":"application/yang-data+json"
    }
    
    try:
    ###
        response = requests.patch(
            url=url, auth=creds, headers=headers,data=payload,verify=False
        )
        if response.status_code == 204:
            logging.info(f"Successfully deployed configuration to {device_name}")
    except Exception:
        logging.exception(f"Failed to deployed configuration to {device_name}")
        return False    
    return True

def main():
    result = True
    
    with os.scandir("./device-templates") as pd:
        for entry in pd:
            if entry.is_file() and entry.name.endswith(".json"):
                result &= process_template(entry.name)
        if not result:
            exit(1)
            
if __name__=="__main__":
    main()
```

# 実行と結果

```shell-session
#python restconf-deploy.py 
INFO:root:Deploying Template Configuration to ios-xe1.
INFO:root:Successfully deployed configuration to ios-xe1.
INFO:root:Deploying Template Configuration to ios-xe2.
INFO:root:Successfully deployed configuration to ios-xe2.

```

```cisco_ios
IOS-XE1#sh ip ospf nei
IOS-XE1#
*Nov 26 09:02:19.433: %DMI-5-AUTH_PASSED: R0/0: dmiauthd: User 'admin' authenticated successfully from 10.2
55.1.51:0 and was authorized for rest over http. External groups: PRIV15
*Nov 26 09:02:21.401: %OSPF-6-DFT_OPT: Protocol timers for fast convergence are Enabled.
*Nov 26 09:02:23.161: %OSPF-5-ADJCHG: Process 1, Nbr 3.3.3.3 on GigabitEthernet3 from LOADING to FULL, Load
ing Done
*Nov 26 09:02:23.172: %OSPF-5-ADJCHG: Process 1, Nbr 4.4.4.4 on GigabitEthernet4 from LOADING to FULL, Load
ing Done
*Nov 26 09:02:23.094: %DMI-5-CONFIG_I: R0/0: nesd: Configured from NETCONF/RESTCONF by admin, transaction-i
d 104
*Nov 26 09:02:41.800: %OSPF-5-ADJCHG: Process 1, Nbr 2.2.2.2 on GigabitEthernet2 from LOADING to FULL, Load
ing Done
IOS-XE1#sh ip ospf nei

Neighbor ID     Pri   State           Dead Time   Address         Interface
4.4.4.4           0   FULL/  -        00:00:38    14.0.0.4        GigabitEthernet4
2.2.2.2           0   FULL/  -        00:00:37    12.0.0.2        GigabitEthernet2
3.3.3.3           0   FULL/  -        00:00:37    13.0.0.3        GigabitEthernet3
IOS-XE1#

IOS-XE2#sh ip ospf nei
IOS-XE2#
*Nov 26 09:02:37.558: %DMI-5-AUTH_PASSED: R0/0: dmiauthd: User 'admin' authenticated successfully from 10.2
55.1.51:0 and was authorized for rest over http. External groups: PRIV15
*Nov 26 09:02:41.265: %OSPF-6-DFT_OPT: Protocol timers for fast convergence are Enabled.
*Nov 26 09:02:41.934: %OSPF-5-ADJCHG: Process 1, Nbr 1.1.1.1 on GigabitEthernet2 from LOADING to FULL, Load
ing Done
*Nov 26 09:02:41.807: %DMI-5-CONFIG_I: R0/0: nesd: Configured from NETCONF/RESTCONF by admin, transaction-i
d 95
*Nov 26 09:02:47.737: %OSPF-5-ADJCHG: Process 1, Nbr 3.3.3.3 on GigabitEthernet4 from LOADING to FULL, Load
ing Done
*Nov 26 09:02:52.761: %OSPF-5-ADJCHG: Process 1, Nbr 4.4.4.4 on GigabitEthernet3 from LOADING to FULL, Load
ing Done
IOS-XE2#sh ip ospf nei

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