Skip to content

Commit

Permalink
[networking_mapper] Switch to best effort strategy
Browse files Browse the repository at this point in the history
With the introduction of IPv6 the mapper now needs to perform
partial maps with hosts in the inventory that are not yet
reachable, so it needs to be able to perform the mapping without
a full set of ansible facts.

The strategy that the PR follows is the next one:
- Despite the type of mapping, full or partial, do a best effort
approach without failing if a fact is missing.
- In partial maps, allow the mapper to take the interfaces-info
- Avoid refreshing networking facts for those hosts that has
not ansible_host fact present, assuming those are not reachable.
  • Loading branch information
pablintino committed May 14, 2024
1 parent 8958f87 commit f6664d1
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 25 deletions.
49 changes: 24 additions & 25 deletions plugins/module_utils/net_map/networking_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,20 +324,23 @@ def __map_instance_network_interface_mac(
def __map_instance_network_interface_data(
self,
) -> typing.Optional[typing.Dict[str, typing.Any]]:
if self.__interface_info is None or self.__host_vars is None:
return {}
elif "mac" not in self.__interface_info:
interfaces_info_mac = (self.__interface_info or {}).get("mac", None)
if self.__interface_info is not None and not interfaces_info_mac:
raise exceptions.NetworkMappingError(
f"interface information for {self.__instance_name} instance "
"does not contain mac address"
)
interface_data = self.__map_instance_network_interface_ansible_data(
interfaces_info_mac
)
if interfaces_info_mac and "macaddress" not in interface_data:
interface_data["macaddress"] = interfaces_info_mac.lower()
return interface_data

def __map_instance_network_interface_ansible_data(
self, interfaces_info_mac: typing.Optional[str]
) -> typing.Dict[str, typing.Any]:
ansible_interfaces = self.__host_vars.get("ansible_interfaces", None)
if not ansible_interfaces:
raise exceptions.NetworkMappingError(
f"Cannot determine network interface for {self.__instance_name}. "
"Ensure ansible_interfaces is an available fact for the host"
)
instance_mac = self.__interface_info["mac"].lower()
for iface_name in ansible_interfaces:
# Ansible internally replaces `-` and `:` by _ to create safe facts names
iface_fact_name = f"ansible_{iface_name}".replace("-", "_").replace(
Expand All @@ -350,11 +353,9 @@ def __map_instance_network_interface_data(
f"ansible_interfaces is present but {iface_fact_name} it's not."
)
mac = ansible_iface_data.get("macaddress", None)
if mac and mac.lower() == instance_mac:
if mac and mac.lower() == interfaces_info_mac.lower():
return ansible_iface_data
raise exceptions.NetworkMappingError(
f"Ansible instance with the given MAC, {instance_mac} was not found"
)
return {}

def __map_instance_network_ips(
self,
Expand Down Expand Up @@ -489,15 +490,7 @@ def map(
during the mapping process.
"""
instance_nets = self.__map_instance_networks()
hostname = (
self.__host_vars.get("ansible_hostname", None) if self.__host_vars else None
)
if self.__host_vars is not None and not hostname:
raise exceptions.NetworkMappingError(
f"Cannot determine hostname for {self.__instance_name}. "
"Ensure ansible_hostname is an available fact for the host"
)

hostname = self.__host_vars.get("ansible_hostname", None)
return networking_env_definitions.MappedInstance(
self.__instance_name,
instance_nets,
Expand Down Expand Up @@ -710,7 +703,9 @@ def map_routers(self, network_definition_raw: typing.Dict[str, typing.Any]):
return self.__safe_encode_to_primitives(routers)

def map_partial(
self, network_definition_raw: typing.Dict[str, typing.Any]
self,
network_definition_raw: typing.Dict[str, typing.Any],
interfaces_info: typing.Dict[str, typing.Any],
) -> typing.Dict[str, typing.Any]:
"""
Parses, validates and maps a Networking Definition into a partially complete
Expand All @@ -721,6 +716,8 @@ def map_partial(
Args:
network_definition_raw: The Networking Definition to map.
interfaces_info: Dict containing the MAC addresses of each instance.
Optional.
Returns: The Networking Environment Definition as a dictionary.
Raises:
Expand All @@ -730,7 +727,9 @@ def map_partial(
during the mapping process.
"""
net_definition = self.__parse_validate_net_definition(network_definition_raw)
return self.__safe_encode_to_primitives(self.__map(net_definition))
return self.__safe_encode_to_primitives(
self.__map(net_definition, interfaces_info=interfaces_info)
)

def map_complete(
self,
Expand Down Expand Up @@ -853,7 +852,7 @@ def __build_instances_net_mappers(
NetworkingInstanceMapper(
instance_name,
pools_manager,
self.__host_vars.get(instance_name, None),
self.__host_vars.get(instance_name, {}),
instance_definition=instance_definition,
group_templates=groups_template_definitions,
interface_info=instance_interface_info,
Expand Down
6 changes: 6 additions & 0 deletions roles/networking_mapper/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@
}}
block:
- name: Gather the facts
vars:
_instance_vars: >-
{{
hostvars[item] | default({})
}}
when: "'ansible_host' in _instance_vars"
ansible.builtin.setup:
gather_subset:
- network
Expand Down

0 comments on commit f6664d1

Please sign in to comment.