Wei-Yu Chen | bd495ba | 2021-08-31 19:46:35 +0800 | [diff] [blame^] | 1 | #!/usr/bin/env python3 |
| 2 | |
| 3 | # SPDX-FileCopyrightText: © 2021 Open Networking Foundation <support@opennetworking.org> |
| 4 | # SPDX-License-Identifier: Apache-2.0 |
| 5 | |
| 6 | # nbhelper.py |
| 7 | # Helper functions for building YAML output from Netbox API calls |
| 8 | |
| 9 | import netaddr |
| 10 | |
| 11 | from .utils import logger, check_name_dns |
| 12 | from .container import PrefixContainer |
| 13 | from .container import DeviceContainer, VirtualMachineContainer |
| 14 | |
| 15 | |
| 16 | class Prefix: |
| 17 | def __init__(self, data, name_segments): |
| 18 | from .utils import netboxapi |
| 19 | |
| 20 | self.data = data |
| 21 | self.name_segments = name_segments |
| 22 | self.nbapi = netboxapi |
| 23 | |
| 24 | if self.data.description: |
| 25 | self.domain_extension = check_name_dns(self.data.description) |
| 26 | |
| 27 | # ip centric info |
| 28 | self.subnet = self.data.prefix |
| 29 | self.dhcp_range = list() |
| 30 | self.routes = list() |
| 31 | self.reserved_ips = {} |
| 32 | |
| 33 | self.neighbor = list() |
| 34 | |
| 35 | # build item lists |
| 36 | self.build_prefix() |
| 37 | |
| 38 | # Find the neighbor relationship in prefix level |
| 39 | self.find_neighbor() |
| 40 | |
| 41 | PrefixContainer().add(self.data.prefix, self) |
| 42 | |
| 43 | def __repr__(self): |
| 44 | return str(self.data.prefix) |
| 45 | |
| 46 | def check_ip_belonging(self, ip): |
| 47 | """ |
| 48 | Check if an IP address is belonging to this prefix |
| 49 | """ |
| 50 | return ip in netaddr.IPSet([self.data.prefix]) |
| 51 | |
| 52 | def find_neighbor(self): |
| 53 | |
| 54 | parent_prefixes = list() |
| 55 | for prefix in PrefixContainer().all(): |
| 56 | if not prefix.data.description: |
| 57 | parent_prefixes.append(prefix) |
| 58 | |
| 59 | for prefix in PrefixContainer().all(): |
| 60 | if not prefix.data.description: |
| 61 | continue |
| 62 | |
| 63 | targetSubnet = netaddr.IPNetwork(prefix.subnet) |
| 64 | mySubnet = netaddr.IPNetwork(self.subnet) |
| 65 | |
| 66 | for parent in parent_prefixes: |
| 67 | parentSubnet = netaddr.IPNetwork(parent.subnet) |
| 68 | if mySubnet in parentSubnet and targetSubnet in parentSubnet: |
| 69 | if prefix not in self.neighbor: |
| 70 | self.neighbor.append(prefix) |
| 71 | if self not in prefix.neighbor: |
| 72 | prefix.neighbor.append(self) |
| 73 | |
| 74 | |
| 75 | def build_prefix(self): |
| 76 | """ |
| 77 | find ip information for items (devices/vms, reserved_ips, dhcp_range) in prefix |
| 78 | """ |
| 79 | ips = self.nbapi.ipam.ip_addresses.filter(parent=self.data.prefix) |
| 80 | |
| 81 | for ip in sorted(ips, key=lambda k: k["address"]): |
| 82 | |
| 83 | logger.debug("prefix_item ip: %s, data: %s", ip, dict(ip)) |
| 84 | |
| 85 | # if it's a DHCP range, add that range to the dev list as prefix_dhcp |
| 86 | if ip.status.value == "dhcp": |
| 87 | self.dhcp_range.append(str(ip.address)) |
| 88 | |
| 89 | # reserved IPs |
| 90 | if ip.status.value == "reserved": |
| 91 | self.reserved_ips[str(ip)] = { |
| 92 | "name": ip.description.lower().split(" ")[0], |
| 93 | "description": ip.description, |
| 94 | "ip4": str(ip.address), |
| 95 | "custom_fields": ip.custom_fields, |
| 96 | } |
| 97 | self.routes.append( |
| 98 | { |
| 99 | "ip": str(ip.address), |
| 100 | "rfc3442routes": [ip.custom_fields.get("rfc3442routes")], |
| 101 | } |
| 102 | ) |