diff --git a/ocaml/tests/test_repository_helpers.ml b/ocaml/tests/test_repository_helpers.ml index dbb5b7f1a42..775c7635665 100644 --- a/ocaml/tests/test_repository_helpers.ml +++ b/ocaml/tests/test_repository_helpers.ml @@ -3881,7 +3881,29 @@ module PruneUpdateInfoForLivepatches = Generic.MakeStateless (struct ; base_build_id= "2cc28689364587682593b6a72e2a586d29996bb9" ; base_version= "4.19.19" ; base_release= "8.0.20.xs8" - ; to_version= "4.13.4" + ; to_version= "4.19.19" + ; to_release= "8.0.21.xs8" + } + + let lp2 = + LivePatch. + { + component= Livepatch.Kernel + ; base_build_id= "2cc28689364587682593b6a72e2a586d29996bb9" + ; base_version= "4.19.19" + ; base_release= "8.0.20.xs8" + ; to_version= "4.19.20" + ; to_release= "8.0.21.xs8" + } + + let lp3 = + LivePatch. + { + component= Livepatch.Kernel + ; base_build_id= "4cc28689364587682593b6a72e2a586d29996bb9" + ; base_version= "4.19.20" + ; base_release= "7.0.20.xs8" + ; to_version= "4.13.5" ; to_release= "8.0.21.xs8" } @@ -3915,6 +3937,12 @@ module PruneUpdateInfoForLivepatches = Generic.MakeStateless (struct ; ( ([], {updateinfo with livepatches= [lp0; lp1]}) , {updateinfo with livepatches= []} ) + ; ( ([lp0; lp2], {updateinfo with livepatches= [lp0; lp1; lp2; lp3]}) + , {updateinfo with livepatches= [lp0; lp1; lp2]} + ) + ; ( ([lp0], {updateinfo with livepatches= [lp0; lp1; lp2; lp3]}) + , {updateinfo with livepatches= [lp0]} + ) ] end) diff --git a/ocaml/xapi/repository_helpers.ml b/ocaml/xapi/repository_helpers.ml index 8a184e52f4c..51699612739 100644 --- a/ocaml/xapi/repository_helpers.ml +++ b/ocaml/xapi/repository_helpers.ml @@ -1298,12 +1298,22 @@ let with_access_token ~token ~token_id f = let msg = Printf.sprintf "%s: The token or token_id is empty" __LOC__ in raise Api_errors.(Server_error (internal_error, [msg])) -let prune_updateinfo_for_livepatches livepatches updateinfo = - let open UpdateInfo in - let lps = - List.filter (fun x -> LivePatchSet.mem x livepatches) updateinfo.livepatches +let prune_updateinfo_for_livepatches latest_lps updateinfo = + let livepatches = + let open LivePatch in + (* Keep a livepatch if it is rolled up by one of the latest livepatches. + * The latest livepatches are the ones to be applied actually. + *) + updateinfo.UpdateInfo.livepatches + |> List.filter (fun lp -> + let is_rolled_up_by latest = + latest.component = lp.component + && latest.base_build_id = lp.base_build_id + in + LivePatchSet.exists is_rolled_up_by latest_lps + ) in - {updateinfo with livepatches= lps} + {updateinfo with livepatches} let do_with_host_pending_guidances ~op guidances = List.iter