Skip to content

Commit 9f83ace

Browse files
authored
[GCU] Add vlanintf-validator (#2697)
What I did Fix the bug of GCU vlan interface modification. It should call ip neigh flush dev after removing interface ip. The fix is basically following config CLI's tradition. How I did it Add vlanintf service validator to check if extra step of ip neigh flush is needed. How to verify it GCU E2E test in dualtor testbed.
1 parent 338d1c0 commit 9f83ace

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

generic_config_updater/gcu_services_validator.conf.json

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
},
4949
"NTP_SERVER": {
5050
"services_to_validate": [ "ntp-service" ]
51+
},
52+
"VLAN_INTERFACE": {
53+
"services_to_validate": [ "vlanintf-service" ]
5154
}
5255
},
5356
"services": {
@@ -71,6 +74,9 @@
7174
},
7275
"ntp-service": {
7376
"validate_commands": [ "generic_config_updater.services_validator.ntp_validator" ]
77+
},
78+
"vlanintf-service": {
79+
"validate_commands": [ "generic_config_updater.services_validator.vlanintf_validator" ]
7480
}
7581
}
7682
}

generic_config_updater/services_validator.py

+21
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,24 @@ def caclmgrd_validator(old_config, upd_config, keys):
101101

102102
def ntp_validator(old_config, upd_config, keys):
103103
return _service_restart("ntp-config")
104+
105+
def vlanintf_validator(old_config, upd_config, keys):
106+
old_vlan_intf = old_config.get("VLAN_INTERFACE", {})
107+
upd_vlan_intf = upd_config.get("VLAN_INTERFACE", {})
108+
109+
# Get the tuple with format (iface, iface_ip) then check deleted tuple
110+
# Example:
111+
# old_keys = [("Vlan1000", "192.168.0.1")]
112+
# upd_keys = [("Vlan1000", "192.168.0.2")]
113+
old_keys = [ tuple(key.split("|"))
114+
for key in old_vlan_intf if len(key.split("|")) == 2 ]
115+
upd_keys = [ tuple(key.split("|"))
116+
for key in upd_vlan_intf if len(key.split("|")) == 2 ]
117+
118+
deleted_keys = list(set(old_keys) - set(upd_keys))
119+
for key in deleted_keys:
120+
iface, iface_ip = key
121+
rc = os.system(f"ip neigh flush dev {iface} {iface_ip}")
122+
if not rc:
123+
return False
124+
return True

tests/generic_config_updater/service_validator_test.py

+50-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from collections import defaultdict
77
from unittest.mock import patch
88

9-
from generic_config_updater.services_validator import vlan_validator, rsyslog_validator, caclmgrd_validator
9+
from generic_config_updater.services_validator import vlan_validator, rsyslog_validator, caclmgrd_validator, vlanintf_validator
1010
import generic_config_updater.gu_common
1111

1212

@@ -152,6 +152,46 @@ def mock_time_sleep_call(sleep_time):
152152
{ "cmd": "systemctl restart rsyslog", "rc": 1 }, # restart again; fails
153153
]
154154

155+
test_vlanintf_data = [
156+
{ "old": {}, "upd": {}, "cmd": "" },
157+
{
158+
"old": { "VLAN_INTERFACE": {
159+
"Vlan1000": {},
160+
"Vlan1000|192.168.0.1/21": {} } },
161+
"upd": { "VLAN_INTERFACE": {
162+
"Vlan1000": {},
163+
"Vlan1000|192.168.0.1/21": {} } },
164+
"cmd": ""
165+
},
166+
{
167+
"old": { "VLAN_INTERFACE": {
168+
"Vlan1000": {},
169+
"Vlan1000|192.168.0.1/21": {} } },
170+
"upd": { "VLAN_INTERFACE": {
171+
"Vlan1000": {},
172+
"Vlan1000|192.168.0.2/21": {} } },
173+
"cmd": "ip neigh flush dev Vlan1000 192.168.0.1/21"
174+
},
175+
{
176+
"old": { "VLAN_INTERFACE": {
177+
"Vlan1000": {},
178+
"Vlan1000|192.168.0.1/21": {} } },
179+
"upd": { "VLAN_INTERFACE": {
180+
"Vlan1000": {},
181+
"Vlan1000|192.168.0.1/21": {},
182+
"Vlan1000|192.168.0.2/21": {} } },
183+
"cmd": ""
184+
},
185+
{
186+
"old": { "VLAN_INTERFACE": {
187+
"Vlan1000": {},
188+
"Vlan1000|192.168.0.1/21": {} } },
189+
"upd": {},
190+
"cmd": "ip neigh flush dev Vlan1000 192.168.0.1/21"
191+
}
192+
]
193+
194+
155195
class TestServiceValidator(unittest.TestCase):
156196

157197
@patch("generic_config_updater.change_applier.os.system")
@@ -177,6 +217,15 @@ def test_change_apply_os_system(self, mock_os_sys):
177217
rc = rsyslog_validator("", "", "")
178218
assert not rc, "rsyslog_validator expected to fail"
179219

220+
os_system_calls = []
221+
os_system_call_index = 0
222+
for entry in test_vlanintf_data:
223+
if entry["cmd"]:
224+
os_system_calls.append({"cmd": entry["cmd"], "rc": 0 })
225+
msg = "case failed: {}".format(str(entry))
226+
227+
vlanintf_validator(entry["old"], entry["upd"], None)
228+
180229
@patch("generic_config_updater.services_validator.time.sleep")
181230
def test_change_apply_time_sleep(self, mock_time_sleep):
182231
global time_sleep_calls, time_sleep_call_index

0 commit comments

Comments
 (0)