55from __future__ import annotations
66
77import re
8+ from collections .abc import Generator
89from concurrent .futures import ThreadPoolExecutor , as_completed
10+ from contextlib import contextmanager
911
1012from lib .host import Host
1113from lib .pool import NotAMasterHostError , Pool
@@ -69,7 +71,8 @@ def _check_packages_available(
6971 repoquery_cmd += f" --disablerepo={ r } "
7072 for r in master_cfg ["repositories" ]:
7173 repoquery_cmd += f" --enablerepo={ r } "
72- available = set (p .master .ssh (repoquery_cmd ).splitlines ())
74+ with _pinned_updates_repo (p .master ):
75+ available = set (p .master .ssh (repoquery_cmd ).splitlines ())
7376 for h in p .hosts :
7477 pkgs = _filter_packages (packages [h ]) - available
7578 if pkgs :
@@ -116,6 +119,26 @@ def _check_consistency(packages: dict[Host, set[str]]) -> None:
116119 lines .append (f" [{ h } ] additional packages:\n { _format_packages (sorted (extra_pkgs ))} " )
117120 logger .warning ("\n " .join (lines ))
118121
122+ @contextmanager
123+ def _pinned_updates_repo (host : Host ) -> Generator [None ]:
124+ """Temporarily drop the mirrors.xcp-ng.org baseurls, restoring the file on exit."""
125+ repo_file = '/etc/yum.repos.d/xcp-ng.repo'
126+ backup_file = f'{ repo_file } .bak'
127+ logger .info (f"[{ host } ] Removing mirrors.xcp-ng.org from { repo_file } " )
128+ host .ssh (f'cp -f { repo_file } { backup_file } ' )
129+ host .ssh (f"sed -i 's|http://mirrors\\ .xcp-ng\\ .org/[^ ]*[ ]*||g' { repo_file } " )
130+ try :
131+ yield
132+ finally :
133+ logger .info (f"[{ host } ] Restoring { repo_file } " )
134+ host .ssh (f'mv -f { backup_file } { repo_file } ' )
135+
136+ def _update_host (host : Host , enablerepos : list [str ], disablerepos : list [str ] = [],
137+ reboot : bool = True ) -> None :
138+ """Update a host, with the mirrors.xcp-ng.org baseurl removed during the update."""
139+ with _pinned_updates_repo (host ):
140+ host .update (enablerepos , disablerepos = disablerepos , reboot = reboot )
141+
119142def update_pools (inventory : Inventory , reboot : bool = True , parallel : bool = False ) -> None :
120143 """Updates hosts in pool(s).
121144
@@ -155,7 +178,8 @@ def update_pools(inventory: Inventory, reboot: bool = True, parallel: bool = Fal
155178 # update master hosts
156179 with ThreadPoolExecutor () as executor :
157180 future_hosts = {executor .submit (
158- p .master .update ,
181+ _update_host ,
182+ p .master ,
159183 inventory_hosts [p .master .hostname_or_ip ]["repositories" ],
160184 disablerepos = inventory_hosts [p .master .hostname_or_ip ]["disabled_repositories" ],
161185 reboot = reboot ,
@@ -168,7 +192,7 @@ def update_pools(inventory: Inventory, reboot: bool = True, parallel: bool = Fal
168192 # repos are the same as for the master host
169193 repos = inventory_hosts [p .master .hostname_or_ip ]["repositories" ]
170194 disablerepos = inventory_hosts [p .master .hostname_or_ip ]["disabled_repositories" ]
171- future_hosts [executor .submit (h . update , repos , disablerepos = disablerepos , reboot = reboot )] = h
195+ future_hosts [executor .submit (_update_host , h , repos , disablerepos = disablerepos , reboot = reboot )] = h
172196 for future in as_completed (future_hosts ):
173197 updated_host = future_hosts [future ]
174198 try :
@@ -191,7 +215,8 @@ def update_pools(inventory: Inventory, reboot: bool = True, parallel: bool = Fal
191215 # repos are the same as for the master host
192216 repos = inventory_hosts [p .master .hostname_or_ip ]["repositories" ]
193217 disablerepos = inventory_hosts [p .master .hostname_or_ip ]["disabled_repositories" ]
194- future_other_hosts [executor .submit (h .update , repos , disablerepos = disablerepos , reboot = reboot )] = h
218+ future_other_hosts [executor .submit (
219+ _update_host , h , repos , disablerepos = disablerepos , reboot = reboot )] = h
195220 for future in as_completed (future_other_hosts ):
196221 other_host = future_other_hosts [future ]
197222 try :
0 commit comments