Desired state, read before write & idempotency
Make changes idempotent
Lesson 11 of 20 · 15 min · Module 3: Change the network
Running a script twice should not change the network twice. Read what is there, compare it with what should be there, and send only the difference.
Start this lesson →Free. No installation: you write and run the code in your browser, and it is checked automatically.
By the end, you’ll be able to…
- Describe the desired state as data
- Send only the difference
- Report what changed
The idea
A change is idempotent when running it again leaves the network as it is. The pattern: describe the desired state as data, read the actual state from the device, and send only what is missing. Return what you changed, so a report can say which devices were touched, and save only when something changed. On Huawei, the text that display vlan shows for a VLAN is set with description in the VLAN view.
DESIRED = {10: "USERS", 30: "GUESTS"}
present = {1, 10}
print(sorted(set(DESIRED) - present))
01Desired minus actual
Set difference gives what is missing. Sorting it makes the result, and the order of the commands, predictable.
DESIRED = {10: "USERS", 20: "VOICE", 30: "GUESTS", 99: "MGMT"}
print(sorted(set(DESIRED) - {1, 10, 20, 99}))[30]02Lines only for what is missing
Build the configuration from the difference. When the difference is empty, the list is empty and nothing needs to be sent.
lines = []
for vid in [30]:
lines += [f"vlan {vid}", f"name {DESIRED[vid]}"]
print(lines)
print([f"vlan {vid}" for vid in []])['vlan 30', 'name GUESTS']
[]03Huawei describes a VLAN
In the VLAN view, Huawei takes description for the text that display vlan shows. The same data gives each vendor its own lines.
import os
from netmiko import ConnectHandler
USERNAME = os.environ["NET_USERNAME"]
PASSWORD = os.environ["NET_PASSWORD"]
with ConnectHandler(device_type="huawei", host="10.0.0.13",
username=USERNAME, password=PASSWORD) as conn:
print(conn.send_config_set(["vlan 50", "description LAB"]))system-view
Enter system view, return user view with return command.
[sw3]vlan 50
[sw3-vlan50]description LAB
[sw3-vlan50]return
<sw3>Your turn
ensure_vlans(conn, platform): read the switch's VLANs, create the VLANs from DESIRED that are missing (with their names), save only if something changed, and return the sorted list of VLAN IDs it added. Run it on sw1, sw2 and sw3 and store the results in first, then run it on all three again and store those results in second.What the checks look for
- first shows what each switch needed
- second shows that nothing was left to do
- VLAN 30 is named GUESTS on every switch
- sw2 received no configuration and no save
- Each VLAN was created only once
- Changed switches are saved
Take this with you
Read, compare, change only the difference, and report what changed. A second run must report nothing.
Go a little further
Also fix VLANs that exist with a different name, and return them separately as renamed.