dropbox / nsot

Network Source of Truth is an open source IPAM and network inventory database
https://nsot.readthedocs.io
Other
399 stars 66 forks source link

[Issue 121] Enabling forceful parent deletion #337

Closed khardsonhurley closed 6 years ago

khardsonhurley commented 6 years ago

This issue is a safe guard for a situation where someone accidentally adds a parent.

Scenario #1: Mistakably adding a top level network Before this change, a situation of adding a quad0 would have been impossible to revert. Let's explore what this would look like:

$ nsot networks add --cidr=0.0.0.0/0
[SUCCESS] Added network!

Oops, now the /24 now has quad0 as it's parent (and all other parent networks would as well):

$ nsot networks list
+-----------------------------------------------------------------------------------+
| ID   CIDR (Key)        Is IP?   IP Ver.   Parent           State       Attributes |
+-----------------------------------------------------------------------------------+
| 1    185.45.19.0/24    False    4         0.0.0.0/0        allocated              |
| 7    185.45.19.5/32    True     4         185.45.19.0/24   assigned               |
| 8    185.45.19.6/32    True     4         185.45.19.0/24   assigned               |
| 9    185.45.19.7/32    True     4         185.45.19.0/24   assigned               |
| 10   185.45.19.10/32   True     4         185.45.19.0/24   assigned               |
| 11   185.45.19.8/32    True     4         185.45.19.0/24   assigned               |
| 17   0.0.0.0/0         False    4         None             allocated              |
+-----------------------------------------------------------------------------------+

Notice that simply running remove raises an error:

$ nsot networks remove -i 17
[FAILURE] Cannot delete some instances of model 'Network' because they are referenced through a protected foreign key: 'Network.parent'

Enter the force-delete flag! The force-delete flag (added in this pynsot PR) overrides the native django PROTECT method on Network.parent. Forceful deletion allows us to forcefully delete a network that has children:

$ nsot networks remove -i 17 --force-delete
[SUCCESS] Removed network!

Notice that the /24 no longer has a parent:

$ nsot networks list
+-----------------------------------------------------------------------------------+
| ID   CIDR (Key)        Is IP?   IP Ver.   Parent           State       Attributes |
+-----------------------------------------------------------------------------------+
| 1    185.45.19.0/24    False    4         None             allocated              |
| 7    185.45.19.5/32    True     4         185.45.19.0/24   assigned               |
| 8    185.45.19.6/32    True     4         185.45.19.0/24   assigned               |
| 9    185.45.19.7/32    True     4         185.45.19.0/24   assigned               |
| 10   185.45.19.10/32   True     4         185.45.19.0/24   assigned               |
| 11   185.45.19.8/32    True     4         185.45.19.0/24   assigned               |
+-----------------------------------------------------------------------------------+

Scenario #2: Deleting a parent with child leaf nodes Forceful deletion does not work when trying to delete a parent network whose children are leaf nodes:

$ nsot networks remove -i 1 --force-delete
[FAILURE] You cannot forcefully delete a network that does not have a parent, and whose children are leaf nodes.

Scenario #3: Deleting a network that has a parent In a scenario where we try to delete a network that has a parent, the children of that network will be reparented to the deleted network's parent.

Notice we've added a new network: 185.45.0.0/17, which is now the parent of 185.45.19.0/24:

$ nsot networks list
+-----------------------------------------------------------------------------------+
| ID   CIDR (Key)        Is IP?   IP Ver.   Parent           State       Attributes |
+-----------------------------------------------------------------------------------+
| 1    185.45.19.0/24    False    4         185.45.0.0/17    allocated              |
| 7    185.45.19.5/32    True     4         185.45.19.0/24   assigned               |
| 8    185.45.19.6/32    True     4         185.45.19.0/24   assigned               |
| 9    185.45.19.7/32    True     4         185.45.19.0/24   assigned               |
| 10   185.45.19.10/32   True     4         185.45.19.0/24   assigned               |
| 11   185.45.19.8/32    True     4         185.45.19.0/24   assigned               |
| 19   185.45.0.0/17     False    4         None             allocated              |
+-----------------------------------------------------------------------------------+

Now let's try to delete 185.45.19.0/24:

$ nsot networks remove -i 1
[FAILURE] Cannot delete some instances of model 'Network' because they are referenced through a protected foreign key: 'Network.parent'

It fails, as expected. Now let's try with the force-delete flag:

$ nsot networks remove -i 1 --force-delete
[SUCCESS] Removed network!

Notice all children have now been reparented to 185.45.0.0/17.

$ nsot networks list
+----------------------------------------------------------------------------------+
| ID   CIDR (Key)        Is IP?   IP Ver.   Parent          State       Attributes |
+----------------------------------------------------------------------------------+
| 7    185.45.19.5/32    True     4         185.45.0.0/17   assigned               |
| 8    185.45.19.6/32    True     4         185.45.0.0/17   assigned               |
| 9    185.45.19.7/32    True     4         185.45.0.0/17   assigned               |
| 10   185.45.19.10/32   True     4         185.45.0.0/17   assigned               |
| 11   185.45.19.8/32    True     4         185.45.0.0/17   assigned               |
| 19   185.45.0.0/17     False    4         None            allocated              |
+----------------------------------------------------------------------------------+