Skip to content

Commit dbfc215

Browse files
committed
fixup! Allow selection of image format during migration
1 parent e28d763 commit dbfc215

File tree

7 files changed

+103
-82
lines changed

7 files changed

+103
-82
lines changed

ocaml/idl/datamodel.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5456,7 +5456,7 @@ module VDI = struct
54565456
; (Ref _sr, "sr", "The destination SR")
54575457
; ( String
54585458
, "dest_img_format"
5459-
, "The image format to use on destination SR"
5459+
, "The image format to use on destination SR: raw, vhd, qcow2"
54605460
)
54615461
; (Map (String, String), "options", "Other parameters")
54625462
]

ocaml/idl/datamodel_vm.ml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,7 @@ let migrate_send =
17181718
param_type= Map (Ref _vdi, String)
17191719
; param_name= "vdi_format_map"
17201720
; param_doc= "Map of source VDI to it's expected type on destination"
1721-
; param_release= numbered_release "25.24.0-next"
1721+
; param_release= numbered_release "25.33.0-next"
17221722
; param_default= Some (VMap [])
17231723
}
17241724
]
@@ -1788,13 +1788,6 @@ let assert_can_migrate =
17881788
; param_release= inverness_release
17891789
; param_default= Some (VMap [])
17901790
}
1791-
; {
1792-
param_type= Map (Ref _vdi, String)
1793-
; param_name= "vdi_format_map"
1794-
; param_doc= "Map of source VDI to it's expected type on destination"
1795-
; param_release= numbered_release "25.24.0-next"
1796-
; param_default= Some (VMap [])
1797-
}
17981791
]
17991792
~allowed_roles:_R_VM_POWER_ADMIN
18001793
~errs:[Api_errors.license_restriction]

ocaml/xapi-cli-server/cli_frontend.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,7 @@ let rec cmdtable_data : (string * cmd_spec) list =
16131613
; "compress"
16141614
; "vif:"
16151615
; "vdi:"
1616+
; "image-format:"
16161617
]
16171618
; help=
16181619
"Migrate the selected VM(s). The parameter '--live' will migrate the \
@@ -1626,7 +1627,9 @@ let rec cmdtable_data : (string * cmd_spec) list =
16261627
'copy=true' will enable the copy mode so that a stopped vm can be \
16271628
copied, instead of migrating, to the destination pool. The vif and \
16281629
vdi mapping parameters take the form 'vif:<source vif uuid>=<dest \
1629-
network uuid>' and 'vdi:<source vdi uuid>=<dest sr uuid>'. \
1630+
network uuid>' and 'vdi:<source vdi uuid>=<dest sr uuid>'. You can \
1631+
also specify the destination image format of the VDI using \
1632+
'image-format:<source vdi uuid>=<destination image format>'. \
16301633
Unfortunately, destination uuids cannot be tab-completed."
16311634
; implementation= No_fd Cli_operations.vm_migrate
16321635
; flags= [Standard; Vm_selectors]

ocaml/xapi-cli-server/cli_operations.ml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4907,7 +4907,6 @@ let vm_migrate printer rpc session_id params =
49074907
let vdi =
49084908
Client.VDI.get_by_uuid ~rpc ~session_id ~uuid:vdi_uuid
49094909
in
4910-
debug "GTNDEBUG: add image format %s,%s" vdi_uuid vdi_fmt ;
49114910
(vdi, vdi_fmt)
49124911
)
49134912
(read_map_params "image-format" params)

ocaml/xapi-storage-script/main.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,6 +1818,8 @@ module DATAImpl (M : META) = struct
18181818
let stat_impl dbg sr vdi vm key = wrap @@ stat dbg sr vdi vm key
18191819

18201820
let mirror dbg sr vdi' image_format vm' remote =
1821+
let _ = image_format in
1822+
(* TODO: really use image format *)
18211823
let vdi = Storage_interface.Vdi.string_of vdi' in
18221824
let domain = Storage_interface.Vm.string_of vm' in
18231825
Attached_SRs.find sr >>>= fun sr ->

ocaml/xapi/message_forwarding.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,11 +2545,11 @@ functor
25452545
assuming it can ignore this check."
25462546

25472547
let assert_can_migrate ~__context ~vm ~dest ~live ~vdi_map ~vif_map
2548-
~options ~vgpu_map ~vdi_format_map =
2548+
~options ~vgpu_map =
25492549
info "VM.assert_can_migrate: VM = '%s'" (vm_uuid ~__context vm) ;
25502550
(* Run the checks that can be done using just the DB directly on the master *)
2551-
Local.VM.assert_can_migrate ~__context ~vm ~dest ~live ~vdi_map
2552-
~vdi_format_map ~vif_map ~vgpu_map ~options ;
2551+
Local.VM.assert_can_migrate ~__context ~vm ~dest ~live ~vdi_map ~vif_map
2552+
~vgpu_map ~options ;
25532553
(* Run further checks on the sending host *)
25542554
assert_can_migrate_sender ~__context ~vm ~dest ~live ~vdi_map ~vif_map
25552555
~vgpu_map ~options
@@ -2625,7 +2625,7 @@ functor
26252625
Server_helpers.exec_with_subtask ~__context
26262626
"VM.assert_can_migrate" (fun ~__context ->
26272627
assert_can_migrate ~__context ~vm ~dest ~live ~vdi_map
2628-
~vdi_format_map ~vif_map ~vgpu_map ~options
2628+
~vif_map ~vgpu_map ~options
26292629
) ;
26302630
if Db.VM.get_VGPUs ~__context ~self:vm <> [] then
26312631
Xapi_stats.incr_pool_vgpu_migration_count () ;

ocaml/xapi/xapi_vm_migrate.ml

Lines changed: 91 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -216,62 +216,91 @@ let assert_sr_support_operations ~__context ~vdi_map ~remote ~local_ops
216216
op_supported_on_dest_sr sr remote_ops sm_record remote
217217
)
218218

219+
(** [check_supported_image_format] checks that the [image_format] string
220+
corresponds to valid image format type listed in [sm_formats].
221+
If [sm_formats] is an empty list or [image_format] is an empty string
222+
there function does nothing. Otherwise, if [image_format] is not found
223+
in [sm_formats], an exception is raised. *)
224+
let check_supported_image_format ~image_format ~sm_formats ~sr_uuid =
225+
if image_format = "" || sm_formats = [] then
226+
()
227+
else
228+
let ty = Record_util.image_format_type_of_string image_format in
229+
if not (List.mem ty sm_formats) then
230+
let msg =
231+
Printf.sprintf "Image format %s is not supported by %s" image_format
232+
sr_uuid
233+
in
234+
raise Api_errors.(Server_error (vdi_incompatible_type, [msg]))
235+
219236
(** [assert_vdi_format_is_supported] checks that all VDIs in [vdi_map] are included in the list of
220237
supported image format of their corresponding SM. The type of the VDI is found in [vdi_format_map].
221238
- If no VDI type is specified we just returned so no error is raised.
222239
- If an SM reports an empty list of supported formats, we cannot verify compatibility and no error
223240
is raised. So if the format is not actually supported, the failure will be detected later when
224241
attempting to create the VDI using that image format. *)
225-
let assert_vdi_format_is_supported ~__context ~vdi_map ~vdi_format_map =
242+
let assert_vdi_format_is_supported ~__context ~remote_opt ~vdi_map
243+
~vdi_format_map =
244+
let get_uuid_sr sr_ref =
245+
match remote_opt with
246+
| None ->
247+
Db.SR.get_uuid ~__context ~self:sr_ref
248+
| Some r ->
249+
XenAPI.SR.get_uuid ~rpc:r.rpc ~session_id:r.session ~self:sr_ref
250+
in
251+
let get_sr_type sr_ref =
252+
match remote_opt with
253+
| None ->
254+
Db.SR.get_type ~__context ~self:sr_ref
255+
| Some r ->
256+
XenAPI.SR.get_type ~rpc:r.rpc ~session_id:r.session ~self:sr_ref
257+
in
258+
let get_sm_refs sr_type =
259+
match remote_opt with
260+
| None ->
261+
Db.SM.get_refs_where ~__context
262+
~expr:(Eq (Field "type", Literal sr_type))
263+
| Some r ->
264+
XenAPI.SM.get_all_where ~rpc:r.rpc ~session_id:r.session
265+
~expr:(Printf.sprintf {|(field "type"="%s")|} sr_type)
266+
in
267+
let get_sm_formats sm_ref =
268+
match remote_opt with
269+
| None ->
270+
Db.SM.get_supported_image_formats ~__context ~self:sm_ref
271+
| Some r ->
272+
XenAPI.SM.get_supported_image_formats ~rpc:r.rpc ~session_id:r.session
273+
~self:sm_ref
274+
in
226275
List.iter
227276
(fun (vdi_ref, sr_ref) ->
228277
let vdi_uuid = Db.VDI.get_uuid ~__context ~self:vdi_ref in
229-
let sr_uuid = Db.SR.get_uuid ~__context ~self:sr_ref in
278+
let sr_uuid = get_uuid_sr sr_ref in
230279
match List.assoc_opt vdi_ref vdi_format_map with
231280
| None ->
232-
debug "GTNDEBUG: read vdi %s, sr %s. No type specified for the VDI"
233-
vdi_uuid sr_uuid
234-
| Some ty -> (
281+
debug "read vdi %s, sr %s. No type specified." vdi_uuid sr_uuid
282+
| Some image_format -> (
283+
debug "GTNDEBUG: within assert vdi format is supported" ;
235284
(* To get the supported image format from SM we need the SR type because both have
236285
the same type. *)
237-
let sr_type = Db.SR.get_type ~__context ~self:sr_ref in
238-
let sm_refs =
239-
Db.SM.get_refs_where ~__context
240-
~expr:(Eq (Field "type", Literal sr_type))
241-
in
286+
let sr_type = get_sr_type sr_ref in
287+
debug "GTNDEBUG: SR has type %s" sr_type ;
288+
let sm_refs = get_sm_refs sr_type in
242289
(* We expect that one sr_type matches one sm_ref *)
243290
match sm_refs with
244291
| [sm_ref] ->
245-
debug "GTNDEBUG: read vdi %s, sr %s. Type is %s" vdi_uuid sr_uuid
246-
ty ;
247-
let sm_formats =
248-
Db.SM.get_supported_image_formats ~__context ~self:sm_ref
249-
in
250-
if ty <> "" && sm_formats <> [] && not (List.mem ty sm_formats)
251-
then
252-
raise
253-
Api_errors.(
254-
Server_error
255-
( vdi_incompatible_type
256-
, [
257-
Printf.sprintf
258-
"Image format %s is not supported by %s" ty sr_uuid
259-
]
260-
)
261-
)
292+
debug "read vdi %s, sr %s. Type is %s" vdi_uuid sr_uuid
293+
image_format ;
294+
let sm_formats = get_sm_formats sm_ref in
295+
check_supported_image_format ~image_format ~sm_formats ~sr_uuid
262296
| _ ->
263-
raise
264-
Api_errors.(
265-
Server_error
266-
( vdi_incompatible_type
267-
, [
268-
Printf.sprintf
269-
"Found more than one SM ref (%d) when checking type \
270-
(%s) of VDI."
271-
(List.length sm_refs) ty
272-
]
273-
)
274-
)
297+
let msg =
298+
Printf.sprintf
299+
"Found more than one SM ref (%d) when checking type (%s) of \
300+
VDI."
301+
(List.length sm_refs) image_format
302+
in
303+
raise Api_errors.(Server_error (vdi_incompatible_type, [msg]))
275304
)
276305
)
277306
vdi_map
@@ -281,7 +310,7 @@ let assert_vdi_format_is_supported ~__context ~vdi_map ~vdi_format_map =
281310
[vdi_map], which contains all the VDIs of the VM.
282311
[check_vdi_map] should be called before this function to verify that this
283312
is the case. *)
284-
let assert_can_migrate_vdis ~__context ~vdi_map ~vdi_format_map =
313+
let assert_can_migrate_vdis ~__context ~vdi_map =
285314
let assert_cbt_not_enabled vdi =
286315
if Db.VDI.get_cbt_enabled ~__context ~self:vdi then
287316
raise Api_errors.(Server_error (vdi_cbt_enabled, [Ref.string_of vdi]))
@@ -291,7 +320,6 @@ let assert_can_migrate_vdis ~__context ~vdi_map ~vdi_format_map =
291320
if List.exists (fun (key, _value) -> key = "key_hash") sm_config then
292321
raise Api_errors.(Server_error (vdi_is_encrypted, [Ref.string_of vdi]))
293322
in
294-
assert_vdi_format_is_supported ~__context ~vdi_map ~vdi_format_map ;
295323
List.iter
296324
(fun (vdi, target_sr) ->
297325
if target_sr <> Db.VDI.get_SR ~__context ~self:vdi then (
@@ -792,27 +820,22 @@ let update_snapshot_info ~__context ~dbg ~url ~vdi_map ~snapshots_map
792820
debug "Remote SMAPI doesn't implement update_snapshot_info_src - ignoring"
793821

794822
type vdi_mirror = {
795-
vdi: [`VDI] API.Ref.t
796-
; (* The API reference of the local VDI *)
797-
format: string
798-
; (* The image format of the VDI the must be used during its creation *)
799-
dp: string
800-
; (* The datapath the VDI will be using if the VM is running *)
801-
location: Storage_interface.Vdi.t
802-
; (* The location of the VDI in the current SR *)
803-
sr: Storage_interface.Sr.t
804-
; (* The VDI's current SR uuid *)
805-
xenops_locator: string
806-
; (* The 'locator' xenops uses to refer to the VDI on the current host *)
807-
size: Int64.t
808-
; (* Size of the VDI *)
809-
snapshot_of: [`VDI] API.Ref.t
810-
; (* API's snapshot_of reference *)
811-
do_mirror: bool (* Whether we should mirror or just copy the VDI *)
823+
vdi: [`VDI] API.Ref.t (** The API reference of the local VDI *)
824+
; format: string
825+
(** The image format of the VDI that must be used during its creation *)
826+
; dp: string (** The datapath the VDI will be using if the VM is running *)
827+
; location: Storage_interface.Vdi.t
828+
(** The location of the VDI in the current SR *)
829+
; sr: Storage_interface.Sr.t (** The VDI's current SR uuid *)
830+
; xenops_locator: string
831+
(** The 'locator' xenops uses to refer to the VDI on the current host *)
832+
; size: Int64.t (** Size of the VDI *)
833+
; snapshot_of: [`VDI] API.Ref.t (** API's snapshot_of reference *)
834+
; do_mirror: bool (** Whether we should mirror or just copy the VDI *)
812835
; mirror_vm: Vm.t
813-
(* The domain slice to which SMAPI calls should be made when mirroring this vdi *)
836+
(** The domain slice to which SMAPI calls should be made when mirroring this vdi *)
814837
; copy_vm: Vm.t
815-
(* The domain slice to which SMAPI calls should be made when copying this vdi *)
838+
(** The domain slice to which SMAPI calls should be made when copying this vdi *)
816839
}
817840

818841
(* For VMs (not snapshots) xenopsd does not allow remapping, so we
@@ -1469,7 +1492,7 @@ let migrate_send' ~__context ~vm ~dest ~live:_ ~vdi_map ~vdi_format_map ~vif_map
14691492
let all_vdis =
14701493
List.map
14711494
(fun vm ->
1472-
match get_vdi_type vm.vdi vdi_format_map with
1495+
match get_vdi_type ~vdi_ref:vm.vdi ~vdi_format_map with
14731496
| None ->
14741497
vm
14751498
| Some vdi_ty ->
@@ -1480,7 +1503,9 @@ let migrate_send' ~__context ~vm ~dest ~live:_ ~vdi_map ~vdi_format_map ~vif_map
14801503
in
14811504
(* This is a good time to check our VDIs, because the vdi_map should be
14821505
complete at this point; it should include all the VDIs in the all_vdis list. *)
1483-
assert_can_migrate_vdis ~__context ~vdi_map ~vdi_format_map ;
1506+
assert_can_migrate_vdis ~__context ~vdi_map ;
1507+
let remote_opt = if is_same_host then None else Some remote in
1508+
assert_vdi_format_is_supported ~__context ~remote_opt ~vdi_map ~vdi_format_map ;
14841509
let dbg = Context.string_of_task_and_tracing __context in
14851510
let open Xapi_xenops_queue in
14861511
let queue_name = queue_of_vm ~__context ~self:vm in
@@ -1859,7 +1884,7 @@ let migration_type ~__context ~remote =
18591884
`cross_pool
18601885

18611886
let assert_can_migrate ~__context ~vm ~dest ~live:_ ~vdi_map ~vif_map ~options
1862-
~vgpu_map ~vdi_format_map =
1887+
~vgpu_map =
18631888
Xapi_vm_helpers.assert_no_legacy_hardware ~__context ~vm ;
18641889
assert_licensed_storage_motion ~__context ;
18651890
let remote = remote_of_dest ~__context dest in
@@ -2020,7 +2045,7 @@ let assert_can_migrate ~__context ~vm ~dest ~live:_ ~vdi_map ~vif_map ~options
20202045
(* Previously there was also a check that none of the VDIs have CBT enabled.
20212046
This is unnecessary, we only need to check that none of the VDIs that
20222047
*will be moved* have CBT enabled. *)
2023-
assert_can_migrate_vdis ~__context ~vdi_map ~vdi_format_map
2048+
assert_can_migrate_vdis ~__context ~vdi_map
20242049

20252050
let assert_can_migrate_sender ~__context ~vm ~dest ~live:_ ~vdi_map:_ ~vif_map:_
20262051
~vgpu_map ~options:_ =
@@ -2131,9 +2156,8 @@ let vdi_pool_migrate ~__context ~vdi ~sr ~dest_img_format ~options =
21312156
XenAPI.Host.migrate_receive ~rpc ~session_id ~host:dest_host ~network
21322157
~options
21332158
in
2134-
assert_can_migrate ~__context ~vm ~dest ~live:true ~vdi_map
2135-
~vdi_format_map:[(vdi, dest_img_format)]
2136-
~vif_map:[] ~vgpu_map:[] ~options:[] ;
2159+
assert_can_migrate ~__context ~vm ~dest ~live:true ~vdi_map ~vif_map:[]
2160+
~vgpu_map:[] ~options:[] ;
21372161
assert_can_migrate_sender ~__context ~vm ~dest ~live:true ~vdi_map
21382162
~vif_map:[] ~vgpu_map:[] ~options:[] ;
21392163
ignore

0 commit comments

Comments
 (0)