Skip to content

Commit c4cdd12

Browse files
author
David Scott
committed
Preliminary support for clone-on-boot / reset-on-boot
Upon VDI.epoch_begin with persistent = false, we call `Volume.stat` to discover the possible URIs. We look first for a datapath plugin which can perform clone-on-boot natively (e.g. by truncating vhd leaves) and delegate to that. If a datapath plugin doesn't exist then we will fall back to the Volume.clone / Volume.destroy API. This will be done in a later patch. We expose the VDI_RESET_ON_BOOT/2 capability if the volume plugin supports VDI_CLONE. This isn't ideal as it won't cover the case where a LUN-per-VDI SR which doesn't support VDI.CLONE nevertheless can support clone-on-boot if the tapdisk datapath is used. Signed-off-by: David Scott <[email protected]>
1 parent bc1b570 commit c4cdd12

File tree

1 file changed

+54
-21
lines changed

1 file changed

+54
-21
lines changed

main.ml

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ let info fmt =
3636
end
3737
) fmt
3838

39+
let _nonpersistent = "NONPERSISTENT"
40+
3941
let backend_error name args =
4042
let open Storage_interface in
4143
let exnty = Exception.Backend_error (name, args) in
@@ -171,6 +173,11 @@ module Datapath_plugins = struct
171173
let unregister root_dir name =
172174
Hashtbl.remove !table name;
173175
return ()
176+
177+
let supports_feature scheme feature =
178+
match Hashtbl.find !table scheme with
179+
| None -> false
180+
| Some query_result -> List.mem query_result.Storage.Plugin.Types.features feature
174181
end
175182

176183
let vdi_of_volume x =
@@ -191,23 +198,36 @@ let vdi_of_volume x =
191198
persistent = true;
192199
}
193200

194-
let choose_datapath = function
195-
| [] -> return (Error (missing_uri ()))
196-
| uri :: _ ->
197-
let uri' = Uri.of_string uri in
198-
let domain = "0" in
199-
begin match Uri.scheme uri' with
200-
| None -> return (Error (missing_uri ()))
201-
| Some scheme -> return (Ok (scheme, uri, domain))
202-
end
203-
204-
let stat root_dir name dbg sr vdi =
201+
let stat ?(persistent = true) root_dir name dbg sr vdi =
205202
let args = Storage.Volume.Types.Volume.Stat.In.make dbg sr vdi in
206203
let args = Storage.Volume.Types.Volume.Stat.In.rpc_of_t args in
207204
let open Deferred.Result.Monad_infix in
208205
fork_exec_rpc root_dir (script root_dir name `Volume "Volume.stat") args Storage.Volume.Types.Volume.Stat.Out.t_of_rpc
209206
>>= fun response ->
210-
choose_datapath response.Storage.Volume.Types.uri
207+
(* We can only use a URI with a valid scheme, since we use the scheme
208+
to name the datapath plugin. *)
209+
let possible =
210+
List.filter_map ~f:(fun x ->
211+
let uri = Uri.of_string x in
212+
match Uri.scheme uri with
213+
| None -> None
214+
| Some scheme -> Some (scheme, uri)
215+
) response.Storage.Volume.Types.uri in
216+
(* We can only use URIs whose schemes correspond to registered plugins *)
217+
let possible = List.filter ~f:(fun (scheme, _) -> Hashtbl.mem !Datapath_plugins.table scheme) possible in
218+
(* If we want to be non-persistent, we prefer if the datapath plugin supports it natively *)
219+
let preference_order =
220+
if persistent
221+
then possible
222+
else
223+
let supports_nonpersistent, others = List.partition_map ~f:(fun (scheme, uri) ->
224+
if Datapath_plugins.supports_feature scheme _nonpersistent
225+
then `Fst (scheme, uri) else `Snd (scheme, uri)
226+
) possible in
227+
supports_nonpersistent @ others in
228+
match preference_order with
229+
| [] -> return (Error (missing_uri ()))
230+
| (scheme, u) :: us -> return (Ok (scheme, Uri.to_string u, "0"))
211231

212232
(* Process a message *)
213233
let process root_dir name x =
@@ -268,6 +288,12 @@ let process root_dir name x =
268288
"VDI_ATTACH"; "VDI_DETACH"; "VDI_ACTIVATE"; "VDI_DEACTIVATE";
269289
"VDI_INTRODUCE"
270290
] in
291+
(* If we have the ability to clone a disk then we can provide
292+
clone on boot. *)
293+
let features =
294+
if List.mem features "VDI_CLONE"
295+
then "VDI_RESET_ON_BOOT/2" :: features
296+
else features in
271297
let response = {
272298
driver = response.Storage.Plugin.Types.plugin;
273299
name = response.Storage.Plugin.Types.name;
@@ -593,19 +619,26 @@ let process root_dir name x =
593619
Attached_SRs.find args.Args.VDI.Epoch_begin.sr
594620
>>= fun sr ->
595621
(* Discover the URIs using Volume.stat *)
596-
stat root_dir name
622+
let persistent = args.Args.VDI.Epoch_begin.persistent in
623+
stat ~persistent root_dir name
597624
args.Args.VDI.Epoch_begin.dbg
598625
sr
599626
args.Args.VDI.Epoch_begin.vdi
600627
>>= fun (datapath, uri, domain) ->
601-
let persistent = args.Args.VDI.Epoch_begin.persistent in
602-
let args = Storage.Datapath.Types.Datapath.Open.In.make
603-
args.Args.VDI.Epoch_begin.dbg
604-
uri persistent in
605-
let args = Storage.Datapath.Types.Datapath.Open.In.rpc_of_t args in
606-
fork_exec_rpc root_dir (script root_dir name (`Datapath datapath) "Datapath.open") args Storage.Datapath.Types.Datapath.Open.Out.t_of_rpc
607-
>>= fun () ->
608-
Deferred.Result.return (R.success (Args.VDI.Epoch_begin.rpc_of_response ()))
628+
(* If non-persistent and the datapath plugin supports NONPERSISTENT
629+
then we delegate this to the datapath plugin. Otherwise we will
630+
make a temporary clone now and attach/detach etc this file. *)
631+
if Datapath_plugins.supports_feature datapath _nonpersistent then begin
632+
let args = Storage.Datapath.Types.Datapath.Open.In.make
633+
args.Args.VDI.Epoch_begin.dbg
634+
uri persistent in
635+
let args = Storage.Datapath.Types.Datapath.Open.In.rpc_of_t args in
636+
fork_exec_rpc root_dir (script root_dir name (`Datapath datapath) "Datapath.open") args Storage.Datapath.Types.Datapath.Open.Out.t_of_rpc
637+
>>= fun () ->
638+
Deferred.Result.return (R.success (Args.VDI.Epoch_begin.rpc_of_response ()))
639+
end else begin
640+
Deferred.return (Error (backend_error "UNIMPLEMENTED" [ name ]))
641+
end
609642
| { R.name = "VDI.epoch_end"; R.params = [ args ] } ->
610643
let open Deferred.Result.Monad_infix in
611644
let args = Args.VDI.Epoch_end.request_of_rpc args in

0 commit comments

Comments
 (0)