Skip to content

Commit

Permalink
[6.15.z] Refactor ipv6 http_proxy code (#16978)
Browse files Browse the repository at this point in the history
Co-authored-by: Jameer Pathan <21165044+jameerpathan111@users.noreply.github.com>
  • Loading branch information
Satellite-QE and jameerpathan111 authored Nov 21, 2024
1 parent 299b02c commit a186efa
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 99 deletions.
1 change: 1 addition & 0 deletions conf/http_proxy.yaml.template
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
HTTP_PROXY:
UN_AUTH_PROXY_URL: # http://proxy-01.example.com:3423
HTTP_PROXY_IPV6_URL: # http://proxy-01.ipv6.example.com:3423
AUTH_PROXY_URL: # http://proxy-02.example.com:3423
USERNAME: auth-proxy-user
PASSWORD: auth-proxy-password
12 changes: 12 additions & 0 deletions conf/migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,15 @@ def migration_231129_deploy_workflow(settings, data):
logger.info(
f'Migrated {product_type}.DEPLOY_WORKFLOW to {product_type}.DEPLOY_WORKFLOWS'
)


def migration_241120_http_proxy_ipv6_url(settings, data):
"""Migrates server.http_proxy_ipv6_url to http_proxy.http_proxy_ipv6_url"""
if (
settings.server.get('http_proxy_ipv6_url')
and isinstance(settings.server.http_proxy_ipv6_url, str)
and not settings.http_proxy.get('http_proxy_ipv6_url')
):
data.http_proxy = {}
data.http_proxy.http_proxy_ipv6_url = settings.server.http_proxy_ipv6_url
logger.info('Migrated SERVER.HTTP_PROXY_IPv6_URL to HTTP_PROXY.HTTP_PROXY_IPV6_URL')
2 changes: 0 additions & 2 deletions conf/server.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ SERVER:
RHEL_VERSION: '8'
# If the the satellite server is IPv6 server
IS_IPV6: False
# HTTP Proxy url for IPv6 satellite to connect for outer world access
HTTP_PROXY_IPv6_URL:
# run-on-one - All xdist runners default to the first satellite
# balance - xdist runners will be split between available satellites
# on-demand - any xdist runner without a satellite will have a new one provisioned.
Expand Down
2 changes: 1 addition & 1 deletion pytest_fixtures/component/maintain.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def module_stash(request):
def sat_maintain(request, module_target_sat, module_capsule_configured):
if settings.remotedb.server:
sat = Satellite(settings.remotedb.server)
sat.enable_ipv6_http_proxy()
sat.enable_satellite_ipv6_http_proxy()
yield sat
else:
module_target_sat.register_to_cdn(pool_ids=settings.subscription.fm_rhn_poolid.split())
Expand Down
4 changes: 2 additions & 2 deletions pytest_fixtures/core/broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def _target_sat_imp(request, _default_sat, satellite_factory):
"""This is the actual working part of the following target_sat fixtures"""
if request.node.get_closest_marker(name='destructive'):
new_sat = satellite_factory()
new_sat.enable_ipv6_http_proxy()
new_sat.enable_satellite_ipv6_http_proxy()
yield new_sat
new_sat.teardown()
Broker(hosts=[new_sat]).checkin()
Expand All @@ -34,7 +34,7 @@ def _target_sat_imp(request, _default_sat, satellite_factory):
yield installer_sat
else:
if _default_sat:
_default_sat.enable_ipv6_http_proxy()
_default_sat.enable_satellite_ipv6_http_proxy()
yield _default_sat


Expand Down
14 changes: 7 additions & 7 deletions pytest_fixtures/core/sat_cap_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def resolve_deploy_args(args_dict):
def _target_satellite_host(request, satellite_factory):
if 'sanity' not in request.config.option.markexpr:
new_sat = satellite_factory()
new_sat.enable_ipv6_http_proxy()
new_sat.enable_satellite_ipv6_http_proxy()
yield new_sat
new_sat.teardown()
Broker(hosts=[new_sat]).checkin()
Expand All @@ -49,7 +49,7 @@ def cached_capsule_cdn_register(hostname=None):
def _target_capsule_host(request, capsule_factory):
if 'sanity' not in request.config.option.markexpr and not request.config.option.n_minus:
new_cap = capsule_factory()
new_cap.enable_ipv6_http_proxy()
new_cap.enable_ipv6_dnf_and_rhsm_proxy()
yield new_cap
new_cap.teardown()
Broker(hosts=[new_cap]).checkin()
Expand Down Expand Up @@ -96,7 +96,7 @@ def factory(retry_limit=3, delay=300, workflow=None, **broker_args):
def large_capsule_host(capsule_factory):
"""A fixture that provides a Capsule based on config settings"""
new_cap = capsule_factory(deploy_flavor=settings.flavors.custom_db)
new_cap.enable_ipv6_http_proxy()
new_cap.enable_ipv6_dnf_and_rhsm_proxy()
yield new_cap
new_cap.teardown()
Broker(hosts=[new_cap]).checkin()
Expand Down Expand Up @@ -250,7 +250,7 @@ def module_lb_capsule(retry_limit=3, delay=300, **broker_args):
)
cap_hosts = wait_for(hosts.checkout, timeout=timeout, delay=delay)

[cap.enable_ipv6_http_proxy() for cap in cap_hosts.out]
[cap.enable_ipv6_dnf_and_rhsm_proxy() for cap in cap_hosts.out]
yield cap_hosts.out

[cap.teardown() for cap in cap_hosts.out]
Expand Down Expand Up @@ -285,7 +285,7 @@ def parametrized_enrolled_sat(
):
"""Yields a Satellite enrolled into [IDM, AD] as parameter."""
new_sat = satellite_factory()
new_sat.enable_ipv6_http_proxy()
new_sat.enable_satellite_ipv6_http_proxy()
ipa_host = IPAHost(new_sat)
new_sat.register_to_cdn()
if 'IDM' in request.param:
Expand Down Expand Up @@ -345,7 +345,7 @@ def cap_ready_rhel():
'workflow': settings.capsule.deploy_workflows.os,
}
with Broker(**deploy_args, host_class=Capsule) as host:
host.enable_ipv6_http_proxy()
host.enable_ipv6_dnf_and_rhsm_proxy()
yield host


Expand Down Expand Up @@ -403,7 +403,7 @@ def installer_satellite(request):
).get_command(),
timeout='30m',
)
sat.enable_ipv6_http_proxy()
sat.enable_satellite_ipv6_http_proxy()
if 'sanity' in request.config.option.markexpr:
configure_nailgun()
configure_airgun()
Expand Down
12 changes: 6 additions & 6 deletions robottelo/config/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@
Validator('server.ssh_password', default=None),
Validator('server.verify_ca', default=False),
Validator('server.is_ipv6', is_type_of=bool, default=False),
# validate http_proxy_ipv6_url only if is_ipv6 is True
Validator(
'server.http_proxy_ipv6_url',
is_type_of=str,
when=Validator('server.is_ipv6', eq=True),
),
],
content_host=[
Validator('content_host.default_rhel_version', must_exist=True),
Expand Down Expand Up @@ -161,6 +155,12 @@
'http_proxy.password',
must_exist=True,
),
# validate http_proxy_ipv6_url only if server.is_ipv6 is True
Validator(
'http_proxy.http_proxy_ipv6_url',
is_type_of=str,
when=Validator('server.is_ipv6', eq=True),
),
],
ipa=[
Validator(
Expand Down
4 changes: 2 additions & 2 deletions robottelo/host_helpers/contenthost_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@ def download_repofile(self, product=None, release=None, snap='', proxy=None):
"""Downloads the tools/client, capsule, or satellite repos on the machine"""
product, release, v_major, _ = self._dogfood_helper(product, release)
if not proxy and settings.server.is_ipv6:
proxy = settings.server.http_proxy_ipv6_url
proxy = settings.http_proxy.http_proxy_ipv6_url
url = dogfood_repofile_url(settings.ohsnap, product, release, v_major, snap, proxy=proxy)
command = f'curl -o /etc/yum.repos.d/{product}.repo -L {url}'
if settings.server.is_ipv6:
command += f' -x {settings.server.http_proxy_ipv6_url}'
command += f' -x {settings.http_proxy.http_proxy_ipv6_url}'
self.execute(command)

def dogfood_repository(self, repo=None, product=None, release=None, snap=''):
Expand Down
149 changes: 81 additions & 68 deletions robottelo/hosts.py
Original file line number Diff line number Diff line change
Expand Up @@ -959,22 +959,39 @@ def put_ssh_key(self, source_key_path, destination_key_name):
raise CLIFactoryError(f'Failed to chmod ssh key file:\n{result.stderr}')

def enable_rhsm_proxy(self, hostname, port=None):
"""Configures proxy for subscription manager"""
"""Configures HTTP proxy for subscription manager"""
cmd = f"subscription-manager config --server.proxy_hostname={hostname}"
if port:
cmd += f' --server.proxy_port={port}'
logger.info(f'Configuring {hostname} HTTP proxy for subscription manager.')
self.execute(cmd)

def enable_dnf_proxy(self, hostname, scheme=None, port=None):
"""Configures proxy for dnf"""
"""Configures HTTP proxy for dnf"""
if not scheme:
scheme = 'http'
cmd = f"echo -e 'proxy = {scheme}://{hostname}"
if port:
cmd += f':{port}'
cmd += "' >> /etc/dnf/dnf.conf"
logger.info(f'Configuring {hostname} HTTP proxy for dnf.')
self.execute(cmd)

def disable_rhsm_proxy(self):
"""Disables HTTP proxy for subscription manager"""
self.execute('subscription-manager remove server.proxy_hostname server.proxy_port')

def disable_dnf_proxy(self):
"""Disable HTTP proxy for dnf"""
self.execute('sed -i "/^proxy/d" /etc/dnf/dnf.conf')

def enable_ipv6_dnf_and_rhsm_proxy(self):
"""Execute procedures for enabling rhsm and dnf IPv6 HTTP Proxy"""
if self.ipv6:
url = urlparse(settings.http_proxy.http_proxy_ipv6_url)
self.enable_rhsm_proxy(url.hostname, url.port)
self.enable_dnf_proxy(url.hostname, url.scheme, url.port)

def add_authorized_key(self, pub_key):
"""Inject a public key into the authorized keys file
Expand Down Expand Up @@ -1088,7 +1105,7 @@ def configure_puppet(self, proxy_hostname=None, run_puppet_agent=True):
# sat6 under the capsule --> certifcates or on capsule via cli "puppetserver
# ca list", so that we sign it.
self.execute('/opt/puppetlabs/bin/puppet agent -t')
proxy_host = Host(hostname=proxy_hostname, ipv6=settings.server.is_ipv6)
proxy_host = Host(hostname=proxy_hostname, ipv6=self.ipv6)
proxy_host.execute(f'puppetserver ca sign --certname {cert_name}')

if run_puppet_agent:
Expand Down Expand Up @@ -1524,8 +1541,8 @@ def register_to_cdn(self, pool_ids=None):
self.remove_katello_ca()

# Enabling proxy for IPv6
if settings.server.is_ipv6:
url = urlparse(settings.server.http_proxy_ipv6_url)
if self.ipv6:
url = urlparse(settings.http_proxy.http_proxy_ipv6_url)
self.enable_rhsm_proxy(url.hostname, url.port)
self.enable_dnf_proxy(url.hostname, url.scheme, url.port)

Expand Down Expand Up @@ -1694,19 +1711,6 @@ def enable_capsule_downstream_repos(self):
snap=settings.capsule.version.snap,
)

def enable_ipv6_http_proxy(self):
"""Execute procedures for enabling IPv6 HTTP Proxy on Capsule using SM"""
if settings.server.is_ipv6:
url = urlparse(settings.server.http_proxy_ipv6_url)
self.enable_rhsm_proxy(url.hostname, url.port)
self.enable_dnf_proxy(url.hostname, url.scheme, url.port)
self.ipv6 = settings.server.is_ipv6

def disable_ipv6_http_proxy(self):
"""Executes procedures for disabling IPv6 HTTP Proxy on Capsule"""
if settings.server.is_ipv6:
self.execute('subscription-manager remove server.proxy_hostname server.proxy_port')

def capsule_setup(self, sat_host=None, capsule_cert_opts=None, **installer_kwargs):
"""Prepare the host and run the capsule installer"""
self._satellite = sat_host or Satellite()
Expand Down Expand Up @@ -1872,56 +1876,6 @@ def _swap_nailgun(self, new_version):
to_clear = [k for k in sys.modules if 'nailgun' in k]
[sys.modules.pop(k) for k in to_clear]

def enable_ipv6_http_proxy(self):
"""Execute procedures for enabling IPv6 HTTP Proxy"""
if not settings.server.is_ipv6:
logger.warning(
'The IPv6 HTTP Proxy setting is not enabled. Skipping the IPv6 HTTP Proxy setup.'
)
return None
self.ipv6 = settings.server.is_ipv6
proxy_name = 'Robottelo IPv6 Automation Proxy'
if not self.cli.HttpProxy.exists(search=('name', proxy_name)):
http_proxy = self.api.HTTPProxy(
name=proxy_name, url=settings.server.http_proxy_ipv6_url
).create()
else:
logger.info(
'The IPv6 HTTP Proxy is already enabled. Skipping the IPv6 HTTP Proxy setup.'
)
http_proxy = self.api.HTTPProxy().search(query={'search': f'name="{proxy_name}"'})[0]
# Setting HTTP Proxy as default in the settings
self.cli.Settings.set(
{
'name': 'content_default_http_proxy',
'value': proxy_name,
}
)
self.cli.Settings.set(
{
'name': 'http_proxy',
'value': settings.server.http_proxy_ipv6_url,
}
)
return http_proxy

def disable_ipv6_http_proxy(self, http_proxy):
"""Execute procedures for disabling IPv6 HTTP Proxy"""
if http_proxy:
http_proxy.delete()
self.cli.Settings.set(
{
'name': 'content_default_http_proxy',
'value': '',
}
)
self.cli.Settings.set(
{
'name': 'http_proxy',
'value': '',
}
)

@property
def api(self):
"""Import all nailgun entities and wrap them under self.api"""
Expand Down Expand Up @@ -2067,6 +2021,65 @@ def satellite(self):
return self
return self._satellite

def enable_satellite_http_proxy(self):
"""Execute procedures for setting HTTP Proxy in Satellite settings.
Sets an HTTP proxy for all outgoing HTTP(S) connections from Satellite and
default HTTP proxy for syncing content.
"""
http_proxy_name = 'IPv4 HTTP Proxy for Content sync'
http_proxy_url = settings.http_proxy.un_auth_proxy_url
if self.ipv6:
http_proxy_name = 'IPv6 HTTP Proxy for Content sync'
http_proxy_url = settings.http_proxy.http_proxy_ipv6_url
if not self.cli.HttpProxy.exists(search=('name', http_proxy_name)):
http_proxy = self.api.HTTPProxy(name=http_proxy_name, url=http_proxy_url).create()
else:
logger.info('The HTTP Proxy is already enabled. Skipping the HTTP Proxy setup.')
http_proxy = self.api.HTTPProxy().search(query={'search': f'name="{http_proxy_name}"'})[
0
]
# Setting HTTP Proxy as default in the settings
logger.info(
f'Setting {http_proxy_name} as content_default_http_proxy in Satellite settings.'
)
self.cli.Settings.set(
{
'name': 'content_default_http_proxy',
'value': http_proxy_name,
}
)
logger.info(f'Setting {http_proxy_name} as general http_proxy in Satellite settings.')
self.cli.Settings.set(
{
'name': 'http_proxy',
'value': http_proxy_url,
}
)
return http_proxy

def disable_satellite_http_proxy(self, http_proxy):
"""Execute procedures for disabling HTTP Proxy in Satellite settings."""
if http_proxy:
http_proxy.delete()
self.cli.Settings.set(
{
'name': 'content_default_http_proxy',
'value': '',
}
)
self.cli.Settings.set(
{
'name': 'http_proxy',
'value': '',
}
)

def enable_satellite_ipv6_http_proxy(self):
"""Execute procedures for setting ipv6 HTTP Proxy in Satellite settings, rhsm and dnf."""
if self.ipv6:
self.enable_satellite_http_proxy()
self.enable_ipv6_dnf_and_rhsm_proxy()

def is_remote_db(self):
return (
self.execute(f'grep "db_manage: false" {constants.SATELLITE_ANSWER_FILE}').status == 0
Expand Down
2 changes: 1 addition & 1 deletion tests/foreman/api/test_http_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
def test_positive_end_to_end(
setup_http_proxy, module_target_sat, module_org, module_repos_collection_with_manifest
):
"""End-to-end test for HTTP Proxy related scenarios.
"""End-to-end test for HTTP proxy related scenarios.
:id: 38df5479-9127-49f3-a30e-26b33655971a
Expand Down
Loading

0 comments on commit a186efa

Please sign in to comment.