Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Netbox Inventory plugin enhancements #54285

Closed
wants to merge 13 commits into from
57 changes: 51 additions & 6 deletions lib/ansible/plugins/inventory/netbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@
region, site, role, platform, and/or tenant. Please check official netbox docs for more info.
default: False
type: boolean
interfaces:
description:
- If True, it adds the device or virtual machine interface information in host vars.
default: False
type: boolean
mkeetman marked this conversation as resolved.
Show resolved Hide resolved
version_added: "2.9"
token:
required: True
description: NetBox token.
Expand Down Expand Up @@ -208,7 +214,8 @@ def group_extractors(self):
"platforms": self.extract_platform,
"device_types": self.extract_device_type,
"config_context": self.extract_config_context,
"manufacturers": self.extract_manufacturer
"manufacturers": self.extract_manufacturer,
"interfaces": self.extract_interfaces
}

def extract_disk(self, host):
Expand Down Expand Up @@ -262,7 +269,10 @@ def extract_device_role(self, host):
def extract_config_context(self, host):
try:
if self.config_context:
url = self.api_endpoint + "/api/dcim/devices/" + str(host["id"])
if 'device_role' in host:
url = self.api_endpoint + "/api/dcim/devices/" + to_text(host["id"])
elif 'role' in host:
url = self.api_endpoint + "/api/virtualization/virtual-machines/" + to_text(host["id"])
device_lookup = self._fetch_information(url)
return [device_lookup["config_context"]]
except Exception:
Expand All @@ -277,27 +287,61 @@ def extract_manufacturer(self, host):
def extract_primary_ip(self, host):
try:
address = host["primary_ip"]["address"]
return str(ip_interface(address).ip)
return to_text(ip_interface(address).ip)
except Exception:
return

def extract_primary_ip4(self, host):
try:
address = host["primary_ip4"]["address"]
return str(ip_interface(address).ip)
return to_text(ip_interface(address).ip)
except Exception:
return

def extract_primary_ip6(self, host):
try:
address = host["primary_ip6"]["address"]
return str(ip_interface(address).ip)
return to_text(ip_interface(address).ip)
except Exception:
return

def extract_tags(self, host):
return host["tags"]

def extract_ipaddresses(self, host):
try:
if self.interfaces:
if 'device_role' in host:
url = urljoin(self.api_endpoint, "/api/ipam/ip-addresses/?limit=0&device_id=%s" % (to_text(host["id"])))
elif 'role' in host:
url = urljoin(self.api_endpoint, "/api/ipam/ip-addresses/?limit=0&virtual_machine_id=%s" % (to_text(host["id"])))
ipaddress_lookup = self.get_resource_list(api_url=url)

return ipaddress_lookup
except Exception:
return

def extract_interfaces(self, host):
try:
if self.interfaces:
if 'device_role' in host:
url = urljoin(self.api_endpoint, "/api/dcim/interfaces/?limit=0&device_id=%s" % (to_text(host["id"])))
elif 'role' in host:
url = urljoin(self.api_endpoint, "/api/virtualization/interfaces/?limit=0&virtual_machine_id=%s" % (to_text(host["id"])))
interface_lookup = self.get_resource_list(api_url=url)

# Collect all IP Addresses associated with the device
device_ipaddresses = self.extract_ipaddresses(host)

# Attach the found IP Addresses record to the interface
for interface in interface_lookup:
interface_ip = [ipaddress for ipaddress in device_ipaddresses if ipaddress["interface"]["id"] == interface["id"]]
interface["ip-addresses"] = interface_ip

return interface_lookup
except Exception:
return

def refresh_platforms_lookup(self):
url = self.api_endpoint + "/api/dcim/platforms/?limit=0"
platforms = self.get_resource_list(api_url=url)
Expand Down Expand Up @@ -391,7 +435,7 @@ def extract_name(self, host):
# An host in an Ansible inventory requires an hostname.
# name is an unique but not required attribute for a device in NetBox
# We default to an UUID for hostname in case the name is not set in NetBox
return host["name"] or str(uuid.uuid4())
return host["name"] or to_text(uuid.uuid4())

def add_host_to_groups(self, host, hostname):
for group in self.group_by:
Expand Down Expand Up @@ -452,6 +496,7 @@ def parse(self, inventory, loader, path, cache=True):
self.timeout = self.get_option("timeout")
self.validate_certs = self.get_option("validate_certs")
self.config_context = self.get_option("config_context")
self.interfaces = self.get_option("interfaces")
self.headers = {
'Authorization': "Token %s" % token,
'User-Agent': "ansible %s Python %s" % (ansible_version, python_version.split(' ')[0]),
Expand Down