[PR #3897] [CLOSED] Fixes #3782: Prevent power loops #12688

Closed
opened 2025-12-29 22:23:03 +01:00 by adam · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbox-community/netbox/pull/3897
Author: @hSaria
Created: 1/12/2020
Status: Closed

Base: developHead: 3782-disallow-power-loops


📝 Commits (1)

📊 Changes

3 files changed (+68 additions, -0 deletions)

View changed files

📝 docs/release-notes/version-2.6.md (+1 -0)
📝 netbox/dcim/models.py (+37 -0)
📝 netbox/dcim/tests/test_models.py (+30 -0)

📄 Description

Fixes: #3782

Prevent power loops from being created. It ended up being a derivative of the Bellman–Ford algorithm, though it didn't start as one.

Please note that this is not necessarily something we'd want to do; I'm not the expert on power so I don't know if loops inherently exist out there. I created this PR as a potential solution to the ticket, but apart from #3377, it makes no difference if a loop is preset (AFAIK), so it might be worth to continue allowing power loops and just figure out a different way to solve #3377. To be honest, I'd like to keep power loops in case someone needs them.

It runs in a ring-like structure (like the rings on a piece of wood), expanding on every iteration. The ring starts with the source node (i.e. termination_a.device of the new connection). On the second iteration, it will include devices on hop away from those processed in the iteration before. It will stop once all vertices (power cables in this case) that connect to the source node (directly or indirectly) have been scanned, or when a loop gets detected (an iteration containing the destination node termination_b.device).

1st iteration/ring:    A -)- B --- C --- D
2nd iteration/ring:    A --- B -)- C --- D
3rd iteration/ring:    A --- B --- C -)- D

I did my best to in-line document the operation and to keep it as simple as I could, though a cup of coffee when reading it would definitely ease your experience.

Some notes:

  • You should probably look at the tests first to understand specifically what this is preventing against.
  • Relating to the number of the database operations, this implementation has an upper bound of O(2n), where n is the longest number of hops involving the source node.
  • A vertex between the nodes must be of type power outlet; there's an in-line explanation for this (tldr; it is always one end of the cable what would cause a power loop). Because of this and how power is modelled, power feeds improve the search by acting as boundaries.
  • Existing power loops will be ignored, but new ones will be prevented.
  • Going back to the algorithm, an alternative solution would be to use recursive queries which would have a O(1) time complexity from the perspective of the ORM. However, I didn't go with that implementation because I'm not all too comfortable with it as it'll involve a raw query, but I'm open to refactoring the code to use that instead.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbox-community/netbox/pull/3897 **Author:** [@hSaria](https://github.com/hSaria) **Created:** 1/12/2020 **Status:** ❌ Closed **Base:** `develop` ← **Head:** `3782-disallow-power-loops` --- ### 📝 Commits (1) - [`cce99f7`](https://github.com/netbox-community/netbox/commit/cce99f77ea31e14a680f9b774de8751a04417eb9) Fixes #3782: Prevent power loops ### 📊 Changes **3 files changed** (+68 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `docs/release-notes/version-2.6.md` (+1 -0) 📝 `netbox/dcim/models.py` (+37 -0) 📝 `netbox/dcim/tests/test_models.py` (+30 -0) </details> ### 📄 Description ### Fixes: #3782 Prevent power loops from being created. It ended up being a derivative of the Bellman–Ford algorithm, though it didn't start as one. > Please note that this is not necessarily something we'd want to do; I'm not the expert on power so I don't know if loops inherently exist out there. I created this PR as a potential solution to the ticket, but apart from #3377, it makes no difference if a loop is preset (AFAIK), so it might be worth to continue allowing power loops and just figure out a different way to solve #3377. To be honest, I'd like to keep power loops in case someone needs them. It runs in a ring-like structure (like the rings on a piece of wood), expanding on every iteration. The ring starts with the source node (i.e. `termination_a.device` of the new connection). On the second iteration, it will include devices on hop away from those processed in the iteration before. It will stop once all vertices (power cables in this case) that connect to the source node (directly or indirectly) have been scanned, or when a loop gets detected (an iteration containing the destination node `termination_b.device`). ``` 1st iteration/ring: A -)- B --- C --- D 2nd iteration/ring: A --- B -)- C --- D 3rd iteration/ring: A --- B --- C -)- D ``` > I did my best to in-line document the operation and to keep it as simple as I could, though a cup of coffee when reading it would definitely ease your experience. Some notes: * You should probably look at the tests first to understand specifically what this is preventing against. * _Relating to the number of the database operations_, this implementation has an upper bound of _O(2n)_, where _n_ is the longest number of hops involving the source node. * A vertex between the nodes must be of type power outlet; there's an in-line explanation for this (tldr; it is __always__ one end of the cable what would cause a power loop). Because of this and how power is modelled, power feeds improve the search by acting as boundaries. * Existing power loops will be ignored, but new ones will be prevented. * Going back to the algorithm, an alternative solution would be to use recursive queries which would have a O(1) time complexity from the perspective of the ORM. However, I didn't go with that implementation because I'm not all too comfortable with it as it'll involve a raw query, but I'm open to refactoring the code to use that instead. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
adam added the pull-request label 2025-12-29 22:23:03 +01:00
adam closed this issue 2025-12-29 22:23:03 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#12688