Skip to content

Commit 01a87ac

Browse files
authored
Merge pull request xapi-project#3164 from gaborigloi/feature/CBT_merge
Merge feature/CBT branch into master
2 parents cc1010b + 5fca553 commit 01a87ac

19 files changed

+422
-103
lines changed

ocaml/idl/datamodel.ml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,8 @@ let _ =
11101110
~doc:"This VDI was not mapped to a destination SR in VM.migrate_send operation" () ;
11111111
error Api_errors.vdi_cbt_enabled [ "vdi" ]
11121112
~doc:"The requested operation is not allowed for VDIs with CBT enabled or VMs having such VDIs, and CBT is enabled for the specified VDI." ();
1113+
error Api_errors.vdi_no_cbt_metadata [ "vdi" ]
1114+
~doc:"The requested operation is not allowed because the specified VDI does not have changed block tracking metadata." ();
11131115
error Api_errors.vdi_copy_failed []
11141116
~doc:"The VDI copy action has failed" ();
11151117
error Api_errors.vdi_on_boot_mode_incompatible_with_operation []
@@ -6005,6 +6007,8 @@ let storage_operations =
60056007
"vdi_mirror", "Mirroring a VDI";
60066008
"vdi_enable_cbt", "Enabling changed block tracking for a VDI";
60076009
"vdi_disable_cbt", "Disabling changed block tracking for a VDI";
6010+
"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";
60086012
"vdi_set_on_boot", "Setting the on_boot field of the VDI";
60096013
"pbd_create", "Creating a PBD for this SR";
60106014
"pbd_destroy", "Destroying one of this SR's PBDs"; ])
@@ -6329,6 +6333,8 @@ let vdi_operations =
63296333
"generate_config", "Generating static configuration";
63306334
"enable_cbt", "Enabling changed block tracking for a VDI";
63316335
"disable_cbt", "Disabling changed block tracking for a VDI";
6336+
"data_destroy", "Deleting the data of the VDI";
6337+
"export_changed_blocks", "Exporting a bitmap that shows the changed blocks between two VDIs";
63326338
"set_on_boot", "Setting the on_boot field of the VDI";
63336339
"blocked", "Operations on this VDI are temporarily blocked";
63346340
])
@@ -6571,6 +6577,57 @@ let vdi_disable_cbt = call
65716577
~allowed_roles:_R_VM_ADMIN
65726578
()
65736579

6580+
let vdi_data_destroy = call
6581+
~name:"data_destroy"
6582+
~in_oss_since:None
6583+
~in_product_since:rel_inverness
6584+
~params:[Ref _vdi, "self", "The VDI whose data should be deleted."]
6585+
~errs:[
6586+
Api_errors.sr_operation_not_supported;
6587+
Api_errors.vdi_missing;
6588+
Api_errors.sr_not_attached;
6589+
Api_errors.sr_no_pbds;
6590+
Api_errors.operation_not_allowed;
6591+
Api_errors.vdi_incompatible_type;
6592+
Api_errors.vdi_no_cbt_metadata;
6593+
Api_errors.vdi_in_use;
6594+
Api_errors.vdi_is_a_physical_device;
6595+
]
6596+
~doc:"Delete the data of the snapshot VDI, but keep its changed block tracking metadata. When successful, this call changes the type of the VDI to cbt_metadata. This operation is idempotent: calling it on a VDI of type cbt_metadata results in a no-op, and no error will be thrown."
6597+
~allowed_roles:_R_VM_ADMIN
6598+
()
6599+
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+
6620+
let vdi_get_nbd_info = call
6621+
~name:"get_nbd_info"
6622+
~in_oss_since:None
6623+
~in_product_since:rel_inverness
6624+
~params:[Ref _vdi, "self", "The VDI to access via NBD."]
6625+
~errs: [Api_errors.vdi_incompatible_type]
6626+
~result:(Set String, "The list of URIs.")
6627+
~doc:"Get a list of URIs specifying how to access this VDI via the NBD server of XenServer. A URI will be returned for each PIF of each host that is connected to the VDI's SR. An empty list is returned in case no network has a PIF on a host with access to the relevant SR. To access the given VDI, any of the returned URIs can be passed to the NBD server running at the IP address and port specified by that URI as the export name."
6628+
~allowed_roles:_R_VM_ADMIN
6629+
()
6630+
65746631
(** A virtual disk *)
65756632
let vdi =
65766633
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"
@@ -6605,6 +6662,9 @@ let vdi =
66056662
vdi_pool_migrate;
66066663
vdi_enable_cbt;
66076664
vdi_disable_cbt;
6665+
vdi_data_destroy;
6666+
vdi_export_changed_blocks;
6667+
vdi_get_nbd_info;
66086668
]
66096669
~contents:
66106670
([ uid _vdi;

ocaml/xapi-consts/api_errors.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ let vdi_io_error = "VDI_IO_ERROR"
240240
let vdi_on_boot_mode_incompatible_with_operation = "VDI_ON_BOOT_MODE_INCOMPATIBLE_WITH_OPERATION"
241241
let vdi_not_in_map = "VDI_NOT_IN_MAP"
242242
let vdi_cbt_enabled = "VDI_CBT_ENABLED"
243+
let vdi_no_cbt_metadata = "VDI_NO_CBT_METADATA"
243244
let vif_not_in_map = "VIF_NOT_IN_MAP"
244245
let cannot_create_state_file = "CANNOT_CREATE_STATE_FILE"
245246

ocaml/xapi/cli_frontend.ml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,6 +1985,22 @@ let rec cmdtable_data : (string*cmd_spec) list =
19851985
implementation=No_fd Cli_operations.vdi_disable_cbt;
19861986
flags=[];
19871987
};
1988+
"vdi-data-destroy",
1989+
{
1990+
reqd=["uuid"];
1991+
optn=[];
1992+
help="Delete the data of the VDI, but keep its changed block tracking metadata.";
1993+
implementation=No_fd Cli_operations.vdi_data_destroy;
1994+
flags=[];
1995+
};
1996+
"vdi-export-changed-blocks",
1997+
{
1998+
reqd=["vdi-from"; "vdi-to"];
1999+
optn=[];
2000+
help="Write the changed blocks between the two given VDIs to the standard output as a base64-encoded bitmap string.";
2001+
implementation=With_fd Cli_operations.vdi_export_changed_blocks;
2002+
flags=[];
2003+
};
19882004
"diagnostic-vdi-status",
19892005
{
19902006
reqd=["uuid"];

ocaml/xapi/cli_operations.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,16 @@ let vdi_disable_cbt printer rpc session_id params =
12561256
let vdi = Client.VDI.get_by_uuid rpc session_id (List.assoc "uuid" params) in
12571257
Client.VDI.disable_cbt rpc session_id vdi
12581258

1259+
let vdi_data_destroy printer rpc session_id params =
1260+
let vdi = Client.VDI.get_by_uuid rpc session_id (List.assoc "uuid" params) in
1261+
Client.VDI.data_destroy rpc session_id vdi
1262+
1263+
let vdi_export_changed_blocks socket _ rpc session_id params =
1264+
let vdi_from = Client.VDI.get_by_uuid rpc session_id (List.assoc "vdi-from" params) in
1265+
let vdi_to = Client.VDI.get_by_uuid rpc session_id (List.assoc "vdi-to" params) in
1266+
let bitmap = Client.VDI.export_changed_blocks ~rpc ~session_id ~vdi_from ~vdi_to in
1267+
marshal socket (Command (Print bitmap))
1268+
12591269
let diagnostic_vdi_status printer rpc session_id params =
12601270
let vdi = Client.VDI.get_by_uuid rpc session_id (List.assoc "uuid" params) in
12611271
let vdi_r = vdi_record rpc session_id vdi in

ocaml/xapi/message_forwarding.ml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3108,8 +3108,9 @@ module Forward = functor(Local: Custom_actions.CUSTOM_ACTIONS) -> struct
31083108
let host = Db.PBD.get_host ~__context ~self:pbd in
31093109
do_op_on ~local_fn ~__context ~host op
31103110

3111-
(* do op on a host that can view multiple SRs, if none is found, an
3112-
exception of Not_found will be raised *)
3111+
(** Do op on a host that can view multiple SRs. If none is found, the
3112+
Not_found exception will be raised.
3113+
WARNING: this may forward the call to a host that is NOT the SR master. *)
31133114
let forward_sr_multiple_op ~local_fn ~__context ~srs ?(prefer_slaves=false) op =
31143115
let choose_fn ~host =
31153116
Xapi_vm_helpers.assert_can_see_specified_SRs ~__context ~reqd_srs:srs ~host in
@@ -3596,6 +3597,28 @@ module Forward = functor(Local: Custom_actions.CUSTOM_ACTIONS) -> struct
35963597
forward_vdi_op ~local_fn ~__context ~self
35973598
(fun session_id rpc -> Client.VDI.disable_cbt rpc session_id self))
35983599

3600+
let data_destroy ~__context ~self =
3601+
info "VDI.data_destroy: VDI = '%s'" (vdi_uuid ~__context self);
3602+
let local_fn = Local.VDI.data_destroy ~self in
3603+
let sR = Db.VDI.get_SR ~__context ~self in
3604+
with_sr_andor_vdi ~__context ~sr:(sR, `vdi_data_destroy) ~vdi:(self, `data_destroy) ~doc:"VDI.data_destroy"
3605+
(fun () ->
3606+
forward_vdi_op ~local_fn ~__context ~self
3607+
(fun session_id rpc -> Client.VDI.data_destroy rpc session_id self))
3608+
3609+
let export_changed_blocks ~__context ~vdi_from ~vdi_to =
3610+
info "VDI.export_changed_blocks: vdi_from = '%s'; vdi_to = '%s'" (vdi_uuid ~__context vdi_from) (vdi_uuid ~__context vdi_to);
3611+
let local_fn = Local.VDI.export_changed_blocks ~vdi_from ~vdi_to 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+
forward_vdi_op ~local_fn ~__context ~self:vdi_to
3616+
(fun session_id rpc -> Client.VDI.export_changed_blocks ~rpc ~session_id ~vdi_from ~vdi_to))
3617+
3618+
let get_nbd_info ~__context ~self =
3619+
info "VDI.get_nbd_info: vdi = '%s'" (vdi_uuid ~__context self);
3620+
Local.VDI.get_nbd_info ~__context ~self
3621+
35993622
end
36003623
module VBD = struct
36013624

ocaml/xapi/ounit_comparators.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module StringDiff =
2+
struct
3+
type t = string
4+
let compare = String.compare
5+
let pp_printer = Format.pp_print_string
6+
let pp_print_sep = OUnitDiff.pp_comma_separator
7+
end
8+
9+
module StringSet = OUnitDiff.SetMake(StringDiff)

ocaml/xapi/record_util.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ let vdi_operation_to_string: API.vdi_operations -> string = function
111111
| `generate_config -> "generate_config"
112112
| `enable_cbt -> "enable_cbt"
113113
| `disable_cbt -> "disable_cbt"
114+
| `data_destroy -> "data_destroy"
115+
| `export_changed_blocks -> "export_changed_blocks"
114116
| `set_on_boot -> "set_on_boot"
115117
| `blocked -> "blocked"
116118

@@ -131,6 +133,8 @@ let sr_operation_to_string: API.storage_operations -> string = function
131133
| `vdi_enable_cbt -> "VDI.enable_cbt"
132134
| `vdi_disable_cbt -> "VDI.disable_cbt"
133135
| `vdi_set_on_boot -> "VDI.set_on_boot"
136+
| `vdi_data_destroy -> "VDI.data_destroy"
137+
| `vdi_export_changed_blocks -> "VDI.export_changed_blocks"
134138
| `pbd_create -> "PBD.create"
135139
| `pbd_destroy -> "PBD.destroy"
136140

ocaml/xapi/sm.ml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,18 @@ let vdi_disable_cbt dconf driver sr vdi =
214214
let call = Sm_exec.make_call ~sr_ref:sr ~vdi_ref:vdi dconf "vdi_disable_cbt" [] in
215215
Sm_exec.parse_unit (Sm_exec.exec_xmlrpc (driver_filename driver) call)
216216

217+
let vdi_data_destroy dconf driver sr vdi =
218+
debug "vdi_data_destroy" driver (sprintf "sr=%s vdi=%s" (Ref.string_of sr) (Ref.string_of vdi));
219+
srmaster_only dconf;
220+
let call = Sm_exec.make_call ~sr_ref:sr ~vdi_ref:vdi dconf "vdi_data_destroy" [] in
221+
Sm_exec.parse_unit (Sm_exec.exec_xmlrpc (driver_filename driver) call)
222+
223+
let vdi_export_changed_blocks dconf driver sr ~vdi_from ~vdi_to =
224+
debug "vdi_export_changed_blocks" driver (sprintf "sr=%s vdi_from=%s vdi_to=%s" (Ref.string_of sr) (Ref.string_of vdi_from) (Ref.string_of vdi_to));
225+
srmaster_only dconf;
226+
let call = Sm_exec.make_call ~sr_ref:sr ~vdi_ref:vdi_from dconf "vdi_export_changed_blocks" [ Ref.string_of vdi_to ] in
227+
Sm_exec.parse_string (Sm_exec.exec_xmlrpc (driver_filename driver) call)
228+
217229
let session_has_internal_sr_access ~__context ~sr =
218230
let session_id = Context.get_session_id __context in
219231
(* XXX: need to move this somewhere else eventually *)

ocaml/xapi/storage_access.ml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,26 @@ module SMAPIv1 = struct
844844
let disable_cbt context =
845845
call_cbt_function context ~f:Sm.vdi_disable_cbt ~f_name:"VDI.disable_cbt"
846846

847+
let data_destroy context ~dbg ~sr ~vdi =
848+
call_cbt_function context ~f:Sm.vdi_data_destroy ~f_name:"VDI.data_destroy" ~dbg ~sr ~vdi;
849+
set_content_id context ~dbg ~sr ~vdi ~content_id:"/No content: this is a cbt_metadata VDI/"
850+
851+
let export_changed_blocks context ~dbg ~sr ~vdi_from ~vdi_to =
852+
try
853+
Server_helpers.exec_with_new_task "VDI.export_changed_blocks" ~subtask_of:(Ref.of_string dbg)
854+
(fun __context ->
855+
let vdi_from = find_vdi ~__context sr vdi_from |> fst in
856+
for_vdi ~dbg ~sr ~vdi:vdi_to "VDI.export_changed_blocks"
857+
(fun device_config _type sr vdi_to ->
858+
Sm.vdi_export_changed_blocks device_config _type sr ~vdi_from ~vdi_to
859+
))
860+
with
861+
| Smint.Not_implemented_in_backend ->
862+
raise (Unimplemented "VDI.export_changed_blocks")
863+
| Api_errors.Server_error(code, params) ->
864+
raise (Backend_error(code, params))
865+
| Sm.MasterOnly -> redirect sr
866+
847867
end
848868

849869
let get_by_name context ~dbg ~name = assert false

ocaml/xapi/storage_impl.ml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -522,16 +522,19 @@ module Wrapper = functor(Impl: Server_impl) -> struct
522522
Impl.VDI.resize context ~dbg ~sr ~vdi ~new_size
523523
)
524524

525-
let destroy context ~dbg ~sr ~vdi =
526-
info "VDI.destroy dbg:%s sr:%s vdi:%s" dbg sr vdi;
525+
let destroy_and_data_destroy call_name call_f context ~dbg ~sr ~vdi =
526+
info "%s dbg:%s sr:%s vdi:%s" call_name dbg sr vdi;
527527
with_vdi sr vdi
528528
(fun () ->
529529
remove_datapaths_andthen_nolock context ~dbg ~sr ~vdi Vdi.all
530530
(fun () ->
531-
Impl.VDI.destroy context ~dbg ~sr ~vdi
531+
call_f context ~dbg ~sr ~vdi
532532
)
533533
)
534534

535+
let destroy = destroy_and_data_destroy "VDI.destroy" Impl.VDI.destroy
536+
let data_destroy = destroy_and_data_destroy "VDI.data_destroy" Impl.VDI.data_destroy
537+
535538
let stat context ~dbg ~sr ~vdi =
536539
info "VDI.stat dbg:%s sr:%s vdi:%s" dbg sr vdi;
537540
Impl.VDI.stat context ~dbg ~sr ~vdi
@@ -589,6 +592,14 @@ module Wrapper = functor(Impl: Server_impl) -> struct
589592
Impl.VDI.disable_cbt context ~dbg ~sr ~vdi
590593
)
591594

595+
(** The [sr] parameter is the SR of VDI [vdi_to]. *)
596+
let export_changed_blocks context ~dbg ~sr ~vdi_from ~vdi_to =
597+
info "VDI.export_changed_blocks dbg:%s sr:%s vdi_from:%s vdi_to:%s" dbg sr vdi_from vdi_to;
598+
with_vdi sr vdi_to
599+
(fun () ->
600+
Impl.VDI.export_changed_blocks context ~dbg ~sr ~vdi_from ~vdi_to
601+
)
602+
592603
end
593604

594605
let get_by_name context ~dbg ~name =

0 commit comments

Comments
 (0)