Merge (IOS)

In addition to translating models to native configuration, ntc_rosetta can create configuration deltas that can be applied into the device. This means that given to different sets of data, ntc_rosetta can compute the needed native commands to go from one to the other.

To see what this means let’s see it with an example. Let’s start by loading the driver:

[1]:
from ntc_rosetta import get_driver

ios = get_driver("ios", "openconfig")
ios_processor = ios()

Now we load some data that will represent the “running” configuration:

[2]:
running = {
    "openconfig-interfaces:interfaces": {
        "interface": [
            {
                "name": "FastEthernet1",
                "config": {
                    "name": "FastEthernet1",
                    "type": "iana-if-type:ethernetCsmacd",
                    "description": "This is Fa1",
                    "enabled": False
                },
                "subinterfaces": {
                    "subinterface": [
                        {
                            "index": 1,
                            "config": {
                                "index": 1,
                                "description": "This is Fa1.1"
                            }
                        },
                        {
                            "index": 2,
                            "config": {
                                "index": 2,
                                "description": "This is Fa1.2"
                            }
                        }
                    ]
                }
            },
            {
                "name": "FastEthernet3",
                "config": {
                    "name": "FastEthernet3",
                    "type": "iana-if-type:ethernetCsmacd",
                    "description": "This is Fa3",
                    "enabled": True
                },
                "openconfig-if-ethernet:ethernet": {
                    "openconfig-vlan:switched-vlan": {
                        "config": {
                            "interface-mode": "ACCESS",
                            "access-vlan": 10
                        }
                    }
                }
            },
            {
                "name": "FastEthernet4",
                "config": {
                    "name": "FastEthernet4",
                    "type": "iana-if-type:ethernetCsmacd",
                    "enabled": False
                },
                "openconfig-if-ethernet:ethernet": {
                    "openconfig-vlan:switched-vlan": {
                        "config": {
                            "interface-mode": "TRUNK",
                            "trunk-vlans": [
                                10,
                                20
                            ]
                        }
                    }
                }
            }
        ]
    },
    "openconfig-network-instance:network-instances": {
        "network-instance": [
            {
                "name": "default",
                "config": {
                    "name": "default"
                },
                "vlans": {
                    "vlan": [
                        {
                            "vlan-id": 10,
                            "config": {
                                "vlan-id": 10,
                                "name": "prod",
                                "status": "ACTIVE"
                            }
                        },
                        {
                            "vlan-id": 20,
                            "config": {
                                "vlan-id": 20,
                                "name": "dev",
                                "status": "SUSPENDED"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Now we are going to copy this data into a “candidate” variable and apply some changes:

[3]:
from copy import deepcopy
candidate = deepcopy(running)

We are going to start by disabling vlan 10:

[4]:
vlan_10 = candidate["openconfig-network-instance:network-instances"]["network-instance"][0]["vlans"]["vlan"][0]
vlan_10["config"]["status"] = "SUSPENDED"

Eliminate vlan 20:

[5]:
candidate["openconfig-network-instance:network-instances"]["network-instance"][0]["vlans"]["vlan"].pop(1)
[5]:
{'vlan-id': 20,
 'config': {'vlan-id': 20, 'name': 'dev', 'status': 'SUSPENDED'}}

And create a new vlan 30:

[6]:
vlan_30 = {
    "vlan-id": 30,
    "config": {
        "vlan-id": 30,
        "name": "staging",
        "status": "ACTIVE"
    }
}
candidate["openconfig-network-instance:network-instances"]["network-instance"][0]["vlans"]["vlan"].append(vlan_30)

Once we have done those changes we can merge those two objects like this:

[7]:
config = ios_processor.merge(candidate=candidate, running=running)

Finally, printing the config variable should return the native commands needed for that merge operation:

[8]:
print(config)
no vlan 20
vlan 10
   shutdown
   exit
!
vlan 30
   name staging
   no shutdown
   exit
!