Skip to content

Commit aa7e2dd

Browse files
committed
Add an option to specify destination format
This patch introduces two options for specifying a destination image format during migration. The first option, `dest-img-format`, is used by `vdi-pool-migrate`. The provided 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. The second option is used by `vm-migrate`, and allows specifying the destination format for individual VDIs mapped to a destination SR. The format is `image-format:<source VDI UUID>=<destination image format>`. As with VDI pool migration, if the destination image format cannot be validated, an error is returned. Signed-off-by: Guillaume <[email protected]>
1 parent 4bf58ff commit aa7e2dd

File tree

12 files changed

+305
-95
lines changed

12 files changed

+305
-95
lines changed

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 an image format"
1721+
; param_release= numbered_release "25.6.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 its expected type on destination"
1795+
; param_release= numbered_release "25.6.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: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,7 @@ let rec cmdtable_data : (string * cmd_spec) list =
15741574
; "compress"
15751575
; "vif:"
15761576
; "vdi:"
1577+
; "image-format:"
15771578
]
15781579
; help=
15791580
"Migrate the selected VM(s). The parameter '--live' will migrate the \
@@ -1587,7 +1588,9 @@ let rec cmdtable_data : (string * cmd_spec) list =
15871588
'copy=true' will enable the copy mode so that a stopped vm can be \
15881589
copied, instead of migrating, to the destination pool. The vif and \
15891590
vdi mapping parameters take the form 'vif:<source vif uuid>=<dest \
1590-
network uuid>' and 'vdi:<source vdi uuid>=<dest sr uuid>'. \
1591+
network uuid>' and 'vdi:<source vdi uuid>=<dest sr uuid>'. You can \
1592+
also specify the destination image format of the VDI using \
1593+
image-format:<source vdi uuid>=<destination image format>. \
15911594
Unfortunately, destination uuids cannot be tab-completed."
15921595
; implementation= No_fd Cli_operations.vm_migrate
15931596
; flags= [Standard; Vm_selectors]
@@ -2409,7 +2412,7 @@ let rec cmdtable_data : (string * cmd_spec) list =
24092412
; ( "vdi-pool-migrate"
24102413
, {
24112414
reqd= ["uuid"; "sr-uuid"]
2412-
; optn= []
2415+
; optn= ["dest-img-format"]
24132416
; help=
24142417
"Migrate a VDI to a specified SR, while the VDI is attached to a \
24152418
running guest."

ocaml/xapi-cli-server/cli_operations.ml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,7 +2060,13 @@ let vdi_pool_migrate printer rpc session_id params =
20602060
Client.VDI.get_by_uuid ~rpc ~session_id ~uuid:(List.assoc "uuid" params)
20612061
and sr =
20622062
Client.SR.get_by_uuid ~rpc ~session_id ~uuid:(List.assoc "sr-uuid" params)
2063-
and options = [] (* no options implemented yet *) in
2063+
and options =
2064+
[
2065+
List.assoc_opt "dest-img-format" params
2066+
|> Option.map (fun fmt -> ("dest_img_format", "&dest-img-format=" ^ fmt))
2067+
]
2068+
|> List.filter_map (fun x -> x)
2069+
in
20642070
let newvdi = Client.VDI.pool_migrate ~rpc ~session_id ~vdi ~sr ~options in
20652071
let newuuid = Client.VDI.get_uuid ~rpc ~session_id ~self:newvdi in
20662072
printer (Cli_printer.PList [newuuid])
@@ -4544,6 +4550,7 @@ let vm_migrate_sxm_params =
45444550
; "remote-network"
45454551
; "vdi"
45464552
; "vgpu"
4553+
; "image-format"
45474554
]
45484555

45494556
let vm_migrate printer rpc session_id params =
@@ -4691,6 +4698,17 @@ let vm_migrate printer rpc session_id params =
46914698
)
46924699
(read_map_params "vdi" params)
46934700
in
4701+
let vdi_format_map =
4702+
List.map
4703+
(fun (vdi_uuid, vdi_fmt) ->
4704+
let vdi =
4705+
Client.VDI.get_by_uuid ~rpc ~session_id ~uuid:vdi_uuid
4706+
in
4707+
debug "GTNDEBUG: add image format %s,%s" vdi_uuid vdi_fmt ;
4708+
(vdi, vdi_fmt)
4709+
)
4710+
(read_map_params "image-format" params)
4711+
in
46944712
let vgpu_map =
46954713
List.map
46964714
(fun (vgpu_uuid, gpu_group_uuid) ->
@@ -4853,7 +4871,8 @@ let vm_migrate printer rpc session_id params =
48534871
rpc session_id
48544872
(fun vm ->
48554873
Client.VM.migrate_send ~rpc ~session_id ~vm:(vm.getref ())
4856-
~dest:token ~live:true ~vdi_map ~vif_map ~options ~vgpu_map
4874+
~dest:token ~live:true ~vdi_map ~vdi_format_map ~vif_map
4875+
~options ~vgpu_map
48574876
)
48584877
params
48594878
(["host"; "host-uuid"; "host-name"; "live"; "force"; "copy"]

ocaml/xapi-idl/storage/storage_interface.ml

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ let string_of_vdi_info (x : vdi_info) = Jsonrpc.to_string (rpc_of vdi_info x)
251251
"datapaths". *)
252252
type dp = string [@@deriving rpcty]
253253

254+
type image_format = string [@@deriving rpcty]
255+
254256
type sock_path = string [@@deriving rpcty]
255257

256258
type dp_stat_t = {
@@ -277,6 +279,8 @@ type probe_result =
277279
module Mirror = struct
278280
type id = string [@@deriving rpcty]
279281

282+
type image_format = string [@@deriving rpcty]
283+
280284
type state = Receiving | Sending | Copying [@@deriving rpcty]
281285

282286
type t = {source_vdi: Vdi.t; dest_vdi: Vdi.t; state: state list; failed: bool}
@@ -998,6 +1002,8 @@ module StorageAPI (R : RPC) = struct
9981002
)
9991003

10001004
module MIRROR = struct
1005+
let image_format_p = Param.mk ~name:"image_format" image_format
1006+
10011007
let mirror_vm_p = Param.mk ~name:"mirror_vm" Vm.t
10021008

10031009
let copy_vm_p = Param.mk ~name:"copy_vm" Vm.t
@@ -1009,6 +1015,7 @@ module StorageAPI (R : RPC) = struct
10091015
(dbg_p
10101016
@-> sr_p
10111017
@-> vdi_p
1018+
@-> image_format_p
10121019
@-> dp_p
10131020
@-> mirror_vm_p
10141021
@-> copy_vm_p
@@ -1034,27 +1041,35 @@ module StorageAPI (R : RPC) = struct
10341041
Use the receive_start2 function instead.
10351042
*)
10361043
let receive_start =
1044+
let image_format_p =
1045+
Param.mk ~name:"image_format" Mirror.image_format
1046+
in
10371047
let similar_p = Param.mk ~name:"similar" Mirror.similars in
10381048
let result = Param.mk ~name:"result" Mirror.mirror_receive_result in
10391049
declare "DATA.MIRROR.receive_start" []
10401050
(dbg_p
10411051
@-> sr_p
10421052
@-> VDI.vdi_info_p
10431053
@-> id_p
1054+
@-> image_format_p
10441055
@-> similar_p
10451056
@-> returning result err
10461057
)
10471058

10481059
(** Called on the receiving end to prepare for receipt of the storage. This
10491060
function should be used in conjunction with [receive_finalize2]*)
10501061
let receive_start2 =
1062+
let image_format_p =
1063+
Param.mk ~name:"image_format" Mirror.image_format
1064+
in
10511065
let similar_p = Param.mk ~name:"similar" Mirror.similars in
10521066
let result = Param.mk ~name:"result" Mirror.mirror_receive_result in
10531067
declare "DATA.MIRROR.receive_start2" []
10541068
(dbg_p
10551069
@-> sr_p
10561070
@-> VDI.vdi_info_p
10571071
@-> id_p
1072+
@-> image_format_p
10581073
@-> similar_p
10591074
@-> vm_p
10601075
@-> returning result err
@@ -1420,6 +1435,7 @@ module type Server_impl = sig
14201435
-> dbg:debug_info
14211436
-> sr:sr
14221437
-> vdi:vdi
1438+
-> image_format:string
14231439
-> dp:dp
14241440
-> mirror_vm:vm
14251441
-> copy_vm:vm
@@ -1438,6 +1454,7 @@ module type Server_impl = sig
14381454
-> sr:sr
14391455
-> vdi_info:vdi_info
14401456
-> id:Mirror.id
1457+
-> image_format:Mirror.image_format
14411458
-> similar:Mirror.similars
14421459
-> Mirror.mirror_receive_result
14431460

@@ -1447,6 +1464,7 @@ module type Server_impl = sig
14471464
-> sr:sr
14481465
-> vdi_info:vdi_info
14491466
-> id:Mirror.id
1467+
-> image_format:Mirror.image_format
14501468
-> similar:Mirror.similars
14511469
-> vm:vm
14521470
-> Mirror.mirror_receive_result
@@ -1633,17 +1651,20 @@ module Server (Impl : Server_impl) () = struct
16331651
Impl.DATA.copy () ~dbg ~sr ~vdi ~vm ~url ~dest ~verify_dest
16341652
) ;
16351653
S.DATA.MIRROR.start
1636-
(fun dbg sr vdi dp mirror_vm copy_vm url dest verify_dest ->
1637-
Impl.DATA.MIRROR.start () ~dbg ~sr ~vdi ~dp ~mirror_vm ~copy_vm ~url
1638-
~dest ~verify_dest
1654+
(fun dbg sr vdi image_format dp mirror_vm copy_vm url dest verify_dest ->
1655+
Impl.DATA.MIRROR.start () ~dbg ~sr ~vdi ~image_format ~dp ~mirror_vm
1656+
~copy_vm ~url ~dest ~verify_dest
16391657
) ;
16401658
S.DATA.MIRROR.stop (fun dbg id -> Impl.DATA.MIRROR.stop () ~dbg ~id) ;
16411659
S.DATA.MIRROR.stat (fun dbg id -> Impl.DATA.MIRROR.stat () ~dbg ~id) ;
1642-
S.DATA.MIRROR.receive_start (fun dbg sr vdi_info id similar ->
1643-
Impl.DATA.MIRROR.receive_start () ~dbg ~sr ~vdi_info ~id ~similar
1660+
S.DATA.MIRROR.receive_start (fun dbg sr vdi_info id image_format similar ->
1661+
Impl.DATA.MIRROR.receive_start () ~dbg ~sr ~vdi_info ~id ~image_format
1662+
~similar
16441663
) ;
1645-
S.DATA.MIRROR.receive_start2 (fun dbg sr vdi_info id similar vm ->
1646-
Impl.DATA.MIRROR.receive_start2 () ~dbg ~sr ~vdi_info ~id ~similar ~vm
1664+
S.DATA.MIRROR.receive_start2
1665+
(fun dbg sr vdi_info id image_format similar vm ->
1666+
Impl.DATA.MIRROR.receive_start2 () ~dbg ~sr ~vdi_info ~id ~image_format
1667+
~similar ~vm
16471668
) ;
16481669
S.DATA.MIRROR.receive_cancel (fun dbg id ->
16491670
Impl.DATA.MIRROR.receive_cancel () ~dbg ~id

ocaml/xapi-idl/storage/storage_skeleton.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,18 @@ module DATA = struct
157157
module MIRROR = struct
158158
(** [start task sr vdi url sr2] creates a VDI in remote [url]'s [sr2] and
159159
writes data synchronously. It returns the id of the VDI.*)
160-
let start ctx ~dbg ~sr ~vdi ~dp ~mirror_vm ~copy_vm ~url ~dest =
160+
let start ctx ~dbg ~sr ~vdi ~image_format ~dp ~mirror_vm ~copy_vm ~url ~dest
161+
=
161162
u "DATA.MIRROR.start"
162163

163164
let stop ctx ~dbg ~id = u "DATA.MIRROR.stop"
164165

165166
let stat ctx ~dbg ~id = u "DATA.MIRROR.stat"
166167

167-
let receive_start ctx ~dbg ~sr ~vdi_info ~id ~similar =
168+
let receive_start ctx ~dbg ~sr ~vdi_info ~id ~image_format ~similar =
168169
u "DATA.MIRROR.receive_start"
169170

170-
let receive_start2 ctx ~dbg ~sr ~vdi_info ~id ~similar ~vm =
171+
let receive_start2 ctx ~dbg ~sr ~vdi_info ~id ~image_format ~similar ~vm =
171172
u "DATA.MIRROR.receive_start2"
172173

173174
let receive_finalize ctx ~dbg ~id = u "DATA.MIRROR.receive_finalize"

ocaml/xapi-storage-cli/main.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,11 @@ let mirror_start common_opts sr vdi dp url dest verify_dest =
322322
let dp = get_opt dp "Need a local data path" in
323323
let url = get_opt url "Need a URL" in
324324
let dest = get_opt dest "Need a destination SR" in
325+
(* TODO: add image_format as a parameter of the CLI *)
326+
let image_format = "" in
325327
let task =
326-
Client.DATA.MIRROR.start dbg sr vdi dp mirror_vm copy_vm url
328+
Client.DATA.MIRROR.start dbg sr vdi image_format dp mirror_vm copy_vm
329+
url
327330
(Storage_interface.Sr.of_string dest)
328331
verify_dest
329332
in

ocaml/xapi/message_forwarding.ml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,26 +2536,28 @@ functor
25362536
assuming it can ignore this check."
25372537

25382538
let assert_can_migrate ~__context ~vm ~dest ~live ~vdi_map ~vif_map
2539-
~options ~vgpu_map =
2539+
~options ~vgpu_map ~vdi_format_map =
25402540
info "VM.assert_can_migrate: VM = '%s'" (vm_uuid ~__context vm) ;
25412541
(* Run the checks that can be done using just the DB directly on the master *)
2542-
Local.VM.assert_can_migrate ~__context ~vm ~dest ~live ~vdi_map ~vif_map
2543-
~vgpu_map ~options ;
2542+
Local.VM.assert_can_migrate ~__context ~vm ~dest ~live ~vdi_map
2543+
~vdi_format_map ~vif_map ~vgpu_map ~options ;
25442544
(* Run further checks on the sending host *)
25452545
assert_can_migrate_sender ~__context ~vm ~dest ~live ~vdi_map ~vif_map
25462546
~vgpu_map ~options
25472547

25482548
let migrate_send ~__context ~vm ~dest ~live ~vdi_map ~vif_map ~options
2549-
~vgpu_map =
2549+
~vgpu_map ~vdi_format_map =
25502550
info "VM.migrate_send: VM = '%s'" (vm_uuid ~__context vm) ;
25512551
let source_host = Db.VM.get_resident_on ~__context ~self:vm in
25522552
let local_fn =
2553-
Local.VM.migrate_send ~vm ~dest ~live ~vdi_map ~vif_map ~vgpu_map
2554-
~options
2553+
debug "GTNDEBUG: Local.VM.migrate_send" ;
2554+
Local.VM.migrate_send ~vm ~dest ~live ~vdi_map ~vdi_format_map
2555+
~vif_map ~vgpu_map ~options
25552556
in
25562557
let op session_id rpc =
2558+
debug "GTNDEBUG: Client.VM.migrate_send" ;
25572559
Client.VM.migrate_send ~rpc ~session_id ~vm ~dest ~live ~vdi_map
2558-
~vif_map ~options ~vgpu_map
2560+
~vdi_format_map ~vif_map ~options ~vgpu_map
25592561
in
25602562
let migration_type =
25612563
if Xapi_vm_lifecycle_helpers.is_live ~__context ~self:vm then
@@ -2568,14 +2570,16 @@ functor
25682570
`Non_live
25692571
in
25702572
let forward_migrate_send () =
2573+
debug "GTNDEBUG: forward_migrate_send" ;
25712574
let forward_internal_async () =
25722575
forward_vm_op ~local_fn ~__context ~vm (fun session_id rpc ->
25732576
(* try InternalAsync.VM.migrate_send first to avoid long running idle stunnel connection
25742577
* fall back on Async.VM.migrate_send if slave doesn't support InternalAsync *)
25752578
Helpers.try_internal_async ~__context API.ref_VM_of_rpc
25762579
(fun () ->
25772580
Client.InternalAsync.VM.migrate_send ~rpc ~session_id ~vm
2578-
~dest ~live ~vdi_map ~vif_map ~options ~vgpu_map
2581+
~dest ~live ~vdi_map ~vdi_format_map ~vif_map ~options
2582+
~vgpu_map
25792583
)
25802584
(fun () -> op session_id rpc)
25812585
)
@@ -2614,7 +2618,7 @@ functor
26142618
Server_helpers.exec_with_subtask ~__context
26152619
"VM.assert_can_migrate" (fun ~__context ->
26162620
assert_can_migrate ~__context ~vm ~dest ~live ~vdi_map
2617-
~vif_map ~vgpu_map ~options
2621+
~vdi_format_map ~vif_map ~vgpu_map ~options
26182622
) ;
26192623
forward_migrate_send ()
26202624
)
@@ -5455,6 +5459,10 @@ functor
54555459
)
54565460

54575461
let pool_migrate ~__context ~vdi ~sr ~options =
5462+
debug "GTNDEBUG: pool_migrate from message forwarder...." ;
5463+
List.iter
5464+
(fun (s1, s2) -> debug "GTNDEBUG: options (%s, %s)" s1 s2)
5465+
options ;
54585466
let vbds =
54595467
let expr =
54605468
Xapi_database.Db_filter_types.(

0 commit comments

Comments
 (0)