From 0fbc9d55e33e1930df937f2693f97d4daae8702e Mon Sep 17 00:00:00 2001 From: Vincent Liu Date: Fri, 9 Aug 2024 16:44:52 +0100 Subject: [PATCH] CP-51042: Raise error in sr-scan when SR.stat finds an unhealthy SR Previously sr-scan first performs an SR.ls followed by an SR.stat, which will fail when the SR is not healthy. Now that we included more health messages in SR.stat, we can give perform SR.stat first and fail the operation if SR.stat gives unhealthy state, and tell the user about the unhealthy state. Signed-off-by: Vincent Liu --- ocaml/xapi-idl/storage/storage_interface.ml | 1 + ocaml/xapi/xapi_sr.ml | 47 ++++++++++++--------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ocaml/xapi-idl/storage/storage_interface.ml b/ocaml/xapi-idl/storage/storage_interface.ml index 698997ac0cd..e66be1c18a7 100644 --- a/ocaml/xapi-idl/storage/storage_interface.ml +++ b/ocaml/xapi-idl/storage/storage_interface.ml @@ -361,6 +361,7 @@ module Errors = struct | Content_ids_do_not_match of (string * string) | Missing_configuration_parameter of string | Internal_error of string + | Sr_unhealthy of sr_health | Unknown_error [@@default Unknown_error] [@@deriving rpcty] end diff --git a/ocaml/xapi/xapi_sr.ml b/ocaml/xapi/xapi_sr.ml index 7b5186d5195..1645088deaf 100644 --- a/ocaml/xapi/xapi_sr.ml +++ b/ocaml/xapi/xapi_sr.ml @@ -787,30 +787,37 @@ let scan ~__context ~sr = SRScanThrottle.execute (fun () -> transform_storage_exn (fun () -> let sr_uuid = Db.SR.get_uuid ~__context ~self:sr in - let vs = - C.SR.scan (Ref.string_of task) - (Storage_interface.Sr.of_string sr_uuid) - in - let db_vdis = - Db.VDI.get_records_where ~__context - ~expr:(Eq (Field "SR", Literal sr')) - in - update_vdis ~__context ~sr db_vdis vs ; + let sr_info = C.SR.stat (Ref.string_of task) (Storage_interface.Sr.of_string sr_uuid) in - let virtual_allocation = - List.fold_left Int64.add 0L - (List.map (fun v -> v.Storage_interface.virtual_size) vs) - in - Db.SR.set_virtual_allocation ~__context ~self:sr - ~value:virtual_allocation ; - Db.SR.set_physical_size ~__context ~self:sr ~value:sr_info.total_space ; - Db.SR.set_physical_utilisation ~__context ~self:sr - ~value:(Int64.sub sr_info.total_space sr_info.free_space) ; - Db.SR.remove_from_other_config ~__context ~self:sr ~key:"dirty" ; - Db.SR.set_clustered ~__context ~self:sr ~value:sr_info.clustered + match sr_info with + | {health; _} when health <> Healthy -> + raise Storage_interface.(Storage_error (Sr_unhealthy health)) + | _ -> + let vs = + C.SR.scan (Ref.string_of task) + (Storage_interface.Sr.of_string sr_uuid) + in + let db_vdis = + Db.VDI.get_records_where ~__context + ~expr:(Eq (Field "SR", Literal sr')) + in + update_vdis ~__context ~sr db_vdis vs ; + let virtual_allocation = + List.fold_left + (fun acc v -> Int64.add v.Storage_interface.virtual_size acc) + 0L vs + in + Db.SR.set_virtual_allocation ~__context ~self:sr + ~value:virtual_allocation ; + Db.SR.set_physical_size ~__context ~self:sr + ~value:sr_info.total_space ; + Db.SR.set_physical_utilisation ~__context ~self:sr + ~value:(Int64.sub sr_info.total_space sr_info.free_space) ; + Db.SR.remove_from_other_config ~__context ~self:sr ~key:"dirty" ; + Db.SR.set_clustered ~__context ~self:sr ~value:sr_info.clustered ) )