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

[6.15.z] Refactor ipv6 http_proxy code #16978

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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