From ebcd11fcf80629107b5eacb23dc9f0259ab71b07 Mon Sep 17 00:00:00 2001 From: Vitaliy Ilnitsky Date: Thu, 25 Aug 2022 18:34:36 +0300 Subject: [PATCH 1/2] emulate recovery-timeout option for juniper switches --- .../juniper/juniper_netconf_datastore.py | 12 ++- fake_switches/switch_configuration.py | 1 + tests/juniper/juniper_base_protocol_test.py | 91 +++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/fake_switches/juniper/juniper_netconf_datastore.py b/fake_switches/juniper/juniper_netconf_datastore.py index febe60b..67fcfaf 100644 --- a/fake_switches/juniper/juniper_netconf_datastore.py +++ b/fake_switches/juniper/juniper_netconf_datastore.py @@ -123,11 +123,11 @@ def commit_candidate(self): actual_port.lldp_transmit = updated_port.lldp_transmit actual_port.lldp_receive = updated_port.lldp_receive actual_port.vendor_specific = updated_port.vendor_specific + actual_port.recovery_timeout = updated_port.recovery_timeout if isinstance(actual_port, AggregatedPort): actual_port.lacp_active = updated_port.lacp_active actual_port.lacp_periodic = updated_port.lacp_periodic - if isinstance(actual_port, VlanPort): actual_port.vlan_id = updated_port.vlan_id actual_port.access_group_in = updated_port.access_group_in @@ -233,6 +233,8 @@ def ethernet_switching_to_etree(self, port, interface_data): if port.access_vlan: vlans.append(port.access_vlan) if len(vlans) > 0: ethernet_switching["vlan"] = [{"members": str(v)} for v in vlans] + if port.recovery_timeout is not None: + ethernet_switching["recovery-timeout"] = port.recovery_timeout if ethernet_switching or not isinstance(port, AggregatedPort): interface_data.append({"unit": { "name": "0", @@ -317,7 +319,7 @@ def apply_interface_data(self, interface_node, port): port.trunk_native_vlan = None port.access_vlan = None port.trunk_vlans = None - port.trunk_vlans = None + port.recovery_timeout = None port.vendor_specific["has-ethernet-switching"] = False else: port_attributes = first(interface_node.xpath("unit/family/{}".format(self.ETHERNET_SWITCHING_TAG))) @@ -337,6 +339,12 @@ def apply_interface_data(self, interface_node, port): else: self.parse_vlan_members(port, port_attributes) + if resolve_operation(first(port_attributes.xpath("recovery-timeout"))) == "delete": + port.recovery_timeout = None + else: + port.recovery_timeout = resolve_new_value(port_attributes, "recovery-timeout", + port.recovery_timeout) + if resolve_operation(first(self.get_trunk_native_vlan_node(interface_node))) == "delete": port.trunk_native_vlan = None else: diff --git a/fake_switches/switch_configuration.py b/fake_switches/switch_configuration.py index bbe3f33..9232df5 100644 --- a/fake_switches/switch_configuration.py +++ b/fake_switches/switch_configuration.py @@ -164,6 +164,7 @@ def reset(self): self.vrf = None self.speed = None self.force_up = None + self.recovery_timeout = None self.auto_negotiation = None self.aggregation_membership = None self.mtu = None diff --git a/tests/juniper/juniper_base_protocol_test.py b/tests/juniper/juniper_base_protocol_test.py index 17fb0dc..07a3b98 100644 --- a/tests/juniper/juniper_base_protocol_test.py +++ b/tests/juniper/juniper_base_protocol_test.py @@ -1720,6 +1720,97 @@ def test_that_force_up_can_be_removed(self): assert_that(get_interface_reply.xpath("data/configuration/interfaces/interface/ether-options"), has_length(0)) self.cleanup(reset_interface("ge-0/0/1")) + def test_that_recovery_timeout_can_be_configured(self): + self.edit({ + "interfaces": [ + {"interface": [ + {"name": "ae1"}, + {"aggregated-ether-options": { + "link-speed": "10g", + "lacp": { + "active": {}, + "periodic": "slow"}}}, + {"unit": [ + {"name": "0"}, + {"family": { + "ethernet-switching": { + "recovery-timeout": "500", + "port-mode": "trunk"}}}]}]}]}) + self.nc.commit() + get_interface_reply = self._interface('ae1') + assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout")[0].text, equal_to("500")) + self.cleanup(reset_interface("ae1")) + + def test_that_recovery_timeout_can_be_updated(self): + self.edit({ + "interfaces": [ + {"interface": [ + {"name": "ae1"}, + {"aggregated-ether-options": { + "link-speed": "10g", + "lacp": { + "active": {}, + "periodic": "slow"}}}, + {"unit": [ + {"name": "0"}, + {"family": { + "ethernet-switching": { + "recovery-timeout": "500", + "port-mode": "trunk"}}}]}]}]}) + self.nc.commit() + get_interface_reply = self._interface('ae1') + assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout")[0].text, equal_to("500")) + + self.edit({ + "interfaces": [ + {"interface": [ + {"name": "ae1"}, + {"unit": [ + {"name": "0"}, + {"family": { + "ethernet-switching": { + "recovery-timeout": "300"}}}]}]}]}) + self.nc.commit() + get_interface_reply = self._interface('ae1') + assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout")[0].text, equal_to("300")) + + self.cleanup(reset_interface("ae1")) + + def test_that_recovery_timeout_can_be_deleted(self): + self.edit({ + "interfaces": [ + {"interface": [ + {"name": "ae1"}, + {"aggregated-ether-options": { + "link-speed": "10g", + "lacp": { + "active": {}, + "periodic": "slow"}}}, + {"unit": [ + {"name": "0"}, + {"family": { + "ethernet-switching": { + "recovery-timeout": "500", + "port-mode": "trunk"}}}]}]}]}) + self.nc.commit() + get_interface_reply = self._interface('ae1') + assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout")[0].text, equal_to("500")) + + self.edit({ + "interfaces": [ + {"interface": [ + {"name": "ae1"}, + {"unit": [ + {"name": "0"}, + {"family": { + "ethernet-switching": { + "recovery-timeout": "delete"}}}]}]}]}) + self.nc.commit() + get_interface_reply = self._interface('ae1') + assert_that(get_interface_reply.xpath("unit/family/ethernet-switching"), has_length(1)) + + self.cleanup(reset_interface("ae1")) + def _interface(self, name): result = self.nc.get_config(source="running", filter=dict_2_etree({"filter": { "configuration": {"interfaces": {"interface": {"name": name}}}} From 5b5acfe221b28c09b6909b8b52509c0d1b35dee3 Mon Sep 17 00:00:00 2001 From: Vitaliy Ilnitsky Date: Tue, 30 Aug 2022 22:31:16 +0300 Subject: [PATCH 2/2] updated xml response for recovery timeout --- .../juniper/juniper_netconf_datastore.py | 2 +- tests/juniper/juniper_base_protocol_test.py | 40 ++----------------- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/fake_switches/juniper/juniper_netconf_datastore.py b/fake_switches/juniper/juniper_netconf_datastore.py index 67fcfaf..60ab5f1 100644 --- a/fake_switches/juniper/juniper_netconf_datastore.py +++ b/fake_switches/juniper/juniper_netconf_datastore.py @@ -234,7 +234,7 @@ def ethernet_switching_to_etree(self, port, interface_data): if len(vlans) > 0: ethernet_switching["vlan"] = [{"members": str(v)} for v in vlans] if port.recovery_timeout is not None: - ethernet_switching["recovery-timeout"] = port.recovery_timeout + ethernet_switching["recovery-timeout"] = {"time-in-seconds": port.recovery_timeout} if ethernet_switching or not isinstance(port, AggregatedPort): interface_data.append({"unit": { "name": "0", diff --git a/tests/juniper/juniper_base_protocol_test.py b/tests/juniper/juniper_base_protocol_test.py index 07a3b98..ce901a5 100644 --- a/tests/juniper/juniper_base_protocol_test.py +++ b/tests/juniper/juniper_base_protocol_test.py @@ -1738,7 +1738,7 @@ def test_that_recovery_timeout_can_be_configured(self): "port-mode": "trunk"}}}]}]}]}) self.nc.commit() get_interface_reply = self._interface('ae1') - assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout")[0].text, equal_to("500")) + assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout/time-in-seconds")[0].text, equal_to("500")) self.cleanup(reset_interface("ae1")) def test_that_recovery_timeout_can_be_updated(self): @@ -1759,7 +1759,7 @@ def test_that_recovery_timeout_can_be_updated(self): "port-mode": "trunk"}}}]}]}]}) self.nc.commit() get_interface_reply = self._interface('ae1') - assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout")[0].text, equal_to("500")) + assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout/time-in-seconds")[0].text, equal_to("500")) self.edit({ "interfaces": [ @@ -1772,44 +1772,10 @@ def test_that_recovery_timeout_can_be_updated(self): "recovery-timeout": "300"}}}]}]}]}) self.nc.commit() get_interface_reply = self._interface('ae1') - assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout")[0].text, equal_to("300")) + assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout/time-in-seconds")[0].text, equal_to("300")) self.cleanup(reset_interface("ae1")) - def test_that_recovery_timeout_can_be_deleted(self): - self.edit({ - "interfaces": [ - {"interface": [ - {"name": "ae1"}, - {"aggregated-ether-options": { - "link-speed": "10g", - "lacp": { - "active": {}, - "periodic": "slow"}}}, - {"unit": [ - {"name": "0"}, - {"family": { - "ethernet-switching": { - "recovery-timeout": "500", - "port-mode": "trunk"}}}]}]}]}) - self.nc.commit() - get_interface_reply = self._interface('ae1') - assert_that(get_interface_reply.xpath("unit/family/ethernet-switching/recovery-timeout")[0].text, equal_to("500")) - - self.edit({ - "interfaces": [ - {"interface": [ - {"name": "ae1"}, - {"unit": [ - {"name": "0"}, - {"family": { - "ethernet-switching": { - "recovery-timeout": "delete"}}}]}]}]}) - self.nc.commit() - get_interface_reply = self._interface('ae1') - assert_that(get_interface_reply.xpath("unit/family/ethernet-switching"), has_length(1)) - - self.cleanup(reset_interface("ae1")) def _interface(self, name): result = self.nc.get_config(source="running", filter=dict_2_etree({"filter": {