Skip to content

Commit 3468d4b

Browse files
committed
Allow selection of image format during migration
This patch allows specifying the destination format for individual VDIs mapped to a destination SR. It adds a new parameter to `VM.migrate_send` and `VM.assert_can_migrate` API. It also adds a new parameter to XE CLI. The format to specify the image format is `image-format:<source VDI UUID>=<destination image format>`. If the given image format cannot be validated, an error is returned. It also adds a new parameter to `VDI.pool-migrate`. This new parameter allows to provide a string that is the destination format. This string is used to check whether the destination SR supports the expected format. If the check fails or cannot be performed due to missing information on the destination SR, an error is returned. Signed-off-by: Guillaume <[email protected]>
1 parent 05e08aa commit 3468d4b

18 files changed

+371
-153
lines changed

ocaml/idl/datamodel.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5443,6 +5443,10 @@ module VDI = struct
54435443
[
54445444
(Ref _vdi, "vdi", "The VDI to migrate")
54455445
; (Ref _sr, "sr", "The destination SR")
5446+
; ( String
5447+
, "dest_img_format"
5448+
, "The image format to use on destination SR"
5449+
)
54465450
; (Map (String, String), "options", "Other parameters")
54475451
]
54485452
~result:(Ref _vdi, "The new reference of the migrated VDI.")

ocaml/idl/datamodel_vm.ml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,6 +1714,13 @@ let migrate_send =
17141714
; param_release= inverness_release
17151715
; param_default= Some (VMap [])
17161716
}
1717+
; {
1718+
param_type= Map (Ref _vdi, String)
1719+
; param_name= "vdi_format_map"
1720+
; param_doc= "Map of source VDI to it's expected type on destination"
1721+
; param_release= numbered_release "25.24.0-next"
1722+
; param_default= Some (VMap [])
1723+
}
17171724
]
17181725
~result:
17191726
(Ref _vm, "The reference of the newly created VM in the destination pool")
@@ -1781,6 +1788,13 @@ let assert_can_migrate =
17811788
; param_release= inverness_release
17821789
; param_default= Some (VMap [])
17831790
}
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+
}
17841798
]
17851799
~allowed_roles:_R_VM_POWER_ADMIN
17861800
~errs:[Api_errors.license_restriction]

ocaml/xapi-cli-server/cli_frontend.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2468,10 +2468,10 @@ let rec cmdtable_data : (string * cmd_spec) list =
24682468
; ( "vdi-pool-migrate"
24692469
, {
24702470
reqd= ["uuid"; "sr-uuid"]
2471-
; optn= []
2471+
; optn= ["dest-img-format"]
24722472
; help=
2473-
"Migrate a VDI to a specified SR, while the VDI is attached to a \
2474-
running guest."
2473+
"Migrate a VDI to a specified SR, while it is attached to a running \
2474+
guest. You can specify the image format for the destination."
24752475
; implementation= No_fd Cli_operations.vdi_pool_migrate
24762476
; flags= []
24772477
}

ocaml/xapi-cli-server/cli_operations.ml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,8 +2064,12 @@ let vdi_pool_migrate printer rpc session_id params =
20642064
Client.VDI.get_by_uuid ~rpc ~session_id ~uuid:(List.assoc "uuid" params)
20652065
and sr =
20662066
Client.SR.get_by_uuid ~rpc ~session_id ~uuid:(List.assoc "sr-uuid" params)
2067+
and dest_img_format =
2068+
List.assoc_opt "dest-img-format" params |> Option.value ~default:""
20672069
and options = [] (* no options implemented yet *) in
2068-
let newvdi = Client.VDI.pool_migrate ~rpc ~session_id ~vdi ~sr ~options in
2070+
let newvdi =
2071+
Client.VDI.pool_migrate ~rpc ~session_id ~vdi ~sr ~dest_img_format ~options
2072+
in
20692073
let newuuid = Client.VDI.get_uuid ~rpc ~session_id ~self:newvdi in
20702074
printer (Cli_printer.PList [newuuid])
20712075

@@ -4592,6 +4596,7 @@ let vm_migrate_sxm_params =
45924596
; "remote-network"
45934597
; "vdi"
45944598
; "vgpu"
4599+
; "image-format"
45954600
]
45964601

45974602
let vm_migrate printer rpc session_id params =
@@ -4896,12 +4901,24 @@ let vm_migrate printer rpc session_id params =
48964901
let token =
48974902
remote Client.Host.migrate_receive ~host ~network ~options
48984903
in
4904+
let vdi_format_map =
4905+
List.map
4906+
(fun (vdi_uuid, vdi_fmt) ->
4907+
let vdi =
4908+
Client.VDI.get_by_uuid ~rpc ~session_id ~uuid:vdi_uuid
4909+
in
4910+
debug "GTNDEBUG: add image format %s,%s" vdi_uuid vdi_fmt ;
4911+
(vdi, vdi_fmt)
4912+
)
4913+
(read_map_params "image-format" params)
4914+
in
48994915
let new_vm =
49004916
do_vm_op ~include_control_vms:false ~include_template_vms:true printer
49014917
rpc session_id
49024918
(fun vm ->
49034919
Client.VM.migrate_send ~rpc ~session_id ~vm:(vm.getref ())
4904-
~dest:token ~live:true ~vdi_map ~vif_map ~options ~vgpu_map
4920+
~dest:token ~live:true ~vdi_map ~vdi_format_map ~vif_map
4921+
~options ~vgpu_map
49054922
)
49064923
params
49074924
(["host"; "host-uuid"; "host-name"; "live"; "force"; "copy"]

ocaml/xapi-idl/storage/storage_interface.ml

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ let string_of_vdi_info (x : vdi_info) = Jsonrpc.to_string (rpc_of vdi_info x)
264264
"datapaths". *)
265265
type dp = string [@@deriving rpcty]
266266

267+
type image_format_t = string [@@deriving rpcty]
268+
267269
type sock_path = string [@@deriving rpcty]
268270

269271
type dp_stat_t = {
@@ -1035,6 +1037,8 @@ module StorageAPI (R : RPC) = struct
10351037
declare "get_by_name" [] (dbg_p @-> name_p @-> returning result_p err)
10361038

10371039
module DATA = struct
1040+
let image_format_p = Param.mk ~name:"image_format" image_format_t
1041+
10381042
let url_p = Param.mk ~name:"url" Types.string
10391043

10401044
let dest_p = Param.mk ~name:"dest" Sr.t
@@ -1066,6 +1070,7 @@ module StorageAPI (R : RPC) = struct
10661070
(dbg_p
10671071
@-> sr_p
10681072
@-> vdi_p
1073+
@-> image_format_p
10691074
@-> vm_p
10701075
@-> url_p
10711076
@-> returning operation_p err
@@ -1109,6 +1114,8 @@ module StorageAPI (R : RPC) = struct
11091114
)
11101115

11111116
module MIRROR = struct
1117+
let image_format_p = Param.mk ~name:"image_format" image_format_t
1118+
11121119
let mirror_vm_p = Param.mk ~name:"mirror_vm" Vm.t
11131120

11141121
let copy_vm_p = Param.mk ~name:"copy_vm" Vm.t
@@ -1117,7 +1124,7 @@ module StorageAPI (R : RPC) = struct
11171124

11181125
let id_p = Param.mk ~name:"id" Mirror.id
11191126

1120-
(** [send_start dbg dp task src_sr vdi mirror_vm mirror_id local_vdi copy_vm
1127+
(** [send_start dbg dp task src_sr vdi image_format mirror_vm mirror_id local_vdi copy_vm
11211128
live_vm url remote_mirror dest_sr verify_dest]
11221129
takes the remote mirror [remote_mirror] prepared by the destination host
11231130
and initiates the mirroring of [vdi] from the source *)
@@ -1134,6 +1141,7 @@ module StorageAPI (R : RPC) = struct
11341141
@-> task_id_p
11351142
@-> src_sr_p
11361143
@-> vdi_p
1144+
@-> image_format_p
11371145
@-> mirror_vm_p
11381146
@-> id_p
11391147
@-> local_vdi_p
@@ -1159,6 +1167,7 @@ module StorageAPI (R : RPC) = struct
11591167
@-> sr_p
11601168
@-> VDI.vdi_info_p
11611169
@-> id_p
1170+
@-> image_format_p
11621171
@-> similar_p
11631172
@-> returning result err
11641173
)
@@ -1176,6 +1185,7 @@ module StorageAPI (R : RPC) = struct
11761185
@-> sr_p
11771186
@-> VDI.vdi_info_p
11781187
@-> id_p
1188+
@-> image_format_p
11791189
@-> similar_p
11801190
@-> vm_p
11811191
@-> returning result err
@@ -1191,6 +1201,7 @@ module StorageAPI (R : RPC) = struct
11911201
@-> sr_p
11921202
@-> VDI.vdi_info_p
11931203
@-> id_p
1204+
@-> image_format_p
11941205
@-> similar_p
11951206
@-> vm_p
11961207
@-> url_p
@@ -1320,6 +1331,7 @@ module type MIRROR = sig
13201331
-> dp:dp
13211332
-> sr:sr
13221333
-> vdi:vdi
1334+
-> image_format:string
13231335
-> mirror_vm:vm
13241336
-> mirror_id:Mirror.id
13251337
-> local_vdi:vdi_info
@@ -1337,6 +1349,7 @@ module type MIRROR = sig
13371349
-> sr:sr
13381350
-> vdi_info:vdi_info
13391351
-> id:Mirror.id
1352+
-> image_format:string
13401353
-> similar:Mirror.similars
13411354
-> Mirror.mirror_receive_result
13421355

@@ -1346,6 +1359,7 @@ module type MIRROR = sig
13461359
-> sr:sr
13471360
-> vdi_info:vdi_info
13481361
-> id:Mirror.id
1362+
-> image_format:string
13491363
-> similar:Mirror.similars
13501364
-> vm:vm
13511365
-> Mirror.mirror_receive_result
@@ -1356,6 +1370,7 @@ module type MIRROR = sig
13561370
-> sr:sr
13571371
-> vdi_info:vdi_info
13581372
-> mirror_id:Mirror.id
1373+
-> image_format:string
13591374
-> similar:Mirror.similars
13601375
-> vm:vm
13611376
-> url:string
@@ -1657,6 +1672,7 @@ module type Server_impl = sig
16571672
-> dbg:debug_info
16581673
-> sr:sr
16591674
-> vdi:vdi
1675+
-> image_format:string
16601676
-> vm:vm
16611677
-> dest:string
16621678
-> operation
@@ -1844,8 +1860,8 @@ module Server (Impl : Server_impl) () = struct
18441860
S.DATA.copy (fun dbg sr vdi vm url dest verify_dest ->
18451861
Impl.DATA.copy () ~dbg ~sr ~vdi ~vm ~url ~dest ~verify_dest
18461862
) ;
1847-
S.DATA.mirror (fun dbg sr vdi vm dest ->
1848-
Impl.DATA.mirror () ~dbg ~sr ~vdi ~vm ~dest
1863+
S.DATA.mirror (fun dbg sr vdi image_format vm dest ->
1864+
Impl.DATA.mirror () ~dbg ~sr ~vdi ~image_format ~vm ~dest
18491865
) ;
18501866
S.DATA.stat (fun dbg sr vdi vm key ->
18511867
Impl.DATA.stat () ~dbg ~sr ~vdi ~vm ~key
@@ -1857,6 +1873,7 @@ module Server (Impl : Server_impl) () = struct
18571873
dp
18581874
sr
18591875
vdi
1876+
image_format
18601877
mirror_vm
18611878
mirror_id
18621879
local_vdi
@@ -1867,20 +1884,23 @@ module Server (Impl : Server_impl) () = struct
18671884
dest_sr
18681885
verify_dest
18691886
->
1870-
Impl.DATA.MIRROR.send_start () ~dbg ~task_id ~dp ~sr ~vdi ~mirror_vm
1871-
~mirror_id ~local_vdi ~copy_vm ~live_vm ~url ~remote_mirror ~dest_sr
1872-
~verify_dest
1887+
Impl.DATA.MIRROR.send_start () ~dbg ~task_id ~dp ~sr ~vdi ~image_format
1888+
~mirror_vm ~mirror_id ~local_vdi ~copy_vm ~live_vm ~url ~remote_mirror
1889+
~dest_sr ~verify_dest
18731890
) ;
1874-
S.DATA.MIRROR.receive_start (fun dbg sr vdi_info id similar ->
1875-
Impl.DATA.MIRROR.receive_start () ~dbg ~sr ~vdi_info ~id ~similar
1891+
S.DATA.MIRROR.receive_start (fun dbg sr vdi_info id image_format similar ->
1892+
Impl.DATA.MIRROR.receive_start () ~dbg ~sr ~vdi_info ~id ~image_format
1893+
~similar
18761894
) ;
1877-
S.DATA.MIRROR.receive_start2 (fun dbg sr vdi_info id similar vm ->
1878-
Impl.DATA.MIRROR.receive_start2 () ~dbg ~sr ~vdi_info ~id ~similar ~vm
1895+
S.DATA.MIRROR.receive_start2
1896+
(fun dbg sr vdi_info id image_format similar vm ->
1897+
Impl.DATA.MIRROR.receive_start2 () ~dbg ~sr ~vdi_info ~id ~image_format
1898+
~similar ~vm
18791899
) ;
18801900
S.DATA.MIRROR.receive_start3
1881-
(fun dbg sr vdi_info mirror_id similar vm url verify_dest ->
1901+
(fun dbg sr vdi_info mirror_id image_format similar vm url verify_dest ->
18821902
Impl.DATA.MIRROR.receive_start3 () ~dbg ~sr ~vdi_info ~mirror_id
1883-
~similar ~vm ~url ~verify_dest
1903+
~image_format ~similar ~vm ~url ~verify_dest
18841904
) ;
18851905
S.DATA.MIRROR.receive_cancel (fun dbg id ->
18861906
Impl.DATA.MIRROR.receive_cancel () ~dbg ~id

ocaml/xapi-idl/storage/storage_skeleton.ml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ module DATA = struct
183183
let copy ctx ~dbg ~sr ~vdi ~vm ~url ~dest =
184184
Storage_interface.unimplemented __FUNCTION__
185185

186-
let mirror ctx ~dbg ~sr ~vdi ~vm ~dest =
186+
let mirror ctx ~dbg ~sr ~vdi ~image_format ~vm ~dest =
187187
Storage_interface.unimplemented __FUNCTION__
188188

189189
let stat ctx ~dbg ~sr ~vdi ~vm ~key =
@@ -198,18 +198,19 @@ module DATA = struct
198198
module MIRROR = struct
199199
type context = unit
200200

201-
let send_start ctx ~dbg ~task_id ~dp ~sr ~vdi ~mirror_vm ~mirror_id
202-
~local_vdi ~copy_vm ~live_vm ~url ~remote_mirror ~dest_sr ~verify_dest =
201+
let send_start ctx ~dbg ~task_id ~dp ~sr ~vdi ~image_format ~mirror_vm
202+
~mirror_id ~local_vdi ~copy_vm ~live_vm ~url ~remote_mirror ~dest_sr
203+
~verify_dest =
203204
Storage_interface.unimplemented __FUNCTION__
204205

205-
let receive_start ctx ~dbg ~sr ~vdi_info ~id ~similar =
206+
let receive_start ctx ~dbg ~sr ~vdi_info ~id ~image_format ~similar =
206207
Storage_interface.unimplemented __FUNCTION__
207208

208-
let receive_start2 ctx ~dbg ~sr ~vdi_info ~id ~similar ~vm =
209+
let receive_start2 ctx ~dbg ~sr ~vdi_info ~id ~image_format ~similar ~vm =
209210
Storage_interface.unimplemented __FUNCTION__
210211

211-
let receive_start3 ctx ~dbg ~sr ~vdi_info ~mirror_id ~similar ~vm ~url
212-
~verify_dest =
212+
let receive_start3 ctx ~dbg ~sr ~vdi_info ~mirror_id ~image_format ~similar
213+
~vm ~url ~verify_dest =
213214
Storage_interface.unimplemented __FUNCTION__
214215

215216
let receive_finalize ctx ~dbg ~id =

ocaml/xapi-storage-cli/main.ml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,16 +317,19 @@ let copy_vm = Vm.of_string "SXM_copy"
317317

318318
let live_vm = Vm.of_string "live_vm"
319319

320-
let mirror_start common_opts sr vdi dp url dest verify_dest =
320+
let mirror_start common_opts sr vdi dp url dest verify_dest dest_img_format =
321321
on_vdi'
322322
(fun sr vdi ->
323323
let get_opt x err = match x with Some y -> y | None -> failwith err in
324324
let dp = get_opt dp "Need a local data path" in
325325
let url = get_opt url "Need a URL" in
326326
let dest = get_opt dest "Need a destination SR" in
327+
let image_format =
328+
match dest_img_format with Some s -> s | None -> ""
329+
in
327330
let task =
328-
Storage_migrate.start ~dbg ~sr ~vdi ~dp ~mirror_vm ~copy_vm ~live_vm
329-
~url
331+
Storage_migrate.start ~dbg ~sr ~vdi ~image_format ~dp ~mirror_vm
332+
~copy_vm ~live_vm ~url
330333
~dest:(Storage_interface.Sr.of_string dest)
331334
~verify_dest
332335
in
@@ -531,6 +534,10 @@ let mirror_start_cmd =
531534
let doc = "Verify certicate of remote server" in
532535
Arg.(value & pos 5 bool false & info [] ~docv:"VERIFYDEST" ~doc)
533536
in
537+
let dest_img_format =
538+
let doc = "Specify the image format on the destination SR" in
539+
Arg.(value & pos 6 (some string) None & info [] ~docv:"IMAGEFORMAT" ~doc)
540+
in
534541
( Term.(
535542
ret
536543
(const mirror_start
@@ -541,6 +548,7 @@ let mirror_start_cmd =
541548
$ url
542549
$ dest
543550
$ verify_dest
551+
$ dest_img_format
544552
)
545553
)
546554
, Cmd.info "mirror-start" ~sdocs:_common_options ~doc ~man

ocaml/xapi-storage-script/main.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,7 +1817,7 @@ module DATAImpl (M : META) = struct
18171817

18181818
let stat_impl dbg sr vdi vm key = wrap @@ stat dbg sr vdi vm key
18191819

1820-
let mirror dbg sr vdi' vm' remote =
1820+
let mirror dbg sr vdi' image_format vm' remote =
18211821
let vdi = Storage_interface.Vdi.string_of vdi' in
18221822
let domain = Storage_interface.Vm.string_of vm' in
18231823
Attached_SRs.find sr >>>= fun sr ->
@@ -1841,7 +1841,8 @@ module DATAImpl (M : META) = struct
18411841
| MirrorV1 v ->
18421842
return (Storage_interface.Mirror.MirrorV1 v)
18431843

1844-
let mirror_impl dbg sr vdi vm remote = wrap @@ mirror dbg sr vdi vm remote
1844+
let mirror_impl dbg sr vdi image_format vm remote =
1845+
wrap @@ mirror dbg sr vdi image_format vm remote
18451846

18461847
let data_import_activate_impl dbg _dp sr vdi' vm' =
18471848
wrap

0 commit comments

Comments
 (0)