diff --git a/fake_switches/juniper/juniper_netconf_datastore.py b/fake_switches/juniper/juniper_netconf_datastore.py index febe60b..60ab5f1 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"] = {"time-in-seconds": 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..ce901a5 100644 --- a/tests/juniper/juniper_base_protocol_test.py +++ b/tests/juniper/juniper_base_protocol_test.py @@ -1720,6 +1720,63 @@ 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/time-in-seconds")[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/time-in-seconds")[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/time-in-seconds")[0].text, equal_to("300")) + + 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}}}}