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

Add possibility to limit the list of examined network interfaces during fact gathering #17586

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/ansible.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
# environment.
# gather_timeout = 10

# by default retrieve facts for all interfaces
# list interfaces to limit the gather process to here
#gather_network_interfaces = lo,eth0,eth1

# additional paths to search for roles in, colon separated
#roles_path = /etc/ansible/roles

Expand Down
2 changes: 2 additions & 0 deletions lib/ansible/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ def load_config_file():
DEFAULT_GATHERING = get_config(p, DEFAULTS, 'gathering', 'ANSIBLE_GATHERING', 'implicit').lower()
DEFAULT_GATHER_SUBSET = get_config(p, DEFAULTS, 'gather_subset', 'ANSIBLE_GATHER_SUBSET', 'all').lower()
DEFAULT_GATHER_TIMEOUT = get_config(p, DEFAULTS, 'gather_timeout', 'ANSIBLE_GATHER_TIMEOUT', 10, integer=True)
DEFAULT_GATHER_NETWORK_INTERFACES = get_config(p, DEFAULTS, 'gather_network_interfaces', 'ANSIBLE_GATHER_NETWORK_INTERFACES', None)

DEFAULT_LOG_PATH = get_config(p, DEFAULTS, 'log_path', 'ANSIBLE_LOG_PATH', '', ispath=True)
DEFAULT_FORCE_HANDLERS = get_config(p, DEFAULTS, 'force_handlers', 'ANSIBLE_FORCE_HANDLERS', False, boolean=True)
DEFAULT_INVENTORY_IGNORE = get_config(p, DEFAULTS, 'inventory_ignore_extensions', 'ANSIBLE_INVENTORY_IGNORE', ["~", ".orig", ".bak", ".ini", ".cfg", ".retry", ".pyc", ".pyo"], islist=True)
Expand Down
5 changes: 5 additions & 0 deletions lib/ansible/executor/play_iterator.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,20 +159,25 @@ def __init__(self, inventory, play, play_context, variable_manager, all_vars, st
# Default options to gather
gather_subset = C.DEFAULT_GATHER_SUBSET
gather_timeout = C.DEFAULT_GATHER_TIMEOUT
gather_interfaces = C.DEFAULT_GATHER_NETWORK_INTERFACES

# Retrieve subset to gather
if self._play.gather_subset is not None:
gather_subset = self._play.gather_subset
# Retrieve timeout for gather
if self._play.gather_timeout is not None:
gather_timeout = self._play.gather_timeout
# Retrieve list of interfaces to gather
if self._play.gather_network_interfaces is not None:
gather_interfaces = self._play.gather_network_interfaces

setup_block = Block(play=self._play)
setup_task = Task(block=setup_block)
setup_task.action = 'setup'
setup_task.tags = ['always']
setup_task.args = {
'gather_subset': gather_subset,
'gather_network_interfaces': gather_interfaces,
}
if gather_timeout:
setup_task.args['gather_timeout'] = gather_timeout
Expand Down
30 changes: 28 additions & 2 deletions lib/ansible/module_utils/facts.py
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,22 @@ def __new__(cls, *arguments, **keyword):
def populate(self):
return self.facts

def _include_interface(self, device_name, default_ipv4=dict(), default_ipv6=dict()):
interfaces_list = self.module.params.get('gather_network_interfaces', None)
# if no limits are set include all interfaces
if interfaces_list is None:
return True
# always include the default interfaces
if default_ipv4 and device_name == default_ipv4.get('interface', None):
return True
if default_ipv6 and device_name == default_ipv6.get('interface', None):
return True
# include all requested interfaces
for pat in interfaces_list:
if fnmatch.fnmatch(device_name, pat):
return True
return False

class LinuxNetwork(Network):
"""
This is a Linux-specific subclass of Network. It defines
Expand Down Expand Up @@ -2228,6 +2244,8 @@ def get_interfaces_info(self, ip_path, default_ipv4, default_ipv6):
if not os.path.isdir(path):
continue
device = os.path.basename(path)
if not self._include_interface(device, default_ipv4, default_ipv6):
continue
interfaces[device] = { 'device': device }
if os.path.exists(os.path.join(path, 'address')):
macaddress = get_file_content(os.path.join(path, 'address'), default='')
Expand Down Expand Up @@ -2432,7 +2450,7 @@ def populate(self):
return self.facts

default_ipv4, default_ipv6 = self.get_default_interfaces(route_path)
interfaces, ips = self.get_interfaces_info(ifconfig_path)
interfaces, ips = self.get_interfaces_info(ifconfig_path, default_ipv4, default_ipv6)
self.merge_default_interface(default_ipv4, interfaces, 'ipv4')
self.merge_default_interface(default_ipv6, interfaces, 'ipv6')
self.facts['interfaces'] = interfaces.keys()
Expand Down Expand Up @@ -2482,9 +2500,10 @@ def get_default_interfaces(self, route_path):

return interface['v4'], interface['v6']

def get_interfaces_info(self, ifconfig_path, ifconfig_options='-a'):
def get_interfaces_info(self, ifconfig_path, default_ipv4, default_ipv6, ifconfig_options='-a'):
interfaces = {}
current_if = {}
skip_current_if = False
ips = dict(
all_ipv4_addresses = [],
all_ipv6_addresses = [],
Expand All @@ -2497,12 +2516,19 @@ def get_interfaces_info(self, ifconfig_path, ifconfig_options='-a'):
for line in out.split('\n'):

if line:
if skip_current_if and not (re.match('^\S', line) and len(words) > 3):
continue

words = line.split()

if words[0] == 'pass':
continue
elif re.match('^\S', line) and len(words) > 3:
skip_current_if = False
current_if = self.parse_interface_line(words)
if not self._include_interface(current_if['device'], default_ipv4, default_ipv6):
skip_current_if = True
continue
interfaces[ current_if['device'] ] = current_if
elif words[0].startswith('options='):
self.parse_options_line(words, current_if, ips)
Expand Down
1 change: 1 addition & 0 deletions lib/ansible/playbook/play.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Play(Base, Taggable, Become):
_gather_facts = FieldAttribute(isa='bool', default=None, always_post_validate=True)
_gather_subset = FieldAttribute(isa='barelist', default=None, always_post_validate=True)
_gather_timeout = FieldAttribute(isa='int', default=None, always_post_validate=True)
_gather_network_interfaces = FieldAttribute(isa='barelist', default=None, always_post_validate=True)
_hosts = FieldAttribute(isa='list', required=True, listof=string_types, always_post_validate=True)
_name = FieldAttribute(isa='string', default='', always_post_validate=True)

Expand Down