Skip to content

Commit

Permalink
feat: Check connection
Browse files Browse the repository at this point in the history
In case of DNS failure. The DNS is queried, then a connection is established to the resolved IP. If resolving fails, a hard-coded IP is tried for production or staging. In case of either failure, DNS query for a public CloudFlare URL one.one.one.one and its IP 1.1.1.1 is tried.
  • Loading branch information
Glutexo committed Dec 20, 2024
1 parent c393d5b commit e3c1f79
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 1 deletion.
64 changes: 63 additions & 1 deletion insights/client/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from __future__ import print_function
from __future__ import absolute_import
import requests
import socket
import os
import six
import json
Expand All @@ -18,10 +19,12 @@
try:
# python 2
from urlparse import urlparse
from urlparse import urlunparse
from urllib import quote
except ImportError:
# python 3
from urllib.parse import urlparse
from urllib.parse import urlunparse
from urllib.parse import quote
from .utilities import (determine_hostname,
generate_machine_id,
Expand Down Expand Up @@ -74,6 +77,26 @@ def _api_request_failed(exception, message='The Insights API could not be reache
logger.error(message)


def _is_dns_error(exception):
while exception:
if isinstance(exception, socket.gaierror):
return True

exception = exception.__context__

return False


def _fallback_ip(hostname):
if hostname.endswith("redhat.com"):
if hostname.endswith("stage.redhat.com"):
return constants.insights_ip_stage
else:
return constants.insights_ip_prod
else:
return None


class InsightsConnection(object):

"""
Expand Down Expand Up @@ -369,7 +392,6 @@ def _legacy_test_urls(self, url, method):
if test_req.status_code in (200, 201):
return True
else:
logger.error(" Failed.")
return False
except REQUEST_FAILED_EXCEPTIONS as exc:
last_ex = exc
Expand Down Expand Up @@ -492,6 +514,22 @@ def test_connection(self, rc=0):
logger.info("Running Connection Tests...")
logger.info("")

# base_url_hostname = urlparse(self.base_url).hostname
# if base_url_hostname.endswith("redhat.com"):
# if base_url_hostname.endswith("stage.redhat.com"):
# base_url_ip = constants.insights_ip_stage
# else:
# base_url_ip = constants.insights_ip_prod
# else:
# base_url_ip = None
#
# resolved_base_url_ip, success_base_url_ip = self._test_connection(base_url_hostname, base_url_ip)
# if not resolved_base_url_ip or not success_base_url_ip:
# resolved_fallback_ip, success_fallback_ip = self._test_connection("www.redhat.com", constants.stable_public_ip)
# logger.debug("dns %s, conn %s", resolved_fallback_ip, success_fallback_ip)
# return False

last_ex = None
for description, url, method in [
("Uploading a file to Ingress", self.upload_url, "POST"),
("Getting hosts from Inventory", self.inventory_url + "/hosts", "GET"),
Expand Down Expand Up @@ -520,6 +558,30 @@ def test_connection(self, rc=0):
logger.error(" Additional information may be in %s" % self.config.logging_file)
logger.error("")

if _is_dns_error(last_ex):
parsed_url = urlparse(url)
logger.error(" Could not resolve %s.", parsed_url.hostname)
fallback = [constants.stable_public_url, constants.stable_public_ip]
ip = _fallback_ip(parsed_url.hostname)
if ip:
fallback = [ip] + fallback

for fallback_url in fallback:
parsed_ip_url = urlunparse((parsed_url.scheme, fallback_url, "/", "", "", ""))
try:
logger.info(' Testing %s', parsed_ip_url)
log_prefix = " "
log_level = NETWORK if self.config.verbose else logging.DEBUG
self.get(parsed_ip_url, log_prefix=log_prefix, log_level=log_level, verify=False)
except REQUEST_FAILED_EXCEPTIONS as exc:
logger.debug(" Caught %s: %s", type(exc).__name__, exc)
logger.error(" Failed.")
else:
logger.info(" SUCCESS.")
break
else:
logger.info(" FAILED.")

return 1

def handle_fail_rcs(self, req):
Expand Down
4 changes: 4 additions & 0 deletions insights/client/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,7 @@ class InsightsConstants(object):
rhsm_facts_file = os.path.join(os.sep, 'etc', 'rhsm', 'facts', 'insights-client.facts')
# In MB
archive_filesize_max = 100
insights_ip_prod = "23.37.45.238"
insights_ip_stage = "23.53.5.13"
stable_public_url = "one.one.one.one" # Public CloudFlare DNS
stable_public_ip = "1.1.1.1" # Public CloudFlare DNS

0 comments on commit e3c1f79

Please sign in to comment.