Skip to content

[feature] Allow zero subnets in SubnetDivisionRuleFix/allow zero subnets#1287

Open
peterishakvr12 wants to merge 11 commits intoopenwisp:masterfrom
peterishakvr12:fix/allow-zero-subnets
Open

[feature] Allow zero subnets in SubnetDivisionRuleFix/allow zero subnets#1287
peterishakvr12 wants to merge 11 commits intoopenwisp:masterfrom
peterishakvr12:fix/allow-zero-subnets

Conversation

@peterishakvr12
Copy link
Copy Markdown

Reference to Existing Issue

Closes #843

Description of Changes

Allow specifying 0 in the "Number of Subnets" field so that
the rule does not trigger the creation of a new subnet but
just assigns IP addresses directly from the main subnet.

Updated help_text to document the new behavior.

Screenshot

No UI changes, backend model fix only.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change allows AbstractSubnetDivisionRule.number_of_subnets to be 0 by updating its MinValueValidator from 1 to 0 and expanding the help_text to state that 0 means assigning IPs from the main subnet. The model's clean() now auto-fills organization_id from master_subnet.organization_id when master_subnet_id is set and organization_id is not provided. Tests were updated to accept number_of_subnets=0 (removed the expectation that zero raises a ValidationError).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title '[feature] Allow zero subnets in SubnetDivisionRuleFix/allow zero subnets' clearly describes the main change and uses the correct [feature] prefix format, though it contains a redundant suffix after the descriptive text.
Description check ✅ Passed The description addresses the linked issue (#843), explains the changes, and covers the updated help_text. However, it lacks evidence of testing from the checklist items (manually tested, test cases written, documentation updated).
Linked Issues check ✅ Passed The code changes fully satisfy issue #843 by allowing 0 in the number_of_subnets field to assign IP addresses directly from the main subnet, with updated help_text and corresponding test adjustments.
Out of Scope Changes check ✅ Passed All changes are focused on the stated objective of allowing zero subnets in SubnetDivisionRule, with modifications to the model validator, help_text, auto-fill logic, and corresponding tests.
Bug Fixes ✅ Passed This PR implements a feature request (Issue #843) to allow zero subnets, not a bug fix of existing broken functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use your project's `ruff` configuration to improve the quality of Python code reviews.

Add a Ruff configuration file to your project to customize how CodeRabbit runs ruff.

@openwisp-companion
Copy link
Copy Markdown

Black and Flake8 Failures in subnet_division/base/models.py

Hello @peterishakvr12,
(Analysis for commit ba15b67)

There are two distinct failures reported in the CI logs:

  1. Code Style/QA Failure (Black): The Black code formatter failed because it encountered a syntax error in the file openwisp_controller/subnet_division/base/models.py. Specifically, Black could not parse the file due to an "UnterminatedString" error on line 41.

    • Explanation: Black is failing because there's an unterminated string literal in the Python code. This usually means a string was started (e.g., with a quote) but not properly closed before the end of the line or file.
    • Remediation: Run the openwisp-qa-format command to automatically fix the formatting and syntax errors. If the issue persists, manually inspect line 41 of openwisp_controller/subnet_division/base/models.py to ensure all strings are correctly terminated with matching quotes.
  2. Code Style/QA Failure (Flake8): Flake8 also reported a syntax error, specifically an "unterminated string literal (detected at line 41)" in the same file, openwisp_controller/subnet_division/base/models.py.

    • Explanation: Flake8, a linter, detected a syntax error related to an unterminated string literal. This indicates a problem with how strings are defined in the code, likely a missing closing quote.
    • Remediation: Similar to the Black failure, running openwisp-qa-format should resolve this. If manual intervention is needed, check line 41 of openwisp_controller/subnet_division/base/models.py for any unclosed string literals.
  3. Test Failure (SyntaxError): Both the Black and Flake8 failures are rooted in a SyntaxError: unterminated string literal occurring during the Django setup phase, specifically when importing models. This error is preventing the tests from even starting properly.

    • Explanation: The SyntaxError in openwisp_controller/subnet_division/base/models.py at line 41 is causing Django's application registry to fail during django.setup(), which is a prerequisite for running tests. The traceback clearly shows the error originating from this file during the model import process.
    • Remediation: The root cause is the unterminated string literal. Fixing this syntax error in openwisp_controller/subnet_division/base/models.py (likely by adding a closing quote) will resolve the SyntaxError and allow the tests to proceed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openwisp_controller/subnet_division/base/models.py`:
- Around line 38-43: The help_text string literal passed to the model field (the
help_text argument just above validators=[MinValueValidator(0)]) is missing a
closing double-quote; fix by closing the string before the closing parenthesis
so the help_text becomes a valid quoted string literal (i.e., add the missing "
to terminate the string in that field definition).
- Around line 36-44: Test expects number_of_subnets=0 to raise a ValidationError
but the model field number_of_subnets (PositiveSmallIntegerField with
MinValueValidator(0)) deliberately allows 0; update the test in test_models.py
to treat 0 as valid instead of asserting a ValidationError — remove the
assertRaises/validation check for value 0 (or change it to assert that
instance.full_clean() passes or that the instance is valid) and adjust any
expected error message checks accordingly so the test accepts
number_of_subnets=0.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e031f080-985e-4ded-be4c-08d73598c9a8

📥 Commits

Reviewing files that changed from the base of the PR and between f3c99c4 and ba15b67.

📒 Files selected for processing (1)
  • openwisp_controller/subnet_division/base/models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=5.2.0
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

📄 CodeRabbit inference engine (Custom checks)

**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
Avoid unnecessary comments or docstrings for code that is already clear
Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
Flag unused or redundant code
Ensure variables, functions, classes, and files have descriptive and consistent names
New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

📄 CodeRabbit inference engine (Custom checks)

Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • openwisp_controller/subnet_division/base/models.py
🧠 Learnings (3)
📚 Learning: 2026-01-15T15:05:49.557Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
Timestamp: 2026-01-15T15:05:49.557Z
Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
📚 Learning: 2026-02-17T19:13:10.088Z
Learnt from: nemesifier
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/whois/commands.py:0-0
Timestamp: 2026-02-17T19:13:10.088Z
Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
📚 Learning: 2026-01-15T15:07:17.354Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
Timestamp: 2026-01-15T15:07:17.354Z
Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
🔇 Additional comments (1)
openwisp_controller/subnet_division/base/models.py (1)

76-82: LGTM!

The auto-fill logic correctly uses master_subnet_id for the initial check to avoid an unnecessary query, then appropriately copies organization_id when the master subnet has an organization set. This aligns with the validation at lines 154-160 that requires organization consistency.

@peterishakvr12
Copy link
Copy Markdown
Author

Hi @nemesifier, I'm Peter, a "Python/Django/Flask" backend developer
preparing for GSoC 2026. I noticed issue #843 was open and
implemented the fix to allow specifying 0 in the
"Number of Subnets" field so that the rule assigns IP
addresses directly from the main subnet.

Please let me know if any changes are needed. I'm happy to
update the PR based on your feedback!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openwisp_controller/subnet_division/base/models.py`:
- Line 76: Remove the redundant inline comment inside the clean() method (the
comment that states "Auto-fill organization from master subnet") since it simply
repeats what the code does; delete that comment line from the clean() function
in models.py and leave the implementation unchanged to improve readability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f933a35c-4545-4a3c-8c1f-f875bac4b13e

📥 Commits

Reviewing files that changed from the base of the PR and between ba15b67 and 34b545a.

📒 Files selected for processing (1)
  • openwisp_controller/subnet_division/base/models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

📄 CodeRabbit inference engine (Custom checks)

**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
Avoid unnecessary comments or docstrings for code that is already clear
Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
Flag unused or redundant code
Ensure variables, functions, classes, and files have descriptive and consistent names
New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

📄 CodeRabbit inference engine (Custom checks)

Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • openwisp_controller/subnet_division/base/models.py
🧠 Learnings (3)
📚 Learning: 2026-01-15T15:05:49.557Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
Timestamp: 2026-01-15T15:05:49.557Z
Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
📚 Learning: 2026-02-17T19:13:10.088Z
Learnt from: nemesifier
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/whois/commands.py:0-0
Timestamp: 2026-02-17T19:13:10.088Z
Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
📚 Learning: 2026-01-15T15:07:17.354Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
Timestamp: 2026-01-15T15:07:17.354Z
Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
🔇 Additional comments (1)
openwisp_controller/subnet_division/base/models.py (1)

38-43: Good update: validator and help text now align with zero-subnet behavior.

This change is coherent and correctly marks the user-facing text as translatable.

return import_string(self.type)

def clean(self):
# Auto-fill organization from master subnet
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Remove redundant inline comment in clean().

The comment at Line [76] repeats what the code already makes clear and can be dropped for cleaner readability.

As per coding guidelines, "Avoid unnecessary comments or docstrings for code that is already clear."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openwisp_controller/subnet_division/base/models.py` at line 76, Remove the
redundant inline comment inside the clean() method (the comment that states
"Auto-fill organization from master subnet") since it simply repeats what the
code does; delete that comment line from the clean() function in models.py and
leave the implementation unchanged to improve readability.

@openwisp-companion
Copy link
Copy Markdown

Missing Migrations and Test Failures

Hello @peterishakvr12,
(Analysis for commit 34b545a)

There are two main issues identified in the CI failure logs:

  1. Missing Migrations: The CI job failed because there are unapplied database migrations. The error message ERROR: Migrations check failed! Models' changes not migrated, please run './manage.py makemigrations' to solve the issue! indicates that the makemigrations command needs to be run to generate the necessary migration files.

    • Remediation:
      Run the following command in your local environment to generate the missing migrations:
      ./manage.py makemigrations
      After generating the migrations, commit them to your repository.
  2. Test Failures: Several tests failed during the execution of ./runtests. The logs indicate that 599 slow tests were detected, and specific tests related to openwisp_controller.config.tests.test_admin and others are marked with [31;1m (red text), signifying failures.

    • Remediation:
      The specific root cause of these test failures cannot be determined from the provided logs alone. However, the failures are concentrated in tests related to the config module, particularly those involving admin interfaces, device management, and template handling.
      To address this, you should:

      1. Review the failing tests: Examine the tests that are marked as failed (indicated by [31;1m in the logs) to understand the specific assertions that are not being met.
      2. Debug the code: Based on the test failures, debug the relevant code in the openwisp_controller/config directory. Pay close attention to the logic that handles device and template management, as well as any interactions with the admin interface.
      3. Fix the tests or the code: Either correct the test assertions if the code logic is correct, or fix the code logic if it does not align with the test expectations.
      4. Re-run tests locally: After making changes, re-run the tests locally to ensure all failures are resolved.

      Given the number of failing tests, it might be beneficial to focus on the most time-consuming ones first, as indicated by the (X.XXs) timing in the logs, to identify potential performance bottlenecks or complex logic errors.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
openwisp_controller/subnet_division/base/models.py (1)

76-76: 🧹 Nitpick | 🔵 Trivial

Remove the redundant inline comment in clean().

Line [76] repeats what the following condition already states.

As per coding guidelines, "Avoid unnecessary comments or docstrings for code that is already clear."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openwisp_controller/subnet_division/base/models.py` at line 76, Remove the
redundant inline comment "Auto-fill organization from master subnet" inside the
clean() method of the SubnetDivision model; the condition logic already makes
this behavior explicit, so delete that single-line comment in the clean()
function (search for clean() in the SubnetDivision class) and leave the code
unchanged otherwise.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openwisp_controller/subnet_division/base/models.py`:
- Line 43: The model currently allows number_of_subnets=0 via
validators=[MinValueValidator(0)] but the validation methods
_validate_master_subnet_consistency and _validate_ip_address_consistency assume
at least one subnet and therefore reject or miscompute zero-subnet cases; fix by
either tightening the field validator to MinValueValidator(1) if zero should be
disallowed, or (preferable for zero-subnet support) keep MinValueValidator(0)
and update _validate_master_subnet_consistency and
_validate_ip_address_consistency to early-return (no-op) when
self.number_of_subnets == 0 so they skip child-subnet checks and avoid
referencing a non-existent target subnet size.

---

Duplicate comments:
In `@openwisp_controller/subnet_division/base/models.py`:
- Line 76: Remove the redundant inline comment "Auto-fill organization from
master subnet" inside the clean() method of the SubnetDivision model; the
condition logic already makes this behavior explicit, so delete that single-line
comment in the clean() function (search for clean() in the SubnetDivision class)
and leave the code unchanged otherwise.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1f0248d7-5a69-4b97-9392-ffe23a0243f6

📥 Commits

Reviewing files that changed from the base of the PR and between 34b545a and bf61fef.

📒 Files selected for processing (1)
  • openwisp_controller/subnet_division/base/models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

📄 CodeRabbit inference engine (Custom checks)

**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
Avoid unnecessary comments or docstrings for code that is already clear
Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
Flag unused or redundant code
Ensure variables, functions, classes, and files have descriptive and consistent names
New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

📄 CodeRabbit inference engine (Custom checks)

Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_controller/subnet_division/base/models.py
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • openwisp_controller/subnet_division/base/models.py
🧠 Learnings (4)
📚 Learning: 2026-03-14T19:34:33.773Z
Learnt from: CR
Repo: openwisp/openwisp-controller PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-14T19:34:33.773Z
Learning: Applies to **/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp} : Avoid unnecessary comments or docstrings for code that is already clear

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
📚 Learning: 2026-01-15T15:05:49.557Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
Timestamp: 2026-01-15T15:05:49.557Z
Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
📚 Learning: 2026-02-17T19:13:10.088Z
Learnt from: nemesifier
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/whois/commands.py:0-0
Timestamp: 2026-02-17T19:13:10.088Z
Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
📚 Learning: 2026-01-15T15:07:17.354Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
Timestamp: 2026-01-15T15:07:17.354Z
Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.

Applied to files:

  • openwisp_controller/subnet_division/base/models.py
🔇 Additional comments (1)
openwisp_controller/subnet_division/base/models.py (1)

77-83: Good improvement: organization auto-fill is correctly placed before custom consistency checks.

This helps prevent avoidable organization mismatch failures when organization_id is omitted but master_subnet is set.

"Set to 0 to assign IP addresses directly "
"from the main subnet."
),
validators=[MinValueValidator(0)],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Allowing 0 here still conflicts with non-zero subnet assumptions in validation.

Line [43] enables number_of_subnets=0, but current validators still enforce child-subnet assumptions (_validate_master_subnet_consistency and _validate_ip_address_consistency). This can reject valid zero-subnet scenarios or validate against the wrong target subnet size.

💡 Suggested alignment for zero-subnet mode
diff --git a/openwisp_controller/subnet_division/base/models.py b/openwisp_controller/subnet_division/base/models.py
@@
-        available = 2 ** (self.size - master_subnet.prefixlen)
-        # Account for the reserved subnet
-        available -= 1
-        if self.number_of_subnets >= available:
+        available = 2 ** (self.size - master_subnet.prefixlen)
+        # Account for the reserved subnet only when subnets are requested
+        available -= 1
+        if self.number_of_subnets > 0 and self.number_of_subnets >= available:
             raise ValidationError(
@@
     def _validate_ip_address_consistency(self):
         try:
-            next(
-                ip_network(str(self.master_subnet.subnet)).subnets(new_prefix=self.size)
-            )[self.number_of_ips - 1]
+            target_subnet = ip_network(str(self.master_subnet.subnet))
+            if self.number_of_subnets > 0:
+                target_subnet = next(target_subnet.subnets(new_prefix=self.size))
+            target_subnet[self.number_of_ips - 1]
         except IndexError:
             raise ValidationError(
                 {
                     "number_of_ips": _(
                         f"Generated subnets of size /{self.size} cannot accommodate "
                         f"{self.number_of_ips} IP Addresses."
                     )
                 }
             )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openwisp_controller/subnet_division/base/models.py` at line 43, The model
currently allows number_of_subnets=0 via validators=[MinValueValidator(0)] but
the validation methods _validate_master_subnet_consistency and
_validate_ip_address_consistency assume at least one subnet and therefore reject
or miscompute zero-subnet cases; fix by either tightening the field validator to
MinValueValidator(1) if zero should be disallowed, or (preferable for
zero-subnet support) keep MinValueValidator(0) and update
_validate_master_subnet_consistency and _validate_ip_address_consistency to
early-return (no-op) when self.number_of_subnets == 0 so they skip child-subnet
checks and avoid referencing a non-existent target subnet size.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openwisp_controller/subnet_division/tests/test_models.py`:
- Around line 136-140: The current test swallows any ValidationError by catching
it and only asserting "number_of_subnets" is not in e.message_dict; instead,
remove the try/except and call rule.full_clean() directly so the test fails if
any ValidationError is raised for number_of_subnets=0; alternatively, if you
must inspect the ValidationError, rework the block to let unexpected
ValidationError fail the test and only assert that e.message_dict does not
contain the "number_of_subnets" key when a ValidationError is intentionally
expected. Ensure changes reference the existing rule.full_clean() call and
ValidationError handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fe4c281f-3e82-459d-b9f5-311b84687b73

📥 Commits

Reviewing files that changed from the base of the PR and between bf61fef and 1f309d1.

📒 Files selected for processing (1)
  • openwisp_controller/subnet_division/tests/test_models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=4.2.0
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

📄 CodeRabbit inference engine (Custom checks)

**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
Avoid unnecessary comments or docstrings for code that is already clear
Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
Flag unused or redundant code
Ensure variables, functions, classes, and files have descriptive and consistent names
New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

Files:

  • openwisp_controller/subnet_division/tests/test_models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

📄 CodeRabbit inference engine (Custom checks)

Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

Files:

  • openwisp_controller/subnet_division/tests/test_models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_controller/subnet_division/tests/test_models.py
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • openwisp_controller/subnet_division/tests/test_models.py
🧠 Learnings (4)
📚 Learning: 2026-01-12T22:27:48.342Z
Learnt from: nemesifier
Repo: openwisp/openwisp-controller PR: 1175
File: tests/openwisp2/sample_config/migrations/0008_whoisinfo_organizationconfigsettings_whois_enabled.py:18-67
Timestamp: 2026-01-12T22:27:48.342Z
Learning: In tests/openwisp2/sample_config/models.py and corresponding test migrations, the WHOISInfo model intentionally includes an additional "details" field not present in the base AbstractWHOISInfo model. This is a testing pattern to verify that swappable models (CONFIG_WHOISINFO_MODEL) can be extended with custom fields without errors.

Applied to files:

  • openwisp_controller/subnet_division/tests/test_models.py
📚 Learning: 2026-01-15T15:05:49.557Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
Timestamp: 2026-01-15T15:05:49.557Z
Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.

Applied to files:

  • openwisp_controller/subnet_division/tests/test_models.py
📚 Learning: 2026-02-17T19:13:10.088Z
Learnt from: nemesifier
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/whois/commands.py:0-0
Timestamp: 2026-02-17T19:13:10.088Z
Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.

Applied to files:

  • openwisp_controller/subnet_division/tests/test_models.py
📚 Learning: 2026-01-15T15:07:17.354Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
Timestamp: 2026-01-15T15:07:17.354Z
Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.

Applied to files:

  • openwisp_controller/subnet_division/tests/test_models.py

@openwisp-companion
Copy link
Copy Markdown

Multiple CI Failures Detected

Hello @peterishakvr12,
(Analysis for commit 1f309d1)

Black Formatting Errors

  • Explanation: The Black code formatter has detected style violations in your code. Specifically, there are issues with indentation and line length.
    • ./openwisp_controller/subnet_division/base/models.py:42:10: E121 continuation line under-indented for hanging indent
    • ./openwisp_controller/subnet_division/tests/test_models.py:132:89: E501 line too long (90 > 88 characters)
  • Remediation: Run the openwisp-qa-format command to automatically fix these style issues.

Flake8 Linting Errors

  • Explanation: Flake8, a Python linter, has found style and quality issues in your code.
    • ./openwisp_controller/subnet_division/base/models.py:42:10: E121 continuation line under-indented for hanging indent
    • ./openwisp_controller/subnet_division/tests/test_models.py:132:89: E501 line too long (90 > 88 characters)
  • Remediation: Run the openwisp-qa-format command to automatically fix these linting errors.

Migrations Check Failed

  • Explanation: The CI pipeline detected unapplied database migrations. This means that changes made to your models have not been reflected in the database schema. The specific migration that failed is related to changes in openwisp_controller/subnet_division/migrations/0006_alter_subnetdivisionrule_number_of_subnets.py.
  • Remediation: You need to run ./manage.py makemigrations to generate the necessary migration files for your model changes. After that, apply the migrations using ./manage.py migrate.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@openwisp_controller/subnet_division/tests/test_models.py`:
- Line 137: Fix the indentation for the statement calling rule.full_clean()
inside the test's with block so it matches the surrounding lines (remove one
extra leading space); locate the call to rule.full_clean() in the test_models.py
with-block and align it with the other statements in that block to avoid the
IndentationError.
- Around line 132-137: The integration test should ensure that when a
SubnetDivisionRule is created with number_of_subnets=0 the provisioning assigns
IPs from the master subnet; update behavior in SubnetDivisionRule by changing
create_subnets and/or create_ips so that if number_of_subnets == 0
create_subnets returns a single entry representing the master subnet (or make
create_ips detect zero and iterate over the master subnet) and then generate IP
addresses from that master subnet; add a new integration test that creates a
rule with number_of_subnets=0, triggers provisioning (e.g., add the
template/config that calls SubnetDivisionRule.provision or equivalent code
path), and assert IP objects were created with addresses within the master
subnet.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 79cd90dc-2a74-4729-b0e5-d828030efdc5

📥 Commits

Reviewing files that changed from the base of the PR and between 1f309d1 and efb189f.

📒 Files selected for processing (1)
  • openwisp_controller/subnet_division/tests/test_models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.2.0
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}

📄 CodeRabbit inference engine (Custom checks)

**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp}: Flag potential security vulnerabilities in code
Avoid unnecessary comments or docstrings for code that is already clear
Code formatting is compact and readable. Do not add excessive blank lines, especially inside function or method bodies
Flag unused or redundant code
Ensure variables, functions, classes, and files have descriptive and consistent names
New code must handle errors properly: log errors that cannot be resolved by the user with error level, log unusual conditions with warning level, log important background actions with info level, and provide user-facing messages for errors that the user can solve autonomously

Files:

  • openwisp_controller/subnet_division/tests/test_models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sql}

📄 CodeRabbit inference engine (Custom checks)

Flag obvious performance regressions, such as heavy loops, repeated I/O, or unoptimized queries

Files:

  • openwisp_controller/subnet_division/tests/test_models.py
**/*.{js,ts,tsx,jsx,py,java,go,cs,rb,php,c,cpp,h,hpp,sh,bash,sql}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_controller/subnet_division/tests/test_models.py
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • openwisp_controller/subnet_division/tests/test_models.py
🧠 Learnings (3)
📚 Learning: 2026-01-15T15:05:49.557Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/management/commands/clear_last_ip.py:38-42
Timestamp: 2026-01-15T15:05:49.557Z
Learning: In Django projects, when using select_related() to traverse relations (for example, select_related("organization__config_settings")), the traversed relation must not be deferred. If you also use .only() in the same query, include the relation name or FK field (e.g., "organization" or "organization_id") in the .only() list to avoid the error "Field X cannot be both deferred and traversed using select_related at the same time." Apply this guideline to Django code in openwisp_controller/config/management/commands/clear_last_ip.py and similar modules by ensuring any select_related with an accompanying only() includes the related field names to prevent deferred/traversed conflicts.

Applied to files:

  • openwisp_controller/subnet_division/tests/test_models.py
📚 Learning: 2026-02-17T19:13:10.088Z
Learnt from: nemesifier
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/config/whois/commands.py:0-0
Timestamp: 2026-02-17T19:13:10.088Z
Learning: In reviews for the openwisp/openwisp-controller repository, do not propose changes based on Ruff warnings. The project does not use Ruff as its linter; ignore Ruff-related suggestions and follow the repository’s established linting and configuration rules. This guidance applies to all Python files under the openwisp_controller directory.

Applied to files:

  • openwisp_controller/subnet_division/tests/test_models.py
📚 Learning: 2026-01-15T15:07:17.354Z
Learnt from: DragnEmperor
Repo: openwisp/openwisp-controller PR: 1175
File: openwisp_controller/geo/estimated_location/tests/tests.py:172-175
Timestamp: 2026-01-15T15:07:17.354Z
Learning: In this repository, flake8 enforces E501 (line too long) via setup.cfg (max-line-length = 88) while ruff ignores E501 via ruff.toml. Therefore, use '# noqa: E501' on lines that intentionally exceed 88 characters to satisfy flake8 without affecting ruff checks. This applies to Python files across the project (any .py) and is relevant for tests as well. Use sparingly and only where breaking lines is not feasible without hurting readability or functionality.

Applied to files:

  • openwisp_controller/subnet_division/tests/test_models.py

Comment on lines +132 to +137
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 for number_of_subnets
rule.full_clean()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify if create_subnets handles number_of_subnets=0 specially
rg -n -A 20 'def create_subnets' openwisp_controller/subnet_division/rule_types/base.py

# Check if there's any special handling for zero subnets in provisioning
rg -n 'number_of_subnets.*==.*0|number_of_subnets.*0' openwisp_controller/subnet_division/

Repository: openwisp/openwisp-controller

Length of output: 2452


🏁 Script executed:

# Check the create_ips method to see if it handles empty subnets list
rg -n -B 5 -A 25 'def create_ips' openwisp_controller/subnet_division/rule_types/base.py

# Look for any special handling or comments about number_of_subnets=0
rg -n -B 3 -A 3 'number_of_subnets.*0' openwisp_controller/subnet_division/rule_types/

# Check the SubnetDivisionRule model for constraints or validation
rg -n -A 30 'class SubnetDivisionRule' openwisp_controller/subnet_division/models.py

Repository: openwisp/openwisp-controller

Length of output: 2118


🏁 Script executed:

# Find the AbstractSubnetDivisionRule model definition
fd -t f 'models.py' openwisp_controller/subnet_division/ | head -5

# Read the abstract model to understand field validation
rg -n -B 5 -A 50 'class AbstractSubnetDivisionRule' openwisp_controller/subnet_division/models.py

# Look for any logic or comments about assigning IPs directly from master subnet
rg -n 'master_subnet|direct.*IP|assign.*direct' openwisp_controller/subnet_division/

Repository: openwisp/openwisp-controller

Length of output: 14305


🏁 Script executed:

# Get more context on the number_of_subnets field definition
rg -n -B 5 -A 15 'number_of_subnets.*=' openwisp_controller/subnet_division/base/models.py | head -60

# Check if there's any TODO or FIXME comments related to number_of_subnets=0
rg -n 'TODO|FIXME|XXX' openwisp_controller/subnet_division/rule_types/base.py

# Look at the full create_ips method for any number_of_subnets=0 handling
rg -n -A 40 'def create_ips' openwisp_controller/subnet_division/rule_types/base.py | head -70

# Check if there are any other tests about number_of_subnets=0 provisioning
rg -n -B 5 -A 10 'number_of_subnets.*0' openwisp_controller/subnet_division/tests/test_models.py

Repository: openwisp/openwisp-controller

Length of output: 7150


Add integration test to verify IP provisioning behavior when number_of_subnets=0.

The current test validates that number_of_subnets=0 passes model validation, but the documented feature—"assign IP addresses directly from the main subnet"—is not implemented. When number_of_subnets=0, the create_subnets method produces an empty list, causing create_ips to generate zero IP addresses.

Add an integration test that:

  1. Creates a rule with number_of_subnets=0
  2. Triggers provisioning (e.g., adding the template to a config)
  3. Asserts that IP addresses are assigned directly from the master subnet
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openwisp_controller/subnet_division/tests/test_models.py` around lines 132 -
137, The integration test should ensure that when a SubnetDivisionRule is
created with number_of_subnets=0 the provisioning assigns IPs from the master
subnet; update behavior in SubnetDivisionRule by changing create_subnets and/or
create_ips so that if number_of_subnets == 0 create_subnets returns a single
entry representing the master subnet (or make create_ips detect zero and iterate
over the master subnet) and then generate IP addresses from that master subnet;
add a new integration test that creates a rule with number_of_subnets=0,
triggers provisioning (e.g., add the template/config that calls
SubnetDivisionRule.provision or equivalent code path), and assert IP objects
were created with addresses within the master subnet.

@openwisp-companion
Copy link
Copy Markdown

CI Failures in OpenWISP Controller

Hello @peterishakvr12,
(Analysis for commit efb189f)

There are three distinct failures in the CI logs:

  1. Code Style/QA Failure: Black and Flake8 checks failed due to indentation errors.
  2. Build/Infrastructure/Other Failure: Migrations check failed because model changes were not migrated.
  3. Test Failure: Multiple integration and unit tests failed, indicated by [31;1m status and long execution times.

Failure 1: Code Style/QA (Black and Flake8)

Explanation:
The CI pipeline failed due to code style violations detected by Black and Flake8. Specifically, there are indentation errors in openwisp_controller/subnet_division/base/models.py and openwisp_controller/subnet_division/tests/test_models.py. The Black check failed with the message "cannot format ... DedentDoesNotMatchAnyOuterIndent", and Flake8 reported "E121 continuation line under-indented for hanging indent" and "E999 IndentationError: unindent does not match any outer indentation level".

Remediation:
Run the QA formatting tool to automatically fix these issues:

openwisp-qa-format

This command will reformat the code according to the project's style guidelines, resolving the indentation problems.


Failure 2: Build/Infrastructure/Other (Migrations Check)

Explanation:
The migrations check failed with the error message: "Migrations check failed! Models' changes not migrated, please run './manage.py makemigrations' to solve the issue!". This indicates that changes were made to the database models without generating the corresponding migration files.

Remediation:
To fix this, you need to generate the missing migrations. Run the following command:

./manage.py makemigrations openwisp_controller/subnet_division

This will create a new migration file (likely 0006_alter_subnetdivisionrule_number_of_subnets.py based on the logs) to record the model changes. After generating the migration, you should also apply it to the test database by running ./manage.py migrate. The CI pipeline should then pass this check.


Failure 3: Test Failure (Multiple Test Failures)

Explanation:
A significant number of tests failed, as indicated by the [31;1m status next to many test names in the runtests output. The log shows "Total slow tests detected: 595", suggesting that many tests are either failing or taking an excessively long time to complete, which can be indicative of underlying issues or performance problems. The specific root cause for each test failure isn't detailed in the provided logs, but the sheer number of failures points to a broader problem, possibly related to the unapplied migrations or the code style issues mentioned above.

Remediation:

  1. Address Migrations and Code Style: First, ensure that the migrations are correctly applied and code style issues are fixed as per the previous remediation steps.
  2. Investigate Failing Tests: After addressing the above, re-run the tests. If specific tests continue to fail, examine the test code and the corresponding application logic to identify the root cause of the assertion errors or unexpected behavior. The logs show failures in various modules like config.tests.test_admin, config.tests.test_api, config.tests.test_selenium, etc., indicating potential issues across different areas of the controller.

@UltraBot05
Copy link
Copy Markdown
Contributor

UltraBot05 commented Mar 17, 2026

Hi @nemesifier, I'm Peter, a "Python/Django/Flask" backend developer preparing for GSoC 2026. I noticed issue #843 was open and implemented the fix to allow specifying 0 in the "Number of Subnets" field so that the rule assigns IP addresses directly from the main subnet.

Please let me know if any changes are needed. I'm happy to update the PR based on your feedback!

@peterishakvr12 Hello there.
Welcome to the Openwisp organization.

have you joined the Matrix chats general and dev in openwisp, and introduced yourself?

https://openwisp.org/support/

And you should talk there for finding new bugs or seeing issues, as well as attempting to meet the community and talk with them, get to know them (with projects and stuff, not personal lives).

Also before attempting to fix the issue you should either comment on the currently open issue, asking, "Since no one is working on this, Can I?" for example. and the same in the matrix chats.

Please do that and then the maintainers will atleast know of your existence and your PR, and then you can patiently wait and let them review your PR, and help you resolve the issues, and ultimately, merge the PR.

@openwisp-companion
Copy link
Copy Markdown

Black and Flake8 Failures

Hello @peterishakvr12,

(Analysis for commit a3c6540)

There are multiple Python code style and syntax errors detected by Black and Flake8.

Fix:
Run the command openwisp-qa-format to automatically fix most of these issues.

The following specific errors require manual attention:

  • Black: openwisp_controller/subnet_division/base/models.py and openwisp_controller/subnet_division/tests/test_models.py have parsing errors that Black cannot automatically fix.
  • Flake8:
  • E999 SyntaxError: unmatched ')' in openwisp_controller/subnet_division/base/models.py
  • E999 IndentationError: unindent does not match any outer indentation level in openwisp_controller/subnet_division/tests/test_models.py

Please review these files and correct the syntax and indentation issues manually.

Test Failures

The CI also failed due to test errors. The logs indicate a SyntaxError: unmatched ')' and IndentationError: unindent does not match any outer indentation level originating from the openwisp_controller/subnet_division/base/models.py and openwisp_controller/subnet_division/tests/test_models.py files, respectively. These are the same files flagged by Flake8.

Fix:
Correct the syntax and indentation errors in openwisp_controller/subnet_division/base/models.py and openwisp_controller/subnet_division/tests/test_models.py.

@openwisp-companion
Copy link
Copy Markdown

Multiple CI Failures Detected

Hello @peterishakvr12,
(Analysis for commit 5231d5c)

The CI pipeline failed due to the following issues:

  • Code Style/QA: Black and Flake8 checks failed. This is likely due to whitespace issues in the test files.

  • Fix: Run openwisp-qa-format to automatically fix these issues.

  • Build/Infrastructure/Other: Migrations check failed. This indicates that database migrations were not generated correctly.

  • Fix: Run ./manage.py makemigrations to generate the necessary migration files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] Allow subnet division rule to assign IP addresses from the main subnet

3 participants