From 05eab3b640324fec60b2de03383fac898b5c3f25 Mon Sep 17 00:00:00 2001 From: Aldo Ortega Date: Thu, 16 Jan 2025 16:56:20 -0500 Subject: [PATCH 1/4] Added condition pair for especial case --- models/evc.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/models/evc.py b/models/evc.py index 703a06ba..b37e1cbc 100644 --- a/models/evc.py +++ b/models/evc.py @@ -1737,7 +1737,7 @@ def is_using_dynamic_path(self): return True return False - def handle_link_up(self, link): + def handle_link_up(self, link=None, interface=None): """Handle circuit when link up. Args: @@ -1757,6 +1757,13 @@ def handle_link_up(self, link): lambda me: me.primary_path.is_affected_by_link(link), lambda me: (me.deploy_to_primary_path(), 'redeploy') ), + # For this special case, it reached this point because interface + # was previously confirmed to be a UNI and both UNI are UP + ( + lambda me: (me.primary_path.status == EntityStatus.UP + and interface), + lambda me: (me.deploy_to_primary_path(), 'redeploy') + ), # We tried to deploy(primary_path) without success. # And in this case is up by some how. Nothing to do. ( @@ -1840,7 +1847,7 @@ def try_to_handle_uni_as_link_up(self, interface: Interface) -> bool: self.current_path.status != EntityStatus.UP and not self.is_intra_switch() ): - succeeded = self.handle_link_up(interface) + succeeded = self.handle_link_up(interface=interface) if succeeded: msg = ( f"Activated {self} due to successful " From 4915653f7f5b7a48d6bef780c230d026739e2e95 Mon Sep 17 00:00:00 2001 From: Aldo Ortega Date: Fri, 17 Jan 2025 12:18:23 -0500 Subject: [PATCH 2/4] Added condition for backup_path --- models/evc.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/models/evc.py b/models/evc.py index b37e1cbc..5af68cae 100644 --- a/models/evc.py +++ b/models/evc.py @@ -1764,6 +1764,10 @@ def handle_link_up(self, link=None, interface=None): and interface), lambda me: (me.deploy_to_primary_path(), 'redeploy') ), + ( + lambda me: interface and me.backup_path.status == EntityStatus.UP, + lambda me: (me.deploy_to_backup_path(), 'redeploy') + ), # We tried to deploy(primary_path) without success. # And in this case is up by some how. Nothing to do. ( From 52c3191f43c1f5ac43fd2f34b653f5446070857e Mon Sep 17 00:00:00 2001 From: Aldo Ortega Date: Tue, 21 Jan 2025 17:10:33 -0500 Subject: [PATCH 3/4] Added unit tests --- models/evc.py | 3 +- tests/unit/models/test_link_protection.py | 58 +++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/models/evc.py b/models/evc.py index 5af68cae..cd013c60 100644 --- a/models/evc.py +++ b/models/evc.py @@ -1765,7 +1765,8 @@ def handle_link_up(self, link=None, interface=None): lambda me: (me.deploy_to_primary_path(), 'redeploy') ), ( - lambda me: interface and me.backup_path.status == EntityStatus.UP, + lambda me: (me.backup_path.status == EntityStatus.UP + and interface), lambda me: (me.deploy_to_backup_path(), 'redeploy') ), # We tried to deploy(primary_path) without success. diff --git a/tests/unit/models/test_link_protection.py b/tests/unit/models/test_link_protection.py index b82b2382..af0e910d 100644 --- a/tests/unit/models/test_link_protection.py +++ b/tests/unit/models/test_link_protection.py @@ -739,6 +739,64 @@ async def test_handle_link_up_case_7(self): assert not self.evc.handle_link_up(MagicMock()) assert self.evc.deploy_to_path.call_count == 0 + @patch(DEPLOY_TO_BACKUP_PATH) + @patch(DEPLOY_TO_PRIMARY_PATH) + async def test_handle_link_up_case_8( + self, deploy_primary_mock, deploy_backup_mock + ): + """Test when UNI is UP and dinamic primary_path from + EVC is UP as well.""" + primary_path = [ + get_link_mocked( + endpoint_a_port=9, + endpoint_b_port=10, + metadata={"s_vlan": 5}, + status=EntityStatus.UP, + ), + get_link_mocked( + endpoint_a_port=11, + endpoint_b_port=12, + metadata={"s_vlan": 6}, + status=EntityStatus.UP, + ), + ] + backup_path = [ + get_link_mocked( + endpoint_a_port=13, + endpoint_b_port=14, + metadata={"s_vlan": 5}, + status=EntityStatus.UP, + ), + get_link_mocked( + endpoint_a_port=11, + endpoint_b_port=12, + metadata={"s_vlan": 6}, + status=EntityStatus.DOWN, + ), + ] + + attributes = { + "controller": get_controller_mock(), + "name": "circuit", + "uni_a": get_uni_mocked(is_valid=True), + "uni_z": get_uni_mocked(is_valid=True), + "primary_path": primary_path, + "backup_path": backup_path, + "enabled": True, + "dynamic_backup_path": True, + } + + evc = EVC(**attributes) + evc.handle_link_up(interface=evc.uni_a.interface) + assert deploy_primary_mock.call_count == 1 + assert deploy_backup_mock.call_count == 0 + + evc.primary_path[0].status = EntityStatus.DOWN + evc.backup_path[1].status = EntityStatus.UP + evc.handle_link_up(interface=evc.uni_a.interface) + assert deploy_primary_mock.call_count == 1 + assert deploy_backup_mock.call_count == 1 + async def test_get_interface_from_switch(self): """Test get_interface_from_switch""" interface = id_to_interface_mock('00:01:1') From ebd410a240c93bfbd986e9c42192f1c84e76c447 Mon Sep 17 00:00:00 2001 From: Aldo Ortega Date: Wed, 22 Jan 2025 09:34:52 -0500 Subject: [PATCH 4/4] Updated changelog --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 57907e59..657820d8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,6 +12,7 @@ Fixed - EVCs activation now take into account UNIs statuses before trying to activate - ``EVC.remove_current_flows()`` had its parameter ``current_path`` used when ``evc.current_path`` fails to install flows. - ``evc.current_path`` is deleted when an error with TAG type is raised. +- Link up from UNI will deploy correctly an EVC when it does not have a path. Added =====