Open cfiehe opened 1 year ago
Hello,
My 2cents here as I’m looking of kind of the same topic. The "Enforce unique space" is the good way. As by having an unique address you’re being certain that this one will not be treated differently. The need here is about being able to update an ip record with the "state:present" attribute.
I'm seeing exact same behaviour. My scenario is that sometimes I need to reserve bunch of IPs ahead of time to get network teams to update firewall rules (which can take days). Once firewall rules are in place I can then build VMs and I would like them to use reserved IPs.
Based on below I would expect to be able to assign an existing IP to a VM if the state is set to present.
With state C(present), if an interface is given, it will ensure
that an IP inside this prefix (and vrf, if given) is attached
to this interface. Otherwise, it will get the next available IP
of this prefix and attach it.
With state C(new), it will force to get the next available IP in
this prefix. If an interface is given, it will also force to attach
it.
The current behavior of the Ansible netbox_ip_address module does not align with the NetBox API's expectations for assigning IP addresses. Specifically, the API uses assigned_object_type and assigned_object_id to identify the target of the IP assignment, whereas the Ansible module accepts assigned_object and interface, which are more descriptive names.
To align the Ansible module with the NetBox API, we need to convert the human-readable names provided by the user into the appropriate assigned_object_type and assigned_object_id values. This can be achieved by modifying the NetboxIpamModule.run() function in the netbox_ipam.py file.
A psudo-code exemple for the fix to the issue:
def run(self):
...
assigned_object = data.get("assigned_object")
if assigned_object:
# Determine the type and ID of the assigned object
interface_name = assigned_object.get("name")
if assigned_object.get("device"):
device_name = assigned_object.get("device")
device_type = DCIM_INTERFACE
elif assigned_object.get("virtual_machine"):
device_name = assigned_object.get("virtual_machine")
device_type = VIRTUALIZATION_VIRTUAL_MACHINE
else:
raise Exception("Invalid assigned_object parameters. Device or virtual machine must be specified.")
# Fetch the interface object based on the type and name
interface = netbox_object.get(device_type, device_name, interface_name)
if not interface:
raise Exception(f"No interface found with device '{device_name}' and name '{interface_name}'")
# Update the data dictionary with the required fields for the API
data.update({
"assigned_object_type": device_type,
"assigned_object_id": interface.id
})
# Process the 'interface' argument similarly
interface = data.get("interface")
if interface:
interface_name = interface.get("name")
device_name = data.get("device")
device_type = DCIM_INTERFACE
# Fetch the interface object based on the type and name
interface = netbox_object.get(device_type, device_name, interface_name)
if not interface:
raise Exception(f"No interface found with device '{device_name}' and name '{interface_name}'")
# Update the data dictionary
data.update({
"assigned_object_type": device_type,
"assigned_object_id": interface.id
})
...
# Update the NetBox instance with the modified data
update_netbox(data)
Mapping Names to IDs: The assigned_object and interface fields contain descriptive names, which are not directly usable by the NetBox API. The proposed changes convert these names into the required assigned_object_type and assigned_object_id.
Exception Handling: Improved error messages and checks ensure that the module fails gracefully if the provided names do not match any known interfaces.
BTW If anyone want's to take these changes and make a pull request, she/he is welcome to do so. I'm not doing it myself since it is a lot of work to create the development environment for proper testing of the fix. Might come around some weekend to do so. If you beat me to the punch then you have my blessing 😄
Ansible NetBox Collection version
v3.12.0
Ansible version
NetBox version
v3.4.7
Python version
3.10
Steps to Reproduce
If an IP address already exists in our Netbox, it cannot be assigned to an interface. The module always instructs the Netbox to create a new IP. This results in a
Duplicate IP address
exception, whenEnforce unique space
is enabled, or in a duplicate IP.Expected Behavior
The existing IP should be modified and should be attached to the specified interface.
Observed Behavior
The VRF
my_company-RFC1918
uses the optionEnforce unique space
, that is why the assignment fails with aDuplicate IP address
, because the module tries to create a new IP instead of modifying the existing one: