Skip to content

Commit 3cd9646

Browse files
authored
xapi: CA-423064: Trigger group upgrades in addition to package upgrades (#6850)
In the event we add a package to one of the yum repository groups, that has no packages requiring it, dnf5 will not install it by default (as it has not implemented the `upgrade_group_objects_upgrade` configuration option - see https://dnf5.readthedocs.io/en/latest/dnf5.conf-todo.5.html). We do not wish to be reliant on having to ensure all new packages are required by an existing package, as such (at least until an implementation of the above option is done in dnf5) trigger a `group upgrade *` in addition to the `upgrade`. Note that a `group upgrade *` alone is not sufficient, as this will not cause any packages that are pulled in as dependencies to be upgraded, only those explicitly listed in the group(s).
2 parents 9393346 + 32adc7d commit 3cd9646

5 files changed

Lines changed: 149 additions & 3 deletions

File tree

ocaml/tests/test_pkg_mgr.ml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,29 @@ let test_dnf_apply_upgrades =
159159
)
160160
]
161161

162+
let test_dnf_apply_group_upgrades =
163+
[
164+
( "<null>"
165+
, `Quick
166+
, check
167+
{
168+
cmd= !Xapi_globs.dnf_cmd
169+
; params=
170+
[
171+
"-y"
172+
; "--disablerepo=*"
173+
; "--enablerepo=testrepo1,testrepo2"
174+
; "group"
175+
; "upgrade"
176+
; "*"
177+
]
178+
}
179+
(Pkg_mgr.Dnf_cmd.apply_group_upgrade
180+
~repositories:["testrepo1"; "testrepo2"]
181+
)
182+
)
183+
]
184+
162185
let test_yum_repo_query_installed =
163186
[
164187
( "<null>"
@@ -286,6 +309,29 @@ let test_yum_apply_upgrades =
286309
)
287310
]
288311

312+
let test_yum_apply_group_upgrades =
313+
[
314+
( "<null>"
315+
, `Quick
316+
, check
317+
{
318+
cmd= !Xapi_globs.yum_cmd
319+
; params=
320+
[
321+
"-y"
322+
; "--disablerepo=*"
323+
; "--enablerepo=testrepo1,testrepo2"
324+
; "group"
325+
; "upgrade"
326+
; "*"
327+
]
328+
}
329+
(Pkg_mgr.Yum_cmd.apply_group_upgrade
330+
~repositories:["testrepo1"; "testrepo2"]
331+
)
332+
)
333+
]
334+
289335
let test_yum_repo_query_updates =
290336
[
291337
( "<null>"
@@ -320,13 +366,15 @@ let tests =
320366
; ("test_dnf_cofig_repo", test_dnf_config_repo)
321367
; ("test_dnf_sync_repo", test_dnf_sync_repo)
322368
; ("test_dnf_apply_upgrades", test_dnf_apply_upgrades)
369+
; ("test_dnf_apply_group_upgrades", test_dnf_apply_group_upgrades)
323370
; ("test_yum_repo_query_installed", test_yum_repo_query_installed)
324371
; ("test_yum_clean_all_cache", test_yum_clean_all_cache)
325372
; ("test_yum_clean_repo_cache", test_yum_clean_repo_cache)
326373
; ("test_yum_get_pkgs_from_updateinfo", test_yum_get_pkgs_from_updateinfo)
327374
; ("test_yum_cofig_repo", test_yum_config_repo)
328375
; ("test_yum_sync_repo", test_yum_sync_repo)
329376
; ("test_yum_apply_upgrades", test_yum_apply_upgrades)
377+
; ("test_yum_apply_group_upgrades", test_yum_apply_group_upgrades)
330378
; ("test_yum_repo_query_updates", test_yum_repo_query_updates)
331379
]
332380

ocaml/xapi/pkg_mgr.ml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ module type S = sig
3737

3838
val get_updates_from_upgrade_dry_run : repositories:string list -> cmd_line
3939

40+
val get_updates_from_group_upgrade_dry_run :
41+
repositories:string list -> cmd_line
42+
4043
val is_obsoleted : pkg_name:string -> repositories:string list -> cmd_line
4144

4245
val repoquery_updates : repositories:string list -> cmd_line
@@ -52,6 +55,8 @@ module type S = sig
5255
val sync_repo : repo_name:string -> cmd_line
5356

5457
val apply_upgrade : repositories:string list -> cmd_line
58+
59+
val apply_group_upgrade : repositories:string list -> cmd_line
5560
end
5661

5762
module type Args = sig
@@ -71,6 +76,8 @@ module type Args = sig
7176

7277
val get_updates_from_upgrade_dry_run : string list -> string list
7378

79+
val get_updates_from_group_upgrade_dry_run : string list -> string list
80+
7481
val is_obsoleted : string -> string list -> string list
7582

7683
val repoquery_updates : string list -> string list
@@ -86,6 +93,8 @@ module type Args = sig
8693
val sync_repo : string -> string list
8794

8895
val apply_upgrade : string list -> string list
96+
97+
val apply_group_upgrade : string list -> string list
8998
end
9099

91100
let repoquery_sep = ":|"
@@ -125,6 +134,16 @@ module Common_args = struct
125134
; "upgrade"
126135
]
127136

137+
let get_updates_from_group_upgrade_dry_run repositories =
138+
[
139+
"--disablerepo=*"
140+
; Printf.sprintf "--enablerepo=%s" (String.concat "," repositories)
141+
; "--assumeno"
142+
; "group"
143+
; "upgrade"
144+
; "*"
145+
]
146+
128147
let repoquery repositories =
129148
[
130149
"--disablerepo=*"
@@ -161,6 +180,16 @@ module Common_args = struct
161180
; Printf.sprintf "--enablerepo=%s" (String.concat "," repositories)
162181
; "upgrade"
163182
]
183+
184+
let apply_group_upgrade repositories =
185+
[
186+
"-y"
187+
; "--disablerepo=*"
188+
; Printf.sprintf "--enablerepo=%s" (String.concat "," repositories)
189+
; "group"
190+
; "upgrade"
191+
; "*"
192+
]
164193
end
165194

166195
module Yum_args : Args = struct
@@ -179,6 +208,10 @@ module Yum_args : Args = struct
179208
let get_updates_from_upgrade_dry_run repositories =
180209
["--quiet"] @ Common_args.get_updates_from_upgrade_dry_run repositories
181210

211+
let get_updates_from_group_upgrade_dry_run repositories =
212+
["--quiet"]
213+
@ Common_args.get_updates_from_group_upgrade_dry_run repositories
214+
182215
let is_obsoleted pkg_name repositories =
183216
["--all"] @ Common_args.is_obsoleted pkg_name repositories @ ["--plugins"]
184217

@@ -283,6 +316,12 @@ module Cmd_line (M : Args) : S = struct
283316
let get_updates_from_upgrade_dry_run ~repositories =
284317
{cmd= M.pkg_cmd; params= M.get_updates_from_upgrade_dry_run repositories}
285318

319+
let get_updates_from_group_upgrade_dry_run ~repositories =
320+
{
321+
cmd= M.pkg_cmd
322+
; params= M.get_updates_from_group_upgrade_dry_run repositories
323+
}
324+
286325
let is_obsoleted ~pkg_name ~repositories =
287326
{cmd= M.repoquery_cmd; params= M.is_obsoleted pkg_name repositories}
288327

@@ -305,6 +344,9 @@ module Cmd_line (M : Args) : S = struct
305344

306345
let apply_upgrade ~repositories =
307346
{cmd= M.pkg_cmd; params= M.apply_upgrade repositories}
347+
348+
let apply_group_upgrade ~repositories =
349+
{cmd= M.pkg_cmd; params= M.apply_group_upgrade repositories}
308350
end
309351

310352
module Yum_cmd = Cmd_line (Yum_args)

ocaml/xapi/pkg_mgr.mli

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ module type S = sig
4141
val get_updates_from_upgrade_dry_run : repositories:string list -> cmd_line
4242
(** Command line and arguments to dry run an upgrade, with repositories enabled *)
4343

44+
val get_updates_from_group_upgrade_dry_run :
45+
repositories:string list -> cmd_line
46+
(** Command line and arguments to dry run a group upgrade, with repositories enabled *)
47+
4448
val is_obsoleted : pkg_name:string -> repositories:string list -> cmd_line
4549
(** Command line and arguments to check whether a package is obsoleted by any other
4650
* package in given repositories *)
@@ -67,6 +71,9 @@ module type S = sig
6771

6872
val apply_upgrade : repositories:string list -> cmd_line
6973
(** Command line and arguments to apply upgrades from repos *)
74+
75+
val apply_group_upgrade : repositories:string list -> cmd_line
76+
(** Command line and arguments to apply group upgrades from repos *)
7077
end
7178

7279
(** Exposed only for unittest, do not use the modules directly

ocaml/xapi/repository.ml

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,20 @@ let get_host_updates_in_json ~__context ~installed =
565565
let latest_updates' =
566566
get_updates_from_yum_upgrade_dry_run repositories
567567
in
568+
let latest_updates_group' =
569+
get_updates_from_yum_group_upgrade_dry_run repositories
570+
in
571+
let latest_updates_combined' =
572+
match (latest_updates', latest_updates_group') with
573+
| Some pkgs', Some group_pkgs' ->
574+
Some (List.sort_uniq compare (pkgs' @ group_pkgs'))
575+
| Some pkgs', None ->
576+
Some pkgs'
577+
| None, Some group_pkgs' ->
578+
Some group_pkgs'
579+
| None, None ->
580+
None
581+
in
568582
let latest_updates'' = get_updates_from_repoquery repositories in
569583
(* To ensure the updating function will not strand, use redundant
570584
* functions to get the update/installation list.
@@ -576,7 +590,7 @@ let get_host_updates_in_json ~__context ~installed =
576590
let fail_on_error = Xapi_fist.fail_on_error_in_yum_upgrade_dry_run () in
577591
let latest_updates =
578592
get_latest_updates_from_redundancy ~fail_on_error
579-
~pkgs:latest_updates' ~fallback_pkgs:latest_updates''
593+
~pkgs:latest_updates_combined' ~fallback_pkgs:latest_updates''
580594
in
581595
List.iter (fun r -> clean_yum_cache r) repositories ;
582596
let latest_updates_in_json =
@@ -686,8 +700,15 @@ let get_pool_updates_in_json ~__context ~hosts =
686700
let apply ~__context ~host =
687701
(* This function runs on member host *)
688702
with_local_repositories ~__context (fun repositories ->
689-
let Pkg_mgr.{cmd; params} = Pkgs.apply_upgrade ~repositories in
690-
try ignore (Helpers.call_script cmd params)
703+
let upgrade () =
704+
let Pkg_mgr.{cmd; params} = Pkgs.apply_upgrade ~repositories in
705+
ignore (Helpers.call_script cmd params)
706+
in
707+
let group_upgrade () =
708+
let Pkg_mgr.{cmd; params} = Pkgs.apply_group_upgrade ~repositories in
709+
ignore (Helpers.call_script cmd params)
710+
in
711+
try upgrade () ; group_upgrade ()
691712
with e ->
692713
let host' = Ref.string_of host in
693714
error "Failed to apply updates on host ref='%s': %s" host'

ocaml/xapi/repository_helpers.ml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,8 +771,10 @@ module YumUpgradeOutput = struct
771771
| false -> (
772772
take_till is_eol <* end_of_line >>= function
773773
| ( "Installing:"
774+
| "Installing group/module packages:"
774775
| "Updating:"
775776
| "Upgrading:"
777+
| "Upgrading groups:"
776778
| "Removing:"
777779
| "Reinstalling:"
778780
| "Downgrading:"
@@ -890,6 +892,7 @@ module YumUpgradeOutput = struct
890892
|> List.filter (fun (section, _) ->
891893
match section with
892894
| "Installing:"
895+
| "Installing group/module packages:"
893896
| "Updating:"
894897
| "Upgrading:"
895898
| "Installing for dependencies:"
@@ -958,6 +961,31 @@ let get_updates_from_yum_upgrade_dry_run repositories =
958961
error "%s" (ExnHelper.string_of_exn e) ;
959962
None
960963

964+
let get_updates_from_yum_group_upgrade_dry_run repositories =
965+
let Pkg_mgr.{cmd; params} =
966+
Pkgs.get_updates_from_group_upgrade_dry_run ~repositories
967+
in
968+
match Forkhelpers.execute_command_get_output cmd params with
969+
| _, _ ->
970+
Some []
971+
| exception Forkhelpers.Spawn_internal_error (stderr, stdout, Unix.WEXITED 1)
972+
-> (
973+
(*Yum put the details to stderr while dnf to stdout*)
974+
(match Pkgs.manager with Yum -> stderr | Dnf -> stdout)
975+
|> YumUpgradeOutput.parse_output_of_dry_run
976+
|> function
977+
| Ok (pkgs, Some txn_file) ->
978+
Unixext.unlink_safe txn_file ;
979+
Some pkgs
980+
| Ok (pkgs, None) ->
981+
Some pkgs
982+
| Error msg ->
983+
error "%s" msg ; None
984+
)
985+
| exception e ->
986+
error "%s" (ExnHelper.string_of_exn e) ;
987+
None
988+
961989
let get_latest_updates_from_redundancy ~fail_on_error ~pkgs ~fallback_pkgs =
962990
let err = "Failed to parse output of 'yum upgrade (dry run)' correctly" in
963991
let get_latest_updates_from_redundancy' ~fail_on_error ~pkgs ~fallback_pkgs =

0 commit comments

Comments
 (0)