From e12cd4eef5eff7bd251795e1f4d8c74b64a1befd Mon Sep 17 00:00:00 2001 From: Jean-Louis Dupond Date: Thu, 5 May 2022 11:22:57 +0200 Subject: [PATCH] Code cleanup + fixes and docs --- README.md | 1 + module/sources/openstack/connection.py | 57 ++--------- requirements.txt | 1 + settings-example.ini | 134 +++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index e02e18c..8df5d0a 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ This ensures stale objects are removed from NetBox keeping an accurate current s * requests==2.24.0 * pyvmomi==6.7.3 * aiodns==2.0.0 +* openstack ### Environment * NetBox >= 2.9 diff --git a/module/sources/openstack/connection.py b/module/sources/openstack/connection.py index 645538a..4a42f24 100644 --- a/module/sources/openstack/connection.py +++ b/module/sources/openstack/connection.py @@ -85,16 +85,13 @@ class OpenStackHandler(SourceBase): "user_domain": None, "project_domain": None, "group_name": "Openstack", - "validate_tls_certs": False, + "permitted_subnets": None, "cluster_exclude_filter": None, "cluster_include_filter": None, "host_exclude_filter": None, "host_include_filter": None, "vm_exclude_filter": None, "vm_include_filter": None, - "permitted_subnets": None, - "collect_hardware_asset_tag": True, - "match_host_by_serial": True, "cluster_site_relation": None, "cluster_tag_relation": None, "cluster_tenant_relation": None, @@ -108,14 +105,12 @@ class OpenStackHandler(SourceBase): "vm_tenant_relation": None, "dns_name_lookup": False, "custom_dns_servers": None, + "validate_tls_certs": False, "set_primary_ip": "when-undefined", + "skip_vm_platform": False, "skip_vm_comments": False, - "skip_vm_templates": True, "strip_host_domain_name": False, - "strip_vm_domain_name": False, - "sync_tags": False, - "sync_parent_tags": False, - "sync_custom_attributes": False + "strip_vm_domain_name": False } deprecated_settings = {} @@ -652,8 +647,7 @@ def add_device_vm_to_inventory(self, object_type, object_data, pnic_data=None, v Try to find object first based on the object data, interface MAC addresses and primary IPs. 1. try to find by name and cluster/site 2. try to find by mac addresses interfaces - 3. try to find by serial number (1st) or asset tag (2nd) (ESXi host) - 4. try to find by primary IP + 3. try to find by primary IP IP addresses for each interface are added here as well. First they will be checked and added if all checks pass. For each IP address a matching IP prefix will be searched for. First we @@ -742,21 +736,6 @@ def add_device_vm_to_inventory(self, object_type, object_data, pnic_data=None, v device_vm_object = self.get_object_based_on_macs(object_type, nic_macs) - # look for devices with same serial or asset tag - if object_type == NBDevice: - - if device_vm_object is None and object_data.get("serial") is not None and \ - bool(self.match_host_by_serial) is True: - log.debug2(f"No match found. Trying to find {object_type.name} based on serial number") - - device_vm_object = self.inventory.get_by_data(object_type, data={"serial": object_data.get("serial")}) - - if device_vm_object is None and object_data.get("asset_tag") is not None: - log.debug2(f"No match found. Trying to find {object_type.name} based on asset tag") - - device_vm_object = self.inventory.get_by_data(object_type, - data={"asset_tag": object_data.get("asset_tag")}) - if device_vm_object is not None: log.debug2("Found a matching %s object: %s" % (object_type.name, device_vm_object.get_display_name(including_second_key=True))) @@ -919,13 +898,8 @@ def add_host(self, obj): does the host pass the host_include_filter and host_exclude_filter Then all necessary host data will be collected. - host model, manufacturer, serial, physical interfaces, virtual interfaces, - virtual switches, proxy switches, host port groups, interface VLANs, IP addresses - Primary IPv4/6 will be determined by - 1. if the interface port group name contains - "management" or "mngt" - 2. interface is the default route of this host + Primary IPv4/6 will be determined by 'host_ip' value Parameters ---------- @@ -1005,9 +979,6 @@ def add_host(self, obj): if get_string_or_none(obj.status) == "enabled": status = "active" - # add asset tag if desired and present - asset_tag = None - # get host_tenant_relation tenant_name = self.get_object_relation(name, "host_tenant_relation") @@ -1029,8 +1000,6 @@ def add_host(self, obj): } # add data if present - if asset_tag is not None: - host_data["asset_tag"] = asset_tag if platform is not None: host_data["platform"] = {"name": platform} if tenant_name is not None: @@ -1078,7 +1047,6 @@ def add_virtual_machine(self, obj): # get VM power state status = "active" if get_string_or_none(obj.status) == "ACTIVE" else "offline" - # hypervisor_name = get_string_or_none(obj.hypervisor_hostname) cluster_name = get_string_or_none(obj.availability_zone) # honor strip_host_domain_name @@ -1113,16 +1081,13 @@ def add_virtual_machine(self, obj): # Collect data # - # check if cluster is a Standalone ESXi - site_name = self.permitted_clusters.get(cluster_name) - if site_name is None: - site_name = self.get_site_name(NBCluster, cluster_name) - # first check against vm_platform_relation - platform = get_string_or_none(obj.flavor["original_name"]) + platform = None + if bool(self.skip_vm_platform) is False: + platform = get_string_or_none(obj.flavor["original_name"]) - if platform is not None: - platform = self.get_object_relation(platform, "vm_platform_relation", fallback=platform) + if platform is not None: + platform = self.get_object_relation(platform, "vm_platform_relation", fallback=platform) disk = 0 for volume in obj.attached_volumes: diff --git a/requirements.txt b/requirements.txt index 533559c..34909eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ wheel requests==2.24.0 pyvmomi==6.7.3 aiodns==2.0.0 +setuptools==60.10.0 openstack diff --git a/settings-example.ini b/settings-example.ini index 58228fc..b39f649 100644 --- a/settings-example.ini +++ b/settings-example.ini @@ -277,4 +277,138 @@ permitted_subnets = 172.16.0.0/12, 10.0.0.0/8, 192.168.0.0/16, fd00::/8 # if False only data which is not preset in NetBox will be added #overwrite_interface_attributes = True + +[source/my-openstack-example] + +# Defines if this source is enabled or not +#enabled = true + +# type of source. This defines which source handler to use. +type = openstack + +# URL to the Openstack API +auth_url = https://api.openstack-instance.local:5000/v3 + +# Openstack project to connect to +project = MyProject + +# Openstack region +region = RegionOne + +# Openstack user_domain +user_domain = Default + +# Openstack project_domain +project_domain = Default + +# Enforces TLS certificate validation. If Openstack API uses a valid TLS certificate then +# this option should be set to 'true' to ensure a secure connection. +#validate_tls_certs = false + +# username and password to use to log into vCenter +username = vcenteruser +password = supersecret + +# IP networks eligible to be synced to NetBox. +# If an IP address is not part of this networks then it WON'T be synced to NetBox +permitted_subnets = 172.16.0.0/12, 10.0.0.0/8, 192.168.0.0/16, fd00::/8 + +# filters can be used to include/exclude certain objects from importing into NetBox +# Include filters are checked first and exclude filters after. An object name has to +# pass both filters to be synced to NetBox. If a filter is unset it will be ignored. +# Filters are all treated as regex expressions! + +# If a cluster is excluded from sync then ALL VMs and HOSTS inside the cluster will +# be ignored! +#cluster_exclude_filter = +#cluster_include_filter = + +# This will only include/exclude the host, not the VM if Host is part of a multi host +# cluster. +#host_exclude_filter = +#host_include_filter = + +# simply include/exclude VMs +#vm_exclude_filter = +#vm_include_filter = + +# This option defines which Openstack Availability Zones is part of a NetBox site. This is done +# with a comma separated key = value list. +# key: defines the cluster name as regex +# value: defines the NetBox site name (use quotes if name contains commas) +# This is a quite important config setting as IP addresses, prefixes, VLANs and +# VRFs are site dependent. In order to assign the correct prefix to an IP +# address it is important to pick the correct site. +# A VM always depends on the cluster site relation +#cluster_site_relation = Cluster_NYC = New York , Cluster_FFM.* = Frankfurt + +# Same as cluster site but on host level. If unset it will fall back +# to cluster_site_relation. +#host_site_relation = nyc02.* = New York, ffm01.* = Frankfurt + +# This option defines which cluster/host/VM belongs to which tenant. This is done +# with a comma separated key = value list. +# key: defines a hosts/VM name as regex +# value: defines the NetBox tenant name (use quotes if name contains commas) +#cluster_tenant_relation = Cluster_NYC.* = Customer A +#host_tenant_relation = esxi300.* = Infrastructure +#vm_tenant_relation = grafana.* = Infrastructure + +# This option defines custom platforms if the used Flavors are not suitable. +# Pretty much a mapping of Openstack flavor name to your own platform name. +# This is done with a comma separated key = value list. +# key: defines a Openstack returned flavor name +# value: defines the desired NetBox platform name +#vm_platform_relation = centos-7.* = centos7, microsoft-windows-server-2016.* = Windows2016 + +# Define the NetBox device role used for hosts and VMs. The default is set to "Server". This is done +# with a comma separated key = value list. +# key: defines a hosts/VM name as regex +# value: defines the NetBox role name (use quotes if name contains commas) +#host_role_relation = .* = Server +#vm_role_relation = .* = Server + +# Define NetBox tags which are assigned to a cluster, host or VM. This is done +# with a comma separated key = value list. +# key: defines a hosts/VM name as regex +# value: defines the NetBox tag (use quotes if name contains commas) +#cluster_tag_relation = Cluster_NYC.* = Infrastructure +#host_tag_relation = esxi300.* = Infrastructure +#vm_tag_relation = grafana.* = Infrastructure + +# Perform a reverse lookup for all collected IP addresses. If a dns name +# was found it will be added to the IP address object in NetBox +#dns_name_lookup = True + +# use custom DNS server to do the reverse lookups +#custom_dns_servers = 192.168.1.11, 192.168.1.12 + +# define how the primary IPs should be set +# possible values +# +# always: will remove primary IP from the object where this address is +# currently set as primary and moves it to new object +# +# when-undefined: (default) +# only sets primary IP if undefined, will cause ERRORs if same IP is +# assigned more then once to different hosts and IP is set as the +# objects primary IP +# +# never: don't set any primary IPs, will cause the same ERRORs +# as "when-undefined" + +#set_primary_ip = when-undefined + +# Do not sync flavors from a VM in Openstack to the comments field on a VM in netbox +#skip_vm_platform = False + +# Do not sync ID from a VM in Openstack to the comments field on a VM in netbox +#skip_vm_comments = False + +# strip domain part from host name before syncing device to NetBox +#strip_host_domain_name = False + +# strip domain part from VM name before syncing VM to NetBox +#strip_vm_domain_name = False + # EOF