diff --git a/openwisp_controller/subnet_division/base/models.py b/openwisp_controller/subnet_division/base/models.py index b6dd58c57..032e3ad76 100644 --- a/openwisp_controller/subnet_division/base/models.py +++ b/openwisp_controller/subnet_division/base/models.py @@ -15,16 +15,6 @@ class AbstractSubnetDivisionRule(TimeStampedEditableModel, OrgMixin): _subnet_division_rule_update_queue = dict() - # It is used to monitor changes in fields of a SubnetDivisionRule object - # An entry is added to the queue from pre_save signal in the following format - # - # ': { - # '': '', - # } - # - # In post_save signal, it is checked whether entry for SubnetDivisionRule object - # exists in this queue. If it exists changes are made to related objects. - type = models.CharField(max_length=200, choices=app_settings.SUBNET_DIVISION_TYPES) master_subnet = models.ForeignKey( swapper.get_model_name("openwisp_ipam", "Subnet"), on_delete=models.CASCADE @@ -35,8 +25,12 @@ class AbstractSubnetDivisionRule(TimeStampedEditableModel, OrgMixin): ) number_of_subnets = models.PositiveSmallIntegerField( verbose_name=_("Number of Subnets"), - help_text=_("Indicates how many subnets will be created"), - validators=[MinValueValidator(1)], + help_text=_( + "Indicates how many subnets will be created. " + "Set to 0 to assign IP addresses directly " + "from the main subnet." + ), + validators=[MinValueValidator(0)], ) size = models.PositiveSmallIntegerField( verbose_name=_("Size of subnets"), @@ -69,6 +63,13 @@ def rule_class(self): return import_string(self.type) def clean(self): + # Auto-fill organization from master subnet + if ( + self.master_subnet_id + and self.master_subnet.organization_id is not None + and not self.organization_id + ): + self.organization_id = self.master_subnet.organization_id super().clean() self._validate_label() self._validate_master_subnet_validity() diff --git a/openwisp_controller/subnet_division/tests/test_models.py b/openwisp_controller/subnet_division/tests/test_models.py index 62e022563..ef5894c3e 100644 --- a/openwisp_controller/subnet_division/tests/test_models.py +++ b/openwisp_controller/subnet_division/tests/test_models.py @@ -129,21 +129,13 @@ def test_field_validations(self): context_manager.exception.message_dict, expected_message_dict ) - with self.subTest("Test rule does not provision any subnet"): + with self.subTest("Test rule allows zero subnets"): options = default_options.copy() options["number_of_subnets"] = 0 rule = SubnetDivisionRule(**options) - with self.assertRaises(ValidationError) as context_manager: - rule.full_clean() - expected_message_dict = { - "number_of_subnets": [ - "Ensure this value is greater than or equal to 1." - ] - } - self.assertDictEqual( - context_manager.exception.message_dict, expected_message_dict - ) - + # Should not raise ValidationError + rule.full_clean() + with self.subTest("Test rule does not provision any IP"): options = default_options.copy() options["number_of_ips"] = 0