-
Hi, I started using Netbox very recently in a python automation script that is triggered by Celerybeat. Every time the script executes, it provisions new devices and assigns an available/unused IP to each new device. I used the Netbox prefix.get_first_available_ip() However, I am seeing errors later in the script because the IP returned was already in use by an existing device. I had a closer look at the Netbox codebase on Github, and it appears that the method My code currently has no checks for this: # 1. Get the first available IP for my chosen prefix (*EDIT: fixed typo)
available_ip = prefix.get_first_available_ip()
# 2. Create and reserve the new ip
new_ip = IPAddress.objects.create(address=available_ip, status=PrefixStatusChoices.STATUS_RESERVED,
description='my device', vrf=prefix.vrf, tenant=prefix.tenant)
# 3. Then assign the new IP later... Should I be checking the IP's status between steps 1 and 2? Or am I doing this all wrong? I would appreciate any help. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
"availabile_ip" and "available_ip" are two different variables. |
Beta Was this translation helpful? Give feedback.
-
So if this is not what you're seeing, please can you provide a reproducible test case with the actual results you're seeing. And also say what version of Netbox you're using. There is another possibility though, which is that there are multiple instances of your script running concurrently. Your code has a race condition: first it gets an available IP, and then it creates an IP. If you run two instances of this at exactly the same time, they will try to obtain the same IP address twice. Unfortunately, the Netbox REST API doesn't provide any way to run multiple actions within the same transaction (and in general this leads to very complex REST APIs, see Salesforce for an example). If this is what's going on, then you could have an external lock to prevent two instances of your script running at once (although it will still be confused if someone else inserts an IP at exactly the wrong time). Better would be to have retry logic in your script; if the create IP fails in step 2, then go back to step 1. This is what's known as "optimistic locking": don't lock, but fail if someone else got there before you. Another option would be to write your atomic action as a custom script, which can then be called from the REST API. However I'm not sure that will work in this case, in the sense that the second transaction could still fail. Furthermore it may be worse because Netbox itself has its own race conditions - it doesn't enforce IP address uniqueness at the database layer, but only using code which queries for non-existence of a conflicting address. So what may happen in this case is you actually get two conflicting IP addresses inserted into the database. |
Beta Was this translation helpful? Give feedback.
get_first_available_ip
will give you the first IP address that doesn't exist within that prefix, i.e. does not overlap any existing IP address or range object. See source here. There's no point in the code checking the status, because addresses with any status are already skipped; it only returns an address where there is no existing record in the database at all.So if this is not what you're seeing, please can you provide a reproducible test case with the actual results you're seeing. And also say what version of Netbox you're using.
There is another possibility though, which is that there are multiple instances of your script running concurrently. Your code has a race condition: first …