Skip to content

Commit 046000c

Browse files
committed
Implement VDI.export_changed_blocks XenAPI call
We require both SRs to be attached for the corner case where we ask for the changed blocks between two VDIs from two different SRs. However, this is not strictly necessary: in the above case we just return all the blocks of the second VDI, so we only need the SR of the second VDI to be attached. For this operation, even though we could allow the VDI to be attached as read-only, we require it to be detached, to simplify the implementation of the storage plugins - now we have one less thing to consider, and this makes the implementation more flexible. Signed-off-by: Gabor Igloi <[email protected]>
1 parent 786a6a0 commit 046000c

File tree

6 files changed

+57
-6
lines changed

6 files changed

+57
-6
lines changed

ocaml/idl/datamodel.ml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6008,6 +6008,7 @@ let storage_operations =
60086008
"vdi_enable_cbt", "Enabling changed block tracking for a VDI";
60096009
"vdi_disable_cbt", "Disabling changed block tracking for a VDI";
60106010
"vdi_data_destroy", "Deleting the data of the VDI";
6011+
"vdi_export_changed_blocks", "Exporting a bitmap that shows the changed blocks between two VDIs";
60116012
"vdi_set_on_boot", "Setting the on_boot field of the VDI";
60126013
"pbd_create", "Creating a PBD for this SR";
60136014
"pbd_destroy", "Destroying one of this SR's PBDs"; ])
@@ -6333,6 +6334,7 @@ let vdi_operations =
63336334
"enable_cbt", "Enabling changed block tracking for a VDI";
63346335
"disable_cbt", "Disabling changed block tracking for a VDI";
63356336
"data_destroy", "Deleting the data of the VDI";
6337+
"export_changed_blocks", "Exporting a bitmap that shows the changed blocks between two VDIs";
63366338
"set_on_boot", "Setting the on_boot field of the VDI";
63376339
"blocked", "Operations on this VDI are temporarily blocked";
63386340
])
@@ -6595,6 +6597,26 @@ let vdi_data_destroy = call
65956597
~allowed_roles:_R_VM_ADMIN
65966598
()
65976599

6600+
let vdi_export_changed_blocks = call
6601+
~name:"export_changed_blocks"
6602+
~in_oss_since:None
6603+
~in_product_since:rel_inverness
6604+
~params:
6605+
[ Ref _vdi, "vdi_from", "The first VDI."
6606+
; Ref _vdi, "vdi_to", "The second VDI."
6607+
]
6608+
~errs:
6609+
[ Api_errors.sr_operation_not_supported
6610+
; Api_errors.vdi_missing
6611+
; Api_errors.sr_not_attached
6612+
; Api_errors.sr_no_pbds
6613+
; Api_errors.vdi_in_use
6614+
]
6615+
~result:(String, "A base64 string-encoding of the bitmap showing which blocks differ in the two VDIs.")
6616+
~doc:"Reports which blocks differ in the two VDIs. This operation is not allowed when vdi_to is attached to a VM."
6617+
~allowed_roles:_R_VM_OP
6618+
()
6619+
65986620
(** A virtual disk *)
65996621
let vdi =
66006622
create_obj ~in_db:true ~in_product_since:rel_rio ~in_oss_since:oss_since_303 ~internal_deprecated_since:None ~persist:PersistEverything ~gen_constructor_destructor:true ~name:_vdi ~descr:"A virtual disk image"
@@ -6630,6 +6652,7 @@ let vdi =
66306652
vdi_enable_cbt;
66316653
vdi_disable_cbt;
66326654
vdi_data_destroy;
6655+
vdi_export_changed_blocks;
66336656
]
66346657
~contents:
66356658
([ uid _vdi;

ocaml/xapi/message_forwarding.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3605,6 +3605,16 @@ module Forward = functor(Local: Custom_actions.CUSTOM_ACTIONS) -> struct
36053605
forward_vdi_op ~local_fn ~__context ~self
36063606
(fun session_id rpc -> Client.VDI.data_destroy rpc session_id self))
36073607

3608+
let export_changed_blocks ~__context ~vdi_from ~vdi_to =
3609+
info "VDI.export_changed_blocks: vdi_from = '%s'; vdi_to = '%s'" (vdi_uuid ~__context vdi_from) (vdi_uuid ~__context vdi_to);
3610+
let local_fn = Local.VDI.export_changed_blocks ~vdi_from ~vdi_to in
3611+
let vdi_from_sr = Db.VDI.get_SR ~__context ~self:vdi_from in
3612+
let vdi_to_sr = Db.VDI.get_SR ~__context ~self:vdi_to in
3613+
with_sr_andor_vdi ~__context ~sr:(vdi_to_sr, `vdi_export_changed_blocks) ~vdi:(vdi_to, `export_changed_blocks) ~doc:"VDI.export_changed_blocks"
3614+
(fun () ->
3615+
SR.forward_sr_multiple_op ~local_fn ~__context ~srs:[vdi_from_sr; vdi_to_sr] ~prefer_slaves:true
3616+
(fun session_id rpc -> Client.VDI.export_changed_blocks ~rpc ~session_id ~vdi_from ~vdi_to))
3617+
36083618
end
36093619
module VBD = struct
36103620

ocaml/xapi/record_util.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ let vdi_operation_to_string: API.vdi_operations -> string = function
112112
| `enable_cbt -> "enable_cbt"
113113
| `disable_cbt -> "disable_cbt"
114114
| `data_destroy -> "data_destroy"
115+
| `export_changed_blocks -> "export_changed_blocks"
115116
| `set_on_boot -> "set_on_boot"
116117
| `blocked -> "blocked"
117118

@@ -133,6 +134,7 @@ let sr_operation_to_string: API.storage_operations -> string = function
133134
| `vdi_disable_cbt -> "VDI.disable_cbt"
134135
| `vdi_set_on_boot -> "VDI.set_on_boot"
135136
| `vdi_data_destroy -> "VDI.data_destroy"
137+
| `vdi_export_changed_blocks -> "VDI.export_changed_blocks"
136138
| `pbd_create -> "PBD.create"
137139
| `pbd_destroy -> "PBD.destroy"
138140

ocaml/xapi/xapi_sr_operations.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ open Record_util
3737

3838
let all_ops : API.storage_operations_set =
3939
[ `scan; `destroy; `forget; `plug; `unplug; `vdi_create; `vdi_destroy; `vdi_resize; `vdi_clone; `vdi_snapshot; `vdi_mirror;
40-
`vdi_enable_cbt; `vdi_disable_cbt; `vdi_data_destroy; `vdi_set_on_boot; `vdi_introduce; `update; `pbd_create; `pbd_destroy ]
40+
`vdi_enable_cbt; `vdi_disable_cbt; `vdi_data_destroy; `vdi_export_changed_blocks; `vdi_set_on_boot; `vdi_introduce; `update; `pbd_create; `pbd_destroy ]
4141

4242
let sm_cap_table : (API.storage_operations * _) list =
4343
[ `vdi_create, Smint.Vdi_create;
@@ -48,6 +48,7 @@ let sm_cap_table : (API.storage_operations * _) list =
4848
`vdi_enable_cbt, Smint.Vdi_configure_cbt;
4949
`vdi_disable_cbt, Smint.Vdi_configure_cbt;
5050
`vdi_data_destroy, Smint.Vdi_configure_cbt;
51+
`vdi_export_changed_blocks, Smint.Vdi_configure_cbt;
5152
`vdi_set_on_boot, Smint.Vdi_reset_on_boot;
5253
`update, Smint.Sr_update;
5354
(* We fake clone ourselves *)

ocaml/xapi/xapi_vdi.ml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ let check_sm_feature_error (op:API.vdi_operations) sm_features sr =
4040
| `generate_config -> Some Vdi_generate_config
4141
| `clone -> Some Vdi_clone
4242
| `mirror -> Some Vdi_mirror
43-
| `enable_cbt | `disable_cbt | `data_destroy -> Some Vdi_configure_cbt
43+
| `enable_cbt | `disable_cbt | `data_destroy | `export_changed_blocks -> Some Vdi_configure_cbt
4444
| `set_on_boot -> Some Vdi_reset_on_boot
4545
) in
4646
match required_sm_feature with
@@ -166,13 +166,13 @@ let check_operation_error ~__context ?(sr_records=[]) ?(pbd_records=[]) ?(vbd_re
166166
else
167167
let allowed_for_cbt_metadata_vdi = match op with
168168
| `clone | `copy | `disable_cbt | `enable_cbt | `mirror | `resize | `resize_online | `snapshot | `set_on_boot -> false
169-
| `blocked |`data_destroy | `destroy | `force_unlock | `forget | `generate_config | `update -> true in
169+
| `blocked | `data_destroy | `destroy | `export_changed_blocks | `force_unlock | `forget | `generate_config | `update -> true in
170170
if not allowed_for_cbt_metadata_vdi && record.Db_actions.vDI_type = `cbt_metadata
171171
then Some (Api_errors.vdi_incompatible_type, [ _ref; Record_util.vdi_type_to_string `cbt_metadata ])
172172
else
173173
let allowed_when_cbt_enabled = match op with
174174
| `mirror | `set_on_boot -> false
175-
| `blocked | `clone | `copy | `data_destroy | `destroy | `disable_cbt | `enable_cbt | `force_unlock | `forget | `generate_config | `resize | `resize_online | `snapshot | `update -> true in
175+
| `blocked | `clone | `copy | `data_destroy | `destroy | `disable_cbt | `enable_cbt | `export_changed_blocks | `force_unlock | `forget | `generate_config | `resize | `resize_online | `snapshot | `update -> true in
176176
if not allowed_when_cbt_enabled && record.Db_actions.vDI_cbt_enabled
177177
then Some (Api_errors.vdi_cbt_enabled, [_ref])
178178
else
@@ -234,10 +234,10 @@ let check_operation_error ~__context ?(sr_records=[]) ?(pbd_records=[]) ?(vbd_re
234234
then Some (Api_errors.operation_not_allowed, ["VDI is a snapshot: " ^ _ref])
235235
else if not (List.mem record.Db_actions.vDI_type [ `user; `system ])
236236
then Some (Api_errors.vdi_incompatible_type, [ _ref; Record_util.vdi_type_to_string record.Db_actions.vDI_type ])
237-
else if record.Db_actions.vDI_on_boot = `reset
237+
else if reset_on_boot
238238
then Some (Api_errors.vdi_on_boot_mode_incompatible_with_operation, [])
239239
else None
240-
| `mirror | `clone | `generate_config | `force_unlock | `set_on_boot | `blocked | `update -> None
240+
| `mirror | `clone | `generate_config | `force_unlock | `set_on_boot | `export_changed_blocks | `blocked | `update -> None
241241
end
242242

243243
let assert_operation_valid ~__context ~self ~(op:API.vdi_operations) =
@@ -859,4 +859,17 @@ let change_cbt_status ~__context ~self ~new_cbt_enabled ~caller_name =
859859
let enable_cbt = change_cbt_status ~new_cbt_enabled:true ~caller_name:"VDI.enable_cbt"
860860
let disable_cbt = change_cbt_status ~new_cbt_enabled:false ~caller_name:"VDI.disable_cbt"
861861

862+
let export_changed_blocks ~__context ~vdi_from ~vdi_to =
863+
let task = Context.get_task_id __context in
864+
(* We have to pass the SR of vdi_to to the SMAPIv2 call *)
865+
let sr = Db.VDI.get_SR ~__context ~self:vdi_to in
866+
let sr = Db.SR.get_uuid ~__context ~self:sr in
867+
let vdi_from = Db.VDI.get_location ~__context ~self:vdi_from in
868+
let vdi_to = Db.VDI.get_location ~__context ~self:vdi_to in
869+
let module C = Storage_interface.Client(struct let rpc = Storage_access.rpc end) in
870+
Storage_access.transform_storage_exn
871+
(fun () ->
872+
C.VDI.export_changed_blocks ~dbg:(Ref.string_of task) ~sr ~vdi_from ~vdi_to
873+
);
874+
862875
(* let pool_migrate = "See Xapi_vm_migrate.vdi_pool_migrate!" *)

ocaml/xapi/xapi_vdi.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,5 @@ val enable_cbt :
210210
__context:Context.t -> self:API.ref_VDI -> unit
211211
val disable_cbt :
212212
__context:Context.t -> self:API.ref_VDI -> unit
213+
val export_changed_blocks :
214+
__context:Context.t -> vdi_from:API.ref_VDI -> vdi_to:API.ref_VDI -> string

0 commit comments

Comments
 (0)