Skip to content

Commit 8ee104f

Browse files
zlimatthiasgoergens
authored andcommitted
CA-41553: Fix logic bugs in vm_install_real and do some code cleanup
There were two logic bugs in vm_install_real * When user create a VM based on a snapshot (which is also considered as a template from XenServer point of view), and neither sr-name-lable or sr-uuid is specified (neither is wanted any way), the code will fail if the pool doesn't have default SR set (which is not necessary as well). This is the problem spot in CA-41553. * When both sr-uuid and sr-name-lable are specified in command line at the same time - If there is some contradiction, say the SR with sr-uuid doesn't have the name as specified in sr-name-label, XenServer will only take sr-name-label into consideration and ignore sr-uuid without a warning - If sr-name-label corresponding to several SRs in the system, instead of using the sr-uuid information to restrict the candidate to one, XenServer will simply fail and complain "Multiple SRs with that name-label found". Signed-off-by: Zheng Li <[email protected]>
1 parent e510e9c commit 8ee104f

File tree

1 file changed

+74
-46
lines changed

1 file changed

+74
-46
lines changed

ocaml/xapi/cli_operations.ml

Lines changed: 74 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,51 +1965,82 @@ let vm_unpause printer rpc session_id params =
19651965
ignore(do_vm_op printer rpc session_id (fun vm -> Client.VM.unpause rpc session_id (vm.getref ())) params [])
19661966

19671967
let vm_install_real printer rpc session_id template name description params =
1968+
1969+
let sr_ref =
1970+
if Client.VM.get_is_a_snapshot rpc session_id template then
1971+
if (List.mem_assoc "sr-name-label" params
1972+
|| List.mem_assoc "sr-uuid" params) then
1973+
failwith "Do not use the sr-name-label or sr-uuid argument when installing from a snapshot. By default, it will install each new disk on the same SR as the corresponding snapshot disks."
1974+
else Some Ref.null
1975+
else None in
1976+
19681977
(* Rewrite the provisioning XML to refer to the sr-name-label, sr-uuid or the pool default_SR *)
1969-
let sr_name_label =
1970-
if List.mem_assoc "sr-name-label" params
1971-
then match Client.SR.get_by_name_label rpc session_id (List.assoc "sr-name-label" params) with
1972-
| [ sr ] -> Some (Client.SR.get_uuid rpc session_id sr)
1978+
1979+
let sr_ref = match sr_ref with
1980+
| Some _ -> sr_ref
1981+
| None ->
1982+
if List.mem_assoc "sr-uuid" params then
1983+
let uuid = List.assoc "sr-uuid" params in
1984+
Some (Client.SR.get_by_uuid rpc session_id uuid)
1985+
else None in
1986+
1987+
let sr_ref =
1988+
if List.mem_assoc "sr-name-label" params then
1989+
let name = List.assoc "sr-name-label" params in
1990+
match Client.SR.get_by_name_label rpc session_id name with
19731991
| [] -> failwith "No SR with that name-label found"
1974-
| _ -> failwith "Multiple SRs with that name-label found"
1975-
else None in
1976-
let sr_uuid =
1977-
if List.mem_assoc "sr-uuid" params
1978-
then (let uuid = List.assoc "sr-uuid" params in
1979-
ignore (Client.SR.get_by_uuid rpc session_id uuid); (* throws an exception if not found *)
1980-
Some uuid)
1981-
else None in
1982-
let pool_default = get_default_sr_uuid rpc session_id in
1983-
1984-
let sr_uuid = match sr_name_label, sr_uuid, pool_default with
1985-
| Some x, _, _ -> x
1986-
| _, Some x, _ -> x
1987-
| _, _, Some x -> x
1988-
| None, None, None ->
1989-
let vbds = Client.VM.get_VBDs rpc session_id template in
1990-
let disks = List.filter (fun vbd -> not (Client.VBD.get_type rpc session_id vbd = `CD && Client.VBD.get_empty rpc session_id vbd)) vbds in
1991-
let has_provisioned_disks =
1992+
| sr_list -> match sr_ref with
1993+
| Some sr ->
1994+
if List.mem sr sr_list then sr_ref
1995+
else failwith "SR specified via sr-uuid doesn't have the name specified via sr-name-label"
1996+
| None ->
1997+
if List.length sr_list > 1 then
1998+
failwith "Multiple SRs with that name-label found"
1999+
else Some (List.hd sr_list)
2000+
else sr_ref in
2001+
2002+
let sr_ref = match sr_ref with
2003+
| Some _ -> sr_ref
2004+
| None ->
2005+
let all_empty_cd_driver =
2006+
let vbds = Client.VM.get_VBDs rpc session_id template in
2007+
let is_empty_cd_drive vbd =
2008+
Client.VBD.get_type rpc session_id vbd = `CD
2009+
&& Client.VBD.get_empty rpc session_id vbd in
2010+
List.for_all is_empty_cd_drive vbds in
2011+
let no_provision_disk =
19922012
let other_config = Client.VM.get_other_config rpc session_id template in
1993-
if List.mem_assoc "disks" other_config && List.assoc "disks" other_config <> ""
1994-
then match Xml.parse_string (List.assoc "disks" other_config) with
1995-
| Xml.Element("provision",[],[]) -> false
1996-
| _ -> true
1997-
else false
1998-
in
1999-
if disks = [] && not has_provisioned_disks
2000-
then Ref.string_of Ref.null
2001-
else failwith "Failed to find a valid default SR for the Pool. Please provide an sr-name-label or sr-uuid parameter."
2002-
in
2013+
not (List.mem_assoc "disks" other_config)
2014+
|| List.assoc "disks" other_config = ""
2015+
|| (Xml.parse_string (List.assoc "disks" other_config)
2016+
= Xml.Element("provision", [], [])) in
2017+
if all_empty_cd_driver && no_provision_disk then Some Ref.null
2018+
else None in
2019+
2020+
let sr_ref = match sr_ref with
2021+
| Some _ -> sr_ref
2022+
| None ->
2023+
let pool = List.hd (Client.Pool.get_all rpc session_id) in
2024+
let sr = Client.Pool.get_default_SR rpc session_id pool in
2025+
Some sr in
2026+
2027+
(* We should now have an sr *)
2028+
let sr_ref = match sr_ref with
2029+
| Some sr -> sr
2030+
| None ->
2031+
failwith "Failed to find a valid default SR for the Pool. Please provide an sr-name-label or sr-uuid parameter." in
20032032

2004-
if Client.VM.get_is_a_snapshot rpc session_id template && (List.mem_assoc "sr-name-label" params || List.mem_assoc "sr-uuid" params) then
2005-
failwith "Do not use the sr-name-label or sr-uuid argument when installing from a snapshot. By default, it will install each new disk on the same SR as the corresponding snapshot disks.";
2033+
let sr_uuid =
2034+
if sr_ref = Ref.null then
2035+
Ref.string_of sr_ref
2036+
else
2037+
Client.SR.get_uuid rpc session_id sr_ref in
20062038

2007-
(* We should now have an sr-uuid *)
20082039
let new_vm =
2009-
if List.mem_assoc "sr-name-label" params || List.mem_assoc "sr-uuid" params
2010-
then Client.VM.copy rpc session_id template name (Client.SR.get_by_uuid rpc session_id sr_uuid)
2011-
else Client.VM.clone rpc session_id template name
2012-
in
2040+
if sr_ref <> Ref.null
2041+
then Client.VM.copy rpc session_id template name sr_ref
2042+
else Client.VM.clone rpc session_id template name in
2043+
20132044
try
20142045
Client.VM.set_name_description rpc session_id new_vm description;
20152046
rewrite_provisioning_xml rpc session_id new_vm sr_uuid;
@@ -2021,15 +2052,12 @@ let vm_install_real printer rpc session_id template name description params =
20212052
let host = Client.Host.get_by_uuid rpc session_id (List.assoc "copy-bios-strings-from" params) in
20222053
Client.VM.copy_bios_strings rpc session_id new_vm host
20232054
end;
2024-
debug "hello";
20252055
let vm_uuid = Client.VM.get_uuid rpc session_id new_vm in
20262056
printer (Cli_printer.PList [vm_uuid])
2027-
with
2028-
e ->
2029-
begin
2030-
(try Client.VM.destroy rpc session_id new_vm with _ -> ());
2031-
raise e
2032-
end
2057+
with e ->
2058+
(try Client.VM.destroy rpc session_id new_vm with _ -> ());
2059+
raise e
2060+
20332061

20342062
(* The process of finding the VM in this case is special-cased since we want to call the
20352063
* params 'template-name', like a foreign key, sort of *)

0 commit comments

Comments
 (0)