From 0f56f2ab2c2dd02bc992b54aacc6e3ac8197d6f0 Mon Sep 17 00:00:00 2001 From: Juliana Cardozo <93846188+boubeejul@users.noreply.github.com> Date: Thu, 21 May 2026 20:36:04 +0000 Subject: [PATCH 1/6] add PATCH to v3/networkv4/force/ --- networkapi/api_network/facade/v3/__init__.py | 3 +- networkapi/api_network/facade/v3/networkv4.py | 26 ++++++++++++++ networkapi/api_network/specs/netv4_patch.json | 28 +++++++++++++++ networkapi/api_network/views/v3/networkv4.py | 18 ++++++++++ networkapi/ip/models.py | 35 +++++++++++++++++++ networkapi/settings.py | 4 +++ 6 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 networkapi/api_network/specs/netv4_patch.json diff --git a/networkapi/api_network/facade/v3/__init__.py b/networkapi/api_network/facade/v3/__init__.py index 11e6ca2af..6c0d8be8c 100644 --- a/networkapi/api_network/facade/v3/__init__.py +++ b/networkapi/api_network/facade/v3/__init__.py @@ -21,6 +21,7 @@ from .networkv4 import get_networkipv4_by_search from .networkv4 import undeploy_networkipv4 from .networkv4 import update_networkipv4 +from .networkv4 import patch_networkipv4 from .networkv6 import create_networkipv6 from .networkv6 import delete_networkipv6 from .networkv6 import deploy_networkipv6 @@ -33,7 +34,7 @@ __all__ = ( 'get_networkipv4_by_id', 'get_networkipv4_by_ids', 'get_networkipv4_by_search', 'create_networkipv4', - 'update_networkipv4', 'delete_networkipv4', 'undeploy_networkipv4', + 'update_networkipv4', 'patch_networkipv4', 'delete_networkipv4', 'undeploy_networkipv4', 'deploy_networkipv4', 'get_networkipv6_by_id', 'get_networkipv6_by_ids', 'get_networkipv6_by_search', 'create_networkipv6', 'update_networkipv6', 'delete_networkipv6', 'undeploy_networkipv6', 'deploy_networkipv6') diff --git a/networkapi/api_network/facade/v3/networkv4.py b/networkapi/api_network/facade/v3/networkv4.py index fa4e95b19..3718ec50a 100644 --- a/networkapi/api_network/facade/v3/networkv4.py +++ b/networkapi/api_network/facade/v3/networkv4.py @@ -130,6 +130,32 @@ def update_networkipv4(networkv4, user, force=False): return netv4_obj +def patch_networkipv4(networkv4, user, force=False): + """Patches a NetworkIPv4.""" + + try: + netv4_obj = get_networkipv4_by_id(networkv4.get('id')) + netv4_obj.patch_v3(networkv4, force=force) + + except ObjectDoesNotExistException, e: + raise ObjectDoesNotExistException(e.detail) + + except ip_models.NetworkIPv4ErrorV3, e: + raise ValidationAPIException(e.message) + + except exceptions.InvalidInputException, e: + raise ValidationAPIException(e.detail) + + except ValidationAPIException, e: + raise ValidationAPIException(e.detail) + + except Exception, e: + raise NetworkAPIException(str(e)) + + else: + return netv4_obj + + def delete_networkipv4(network_ids, user, force=False): """Deletes a list of NetworkIPv4.""" diff --git a/networkapi/api_network/specs/netv4_patch.json b/networkapi/api_network/specs/netv4_patch.json new file mode 100644 index 000000000..37c3f168d --- /dev/null +++ b/networkapi/api_network/specs/netv4_patch.json @@ -0,0 +1,28 @@ +{ + "title": "NetworkIPv4 Patch", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "required": [ + "networks" + ], + "properties": { + "networks": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "active": { + "type": "boolean" + } + }, + "required": [ + "id" + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/networkapi/api_network/views/v3/networkv4.py b/networkapi/api_network/views/v3/networkv4.py index 9d8431a4f..b47331ed9 100644 --- a/networkapi/api_network/views/v3/networkv4.py +++ b/networkapi/api_network/views/v3/networkv4.py @@ -337,6 +337,24 @@ def put(self, request, *args, **kwargs): return Response(response, status=status.HTTP_200_OK) + @logs_method_apiview + @raise_json_validate('networkv4_patch') + @permission_classes_apiview((IsAuthenticated, permissions.WriteForce)) + @commit_on_success + def patch(self, request, *args, **kwargs): + """Patches list of networkv4.""" + + data = request.DATA + + json_validate(SPECS.get('networkv4_patch')).validate(data) + + response = list() + for networkv4 in data['networks']: + vl = facade.patch_networkipv4(networkv4, request.user, force=True) + response.append({'id': vl.id, 'active': vl.active}) + + return Response(response, status=status.HTTP_200_OK) + @logs_method_apiview @raise_json_validate('') @permission_classes_apiview((IsAuthenticated, permissions.WriteForce)) diff --git a/networkapi/ip/models.py b/networkapi/ip/models.py index 4867fe907..d9e55d0a7 100644 --- a/networkapi/ip/models.py +++ b/networkapi/ip/models.py @@ -918,6 +918,41 @@ def update_v3(self, networkv4, locks_used=[], force=False): finally: destroy_lock(locks_list) + def patch_v3(self, networkv4, locks_used=[], force=False): + """Patch networkipv4.""" + + try: + if force: + self.active = networkv4.get('active', self.active) + + except Exception, e: + self.log.error(e) + raise NetworkIPv4ErrorV3(e) + + else: + # Create locks for network + locks_name = list() + lock_name = LOCK_NETWORK_IPV4 % self.id + if lock_name not in locks_used: + locks_name.append(lock_name) + + locks_list = create_lock_with_blocking(locks_name) + + try: + self.validate_v3() + self.save() + + except NetworkIPv4ErrorV3, e: + self.log.error(e.message) + raise NetworkIPv4ErrorV3(e.message) + + except Exception, e: + self.log.error(e) + raise NetworkIPv4ErrorV3(e) + + finally: + destroy_lock(locks_list) + def delete_v3(self, locks_used=[], force=False): """Method V3 to remove NetworkIPv4. diff --git a/networkapi/settings.py b/networkapi/settings.py index fbd44242d..2f0b2d605 100644 --- a/networkapi/settings.py +++ b/networkapi/settings.py @@ -474,6 +474,10 @@ def local_files(path): PROJECT_ROOT_PATH, 'api_network/specs/netv4_put.json' ), + 'networkv4_patch': os.path.join( + PROJECT_ROOT_PATH, + 'api_network/specs/netv4_patch.json' + ), 'networkv6_post': os.path.join( PROJECT_ROOT_PATH, 'api_network/specs/netv6_post.json' From fa41c6d045d67992d51d6c9eb58eb749ccace7a7 Mon Sep 17 00:00:00 2001 From: Iuri Malinoski Date: Fri, 22 May 2026 16:17:46 -0300 Subject: [PATCH 2/6] Including brand to GET interface search --- networkapi/api_interface/serializers.py | 7 +++++- .../sanity/interface/test_interface_get.py | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/networkapi/api_interface/serializers.py b/networkapi/api_interface/serializers.py index de120b064..b566fc4f2 100644 --- a/networkapi/api_interface/serializers.py +++ b/networkapi/api_interface/serializers.py @@ -281,7 +281,12 @@ def get_serializers(self): 'equipment__basic': { 'serializer': equipment_serializers.EquipmentV3Serializer, 'kwargs': { - 'kind': 'basic' + 'kind': 'details', + 'fields': ( + 'id', + 'name', + 'model__details__brand', + ) }, 'obj': 'equipamento', }, diff --git a/networkapi/api_interface/tests/sanity/interface/test_interface_get.py b/networkapi/api_interface/tests/sanity/interface/test_interface_get.py index 3382a38b1..9934f8fa9 100644 --- a/networkapi/api_interface/tests/sanity/interface/test_interface_get.py +++ b/networkapi/api_interface/tests/sanity/interface/test_interface_get.py @@ -73,3 +73,28 @@ def test_get_interface_by_search(self): self.compare_status(200, response.status_code) self.compare_json(expected_data, response.data["interfaces"]) + + def test_get_interface_list_with_equipment_model_brand(self): + """Test list interfaces returning equipment model brand.""" + + search = urllib.urlencode({'extends_search': [], + 'start_record': 0, + 'custom_search': '', + 'end_record': 10000, + 'asorting_cols': ['id'], + 'searchable_columns': ['id']}) + + url = '/api/v3/interface/?search=%s&include=equipment__basic' % search + + response = self.client.get(url, + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + interface = response.data['interfaces'][0] + equipment = interface['equipment'] + + self.assertEqual(['id', 'model', 'name'], sorted(equipment.keys())) + self.assertEqual(['brand', 'id', 'name'], sorted(equipment['model'].keys())) + self.assertEqual(['id', 'name'], sorted(equipment['model']['brand'].keys())) From bf4adefd7a30a881a567e50cd97ac4be38b53fdf Mon Sep 17 00:00:00 2001 From: Juliana Cardozo <93846188+boubeejul@users.noreply.github.com> Date: Mon, 25 May 2026 13:54:27 +0000 Subject: [PATCH 3/6] add PATCH to v3/networkv6/force/ --- networkapi/api_network/facade/v3/__init__.py | 3 +- networkapi/api_network/facade/v3/networkv6.py | 26 ++++++++++++++ networkapi/api_network/specs/netv6_patch.json | 28 +++++++++++++++ networkapi/api_network/views/v3/networkv6.py | 18 ++++++++++ networkapi/ip/models.py | 35 +++++++++++++++++++ networkapi/settings.py | 4 +++ 6 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 networkapi/api_network/specs/netv6_patch.json diff --git a/networkapi/api_network/facade/v3/__init__.py b/networkapi/api_network/facade/v3/__init__.py index 6c0d8be8c..fa6f09591 100644 --- a/networkapi/api_network/facade/v3/__init__.py +++ b/networkapi/api_network/facade/v3/__init__.py @@ -30,11 +30,12 @@ from .networkv6 import get_networkipv6_by_search from .networkv6 import undeploy_networkipv6 from .networkv6 import update_networkipv6 +from .networkv6 import patch_networkipv6 __all__ = ( 'get_networkipv4_by_id', 'get_networkipv4_by_ids', 'get_networkipv4_by_search', 'create_networkipv4', 'update_networkipv4', 'patch_networkipv4', 'delete_networkipv4', 'undeploy_networkipv4', 'deploy_networkipv4', 'get_networkipv6_by_id', 'get_networkipv6_by_ids', - 'get_networkipv6_by_search', 'create_networkipv6', 'update_networkipv6', + 'get_networkipv6_by_search', 'create_networkipv6', 'update_networkipv6', 'patch_networkipv6', 'delete_networkipv6', 'undeploy_networkipv6', 'deploy_networkipv6') diff --git a/networkapi/api_network/facade/v3/networkv6.py b/networkapi/api_network/facade/v3/networkv6.py index 6504d1903..d874a9894 100644 --- a/networkapi/api_network/facade/v3/networkv6.py +++ b/networkapi/api_network/facade/v3/networkv6.py @@ -130,6 +130,32 @@ def update_networkipv6(networkv6, user, force=False): return netv6_obj +def patch_networkipv6(networkv6, user, force=False): + """Patches a NetworkIPv6.""" + + try: + netv6_obj = get_networkipv6_by_id(networkv6.get('id')) + netv6_obj.patch_v3(networkv6, force=force) + + except ObjectDoesNotExistException, e: + raise ObjectDoesNotExistException(e.detail) + + except ip_models.NetworkIPv6ErrorV3, e: + raise ValidationAPIException(e.message) + + except exceptions.InvalidInputException, e: + raise ValidationAPIException(e.detail) + + except ValidationAPIException, e: + raise ValidationAPIException(e.detail) + + except Exception, e: + raise NetworkAPIException(str(e)) + + else: + return netv6_obj + + def delete_networkipv6(network_ids, user, force=False): """Deletes a list of NetworkIPv6.""" diff --git a/networkapi/api_network/specs/netv6_patch.json b/networkapi/api_network/specs/netv6_patch.json new file mode 100644 index 000000000..9f8443bf9 --- /dev/null +++ b/networkapi/api_network/specs/netv6_patch.json @@ -0,0 +1,28 @@ +{ + "title": "NetworkIPv6 Patch", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "required": [ + "networks" + ], + "properties": { + "networks": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "active": { + "type": "boolean" + } + }, + "required": [ + "id" + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/networkapi/api_network/views/v3/networkv6.py b/networkapi/api_network/views/v3/networkv6.py index 04bdf24ab..20d1d785d 100644 --- a/networkapi/api_network/views/v3/networkv6.py +++ b/networkapi/api_network/views/v3/networkv6.py @@ -337,6 +337,24 @@ def put(self, request, *args, **kwargs): return Response(response, status=status.HTTP_200_OK) + @logs_method_apiview + @raise_json_validate('networkv6_patch') + @permission_classes_apiview((IsAuthenticated, permissions.WriteForce)) + @commit_on_success + def patch(self, request, *args, **kwargs): + """Patches list of networkv6.""" + + data = request.DATA + + json_validate(SPECS.get('networkv6_patch')).validate(data) + + response = list() + for networkv6 in data['networks']: + vl = facade.patch_networkipv6(networkv6, request.user, force=True) + response.append({'id': vl.id, 'active': vl.active}) + + return Response(response, status=status.HTTP_200_OK) + @logs_method_apiview @raise_json_validate('') @permission_classes_apiview((IsAuthenticated, permissions.WriteForce)) diff --git a/networkapi/ip/models.py b/networkapi/ip/models.py index d9e55d0a7..260f3f04e 100644 --- a/networkapi/ip/models.py +++ b/networkapi/ip/models.py @@ -3298,6 +3298,41 @@ def update_v3(self, networkv6, locks_used=[], force=False): finally: destroy_lock(locks_list) + def patch_v3(self, networkv6, locks_used=[], force=False): + """Patch networkipv6.""" + + try: + if force: + self.active = networkv6.get('active', self.active) + + except Exception, e: + self.log.error(e) + raise NetworkIPv6ErrorV3(e) + + else: + # Create locks for network + locks_name = list() + lock_name = LOCK_NETWORK_IPV6 % self.id + if lock_name not in locks_used: + locks_name.append(lock_name) + + locks_list = create_lock_with_blocking(locks_name) + + try: + self.validate_v3() + self.save() + + except NetworkIPv6ErrorV3, e: + self.log.error(e.message) + raise NetworkIPv6ErrorV3(e.message) + + except Exception, e: + self.log.error(e) + raise NetworkIPv6ErrorV3(e) + + finally: + destroy_lock(locks_list) + def delete_v3(self, locks_used=[], force=False): """Method V3 to remove networkIPv6. diff --git a/networkapi/settings.py b/networkapi/settings.py index 2f0b2d605..ea5e647d1 100644 --- a/networkapi/settings.py +++ b/networkapi/settings.py @@ -482,6 +482,10 @@ def local_files(path): PROJECT_ROOT_PATH, 'api_network/specs/netv6_post.json' ), + 'networkv6_patch': os.path.join( + PROJECT_ROOT_PATH, + 'api_network/specs/netv6_patch.json' + ), 'networkv6_put': os.path.join( PROJECT_ROOT_PATH, 'api_network/specs/netv6_put.json' From c5d118b7f2454103176ae9f47867722b2b42a72d Mon Sep 17 00:00:00 2001 From: Juliana Cardozo <93846188+boubeejul@users.noreply.github.com> Date: Tue, 26 May 2026 16:44:43 +0000 Subject: [PATCH 4/6] add PATCH to /v3/vlan/ --- docs/vlan/url-api-v3-vlan.rst | 1 + docs/vlan/url-api-v3-vlan/patch.rst | 37 +++++++++++++++++++++++ networkapi/api_vlan/facade/v3.py | 16 ++++++++++ networkapi/api_vlan/specs/vlan_patch.json | 28 +++++++++++++++++ networkapi/api_vlan/views/v3.py | 19 ++++++++++++ networkapi/settings.py | 4 +++ networkapi/vlan/models.py | 28 +++++++++++++++++ 7 files changed, 133 insertions(+) create mode 100644 docs/vlan/url-api-v3-vlan/patch.rst create mode 100644 networkapi/api_vlan/specs/vlan_patch.json diff --git a/docs/vlan/url-api-v3-vlan.rst b/docs/vlan/url-api-v3-vlan.rst index 9f8a9f4b1..dcf1d9a99 100644 --- a/docs/vlan/url-api-v3-vlan.rst +++ b/docs/vlan/url-api-v3-vlan.rst @@ -6,3 +6,4 @@ url-api-v3-vlan/post url-api-v3-vlan/put url-api-v3-vlan/delete + url-api-v3-vlan/patch diff --git a/docs/vlan/url-api-v3-vlan/patch.rst b/docs/vlan/url-api-v3-vlan/patch.rst new file mode 100644 index 000000000..5731db99a --- /dev/null +++ b/docs/vlan/url-api-v3-vlan/patch.rst @@ -0,0 +1,37 @@ +PATCH +##### + +.. _url-api-v3-vlan-patch-partially-update-list-vlans: + +Partially updating list of Vlans in database +******************************************** + +URL:: + + /api/v3/vlan/ + +Request body: + +.. code-block:: json + + { + "vlans": [{ + "id": [integer], + "active": [boolean] + },..] + } + +Request Example: + +.. code-block:: json + + { + "vlans": [{ + "id": 1, + "active": false + }] + } + +In Vlan PATCH request, you only need to specify the fields you want to change. For now, only **active** field can be changed. + +* **active** - If not specified, Vlan will be the same as before. If specified, it will be updated with the new value. diff --git a/networkapi/api_vlan/facade/v3.py b/networkapi/api_vlan/facade/v3.py index b109665d5..74a146260 100644 --- a/networkapi/api_vlan/facade/v3.py +++ b/networkapi/api_vlan/facade/v3.py @@ -70,6 +70,22 @@ def update_vlan(vlan, user): return vlan_obj +def patch_vlan(vlan, user): + """Patch vlan.""" + + try: + vlan_obj = get_vlan_by_id(vlan.get('id')) + vlan_obj.patch_v3(vlan, user) + except ObjectDoesNotExistException, e: + raise ObjectDoesNotExistException(str(e)) + except (VlanError, VlanErrorV3, ValidationAPIException), e: + raise ValidationAPIException(str(e)) + except (Exception, NetworkAPIException), e: + raise NetworkAPIException(str(e)) + else: + return vlan_obj + + def create_vlan(vlan, user): """Create vlan.""" diff --git a/networkapi/api_vlan/specs/vlan_patch.json b/networkapi/api_vlan/specs/vlan_patch.json new file mode 100644 index 000000000..fdf8c0126 --- /dev/null +++ b/networkapi/api_vlan/specs/vlan_patch.json @@ -0,0 +1,28 @@ +{ + "title": "Vlan Patch", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "required": [ + "vlans" + ], + "properties": { + "vlans": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "active": { + "type": "boolean" + } + }, + "required": [ + "id" + ], + "additionalProperties": false + } + } + } +} \ No newline at end of file diff --git a/networkapi/api_vlan/views/v3.py b/networkapi/api_vlan/views/v3.py index cb06a8ee1..9ac4c39b5 100644 --- a/networkapi/api_vlan/views/v3.py +++ b/networkapi/api_vlan/views/v3.py @@ -172,6 +172,25 @@ def put(self, request, *args, **kwargs): return Response(response, status=status.HTTP_202_ACCEPTED) + @logs_method_apiview + @raise_json_validate('vlan_patch') + @permission_classes_apiview((IsAuthenticated, permissions.Write)) + @permission_obj_apiview([permissions.write_obj_permission]) + @commit_on_success + def patch(self, request, *args, **kwargs): + """Patches list of vlans.""" + + data = request.DATA + + json_validate(SPECS.get('vlan_patch')).validate(data) + + response = list() + for vlan in data['vlans']: + vl = facade.patch_vlan(vlan, request.user) + response.append({'id': vl.id, 'active': vl.ativada}) + + return Response(response, status=status.HTTP_200_OK) + @logs_method_apiview @raise_json_validate('') @permission_classes_apiview((IsAuthenticated, permissions.Write)) diff --git a/networkapi/settings.py b/networkapi/settings.py index ea5e647d1..a9d909b2c 100644 --- a/networkapi/settings.py +++ b/networkapi/settings.py @@ -518,6 +518,10 @@ def local_files(path): PROJECT_ROOT_PATH, 'api_vlan/specs/vlan_post.json' ), + 'vlan_patch': os.path.join( + PROJECT_ROOT_PATH, + 'api_vlan/specs/vlan_patch.json' + ), 'vlan_put': os.path.join( PROJECT_ROOT_PATH, 'api_vlan/specs/vlan_put.json' diff --git a/networkapi/vlan/models.py b/networkapi/vlan/models.py index 666e63f29..2a25c8c16 100644 --- a/networkapi/vlan/models.py +++ b/networkapi/vlan/models.py @@ -1260,6 +1260,34 @@ def update_v3(self, vlan, user): return self + def patch_v3(self, vlan, user): + """Patch vlan.""" + + try: + self.ativada = vlan.get('active', self.ativada) + + except Exception, e: + raise VlanErrorV3(e) + + else: + # Prepare locks for vlan + locks_name = [LOCK_VLAN % self.id] + locks_list = create_lock_with_blocking(locks_name) + + try: + # validate name and number + #self.validate_v3() + self.save() + + except Exception, e: + raise VlanErrorV3(e) + + finally: + # Destroy locks + destroy_lock(locks_list) + + return self + def delete_v3(self): ogp_models = get_app('api_ogp', 'models') ipcantberemovedfromvip = get_model('ip', 'IpCantBeRemovedFromVip') From a59b74bf96b63794a76439ccbe6d5eb85118f1f0 Mon Sep 17 00:00:00 2001 From: Juliana Cardozo <93846188+boubeejul@users.noreply.github.com> Date: Wed, 27 May 2026 13:24:56 +0000 Subject: [PATCH 5/6] change patch method from VlanAsyncView to VlanDBView --- networkapi/api_vlan/views/v3.py | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/networkapi/api_vlan/views/v3.py b/networkapi/api_vlan/views/v3.py index 9ac4c39b5..98c480b41 100644 --- a/networkapi/api_vlan/views/v3.py +++ b/networkapi/api_vlan/views/v3.py @@ -101,6 +101,25 @@ def put(self, request, *args, **kwargs): response.append({'id': vl.id}) return Response(response, status=status.HTTP_200_OK) + + @logs_method_apiview + @raise_json_validate('vlan_patch') + @permission_classes_apiview((IsAuthenticated, permissions.Write)) + @permission_obj_apiview([permissions.write_obj_permission]) + @commit_on_success + def patch(self, request, *args, **kwargs): + """Patches list of vlans.""" + + data = request.DATA + + json_validate(SPECS.get('vlan_patch')).validate(data) + + response = list() + for vlan in data['vlans']: + vl = facade.patch_vlan(vlan, request.user) + response.append({'id': vl.id, 'active': vl.ativada}) + + return Response(response, status=status.HTTP_200_OK) @logs_method_apiview @raise_json_validate('') @@ -171,25 +190,6 @@ def put(self, request, *args, **kwargs): response.append(task) return Response(response, status=status.HTTP_202_ACCEPTED) - - @logs_method_apiview - @raise_json_validate('vlan_patch') - @permission_classes_apiview((IsAuthenticated, permissions.Write)) - @permission_obj_apiview([permissions.write_obj_permission]) - @commit_on_success - def patch(self, request, *args, **kwargs): - """Patches list of vlans.""" - - data = request.DATA - - json_validate(SPECS.get('vlan_patch')).validate(data) - - response = list() - for vlan in data['vlans']: - vl = facade.patch_vlan(vlan, request.user) - response.append({'id': vl.id, 'active': vl.ativada}) - - return Response(response, status=status.HTTP_200_OK) @logs_method_apiview @raise_json_validate('') From db0dd169e90450977f7c75da97675bfc405b8759 Mon Sep 17 00:00:00 2001 From: Juliana Cardozo <93846188+boubeejul@users.noreply.github.com> Date: Wed, 27 May 2026 17:17:09 +0000 Subject: [PATCH 6/6] fix exception raise and add message for network validation in PATCH without CIDR --- networkapi/ambiente/models.py | 3 +++ networkapi/api_network/facade/v3/networkv4.py | 2 +- networkapi/api_network/facade/v3/networkv6.py | 2 +- networkapi/api_vlan/urls.py | 4 ++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/networkapi/ambiente/models.py b/networkapi/ambiente/models.py index c072dc566..5d8c5aec8 100644 --- a/networkapi/ambiente/models.py +++ b/networkapi/ambiente/models.py @@ -2130,6 +2130,9 @@ def get(self, cidr_id=None, env_id=None): objects = EnvCIDR.objects.filter(id_env=env_id) if not objects: log.debug('There is no CIDR linked with the environment id=%s.' % env_id) + raise ObjectDoesNotExist + except ObjectDoesNotExist: + raise CIDRErrorV3('There is no CIDR linked with the environment id=%s.' % env_id) except OperationalError as e: self.log.error('Lock wait timeout exceeded.') raise OperationalError(e, 'Lock wait timeout exceeded; try restarting transaction') diff --git a/networkapi/api_network/facade/v3/networkv4.py b/networkapi/api_network/facade/v3/networkv4.py index 3718ec50a..c540d6f4e 100644 --- a/networkapi/api_network/facade/v3/networkv4.py +++ b/networkapi/api_network/facade/v3/networkv4.py @@ -141,7 +141,7 @@ def patch_networkipv4(networkv4, user, force=False): raise ObjectDoesNotExistException(e.detail) except ip_models.NetworkIPv4ErrorV3, e: - raise ValidationAPIException(e.message) + raise ValidationAPIException('NetworkIPv4 id=%s - %s' % (netv4_obj.id, str(e))) except exceptions.InvalidInputException, e: raise ValidationAPIException(e.detail) diff --git a/networkapi/api_network/facade/v3/networkv6.py b/networkapi/api_network/facade/v3/networkv6.py index d874a9894..5c4f0bbd5 100644 --- a/networkapi/api_network/facade/v3/networkv6.py +++ b/networkapi/api_network/facade/v3/networkv6.py @@ -141,7 +141,7 @@ def patch_networkipv6(networkv6, user, force=False): raise ObjectDoesNotExistException(e.detail) except ip_models.NetworkIPv6ErrorV3, e: - raise ValidationAPIException(e.message) + raise ValidationAPIException('NetworkIPv6 id=%s - %s' % (netv6_obj.id, str(e))) except exceptions.InvalidInputException, e: raise ValidationAPIException(e.detail) diff --git a/networkapi/api_vlan/urls.py b/networkapi/api_vlan/urls.py index 4138e063b..cce33e994 100644 --- a/networkapi/api_vlan/urls.py +++ b/networkapi/api_vlan/urls.py @@ -30,7 +30,7 @@ ######################## # Vlan V3 ######################## - url(r'^v3/vlan/async/((?P[;\w]+)/)?$', + url(r'^v3/vlan/async(?:/(?P[;\w]+))?/?$', views.VlanAsyncView.as_view()), - url(r'^v3/vlan/((?P[;\w]+)/)?$', views.VlanDBView.as_view()), + url(r'^v3/vlan(?:/(?P[;\w]+))?/?$', views.VlanDBView.as_view()), )