Skip to content

Commit f487aef

Browse files
johnelsepsafont
authored andcommitted
xapi_vdi: Introduce VDI operations needed for revert
This is for both the live VDI (revert_from) and the snapshot (revert_to) These correspond to the VM operations `reverting` and `revert`, respectively. Only snapshots backed by an SR that allows clones are allowed to be reverted to. This is because SRs supporting revert is not enough to use vdi revert without clone: having an incorrect snapshot_of field will also cause the use of clone. With this we can ensure that if a bad edge case is met the system has a working fallback. Reverting to "live" snapshot VDIs is allowed, this happens when reverting to a checkpoint. Currently reverting requires the cloning feature because it's not possible to discriminate between backends that support vdi revert and ones that done. This will be possible once all of them do Test that VDIs... * can be reverted to a snapshot. * can be reverted to an attached snapshot. * cannot be reverted to a leaf VDI. * cannot be reverted to an attached leaf. Co-authored-by: John Else <john.else@citrix.com> Signed-off-by: Pau Ruiz Safont <pau.safont@vates.tech> (cherry picked from commit 639bc3d)
1 parent 2bb61f0 commit f487aef

6 files changed

Lines changed: 79 additions & 8 deletions

File tree

ocaml/idl/datamodel.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5718,6 +5718,8 @@ module VDI = struct
57185718
)
57195719
; ("set_on_boot", "Setting the on_boot field of the VDI")
57205720
; ("blocked", "Operations on this VDI are temporarily blocked")
5721+
; ("revert_to", "Reverting a VDI to a clone of this snapshot")
5722+
; ("revert_from", "Reverting this VDI to a clone of a snapshot")
57215723
]
57225724
)
57235725

ocaml/idl/schematest.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ let hash x = Digest.string x |> Digest.to_hex
33
(* BEWARE: if this changes, check that schema has been bumped accordingly in
44
ocaml/idl/datamodel_common.ml, usually schema_minor_vsn *)
55

6-
let last_known_schema_hash = "62c803c7341a736eef8293337105206f"
6+
let last_known_schema_hash = "f45d29452df691507ce8fc9f539649f1"
77

88
let current_schema_hash : string =
99
let open Datamodel_types in

ocaml/tests/record_util/old_record_util.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ let vdi_operation_to_string : API.vdi_operations -> string = function
299299
"set_on_boot"
300300
| `blocked ->
301301
"blocked"
302+
| `revert_to ->
303+
"revert_to"
304+
| `revert_from ->
305+
"revert_from"
302306

303307
let sr_operation_to_string : API.storage_operations -> string = function
304308
| `scan ->

ocaml/tests/test_vdi_allowed_operations.ml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,54 @@ let test_update_allowed_operations () =
573573
Alcotest.(check Alcotest_comparators.vdi_operations_set)
574574
"update_allowed_operations should be correct" ok_ops allowed_operations
575575

576+
(* Tests for revert operation *)
577+
let test_revert =
578+
let test_can_revert_to_snapshot () =
579+
let __context = Mock.make_context_with_new_db "Mock context" in
580+
581+
run_assert_equal_with_vdi ~__context
582+
~vdi_fun:(fun vdi_ref ->
583+
Db.VDI.set_is_a_snapshot ~__context ~self:vdi_ref ~value:true
584+
)
585+
`revert_to (Ok ())
586+
in
587+
(* VBDs of checkpoints are marked with currently_attached = true, but we still
588+
need to be able to revert to them. *)
589+
let test_can_revert_to_checkpoint () =
590+
let __context = Mock.make_context_with_new_db "Mock context" in
591+
592+
run_assert_equal_with_vdi ~__context
593+
~vdi_fun:(fun vdi_ref ->
594+
Db.VDI.set_is_a_snapshot ~__context ~self:vdi_ref ~value:true ;
595+
make_vbd ~__context ~vDI:vdi_ref ~currently_attached:true ~mode:`RW ()
596+
)
597+
`revert_to (Ok ())
598+
in
599+
let test_cannot_revert_to_leaf () =
600+
let __context = Mock.make_context_with_new_db "Mock context" in
601+
602+
run_assert_equal_with_vdi ~__context
603+
~vdi_fun:(fun _ -> ())
604+
`revert_to
605+
(Error (Api_errors.only_revert_snapshot, []))
606+
in
607+
let test_cannot_revert_live () =
608+
let __context = Mock.make_context_with_new_db "Mock context" in
609+
610+
run_assert_equal_with_vdi ~__context
611+
~vdi_fun:(fun vdi_ref ->
612+
make_vbd ~__context ~vDI:vdi_ref ~currently_attached:true ~mode:`RW ()
613+
)
614+
`revert_from
615+
(Error (Api_errors.vdi_in_use, []))
616+
in
617+
[
618+
("Revert: Can revert to snapshot", `Quick, test_can_revert_to_snapshot)
619+
; ("Revert: Can revert to checkpoint", `Quick, test_can_revert_to_checkpoint)
620+
; ("Revert: Cannot revert to leaf", `Quick, test_cannot_revert_to_leaf)
621+
; ("Revert: Cannot revert live", `Quick, test_cannot_revert_live)
622+
]
623+
576624
let test =
577625
[
578626
("test_ca98944", `Quick, test_ca98944)
@@ -586,3 +634,4 @@ let test =
586634
("test_null_vm", `Quick, test_null_vm)
587635
; ("test_update_allowed_operations", `Quick, test_update_allowed_operations)
588636
]
637+
@ test_revert
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
val test : (string * [> `Quick] * (unit -> unit)) list

ocaml/xapi/xapi_vdi.ml

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ let feature_of_op =
3939
Some Vdi_resize_online
4040
| `generate_config ->
4141
Some Vdi_generate_config
42-
| `clone ->
42+
| `clone | `revert_to | `revert_from ->
4343
Some Vdi_clone
4444
| `mirror ->
4545
Some Vdi_mirror
@@ -210,18 +210,24 @@ let check_operation_error ~__context ?sr_records:_ ?(pbd_records = [])
210210
(* check to see whether VBDs exist which are using this VDI *)
211211

212212
(* If the VBD is currently_attached then some operations can still be
213-
performed ie: VDI.clone (if the VM is suspended we have to have the
214-
'allow_clone_suspended_vm' flag); VDI.snapshot; VDI.resize_online;
215-
'blocked' (CP-831); VDI.data_destroy: it is not allowed on VDIs linked
216-
to a VM, but the implementation first waits for the VDI's VBDs to be
217-
unplugged and destroyed, and the checks are performed there.
213+
performed ie:
214+
- VDI.clone (if the VM is suspended we have to have the
215+
'allow_clone_suspended_vm' flag)
216+
- VDI.snapshot
217+
- VDI.resize_online
218+
- VDI.blocked (CP-831)
219+
- VDI.data_destroy: it is not allowed on VDIs linked to a VM, but the
220+
implementation first waits for the VDI's VBDs to be unplugged and
221+
destroyed, and the checks are performed there
222+
- VDI.revert: is allowed as checkpoints have currently_attached VBDs
218223
*)
219224
let operation_can_be_performed_live =
220225
match op with
221226
| `snapshot
222227
| `resize_online
223228
| `blocked
224229
| `clone
230+
| `revert_to
225231
| `mirror
226232
| `enable_cbt
227233
| `disable_cbt
@@ -305,6 +311,8 @@ let check_operation_error ~__context ?sr_records:_ ?(pbd_records = [])
305311
| `resize
306312
| `resize_online
307313
| `snapshot
314+
| `revert_to
315+
| `revert_from
308316
| `set_on_boot ->
309317
false
310318
| `blocked
@@ -347,6 +355,8 @@ let check_operation_error ~__context ?sr_records:_ ?(pbd_records = [])
347355
| `resize
348356
| `resize_online
349357
| `snapshot
358+
| `revert_to
359+
| `revert_from
350360
| `update ->
351361
true
352362
in
@@ -387,7 +397,7 @@ let check_operation_error ~__context ?sr_records:_ ?(pbd_records = [])
387397
Error (Api_errors.vdi_has_rrds, [_ref])
388398
else
389399
Ok ()
390-
| `destroy ->
400+
| `destroy | `revert_from ->
391401
check_destroy ()
392402
| `data_destroy ->
393403
if not record.Db_actions.vDI_is_a_snapshot then
@@ -445,6 +455,11 @@ let check_operation_error ~__context ?sr_records:_ ?(pbd_records = [])
445455
Error (Api_errors.vdi_on_boot_mode_incompatible_with_operation, [])
446456
else
447457
Ok ()
458+
| `revert_to ->
459+
if not record.Db_actions.vDI_is_a_snapshot then
460+
Error (Api_errors.only_revert_snapshot, [])
461+
else
462+
Ok ()
448463
| `mirror
449464
| `clone
450465
| `generate_config

0 commit comments

Comments
 (0)