Do not require a nameserver to detect the local IP address

There may be cases where a name server is not configured on a system,
and there is no Internet access. Changing the local IP detection code
to work on these cases, by using the default gateway as a reference.

Change-Id: I3a6da3cdd3f3a17c24a855a912a3134e651cdc61
Closes-Bug: #1656459
This commit is contained in:
Javier Pena 2017-01-16 11:29:11 +01:00 committed by Alfredo Moralejo
parent 18f95c05fd
commit b1f8a221cf
2 changed files with 29 additions and 31 deletions

View File

@ -12,50 +12,47 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import netifaces
import socket
import logging
from ..exceptions import NetworkError
from .shell import ScriptRunner
netaddr_available = True
try:
import netaddr
except ImportError:
netaddr_available = False
import re
import socket
import logging
from ..exceptions import NetworkError
from .shell import execute
from .shell import ScriptRunner
def get_localhost_ip():
"""
Returns IP address of localhost.
"""
# TO-DO: Will probably need to find better way to find out localhost
# address.
# find nameservers
ns_regex = re.compile('nameserver\s*(?P<ns_ip>[\d\.\:]+)')
rc, resolv = execute('cat /etc/resolv.conf | grep nameserver',
can_fail=False, use_shell=True, log=False)
nsrvs = []
for line in resolv.split('\n'):
match = ns_regex.match(line.strip())
if match:
nsrvs.append(match.group('ns_ip'))
# try to connect to nameservers and return own IP address
nsrvs.append('8.8.8.8') # default to google dns
for i in nsrvs:
# Try to get the IPv4 or IPv6 default gateway, then open a socket
# to discover our local IP
gw = None
for protocol in (socket.AF_INET, socket.AF_INET6):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((i, 0))
loc_ip = s.getsockname()[0]
except socket.error:
gw = netifaces.gateways()['default'][protocol][0]
if protocol == socket.AF_INET6:
gw = gw + '%' + netifaces.gateways()['default'][protocol][1]
discovered_protocol = protocol
break
except KeyError: # No default gw for this protocol
continue
else:
return loc_ip
raise NetworkError('Local IP address discovery failed. Please set '
'nameserver correctly.')
else:
raise NetworkError('Local IP address discovery failed. Please set '
'a default gateway for your system.')
address = socket.getaddrinfo(gw, 0, discovered_protocol,
socket.SOCK_DGRAM)[0]
s = socket.socket(discovered_protocol, socket.SOCK_DGRAM)
s.connect(address[4])
# Remove chars after %. Does nothing on IPv4, removes scope id in IPv6
loc_ip = s.getsockname()[0].split('%')[0]
return loc_ip
_host_cache = {}

View File

@ -4,3 +4,4 @@ PyYAML>=3.10
docutils>=0.11
cryptography!=1.3.0,>=1.0
pyOpenSSL<15.0.0
netifaces