Skip to content

Commit be9b321

Browse files
author
Grigory Ponomarenko
committed
CLOS-2759: The elevation process failed during stage 3 - Cache-only enabled but no cache for 'cloudlinux-x86_64-server-8'
* Pin CLN mirror before downloading packages to cache * Unpin after first boot * Fix error handling in CLN cache only flag handling
1 parent a17bd9e commit be9b321

File tree

6 files changed

+149
-6
lines changed

6 files changed

+149
-6
lines changed

repos/system_upgrade/cloudlinux/actors/setclncacheonlyflag/actor.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from leapp.actors import Actor
22
from leapp.tags import PreparationPhaseTag, IPUWorkflowTag
33
from leapp.libraries.common.cllaunch import run_on_cloudlinux
4-
4+
from leapp.libraries.common.cln_switch import get_cln_cacheonly_flag_path
55

66
class SetClnCacheOnlyFlag(Actor):
77
"""
@@ -20,6 +20,7 @@ class SetClnCacheOnlyFlag(Actor):
2020
@run_on_cloudlinux
2121
def process(self):
2222
# TODO: Use a more reliable method to detect if we're running from the isolated userspace
23-
# TODO: Replace hardcoded path with a constant (from target_userspace_creator.constants?)
24-
with open('/var/lib/leapp/el8userspace/etc/cln_leapp_in_progress', 'w') as file:
23+
# Currently we're directly placing the file into the userspace directory '/var/lib/leapp/el{}userspace'
24+
# There should be better options
25+
with open(get_cln_cacheonly_flag_path(), 'w') as file:
2526
file.write('1')

repos/system_upgrade/cloudlinux/actors/switchclnchanneldownload/actor.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
import os
2+
import json
3+
14
from leapp.actors import Actor
25
from leapp.libraries.stdlib import api
36
from leapp.tags import DownloadPhaseTag, IPUWorkflowTag
47
from leapp.libraries.stdlib import CalledProcessError
58
from leapp.libraries.common.cllaunch import run_on_cloudlinux
6-
from leapp.libraries.common.cln_switch import cln_switch
9+
from leapp.libraries.common.cln_switch import cln_switch, get_target_userspace_path
710
from leapp import reporting
811
from leapp.reporting import Report
912

1013

14+
15+
CLN_REPO_ID = "cloudlinux-x86_64-server-8"
16+
DEFAULT_CLN_MIRROR = "https://xmlrpc.cln.cloudlinux.com/XMLRPC/"
17+
18+
1119
class SwitchClnChannelDownload(Actor):
1220
"""
1321
Switch CLN channel from 7 to 8 to be able to download upgrade packages.
@@ -48,3 +56,45 @@ def process(self):
4856
api.current_logger().error(
4957
"Could not call RHN command: Message: %s", str(e), exc_info=True
5058
)
59+
60+
self._pin_cln_mirror()
61+
62+
def _pin_cln_mirror(self):
63+
"""Pin CLN mirror"""
64+
target_userspace = get_target_userspace_path()
65+
api.current_logger().info("Pin CLN mirror: target userspace=%s", target_userspace)
66+
67+
# load last mirror URL from dnf spacewalk plugin cache
68+
spacewalk_settings = {}
69+
70+
# find the mirror used in the last transaction
71+
# (expecting to find the one used in dnf_package_download actor)
72+
spacewalk_json_path = os.path.join(target_userspace, 'var/lib/dnf/_spacewalk.json')
73+
try:
74+
with open(spacewalk_json_path) as file:
75+
spacewalk_settings = json.load(file)
76+
except (OSError, IOError, ValueError):
77+
api.current_logger().error(
78+
"No spacewalk settings found in %s - can't identify the last used CLN mirror",
79+
spacewalk_json_path,
80+
)
81+
82+
mirror_url = spacewalk_settings.get(CLN_REPO_ID, {}).get("url", [DEFAULT_CLN_MIRROR])[0]
83+
84+
# pin mirror
85+
for mirrorlist_path in [
86+
'/etc/mirrorlist',
87+
os.path.join(target_userspace, 'etc/mirrorlist'),
88+
]:
89+
with open(mirrorlist_path, 'w') as file:
90+
file.write(mirror_url + '\n')
91+
api.current_logger().info("Pin CLN mirror %s in %s", mirror_url, mirrorlist_path)
92+
93+
for up2date_path in [
94+
'/etc/sysconfig/rhn/up2date',
95+
os.path.join(target_userspace, 'etc/sysconfig/rhn/up2date'),
96+
]:
97+
# At some point up2date in `target_userspace` might be overwritten by a default one
98+
with open(up2date_path, 'a+') as file:
99+
file.write('\nmirrorURL[comment]=Set mirror URL to /etc/mirrorlist\nmirrorURL=file:///etc/mirrorlist\n')
100+
api.current_logger().info("Updated up2date_path %s", up2date_path)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import os
2+
3+
from leapp.actors import Actor
4+
from leapp.libraries.common.cllaunch import run_on_cloudlinux
5+
from leapp.libraries.common.cln_switch import get_target_userspace_path
6+
from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag
7+
8+
class UnpinClnMirror(Actor):
9+
"""
10+
Remove the pinned CLN mirror.
11+
See the pin_cln_mirror actor for more details.
12+
"""
13+
14+
name = 'unpin_cln_mirror'
15+
consumes = ()
16+
produces = ()
17+
tags = (IPUWorkflowTag, FirstBootPhaseTag)
18+
19+
CLN_REPO_ID = "cloudlinux-x86_64-server-8"
20+
DEFAULT_CLN_MIRROR = "https://xmlrpc.cln.cloudlinux.com/XMLRPC/"
21+
22+
@run_on_cloudlinux
23+
def process(self):
24+
target_userspace = get_target_userspace_path()
25+
26+
for mirrorlist_path in [
27+
'/etc/mirrorlist',
28+
os.path.join(target_userspace, 'etc/mirrorlist'),
29+
]:
30+
try:
31+
os.remove(mirrorlist_path)
32+
except OSError:
33+
self.log.info('Can\'t remove %s, file does not exist, doing nothing', mirrorlist_path)
34+
35+
for up2date_path in [
36+
'/etc/sysconfig/rhn/up2date',
37+
os.path.join(target_userspace, 'etc/sysconfig/rhn/up2date'),
38+
]:
39+
try:
40+
with open(up2date_path, 'r') as file:
41+
lines = [
42+
line for line in file.readlines() if 'etc/mirrorlist' not in line
43+
]
44+
with open(up2date_path, 'w') as file:
45+
file.writelines(lines)
46+
except (OSError, IOError, ValueError):
47+
self.log.info('Can update %s file, doing nothing', up2date_path)

repos/system_upgrade/cloudlinux/actors/unsetclncacheonlyflag/actor.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from leapp.actors import Actor
22
from leapp.tags import FirstBootPhaseTag, IPUWorkflowTag
33
from leapp.libraries.common.cllaunch import run_on_cloudlinux
4+
from leapp.libraries.common.cln_switch import get_cln_cacheonly_flag_path
45

56
import os
67

@@ -17,6 +18,6 @@ class UnsetClnCacheOnlyFlag(Actor):
1718
@run_on_cloudlinux
1819
def process(self):
1920
try:
20-
os.remove('/var/lib/leapp/el8userspace/etc/cln_leapp_in_progress')
21-
except FileNotFoundError:
21+
os.remove(get_cln_cacheonly_flag_path())
22+
except OSError:
2223
self.log.info('CLN cache file marker does not exist, doing nothing.')

repos/system_upgrade/cloudlinux/libraries/cln_switch.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,46 @@
1+
import os
2+
13
from leapp.libraries.stdlib import api
24
from leapp.libraries.stdlib import run
5+
from leapp.libraries.common.config.version import get_target_major_version
36

47
SWITCH_BIN = "/usr/sbin/cln-switch-channel"
8+
TARGET_USERSPACE = '/var/lib/leapp/el{}userspace'
9+
CLN_CACHEONLY_MARKER = '/etc/cln_leapp_in_progress'
10+
11+
def get_target_userspace_path():
12+
"""
13+
Returns the path to the target OS userspace directory.
14+
15+
Used as a root dir for Leapp-related package operations.
16+
Modifications performed in this directory are not visible to the host OS.
17+
"""
18+
return TARGET_USERSPACE.format(get_target_major_version())
19+
20+
def get_cln_cacheonly_flag_path():
21+
"""
22+
Get the path to the flag file used to prevent the dnf-spacewalk-plugin
23+
from contacting the CLN server during transaction.
24+
25+
Effectively forces the plugin to act as if network connectivity was disabled,
26+
(no matter if it actually is or not), making it use the local cache only.
27+
28+
If this flag isn't present during the upgrade,
29+
the plugin would attempt to contact the CLN server and fail due to the lack
30+
of network connectivity, disrupting the upgrade.
31+
32+
DNF plugin runs in the target OS userspace, so the flag must be placed there.
33+
"""
34+
return os.path.join(get_target_userspace_path(), CLN_CACHEONLY_MARKER.lstrip('/'))
535

636
def cln_switch(target):
37+
"""
38+
Switch the CloudLinux Network channel to the specified target OS.
39+
40+
Target OS is stored server-side, so the switch is permanent unless changed again.
41+
For a CL7 to CL8 upgrade, we need to switch to the CL8 channel to
42+
get served the correct packages.
43+
"""
744
switch_cmd = [SWITCH_BIN, "-t", str(target), "-o", "-f"]
845
yum_clean_cmd = ["yum", "clean", "all"]
946
res = run(switch_cmd)

repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,13 @@ def _prep_repository_access(context, target_userspace):
299299
with open(os.path.join(target_etc, 'dnf/plugins/spacewalk.conf'), 'w') as f:
300300
f.writelines(new_lines)
301301

302+
if os.path.isfile('/etc/mirrorlist'):
303+
try:
304+
os.remove(os.path.join(target_etc, 'mirrorlist'))
305+
except OSError:
306+
pass
307+
context.copy_from('/etc/mirrorlist', os.path.join(target_etc, 'mirrorlist'))
308+
302309
# NOTE: we cannot just remove the original target yum.repos.d dir
303310
# as e.g. in case of RHUI a special RHUI repofiles are installed by a pkg
304311
# when the target userspace container is created. Removing these files we loose

0 commit comments

Comments
 (0)