Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CP-46179 backport for deterministic backup VDI #5552

Merged
merged 4 commits into from
Apr 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ocaml/xapi-aux/dune
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
(name xapi_aux)

(libraries
uuidm
xapi-types
stdext
)
13 changes: 13 additions & 0 deletions ocaml/xapi-aux/uuidx.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
include Uuidm

module Hash = struct
(** Derive a deterministic UUID from a string: the same
string maps to the same UUID. We are using our own namespace; the
namespace is not a secret *)

let namespace =
let ns = "e93e0639-2bdb-4a59-8b46-352b3f408c19" in
Uuidm.(of_string ns |> Option.get)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Uuidx library is available as Uuid in yangtze. Patching it seems more involved than doing it here, so I think this change makes more sense than backporting it to https://github.com/xapi-project/xen-api-libs-transitional/blob/2.25-lcm/uuid/uuid.ml


let string str = Uuidm.v5 namespace str
end
11 changes: 11 additions & 0 deletions ocaml/xapi-aux/uuidx.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
type t

val to_string : ?upper:bool -> t -> string

module Hash : sig
(** hash a string (deterministically) into a UUID. This uses
namespace UUID e93e0639-2bdb-4a59-8b46-352b3f408c19. *)

(* UUID Version 5 derived from argument string and namespace UUID *)
val string : string -> t
end
6 changes: 3 additions & 3 deletions ocaml/xapi/sm.ml
Original file line number Diff line number Diff line change
@@ -134,7 +134,7 @@ let sr_update dconf driver sr =
let call = Sm_exec.make_call ~sr_ref:sr dconf "sr_update" [] in
Sm_exec.parse_unit (Sm_exec.exec_xmlrpc (driver_filename driver) call)

let vdi_create dconf driver sr sm_config vdi_type size name_label
let vdi_create ?vdi_uuid dconf driver sr sm_config vdi_type size name_label
name_description metadata_of_pool is_a_snapshot snapshot_time snapshot_of
read_only =
debug "vdi_create" driver
@@ -144,8 +144,8 @@ let vdi_create dconf driver sr sm_config vdi_type size name_label
) ;
srmaster_only dconf ;
let call =
Sm_exec.make_call ~sr_ref:sr ~vdi_sm_config:sm_config ~vdi_type dconf
"vdi_create"
Sm_exec.make_call ?vdi_uuid ~sr_ref:sr ~vdi_sm_config:sm_config ~vdi_type
dconf "vdi_create"
[
sprintf "%Lu" size
; name_label
22 changes: 19 additions & 3 deletions ocaml/xapi/sm_exec.ml
Original file line number Diff line number Diff line change
@@ -65,8 +65,8 @@ type call = {
}

let make_call ?driver_params ?sr_sm_config ?vdi_sm_config ?vdi_type
?vdi_location ?new_uuid ?sr_ref ?vdi_ref (subtask_of, device_config) cmd
args =
?vdi_location ?new_uuid ?sr_ref ?vdi_ref ?vdi_uuid
(subtask_of, device_config) cmd args =
Server_helpers.exec_with_new_task "sm_exec" (fun __context ->
(* Only allow a subset of calls if the SR has been introduced by a DR task. *)
Option.iter
@@ -113,7 +113,23 @@ let make_call ?driver_params ?sr_sm_config ?vdi_sm_config ?vdi_type
may (fun self -> Db.VDI.get_location ~__context ~self) vdi_ref
in
let vdi_uuid =
may (fun self -> Db.VDI.get_uuid ~__context ~self) vdi_ref
let __FUNCTION__ = "Sm_exec.make_call" in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why redefining __FUNCTION__?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not defined in the compiler version on Yangtze. So now I don't have to change the code in the back port.

match (cmd, vdi_ref, vdi_uuid) with
| "vdi_create", None, (Some x as uuid) ->
debug "%s: cmd=%s vdi_uuid=%s" __FUNCTION__ cmd x ;
uuid
(* when creating a VDI we sometimes want to provide the UUID
rather than letting the backend pick one. This is to
support backup VDIs CP-46179. So in that case, use the
provided UUID but not for other commands *)
| _, None, Some uuid ->
warn "%s: cmd=%s vdi_uuid=%s - should not happen" __FUNCTION__ cmd
uuid ;
None
| _, Some self, _ ->
Db.VDI.get_uuid ~__context ~self |> Option.some
| _, None, None ->
None
in
let vdi_on_boot =
may
25 changes: 20 additions & 5 deletions ocaml/xapi/storage_access.ml
Original file line number Diff line number Diff line change
@@ -688,16 +688,31 @@ module SMAPIv1 = struct
vdi_info_from_db ~__context (Db.VDI.get_by_uuid ~__context ~uuid)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this storage_access.ml file corresponds to storage_smapiv1.ml in master, no smapiv3 back then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

let create context ~dbg ~sr ~vdi_info =
let __FUNCTION__ = "Storage_access.create" in
try
Server_helpers.exec_with_new_task "VDI.create"
~subtask_of:(Ref.of_string dbg) (fun __context ->
let sr = Db.SR.get_by_uuid ~__context ~uuid:(s_of_sr sr) in
let sr_uuid = s_of_sr sr in
let sr = Db.SR.get_by_uuid ~__context ~uuid:sr_uuid in
let vi =
(* we want to set vdi_uuid when creating a backup VDI with
a specific UUID. SM picks up vdi_uuid instead of creating
a new random UUID; Cf. Xapi_vdi.create *)
let vdi_uuid =
match vdi_info.uuid with
| Some uuid when uuid = Uuidx.(Hash.string sr_uuid |> to_string)
->
info "%s: creating a backup VDI %s" __FUNCTION__ uuid ;
vdi_info.uuid
| _ ->
None
in
Sm.call_sm_functions ~__context ~sR:sr (fun device_config _type ->
Sm.vdi_create device_config _type sr vdi_info.sm_config
vdi_info.ty vdi_info.virtual_size vdi_info.name_label
vdi_info.name_description vdi_info.metadata_of_pool
vdi_info.is_a_snapshot vdi_info.snapshot_time
Sm.vdi_create ?vdi_uuid device_config _type sr
vdi_info.sm_config vdi_info.ty vdi_info.virtual_size
vdi_info.name_label vdi_info.name_description
vdi_info.metadata_of_pool vdi_info.is_a_snapshot
vdi_info.snapshot_time
(s_of_vdi vdi_info.snapshot_of)
vdi_info.read_only
)
17 changes: 16 additions & 1 deletion ocaml/xapi/xapi_vdi.ml
Original file line number Diff line number Diff line change
@@ -595,6 +595,7 @@ let update_vdi_db ~__context ~sr newvdi =

let create ~__context ~name_label ~name_description ~sR ~virtual_size ~_type
~sharable ~read_only ~other_config ~xenstore_data ~sm_config ~tags =
let __FUNCTION__ = "Xapi_vdi.create" in
if _type = `cbt_metadata then (
error
"VDI.create: creation of VDIs with type cbt_metadata is not allowed (at \
@@ -634,13 +635,27 @@ let create ~__context ~name_label ~name_description ~sR ~virtual_size ~_type
| `cbt_metadata ->
"cbt_metadata"
in
(* special case: we want to use a specific UUID for Pool Meta Data
Backup *)
let uuid_ =
match (_type, name_label) with
| `user, "Pool Metadata Backup" ->
let sr = Db.SR.get_uuid ~__context ~self:sR in
let uuid = Uuidx.(Hash.string sr |> to_string) in
info "%s: using deterministic UUID for '%s' VDI: %s" __FUNCTION__
name_label uuid ;
Some uuid
| _ ->
None
in
let open Storage_access in
let task = Context.get_task_id __context in
let open Storage_interface in
let vdi_info =
{
Storage_interface.default_vdi_info with
name_label
uuid= uuid_
; name_label
; name_description
; ty= vdi_type
; read_only
Loading