Skip to content

Commit 11bea26

Browse files
committed
CA-390277: Reduce record usage on CLI cross-pool migrations
Using records in cross-pool migration code is dangerous, as the code interacts with potentially newer hosts. This means that fields in the record might be different from what's expected. In particular adding an enum field can break the deserialization, and removing a field as well. With this change, only SR records are used. This is done to minimize the number of calls done. Signed-off-by: Pau Ruiz Safont <[email protected]>
1 parent 7fff979 commit 11bea26

File tree

2 files changed

+64
-56
lines changed

2 files changed

+64
-56
lines changed

ocaml/xapi-cli-server/cli_operations.ml

Lines changed: 63 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4582,52 +4582,56 @@ let vm_migrate printer rpc session_id params =
45824582
let remote f = f ~rpc:remote_rpc ~session_id:remote_session in
45834583
finally
45844584
(fun () ->
4585-
let host, host_record =
4586-
let all = remote Client.Host.get_all_records in
4587-
if List.mem_assoc "host" params then
4588-
let x = List.assoc "host" params in
4589-
try
4590-
List.find
4591-
(fun (_, h) ->
4592-
h.API.host_hostname = x
4593-
|| h.API.host_name_label = x
4594-
|| h.API.host_uuid = x
4595-
)
4596-
all
4597-
with Not_found ->
4598-
failwith (Printf.sprintf "Failed to find host: %s" x)
4599-
else
4600-
List.hd all
4585+
let host =
4586+
let expr_match x =
4587+
Printf.sprintf
4588+
{|(field "hostname"="%s") or (field "name__label"="%s") or (field "uuid"="%s")|}
4589+
x x x
4590+
in
4591+
let expr, fail_msg =
4592+
match List.assoc_opt "host" params with
4593+
| Some x ->
4594+
(expr_match x, Printf.sprintf "Failed to find host: %s" x)
4595+
| None ->
4596+
("true", Printf.sprintf "Failed to find a suitable host")
4597+
in
4598+
match remote Client.Host.get_all_where ~expr with
4599+
| host :: _ ->
4600+
host
4601+
| [] ->
4602+
failwith fail_msg
46014603
in
4602-
let network, network_record =
4603-
let all = remote Client.Network.get_all_records in
4604-
if List.mem_assoc "remote-network" params then
4605-
let x = List.assoc "remote-network" params in
4606-
try
4607-
List.find
4608-
(fun (_, net) ->
4609-
net.API.network_bridge = x
4610-
|| net.API.network_name_label = x
4611-
|| net.API.network_uuid = x
4612-
)
4613-
all
4614-
with Not_found ->
4615-
failwith (Printf.sprintf "Failed to find network: %s" x)
4616-
else
4617-
let pifs = host_record.API.host_PIFs in
4618-
let management_pifs =
4619-
List.filter
4620-
(fun self -> remote Client.PIF.get_management ~self)
4621-
pifs
4622-
in
4623-
if List.length management_pifs = 0 then
4624-
failwith
4625-
(Printf.sprintf "Could not find management PIF on host %s"
4626-
host_record.API.host_uuid
4627-
) ;
4628-
let pif = List.hd management_pifs in
4629-
let net = remote Client.PIF.get_network ~self:pif in
4630-
(net, remote Client.Network.get_record ~self:net)
4604+
let network =
4605+
let expr x =
4606+
Printf.sprintf
4607+
{|(field "bridge"="%s") or (field "name__label"="%s") or (field "uuid"="%s")|}
4608+
x x x
4609+
in
4610+
match List.assoc_opt "remote-network" params with
4611+
| Some x -> (
4612+
match remote Client.Network.get_all_where ~expr:(expr x) with
4613+
| network :: _ ->
4614+
network
4615+
| [] ->
4616+
failwith (Printf.sprintf "Failed to find network: %s" x)
4617+
)
4618+
| None -> (
4619+
let expr =
4620+
Printf.sprintf
4621+
{|(field "host"="%s") and (field "management"="true")|}
4622+
Ref.(string_of host)
4623+
in
4624+
let management_pifs = remote Client.PIF.get_all_where ~expr in
4625+
match management_pifs with
4626+
| [] ->
4627+
let host_uuid = remote Client.Host.get_uuid ~self:host in
4628+
failwith
4629+
(Printf.sprintf "Could not find management PIF on host %s"
4630+
host_uuid
4631+
)
4632+
| pif :: _ ->
4633+
remote Client.PIF.get_network ~self:pif
4634+
)
46314635
in
46324636
let vif_map =
46334637
List.map
@@ -4674,15 +4678,12 @@ let vm_migrate printer rpc session_id params =
46744678
{|(field "host"="%s") and (field "currently_attached"="true")|}
46754679
(Ref.string_of host)
46764680
in
4677-
let host_pbds = remote Client.PBD.get_all_records_where ~expr in
46784681
let srs =
4679-
List.map
4680-
(fun (_, pbd_rec) ->
4681-
( pbd_rec.API.pBD_SR
4682-
, remote Client.SR.get_record ~self:pbd_rec.API.pBD_SR
4683-
)
4684-
)
4685-
host_pbds
4682+
remote Client.PBD.get_all_where ~expr
4683+
|> List.map (fun pbd ->
4684+
let sr = remote Client.PBD.get_SR ~self:pbd in
4685+
(sr, remote Client.SR.get_record ~self:sr)
4686+
)
46864687
in
46874688
(* In the following loop, the current SR:sr' will be compared with previous checked ones,
46884689
first if it is an ISO type, then pass this one for selection, then the only shared one from this and
@@ -4781,13 +4782,20 @@ let vm_migrate printer rpc session_id params =
47814782
)
47824783
params
47834784
in
4785+
let host_name_label =
4786+
Client.Host.get_name_label ~rpc:remote_rpc ~session_id:remote_session
4787+
~self:host
4788+
in
4789+
let network_name_label =
4790+
Client.Network.get_name_label ~rpc:remote_rpc
4791+
~session_id:remote_session ~self:network
4792+
in
47844793
printer
47854794
(Cli_printer.PMsg
47864795
(Printf.sprintf
47874796
"Will migrate to remote host: %s, using remote network: %s. \
47884797
Here is the VDI mapping:"
4789-
host_record.API.host_name_label
4790-
network_record.API.network_name_label
4798+
host_name_label network_name_label
47914799
)
47924800
) ;
47934801
List.iter

quality-gate.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set -e
44

55
list-hd () {
6-
N=312
6+
N=310
77
LIST_HD=$(git grep -r --count 'List.hd' -- **/*.ml | cut -d ':' -f 2 | paste -sd+ - | bc)
88
if [ "$LIST_HD" -eq "$N" ]; then
99
echo "OK counted $LIST_HD List.hd usages"

0 commit comments

Comments
 (0)