@@ -37,6 +37,7 @@ let info fmt =
37
37
) fmt
38
38
39
39
let _nonpersistent = " NONPERSISTENT"
40
+ let _clone_on_boot_key = " clone-on-boot"
40
41
41
42
let backend_error name args =
42
43
let open Storage_interface in
@@ -198,12 +199,27 @@ let vdi_of_volume x =
198
199
persistent = true ;
199
200
}
200
201
201
- let stat ?( persistent = true ) root_dir name dbg sr vdi =
202
+ let stat root_dir name dbg sr vdi =
202
203
let args = Storage.Volume.Types.Volume.Stat.In. make dbg sr vdi in
203
204
let args = Storage.Volume.Types.Volume.Stat.In. rpc_of_t args in
204
- let open Deferred.Result.Monad_infix in
205
205
fork_exec_rpc root_dir (script root_dir name `Volume " Volume.stat" ) args Storage.Volume.Types.Volume.Stat.Out. t_of_rpc
206
- >> = fun response ->
206
+
207
+ let clone root_dir name dbg sr vdi =
208
+ let args = Storage.Volume.Types.Volume.Clone.In. make dbg sr vdi in
209
+ let args = Storage.Volume.Types.Volume.Clone.In. rpc_of_t args in
210
+ fork_exec_rpc root_dir (script root_dir name `Volume " Volume.clone" ) args Storage.Volume.Types.Volume.Clone.Out. t_of_rpc
211
+
212
+ let destroy root_dir name dbg sr vdi =
213
+ let args = Storage.Volume.Types.Volume.Destroy.In. make dbg sr vdi in
214
+ let args = Storage.Volume.Types.Volume.Destroy.In. rpc_of_t args in
215
+ fork_exec_rpc root_dir (script root_dir name `Volume " Volume.destroy" ) args Storage.Volume.Types.Volume.Destroy.Out. t_of_rpc
216
+
217
+ let set root_dir name dbg sr vdi k v =
218
+ let args = Storage.Volume.Types.Volume.Set.In. make dbg sr vdi k v in
219
+ let args = Storage.Volume.Types.Volume.Set.In. rpc_of_t args in
220
+ fork_exec_rpc root_dir (script root_dir name `Volume " Volume.set" ) args Storage.Volume.Types.Volume.Set.Out. t_of_rpc
221
+
222
+ let choose_datapath ?(persistent = true ) response =
207
223
(* We can only use a URI with a valid scheme, since we use the scheme
208
224
to name the datapath plugin. *)
209
225
let possible =
@@ -403,14 +419,19 @@ let process root_dir name x =
403
419
let args = Args.VDI.Destroy. request_of_rpc args in
404
420
Attached_SRs. find args.Args.VDI.Destroy. sr
405
421
>> = fun sr ->
406
- let args = Storage.Volume.Types.Volume.Destroy.In. make
407
- args.Args.VDI.Destroy. dbg
408
- sr
409
- args.Args.VDI.Destroy. vdi in
410
- let args = Storage.Volume.Types.Volume.Destroy.In. rpc_of_t args in
411
- fork_exec_rpc root_dir (script root_dir name `Volume " Volume.destroy" ) args Storage.Volume.Types.Volume.Destroy.Out. t_of_rpc
422
+ stat root_dir name args.Args.VDI.Destroy. dbg sr args.Args.VDI.Destroy. vdi
412
423
>> = fun response ->
413
- Deferred.Result. return (R. success (Args.VDI.Destroy. rpc_of_response response))
424
+ (* Destroy any clone-on-boot volume that might exist *)
425
+ ( match List.Assoc. find response.Storage.Volume.Types. keys _clone_on_boot_key with
426
+ | None ->
427
+ return (Ok () )
428
+ | Some temporary ->
429
+ (* Destroy the temporary disk we made earlier *)
430
+ destroy root_dir name args.Args.VDI.Destroy. dbg sr temporary
431
+ ) >> = fun () ->
432
+ destroy root_dir name args.Args.VDI.Destroy. dbg sr args.Args.VDI.Destroy. vdi
433
+ >> = fun () ->
434
+ Deferred.Result. return (R. success (Args.VDI.Destroy. rpc_of_response () ))
414
435
| { R. name = "VDI.snapshot" ; R. params = [ args ] } ->
415
436
let open Deferred.Result.Monad_infix in
416
437
let args = Args.VDI.Snapshot. request_of_rpc args in
@@ -432,12 +453,7 @@ let process root_dir name x =
432
453
Attached_SRs. find args.Args.VDI.Clone. sr
433
454
>> = fun sr ->
434
455
let vdi_info = args.Args.VDI.Clone. vdi_info in
435
- let args = Storage.Volume.Types.Volume.Clone.In. make
436
- args.Args.VDI.Clone. dbg
437
- sr
438
- vdi_info.vdi in
439
- let args = Storage.Volume.Types.Volume.Clone.In. rpc_of_t args in
440
- fork_exec_rpc root_dir (script root_dir name `Volume " Volume.clone" ) args Storage.Volume.Types.Volume.Clone.Out. t_of_rpc
456
+ clone root_dir name args.Args.VDI.Clone. dbg sr vdi_info.vdi
441
457
>> = fun response ->
442
458
let response = vdi_of_volume response in
443
459
Deferred.Result. return (R. success (Args.VDI.Clone. rpc_of_response response))
@@ -480,9 +496,7 @@ let process root_dir name x =
480
496
fork_exec_rpc root_dir (script root_dir name `Volume " Volume.resize" ) args Storage.Volume.Types.Volume.Resize.Out. t_of_rpc
481
497
>> = fun () ->
482
498
(* Now call Volume.stat to discover the size *)
483
- let args = Storage.Volume.Types.Volume.Stat.In. make dbg sr vdi in
484
- let args = Storage.Volume.Types.Volume.Stat.In. rpc_of_t args in
485
- fork_exec_rpc root_dir (script root_dir name `Volume " Volume.stat" ) args Storage.Volume.Types.Volume.Stat.Out. t_of_rpc
499
+ stat root_dir name dbg sr vdi
486
500
>> = fun response ->
487
501
Deferred.Result. return (R. success (Args.VDI.Resize. rpc_of_response response.Storage.Volume.Types. virtual_size))
488
502
| { R. name = "VDI.stat" ; R. params = [ args ] } ->
@@ -491,12 +505,7 @@ let process root_dir name x =
491
505
Attached_SRs. find args.Args.VDI.Stat. sr
492
506
>> = fun sr ->
493
507
let vdi = args.Args.VDI.Stat. vdi in
494
- let args = Storage.Volume.Types.Volume.Stat.In. make
495
- args.Args.VDI.Stat. dbg
496
- sr
497
- vdi in
498
- let args = Storage.Volume.Types.Volume.Stat.In. rpc_of_t args in
499
- fork_exec_rpc root_dir (script root_dir name `Volume " Volume.stat" ) args Storage.Volume.Types.Volume.Stat.Out. t_of_rpc
508
+ stat root_dir name args.Args.VDI.Stat. dbg sr vdi
500
509
>> = fun response ->
501
510
let response = vdi_of_volume response in
502
511
Deferred.Result. return (R. success (Args.VDI.Stat. rpc_of_response response))
@@ -506,12 +515,7 @@ let process root_dir name x =
506
515
Attached_SRs. find args.Args.VDI.Introduce. sr
507
516
>> = fun sr ->
508
517
let vdi = args.Args.VDI.Introduce. location in
509
- let args = Storage.Volume.Types.Volume.Stat.In. make
510
- args.Args.VDI.Introduce. dbg
511
- sr
512
- vdi in
513
- let args = Storage.Volume.Types.Volume.Stat.In. rpc_of_t args in
514
- fork_exec_rpc root_dir (script root_dir name `Volume " Volume.stat" ) args Storage.Volume.Types.Volume.Stat.Out. t_of_rpc
518
+ stat root_dir name args.Args.VDI.Introduce. dbg sr vdi
515
519
>> = fun response ->
516
520
let response = vdi_of_volume response in
517
521
Deferred.Result. return (R. success (Args.VDI.Introduce. rpc_of_response response))
@@ -521,10 +525,16 @@ let process root_dir name x =
521
525
Attached_SRs. find args.Args.VDI.Attach. sr
522
526
>> = fun sr ->
523
527
(* Discover the URIs using Volume.stat *)
524
- stat root_dir name
525
- args.Args.VDI.Attach. dbg
526
- sr
527
- args.Args.VDI.Attach. vdi
528
+ stat root_dir name args.Args.VDI.Attach. dbg sr args.Args.VDI.Attach. vdi
529
+ >> = fun response ->
530
+ (* If we have a clone-on-boot volume then use that instead *)
531
+ ( match List.Assoc. find response.Storage.Volume.Types. keys _clone_on_boot_key with
532
+ | None ->
533
+ return (Ok response)
534
+ | Some temporary ->
535
+ stat root_dir name args.Args.VDI.Attach. dbg sr temporary
536
+ ) >> = fun response ->
537
+ choose_datapath response
528
538
>> = fun (datapath , uri , domain ) ->
529
539
let args' = Storage.Datapath.Types.Datapath.Attach.In. make
530
540
args.Args.VDI.Attach. dbg
@@ -549,10 +559,16 @@ let process root_dir name x =
549
559
Attached_SRs. find args.Args.VDI.Activate. sr
550
560
>> = fun sr ->
551
561
(* Discover the URIs using Volume.stat *)
552
- stat root_dir name
553
- args.Args.VDI.Activate. dbg
554
- sr
555
- args.Args.VDI.Activate. vdi
562
+ stat root_dir name args.Args.VDI.Activate. dbg sr args.Args.VDI.Activate. vdi
563
+ >> = fun response ->
564
+ (* If we have a clone-on-boot volume then use that instead *)
565
+ ( match List.Assoc. find response.Storage.Volume.Types. keys _clone_on_boot_key with
566
+ | None ->
567
+ return (Ok response)
568
+ | Some temporary ->
569
+ stat root_dir name args.Args.VDI.Activate. dbg sr temporary
570
+ ) >> = fun response ->
571
+ choose_datapath response
556
572
>> = fun (datapath , uri , domain ) ->
557
573
let args' = Storage.Datapath.Types.Datapath.Activate.In. make
558
574
args.Args.VDI.Activate. dbg
@@ -567,10 +583,15 @@ let process root_dir name x =
567
583
Attached_SRs. find args.Args.VDI.Deactivate. sr
568
584
>> = fun sr ->
569
585
(* Discover the URIs using Volume.stat *)
570
- stat root_dir name
571
- args.Args.VDI.Deactivate. dbg
572
- sr
573
- args.Args.VDI.Deactivate. vdi
586
+ stat root_dir name args.Args.VDI.Deactivate. dbg sr args.Args.VDI.Deactivate. vdi
587
+ >> = fun response ->
588
+ ( match List.Assoc. find response.Storage.Volume.Types. keys _clone_on_boot_key with
589
+ | None ->
590
+ return (Ok response)
591
+ | Some temporary ->
592
+ stat root_dir name args.Args.VDI.Deactivate. dbg sr temporary
593
+ ) >> = fun response ->
594
+ choose_datapath response
574
595
>> = fun (datapath , uri , domain ) ->
575
596
let args' = Storage.Datapath.Types.Datapath.Deactivate.In. make
576
597
args.Args.VDI.Deactivate. dbg
@@ -585,10 +606,15 @@ let process root_dir name x =
585
606
Attached_SRs. find args.Args.VDI.Detach. sr
586
607
>> = fun sr ->
587
608
(* Discover the URIs using Volume.stat *)
588
- stat root_dir name
589
- args.Args.VDI.Detach. dbg
590
- sr
591
- args.Args.VDI.Detach. vdi
609
+ stat root_dir name args.Args.VDI.Detach. dbg sr args.Args.VDI.Detach. vdi
610
+ >> = fun response ->
611
+ ( match List.Assoc. find response.Storage.Volume.Types. keys _clone_on_boot_key with
612
+ | None ->
613
+ return (Ok response)
614
+ | Some temporary ->
615
+ stat root_dir name args.Args.VDI.Detach. dbg sr temporary
616
+ ) >> = fun response ->
617
+ choose_datapath response
592
618
>> = fun (datapath , uri , domain ) ->
593
619
let args' = Storage.Datapath.Types.Datapath.Detach.In. make
594
620
args.Args.VDI.Detach. dbg
@@ -620,15 +646,15 @@ let process root_dir name x =
620
646
>> = fun sr ->
621
647
(* Discover the URIs using Volume.stat *)
622
648
let persistent = args.Args.VDI.Epoch_begin. persistent in
623
- stat ~persistent root_dir name
624
- args.Args.VDI.Epoch_begin. dbg
625
- sr
626
- args.Args.VDI.Epoch_begin. vdi
649
+ stat root_dir name args.Args.VDI.Epoch_begin. dbg sr args.Args.VDI.Epoch_begin. vdi
650
+ >> = fun response ->
651
+ choose_datapath ~persistent response
627
652
>> = fun (datapath , uri , domain ) ->
628
653
(* If non-persistent and the datapath plugin supports NONPERSISTENT
629
654
then we delegate this to the datapath plugin. Otherwise we will
630
655
make a temporary clone now and attach/detach etc this file. *)
631
656
if Datapath_plugins. supports_feature datapath _nonpersistent then begin
657
+ (* We delegate handling non-persistent disks to the datapath plugin. *)
632
658
let args = Storage.Datapath.Types.Datapath.Open.In. make
633
659
args.Args.VDI.Epoch_begin. dbg
634
660
uri persistent in
@@ -637,27 +663,42 @@ let process root_dir name x =
637
663
>> = fun () ->
638
664
Deferred.Result. return (R. success (Args.VDI.Epoch_begin. rpc_of_response () ))
639
665
end else begin
640
- Deferred. return (Error (backend_error " UNIMPLEMENTED" [ name ]))
666
+ (* We create a non-persistent disk here with Volume.clone, and store
667
+ the name of the cloned disk in the metadata of the original. *)
668
+ clone root_dir name args.Args.VDI.Epoch_begin. dbg sr args.Args.VDI.Epoch_begin. vdi
669
+ >> = fun vdi ->
670
+ set root_dir name args.Args.VDI.Epoch_begin. dbg sr args.Args.VDI.Epoch_begin. vdi _clone_on_boot_key vdi.Storage.Volume.Types. key
671
+ >> = fun () ->
672
+ Deferred.Result. return (R. success (Args.VDI.Epoch_begin. rpc_of_response () ))
641
673
end
642
674
| { R. name = "VDI.epoch_end" ; R. params = [ args ] } ->
643
675
let open Deferred.Result.Monad_infix in
644
676
let args = Args.VDI.Epoch_end. request_of_rpc args in
645
677
Attached_SRs. find args.Args.VDI.Epoch_end. sr
646
678
>> = fun sr ->
647
679
(* Discover the URIs using Volume.stat *)
648
- stat root_dir name
649
- args.Args.VDI.Epoch_end. dbg
650
- sr
651
- args.Args.VDI.Epoch_end. vdi
680
+ stat root_dir name args.Args.VDI.Epoch_end. dbg sr args.Args.VDI.Epoch_end. vdi
681
+ >> = fun response ->
682
+ choose_datapath response
652
683
>> = fun (datapath , uri , domain ) ->
653
- let args = Storage.Datapath.Types.Datapath.Close.In. make
654
- args.Args.VDI.Epoch_end. dbg
655
- uri in
656
- let args = Storage.Datapath.Types.Datapath.Close.In. rpc_of_t args in
657
- fork_exec_rpc root_dir (script root_dir name (`Datapath datapath) " Datapath.close" ) args Storage.Datapath.Types.Datapath.Close.Out. t_of_rpc
658
- >> = fun () ->
659
- Deferred.Result. return (R. success (Args.VDI.Epoch_end. rpc_of_response () ))
660
-
684
+ if Datapath_plugins. supports_feature datapath _nonpersistent then begin
685
+ let args = Storage.Datapath.Types.Datapath.Close.In. make
686
+ args.Args.VDI.Epoch_end. dbg
687
+ uri in
688
+ let args = Storage.Datapath.Types.Datapath.Close.In. rpc_of_t args in
689
+ fork_exec_rpc root_dir (script root_dir name (`Datapath datapath) " Datapath.close" ) args Storage.Datapath.Types.Datapath.Close.Out. t_of_rpc
690
+ >> = fun () ->
691
+ Deferred.Result. return (R. success (Args.VDI.Epoch_end. rpc_of_response () ))
692
+ end else begin
693
+ match List.Assoc. find response.Storage.Volume.Types. keys _clone_on_boot_key with
694
+ | None ->
695
+ Deferred.Result. return (R. success (Args.VDI.Epoch_end. rpc_of_response () ))
696
+ | Some temporary ->
697
+ (* Destroy the temporary disk we made earlier *)
698
+ destroy root_dir name args.Args.VDI.Epoch_end. dbg sr temporary
699
+ >> = fun () ->
700
+ Deferred.Result. return (R. success (Args.VDI.Epoch_end. rpc_of_response () ))
701
+ end
661
702
| { R. name = name } ->
662
703
Deferred. return (Error (backend_error " UNIMPLEMENTED" [ name ])))
663
704
>> = function
0 commit comments