From cffab215937521b17e3e2006183edd66c5dcd4a6 Mon Sep 17 00:00:00 2001 From: ApurveKaranwal Date: Sat, 11 Jul 2026 21:45:58 +0530 Subject: [PATCH] [fix] Fixed SubnetDivisionIndex foreign keys saved as NULL #1435 Ensured that the subnet and ip foreign keys are populated correctly on SubnetDivisionIndex records during initial provisioning and when updating the number of IPs. Closes #1435 --- .../subnet_division/rule_types/base.py | 6 +-- openwisp_controller/subnet_division/tasks.py | 2 +- .../subnet_division/tests/test_models.py | 42 +++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/openwisp_controller/subnet_division/rule_types/base.py b/openwisp_controller/subnet_division/rule_types/base.py index e22c565ca..2b959c008 100644 --- a/openwisp_controller/subnet_division/rule_types/base.py +++ b/openwisp_controller/subnet_division/rule_types/base.py @@ -256,7 +256,7 @@ def create_subnets(config, division_rule, max_subnet, generated_indexes): generated_indexes.append( SubnetDivisionIndex( keyword=f"{division_rule.label}_subnet{subnet_id}", - subnet_id=subnet_obj.id, + subnet=subnet_obj, rule_id=division_rule.id, config=config, ) @@ -294,8 +294,8 @@ def create_ips(config, division_rule, generated_subnets, generated_indexes): generated_indexes.append( SubnetDivisionIndex( keyword=f"{subnet_obj.name}_ip{keyword_index}", - subnet_id=subnet_obj.id, - ip_id=ip_obj.id, + subnet=subnet_obj, + ip=ip_obj, rule_id=division_rule.id, config=config, ) diff --git a/openwisp_controller/subnet_division/tasks.py b/openwisp_controller/subnet_division/tasks.py index 998e9a1c2..612dea16e 100644 --- a/openwisp_controller/subnet_division/tasks.py +++ b/openwisp_controller/subnet_division/tasks.py @@ -118,7 +118,7 @@ def _create_ipaddress_and_subnetdivision_index_objects(ips, indexes): SubnetDivisionIndex( keyword=f"{division_rule.label}_subnet{subnet.id}_ip{ip_id}", subnet_id=subnet.id, - ip_id=ip.id, + ip=ip, rule_id=division_rule.id, config_id=index.config_id, ) diff --git a/openwisp_controller/subnet_division/tests/test_models.py b/openwisp_controller/subnet_division/tests/test_models.py index 071fb576f..08b98d52b 100644 --- a/openwisp_controller/subnet_division/tests/test_models.py +++ b/openwisp_controller/subnet_division/tests/test_models.py @@ -1050,6 +1050,48 @@ def test_invalid_master_subnet(self): e.message_dict.get("master_subnet", []), ) + def test_subnet_division_index_integrity(self): + rule = self._get_vpn_subdivision_rule() + self.config.templates.add(self.template) + + # Verify initial indexes have non-NULL subnet_id and ip_id + # (if they are IP indexes) + indexes = rule.subnetdivisionindex_set.all() + self.assertTrue(indexes.exists()) + initial_count = indexes.count() + for index in indexes: + self.assertIsNotNone( + index.subnet_id, + f"SubnetDivisionIndex {index.keyword} has NULL subnet_id", + ) + if "_ip" in index.keyword: + self.assertIsNotNone( + index.ip_id, + f"SubnetDivisionIndex {index.keyword} has NULL ip_id", + ) + + # Update number of IPs to trigger tasks.provision_extra_ips + rule.number_of_ips = rule.number_of_ips + 2 + rule.save() + rule.refresh_from_db() + + # Verify count increased and all indexes, including new ones, + # have non-NULL subnet_id and ip_id + new_indexes = rule.subnetdivisionindex_set.all() + self.assertEqual( + new_indexes.count(), initial_count + (rule.number_of_subnets * 2) + ) + for index in new_indexes: + self.assertIsNotNone( + index.subnet_id, + f"SubnetDivisionIndex {index.keyword} has NULL subnet_id after update", + ) + if "_ip" in index.keyword: + self.assertIsNotNone( + index.ip_id, + f"SubnetDivisionIndex {index.keyword} has NULL ip_id after update", + ) + class TestOpenVPNSubnetDivisionRule( SubnetDivisionTestMixin,