Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
salt.21019
implement-network.fqdns-module-function-bsc-113...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File implement-network.fqdns-module-function-bsc-1134860-.patch of Package salt.21019
From a11587a1209cd198f421fafdb43510b6d651f4b2 Mon Sep 17 00:00:00 2001 From: EricS <54029547+ESiebigteroth@users.noreply.github.com> Date: Tue, 3 Sep 2019 11:22:53 +0200 Subject: [PATCH] Implement network.fqdns module function (bsc#1134860) (#172) * Duplicate fqdns logic in module.network * Move _get_interfaces to utils.network * Reuse network.fqdns in grains.core.fqdns * Return empty list when fqdns grains is disabled Co-authored-by: Eric Siebigteroth <eric.siebigteroth@suse.de> --- salt/grains/core.py | 66 +++++------------------------------------- salt/modules/network.py | 60 ++++++++++++++++++++++++++++++++++++++ salt/utils/network.py | 12 ++++++++ tests/unit/grains/test_core.py | 63 +++++++++++++++++++++++++++++++--------- 4 files changed, 130 insertions(+), 71 deletions(-) diff --git a/salt/grains/core.py b/salt/grains/core.py index 0f3ccd9b92..77ae99590f 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -26,8 +26,9 @@ from errno import EACCES, EPERM import datetime import warnings import time +import salt.modules.network -from multiprocessing.pool import ThreadPool +from salt.utils.network import _get_interfaces # pylint: disable=import-error try: @@ -84,6 +85,7 @@ __salt__ = { 'cmd.run_all': salt.modules.cmdmod._run_all_quiet, 'smbios.records': salt.modules.smbios.records, 'smbios.get': salt.modules.smbios.get, + 'network.fqdns': salt.modules.network.fqdns, } log = logging.getLogger(__name__) @@ -107,7 +109,6 @@ HAS_UNAME = True if not hasattr(os, 'uname'): HAS_UNAME = False -_INTERFACES = {} # Possible value for h_errno defined in netdb.h HOST_NOT_FOUND = 1 @@ -1553,17 +1554,6 @@ def _linux_bin_exists(binary): return False -def _get_interfaces(): - ''' - Provide a dict of the connected interfaces and their ip addresses - ''' - - global _INTERFACES - if not _INTERFACES: - _INTERFACES = salt.utils.network.interfaces() - return _INTERFACES - - def _parse_lsb_release(): ret = {} try: @@ -2271,52 +2261,12 @@ def fqdns(): ''' Return all known FQDNs for the system by enumerating all interfaces and then trying to reverse resolve them (excluding 'lo' interface). + To disable the fqdns grain, set enable_fqdns_grains: False in the minion configuration file. ''' - # Provides: - # fqdns - - grains = {} - fqdns = set() - - def _lookup_fqdn(ip): - try: - name, aliaslist, addresslist = socket.gethostbyaddr(ip) - return [socket.getfqdn(name)] + [als for als in aliaslist if salt.utils.network.is_fqdn(als)] - except socket.herror as err: - if err.errno in (0, HOST_NOT_FOUND, NO_DATA): - # No FQDN for this IP address, so we don't need to know this all the time. - log.debug("Unable to resolve address %s: %s", ip, err) - else: - log.error(err_message, ip, err) - except (socket.error, socket.gaierror, socket.timeout) as err: - log.error(err_message, ip, err) - - start = time.time() - - addresses = salt.utils.network.ip_addrs(include_loopback=False, interface_data=_get_interfaces()) - addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False, interface_data=_get_interfaces())) - err_message = 'Exception during resolving address: %s' - - # Create a ThreadPool to process the underlying calls to 'socket.gethostbyaddr' in parallel. - # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing - # that "socket.timeout" was reached multiple times secuencially, blocking execution for several seconds. - - try: - pool = ThreadPool(8) - results = pool.map(_lookup_fqdn, addresses) - pool.close() - pool.join() - except Exception as exc: - log.error("Exception while creating a ThreadPool for resolving FQDNs: %s", exc) - - for item in results: - if item: - fqdns.update(item) - - elapsed = time.time() - start - log.debug('Elapsed time getting FQDNs: {} seconds'.format(elapsed)) - - return {"fqdns": sorted(list(fqdns))} + opt = {"fqdns": []} + if __opts__.get('enable_fqdns_grains', True) == True: + opt = __salt__['network.fqdns']() + return opt def ip_fqdn(): diff --git a/salt/modules/network.py b/salt/modules/network.py index 38e2bc326e..880f4f8d5f 100644 --- a/salt/modules/network.py +++ b/salt/modules/network.py @@ -11,6 +11,10 @@ import logging import re import os import socket +import time + +from multiprocessing.pool import ThreadPool + # Import salt libs import salt.utils.decorators.path @@ -1887,3 +1891,59 @@ def iphexval(ip): a = ip.split('.') hexval = ['%02X' % int(x) for x in a] # pylint: disable=E1321 return ''.join(hexval) + + +def fqdns(): + ''' + Return all known FQDNs for the system by enumerating all interfaces and + then trying to reverse resolve them (excluding 'lo' interface). + ''' + # Provides: + # fqdns + + # Possible value for h_errno defined in netdb.h + HOST_NOT_FOUND = 1 + NO_DATA = 4 + + grains = {} + fqdns = set() + + def _lookup_fqdn(ip): + try: + name, aliaslist, addresslist = socket.gethostbyaddr(ip) + return [socket.getfqdn(name)] + [als for als in aliaslist if salt.utils.network.is_fqdn(als)] + except socket.herror as err: + if err.errno in (0, HOST_NOT_FOUND, NO_DATA): + # No FQDN for this IP address, so we don't need to know this all the time. + log.debug("Unable to resolve address %s: %s", ip, err) + else: + log.error(err_message, err) + except (socket.error, socket.gaierror, socket.timeout) as err: + log.error(err_message, err) + + start = time.time() + + addresses = salt.utils.network.ip_addrs(include_loopback=False, interface_data=salt.utils.network._get_interfaces()) + addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False, interface_data=salt.utils.network._get_interfaces())) + err_message = 'Exception during resolving address: %s' + + # Create a ThreadPool to process the underlying calls to 'socket.gethostbyaddr' in parallel. + # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing + # that "socket.timeout" was reached multiple times secuencially, blocking execution for several seconds. + + try: + pool = ThreadPool(8) + results = pool.map(_lookup_fqdn, addresses) + pool.close() + pool.join() + except Exception as exc: + log.error("Exception while creating a ThreadPool for resolving FQDNs: %s", exc) + + for item in results: + if item: + fqdns.update(item) + + elapsed = time.time() - start + log.debug('Elapsed time getting FQDNs: {} seconds'.format(elapsed)) + + return {"fqdns": sorted(list(fqdns))} \ No newline at end of file diff --git a/salt/utils/network.py b/salt/utils/network.py index 74536cc143..4cc8a05c4a 100644 --- a/salt/utils/network.py +++ b/salt/utils/network.py @@ -50,6 +50,18 @@ except (ImportError, OSError, AttributeError, TypeError): pass +_INTERFACES = {} +def _get_interfaces(): #! function + ''' + Provide a dict of the connected interfaces and their ip addresses + ''' + + global _INTERFACES + if not _INTERFACES: + _INTERFACES = interfaces() + return _INTERFACES + + def sanitize_host(host): ''' Sanitize host string. diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py index ac03b57226..60914204b0 100644 --- a/tests/unit/grains/test_core.py +++ b/tests/unit/grains/test_core.py @@ -35,6 +35,7 @@ import salt.utils.path import salt.modules.cmdmod import salt.modules.smbios import salt.grains.core as core +import salt.modules.network # Import 3rd-party libs from salt.ext import six @@ -1029,6 +1030,40 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin): with patch.object(salt.utils.dns, 'parse_resolv', MagicMock(return_value=resolv_mock)): assert core.dns() == ret + + def test_enablefqdnsFalse(self): + ''' + tests enable_fqdns_grains is set to False + ''' + with patch.dict('salt.grains.core.__opts__', {'enable_fqdns_grains':False}): + assert core.fqdns() == {"fqdns": []} + + + def test_enablefqdnsTrue(self): + ''' + testing that grains uses network.fqdns module + ''' + with patch.dict('salt.grains.core.__salt__', {'network.fqdns': MagicMock(return_value="my.fake.domain")}): + with patch.dict('salt.grains.core.__opts__', {'enable_fqdns_grains':True}): + assert core.fqdns() == 'my.fake.domain' + + + def test_enablefqdnsNone(self): + ''' + testing default fqdns grains is returned when enable_fqdns_grains is None + ''' + with patch.dict('salt.grains.core.__opts__', {'enable_fqdns_grains':None}): + assert core.fqdns() == {"fqdns": []} + + + def test_enablefqdnswithoutpaching(self): + ''' + testing fqdns grains is enabled by default + ''' + with patch.dict('salt.grains.core.__salt__', {'network.fqdns': MagicMock(return_value="my.fake.domain")}): + assert core.fqdns() == 'my.fake.domain' + + @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux') @patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4', '5.6.7.8'])) @patch('salt.utils.network.ip_addrs6', @@ -1044,11 +1079,12 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin): ('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']), ('bluesniff.foo.bar', [], ['fe80::a8b2:93ff:dead:beef'])] ret = {'fqdns': ['bluesniff.foo.bar', 'foo.bar.baz', 'rinzler.evil-corp.com']} - with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock): - fqdns = core.fqdns() - assert "fqdns" in fqdns - assert len(fqdns['fqdns']) == len(ret['fqdns']) - assert set(fqdns['fqdns']) == set(ret['fqdns']) + with patch.dict(core.__salt__, {'network.fqdns': salt.modules.network.fqdns}): + with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock): + fqdns = core.fqdns() + assert "fqdns" in fqdns + assert len(fqdns['fqdns']) == len(ret['fqdns']) + assert set(fqdns['fqdns']) == set(ret['fqdns']) @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux') @patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4'])) @@ -1094,14 +1130,15 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin): ('rinzler.evil-corp.com', ["false-hostname", "badaliass"], ['5.6.7.8']), ('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']), ('bluesniff.foo.bar', ["alias.bluesniff.foo.bar"], ['fe80::a8b2:93ff:dead:beef'])] - with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock): - fqdns = core.fqdns() - assert "fqdns" in fqdns - for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]: - assert alias in fqdns["fqdns"] - - for alias in ["throwmeaway", "false-hostname", "badaliass"]: - assert alias not in fqdns["fqdns"] + with patch.dict(core.__salt__, {'network.fqdns': salt.modules.network.fqdns}): + with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock): + fqdns = core.fqdns() + assert "fqdns" in fqdns + for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]: + assert alias in fqdns["fqdns"] + + for alias in ["throwmeaway", "false-hostname", "badaliass"]: + assert alias not in fqdns["fqdns"] def test_core_virtual(self): ''' -- 2.16.4
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor