From 43d233062753f687010a5c55493c3cf0a29ee64d Mon Sep 17 00:00:00 2001 From: Aldo Ortega Date: Mon, 6 Nov 2023 10:57:31 -0500 Subject: [PATCH 1/4] Moved _get_tag_ranges() to kytos/core --- main.py | 56 +++++------------------------------------ requirements/dev.in | 2 +- tests/unit/test_main.py | 52 -------------------------------------- 3 files changed, 7 insertions(+), 103 deletions(-) diff --git a/main.py b/main.py index e03bf67..5f027e7 100644 --- a/main.py +++ b/main.py @@ -12,7 +12,7 @@ from kytos.core import KytosEvent, KytosNApp, log, rest from kytos.core.common import EntityStatus -from kytos.core.exceptions import (KytosLinkCreationError, +from kytos.core.exceptions import (KytosInvalidRanges, KytosLinkCreationError, KytosSetTagRangeError, KytosTagtypeNotSupported) from kytos.core.helpers import listen_to, load_spec, now, validate_openapi @@ -21,6 +21,7 @@ from kytos.core.rest_api import (HTTPException, JSONResponse, Request, content_type_json_or_415, get_json_or_400) from kytos.core.switch import Switch +from kytos.core.tag_ranges import get_tag_ranges from napps.kytos.topology import settings from .controllers import TopoController @@ -486,54 +487,6 @@ def delete_interface_metadata(self, request: Request) -> JSONResponse: self.notify_metadata_changes(interface, 'removed') return JSONResponse("Operation successful") - @staticmethod - def map_singular_values(tag_range): - """Change integer or singular interger list to - list[int, int] when necessary""" - if isinstance(tag_range, int): - tag_range = [tag_range] * 2 - elif len(tag_range) == 1: - tag_range = [tag_range[0]] * 2 - return tag_range - - def _get_tag_ranges(self, content: dict): - """Get tag_ranges and check validity: - - It should be ordered - - Not unnecessary partition (eg. [[10,20],[20,30]]) - - Singular intergers are changed to ranges (eg. [10] to [[10, 10]]) - The ranges are understood as [inclusive, inclusive]""" - ranges = content["tag_ranges"] - if len(ranges) < 1: - detail = "tag_ranges is empty" - raise HTTPException(400, detail=detail) - last_tag = 0 - ranges_n = len(ranges) - for i in range(0, ranges_n): - ranges[i] = self.map_singular_values(ranges[i]) - if ranges[i][0] > ranges[i][1]: - detail = f"The range {ranges[i]} is not ordered" - raise HTTPException(400, detail=detail) - if last_tag and last_tag > ranges[i][0]: - detail = f"tag_ranges is not ordered. {last_tag}"\ - f" is higher than {ranges[i][0]}" - raise HTTPException(400, detail=detail) - if last_tag and last_tag == ranges[i][0] - 1: - detail = f"tag_ranges has an unnecessary partition. "\ - f"{last_tag} is before to {ranges[i][0]}" - raise HTTPException(400, detail=detail) - if last_tag and last_tag == ranges[i][0]: - detail = f"tag_ranges has repetition. {ranges[i-1]}"\ - f" have same values as {ranges[i]}" - raise HTTPException(400, detail=detail) - last_tag = ranges[i][1] - if ranges[-1][1] > 4095: - detail = "Maximum value for tag_ranges is 4095" - raise HTTPException(400, detail=detail) - if ranges[0][0] < 1: - detail = "Minimum value for tag_ranges is 1" - raise HTTPException(400, detail=detail) - return ranges - @rest('v3/interfaces/{interface_id}/tag_ranges', methods=['POST']) @validate_openapi(spec) def set_tag_range(self, request: Request) -> JSONResponse: @@ -541,7 +494,10 @@ def set_tag_range(self, request: Request) -> JSONResponse: content_type_json_or_415(request) content = get_json_or_400(request, self.controller.loop) tag_type = content.get("tag_type") - ranges = self._get_tag_ranges(content) + try: + ranges = get_tag_ranges(content["tag_ranges"]) + except KytosInvalidRanges as err: + raise HTTPException(400, detail=err) interface_id = request.path_params["interface_id"] interface = self.controller.get_interface_by_id(interface_id) if not interface: diff --git a/requirements/dev.in b/requirements/dev.in index bc9754c..12a7ac1 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -1,3 +1,3 @@ -e git+https://github.com/kytos-ng/python-openflow.git#egg=python-openflow --e git+https://github.com/kytos-ng/kytos.git#egg=kytos[dev] +-e git+https://github.com/kytos-ng/kytos.git@epic/vlan_range#egg=kytos[dev] -e . diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index c474c60..a5699df 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -13,7 +13,6 @@ KytosTagtypeNotSupported) from kytos.core.interface import Interface from kytos.core.link import Link -from kytos.core.rest_api import HTTPException from kytos.core.switch import Switch from kytos.lib.helpers import (get_interface_mock, get_link_mock, get_controller_mock, get_switch_mock, @@ -1630,57 +1629,6 @@ def test_interruption_end( assert mock_notify_link_status_change.call_count == 2 mock_notify_topology_update.assert_called_once() - def test_map_singular_values(self): - """Test map_singular_values""" - mock_tag = 201 - result = self.napp.map_singular_values(mock_tag) - assert result == [201, 201] - - mock_tag = [201] - result = self.napp.map_singular_values(mock_tag) - assert result == [201, 201] - - def test_get_tag_ranges(self): - """Test _get_tag_ranges""" - mock_content = {'tag_ranges': [100, [150], [200, 3000]]} - result = self.napp._get_tag_ranges(mock_content) - assert result == [[100, 100], [150, 150], [200, 3000]] - - # Empty - mock_content = {'tag_ranges': []} - with pytest.raises(HTTPException): - self.napp._get_tag_ranges(mock_content) - - # Range not ordered - mock_content = {'tag_ranges': [[20, 19]]} - with pytest.raises(HTTPException): - self.napp._get_tag_ranges(mock_content) - - # Ranges not ordered - mock_content = {'tag_ranges': [[20, 50], [30, 3000]]} - with pytest.raises(HTTPException): - self.napp._get_tag_ranges(mock_content) - - # Unnecessary partition - mock_content = {'tag_ranges': [[20, 50], [51, 3000]]} - with pytest.raises(HTTPException): - self.napp._get_tag_ranges(mock_content) - - # Repeated tag - mock_content = {'tag_ranges': [[20, 50], [50, 3000]]} - with pytest.raises(HTTPException): - self.napp._get_tag_ranges(mock_content) - - # Over 4095 - mock_content = {'tag_ranges': [[20, 50], [50, 4096]]} - with pytest.raises(HTTPException): - self.napp._get_tag_ranges(mock_content) - - # Under 1 - mock_content = {'tag_ranges': [[0, 50], [50, 3000]]} - with pytest.raises(HTTPException): - self.napp._get_tag_ranges(mock_content) - async def test_set_tag_range(self, event_loop): """Test set_tag_range""" self.napp.controller.loop = event_loop From cec922c097e82f8b9b9ef8294103e890b569dc17 Mon Sep 17 00:00:00 2001 From: Aldo Ortega Date: Thu, 9 Nov 2023 03:32:38 -0500 Subject: [PATCH 2/4] Adjusted exceptions --- main.py | 18 +++++++----------- tests/unit/test_main.py | 8 +++++--- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/main.py b/main.py index 5f027e7..5732ee3 100644 --- a/main.py +++ b/main.py @@ -12,9 +12,8 @@ from kytos.core import KytosEvent, KytosNApp, log, rest from kytos.core.common import EntityStatus -from kytos.core.exceptions import (KytosInvalidRanges, KytosLinkCreationError, - KytosSetTagRangeError, - KytosTagtypeNotSupported) +from kytos.core.exceptions import (KytosInvalidTagRanges, + KytosLinkCreationError, KytosTagError) from kytos.core.helpers import listen_to, load_spec, now, validate_openapi from kytos.core.interface import Interface from kytos.core.link import Link @@ -496,8 +495,8 @@ def set_tag_range(self, request: Request) -> JSONResponse: tag_type = content.get("tag_type") try: ranges = get_tag_ranges(content["tag_ranges"]) - except KytosInvalidRanges as err: - raise HTTPException(400, detail=err) + except KytosInvalidTagRanges as err: + raise HTTPException(400, detail=str(err)) interface_id = request.path_params["interface_id"] interface = self.controller.get_interface_by_id(interface_id) if not interface: @@ -505,11 +504,8 @@ def set_tag_range(self, request: Request) -> JSONResponse: try: interface.set_tag_ranges(ranges, tag_type) self.handle_on_interface_tags(interface) - except KytosSetTagRangeError as err: - detail = f"The new tag_ranges cannot be applied {err}" - raise HTTPException(400, detail=detail) - except KytosTagtypeNotSupported as err: - detail = f"Error with tag_type. {err}" + except KytosTagError as err: + detail = f"Error when setting tag ranges: {err}" raise HTTPException(400, detail=detail) return JSONResponse("Operation Successful", status_code=200) @@ -526,7 +522,7 @@ def delete_tag_range(self, request: Request) -> JSONResponse: try: interface.remove_tag_ranges(tag_type) self.handle_on_interface_tags(interface) - except KytosTagtypeNotSupported as err: + except KytosTagError as err: detail = f"Error with tag_type. {err}" raise HTTPException(400, detail=detail) return JSONResponse("Operation Successful", status_code=200) diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index a5699df..2fa7a04 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -1675,7 +1675,7 @@ async def test_set_tag_range_tag_error(self, event_loop): mock_switch = get_switch_mock(dpid) mock_interface = get_interface_mock('s1-eth1', 1, mock_switch) mock_interface.set_tag_ranges = MagicMock() - mock_interface.set_tag_ranges.side_effect = KytosSetTagRangeError() + mock_interface.set_tag_ranges.side_effect = KytosSetTagRangeError("") mock_interface.notify_interface_tags = MagicMock() self.napp.controller.get_interface_by_id = MagicMock() self.napp.controller.get_interface_by_id.return_value = mock_interface @@ -1696,7 +1696,9 @@ async def test_set_tag_range_type_error(self, event_loop): mock_switch = get_switch_mock(dpid) mock_interface = get_interface_mock('s1-eth1', 1, mock_switch) mock_interface.set_tag_ranges = MagicMock() - mock_interface.set_tag_ranges.side_effect = KytosTagtypeNotSupported() + mock_interface.set_tag_ranges.side_effect = KytosTagtypeNotSupported( + "" + ) self.napp.handle_on_interface_tags = MagicMock() self.napp.controller.get_interface_by_id = MagicMock() self.napp.controller.get_interface_by_id.return_value = mock_interface @@ -1749,7 +1751,7 @@ async def test_delete_tag_range_type_error(self, event_loop): mock_interface = get_interface_mock('s1-eth1', 1, mock_switch) mock_interface.remove_tag_ranges = MagicMock() remove_tag = mock_interface.remove_tag_ranges - remove_tag.side_effect = KytosTagtypeNotSupported() + remove_tag.side_effect = KytosTagtypeNotSupported("") self.napp.controller.get_interface_by_id = MagicMock() self.napp.controller.get_interface_by_id.return_value = mock_interface url = f"{self.base_endpoint}/interfaces/{interface_id}/tag_ranges" From f4cf741c6bcaac82acedba0e9e0ecb0bacab17ea Mon Sep 17 00:00:00 2001 From: Aldo Ortega Date: Thu, 9 Nov 2023 15:43:38 -0500 Subject: [PATCH 3/4] Updated exception msg --- main.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 5732ee3..083c8c8 100644 --- a/main.py +++ b/main.py @@ -505,8 +505,7 @@ def set_tag_range(self, request: Request) -> JSONResponse: interface.set_tag_ranges(ranges, tag_type) self.handle_on_interface_tags(interface) except KytosTagError as err: - detail = f"Error when setting tag ranges: {err}" - raise HTTPException(400, detail=detail) + raise HTTPException(400, detail=str(err)) return JSONResponse("Operation Successful", status_code=200) @rest('v3/interfaces/{interface_id}/tag_ranges', methods=['DELETE']) @@ -523,8 +522,7 @@ def delete_tag_range(self, request: Request) -> JSONResponse: interface.remove_tag_ranges(tag_type) self.handle_on_interface_tags(interface) except KytosTagError as err: - detail = f"Error with tag_type. {err}" - raise HTTPException(400, detail=detail) + raise HTTPException(400, detail=str(err)) return JSONResponse("Operation Successful", status_code=200) @rest('v3/interfaces/tag_ranges', methods=['GET']) From 163701995cde73a7afab529a13aec6f99cbb01f4 Mon Sep 17 00:00:00 2001 From: Aldo Ortega Date: Tue, 21 Nov 2023 09:23:20 -0500 Subject: [PATCH 4/4] Reverted dev.in --- requirements/dev.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev.in b/requirements/dev.in index 12a7ac1..bc9754c 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -1,3 +1,3 @@ -e git+https://github.com/kytos-ng/python-openflow.git#egg=python-openflow --e git+https://github.com/kytos-ng/kytos.git@epic/vlan_range#egg=kytos[dev] +-e git+https://github.com/kytos-ng/kytos.git#egg=kytos[dev] -e .