Skip to content

Commit 174bc20

Browse files
committed
[CA-58880] Change VM_appliance.recover behaviour.
Previously when a VM appliance was recovered, if an appliance with the same UUID already existed then a new appliance with a fresh UUID would be created. In this case now, all VMs are removed from the existing appliance, all recovered VMs are added and the appliance's name_label and name_description are updated to match those of the recovered appliance. Signed-off-by: John Else <john.else@citrix.com>
1 parent 417090f commit 174bc20

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

ocaml/xapi/xapi_vm_appliance.ml

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -178,26 +178,38 @@ let recover ~__context ~self ~session_to ~force =
178178
assert_can_be_recovered ~__context ~self ~session_to;
179179
let vms = Db.VM_appliance.get_VMs ~__context ~self in
180180
let recovered_vms = Xapi_dr.recover_vms ~__context ~vms ~session_to ~force in
181-
(* Recreate the VM appliance object. *)
181+
(* Deal with the VM appliance object. *)
182182
let old_appliance = Db.VM_appliance.get_record ~__context ~self in
183183
Server_helpers.exec_with_new_task ~session_id:session_to "Recreating VM appliance object"
184184
(fun __context_to ->
185-
let new_appliance = create ~__context:__context_to
186-
~name_label:old_appliance.API.vM_appliance_name_label
187-
~name_description:old_appliance.API.vM_appliance_name_description in
185+
let recovered_appliance = try
186+
(* If an appliance with the same UUID exists, remove all VMs from the appliance and update its name_label/name_description. *)
187+
let existing_appliance = Db.VM_appliance.get_by_uuid ~__context:__context_to ~uuid:old_appliance.API.vM_appliance_uuid in
188+
debug "An appliance with UUID %s already exists - reusing it." old_appliance.API.vM_appliance_uuid;
189+
let vms = Db.VM_appliance.get_VMs ~__context:__context_to ~self:existing_appliance in
190+
List.iter
191+
(fun vm -> Db.VM.set_appliance ~__context:__context_to ~self:vm ~value:Ref.null)
192+
vms;
193+
Db.VM_appliance.set_name_label ~__context:__context_to ~self:existing_appliance ~value:old_appliance.API.vM_appliance_name_label;
194+
Db.VM_appliance.set_name_description ~__context:__context_to ~self:existing_appliance ~value:old_appliance.API.vM_appliance_name_description;
195+
existing_appliance
196+
with Db_exn.Read_missing_uuid("VM_appliance", _, _) ->
197+
(* If no appliance with the same UUID exists, create a new one from the old appliance's data. *)
198+
debug "No appliance with UUID %s exists - creating a new one." old_appliance.API.vM_appliance_uuid;
199+
begin
200+
let new_appliance = create ~__context:__context_to
201+
~name_label:old_appliance.API.vM_appliance_name_label
202+
~name_description:old_appliance.API.vM_appliance_name_description in
203+
Db.VM_appliance.set_uuid ~__context:__context_to
204+
~self:new_appliance
205+
~value:old_appliance.API.vM_appliance_uuid;
206+
new_appliance
207+
end
208+
in
188209
(* Add all the non-template VMs to the appliance. *)
189210
List.iter
190211
(fun vm ->
191212
if not (Db.VM.get_is_a_template ~__context:__context_to ~self:vm) then
192-
Db.VM.set_appliance ~__context:__context_to ~self:vm ~value:new_appliance)
213+
Db.VM.set_appliance ~__context:__context_to ~self:vm ~value:recovered_appliance)
193214
recovered_vms;
194-
update_allowed_operations ~__context:__context_to ~self:new_appliance;
195-
try
196-
Db.VM_appliance.set_uuid ~__context:__context_to
197-
~self:new_appliance
198-
~value:old_appliance.API.vM_appliance_uuid
199-
with Db_exn.Uniqueness_constraint_violation(_, _, _) ->
200-
(* Fail silently if the appliance's uuid already exists. *)
201-
debug
202-
"Could not give VM appliance the uuid %s as a VM appliance with this uuid already exists."
203-
old_appliance.API.vM_appliance_uuid)
215+
update_allowed_operations ~__context:__context_to ~self:recovered_appliance)

0 commit comments

Comments
 (0)