Skip to content

Commit

Permalink
[CA-60540] Fix forced SR/VDI import.
Browse files Browse the repository at this point in the history
When doing a forced VM metadata import, xapi will now skip over any
missing SRs and their VDIs instead of causing the import to fail.

Signed-off-by: John Else <john.else@citrix.com>
  • Loading branch information
johnelse committed Jul 6, 2011
1 parent 63cbdf7 commit 83cd558
Showing 1 changed file with 38 additions and 33 deletions.
71 changes: 38 additions & 33 deletions ocaml/xapi/import.ml
Expand Up @@ -331,12 +331,14 @@ let handle_sr __context config rpc session_id (state: state) (x: obj) : unit =
let sr = Client.SR.get_by_uuid rpc session_id sr_record.API.sR_uuid in
state.table <- (x.cls, x.id, Ref.string_of sr) :: state.table
with e ->
let msg, fail = match sr_record.API.sR_content_type, config.force with
| "iso", _ -> "- will eject disk", false (* Will be handled specially in handle_vdi *)
| _, false -> "- this is fatal", true
| _, true -> "- skipping SR as import was forced", false
in
warn "Failed to find SR with UUID: %s content-type: %s %s"
sr_record.API.sR_uuid sr_record.API.sR_content_type
(if sr_record.API.sR_content_type = "iso" then " will eject disk" else "-- this is fatal");
if sr_record.API.sR_content_type = "iso"
then () (* this one will be handled specially in handle_vdi *)
else raise e (* fatal error *)
sr_record.API.sR_uuid sr_record.API.sR_content_type msg;
if fail then raise e
end else begin
if sr_record.API.sR_content_type = "iso"
then () (* this one will be ejected *)
Expand Down Expand Up @@ -373,35 +375,38 @@ let handle_vdi __context config rpc session_id (state: state) (x: obj) : unit =
| _ ->
warn "Found no ISO VDI with location = %s; attempting to eject" vdi_record.API.vDI_location
end else begin
let sr = lookup vdi_record.API.vDI_SR state.table in
if config.vm_metadata_only then begin
(* Look up the existing VDI record by location *)
match List.filter (fun (_, vdir) ->
vdir.API.vDI_location = vdi_record.API.vDI_location && vdir.API.vDI_SR = sr)
(Client.VDI.get_all_records rpc session_id) with
| (vdi, _) :: [] ->
(* perfect, found exactly one *)
state.table <- (x.cls, x.id, Ref.string_of vdi) :: state.table
| (vdi, _) :: _ ->
(* hmm, wasn't expecting to have to choose! *)
warn "Found multiple VDIs with location = %s (location should be unique per-SR); choosing at random" vdi_record.API.vDI_location;
if exists vdi_record.API.vDI_SR state.table then begin
let sr = lookup vdi_record.API.vDI_SR state.table in
if config.vm_metadata_only then begin
(* Look up the existing VDI record by location *)
match List.filter (fun (_, vdir) ->
vdir.API.vDI_location = vdi_record.API.vDI_location && vdir.API.vDI_SR = sr)
(Client.VDI.get_all_records rpc session_id) with
| (vdi, _) :: [] ->
(* perfect, found exactly one *)
state.table <- (x.cls, x.id, Ref.string_of vdi) :: state.table
| (vdi, _) :: _ ->
(* hmm, wasn't expecting to have to choose! *)
warn "Found multiple VDIs with location = %s (location should be unique per-SR); choosing at random" vdi_record.API.vDI_location;
state.table <- (x.cls, x.id, Ref.string_of vdi) :: state.table
| _ ->
error "Found no VDI with location = %s: %s" vdi_record.API.vDI_location
(if config.force
then "ignoring error because '--force' is set"
else "treating as fatal and abandoning import");
if not(config.force)
then raise (Api_errors.Server_error(Api_errors.vdi_location_missing, [ Ref.string_of sr; vdi_record.API.vDI_location ]))
end else begin
(* Make a new VDI for streaming data into; adding task-id to sm-config on VDI.create so SM backend can see this is an import *)
let task_id = Ref.string_of (Context.get_task_id __context) in
let sm_config = List.filter (fun (k,_)->k<>Xapi_globs.import_task) vdi_record.API.vDI_sm_config in
let sm_config = (Xapi_globs.import_task, task_id)::sm_config in
let vdi = Client.VDI.create_from_record rpc session_id { vdi_record with API.vDI_SR = sr; API.vDI_sm_config = sm_config } in
state.cleanup <- (fun __context rpc session_id -> Client.VDI.destroy rpc session_id vdi) :: state.cleanup;
state.table <- (x.cls, x.id, Ref.string_of vdi) :: state.table
| _ ->
error "Found no VDI with location = %s: %s" vdi_record.API.vDI_location
(if config.force
then "ignoring error because '--force' is set"
else "treating as fatal and abandoning import");
if not(config.force)
then raise (Api_errors.Server_error(Api_errors.vdi_location_missing, [ Ref.string_of sr; vdi_record.API.vDI_location ]))
end else begin
(* Make a new VDI for streaming data into; adding task-id to sm-config on VDI.create so SM backend can see this is an import *)
let task_id = Ref.string_of (Context.get_task_id __context) in
let sm_config = List.filter (fun (k,_)->k<>Xapi_globs.import_task) vdi_record.API.vDI_sm_config in
let sm_config = (Xapi_globs.import_task, task_id)::sm_config in
let vdi = Client.VDI.create_from_record rpc session_id { vdi_record with API.vDI_SR = sr; API.vDI_sm_config = sm_config } in
state.cleanup <- (fun __context rpc session_id -> Client.VDI.destroy rpc session_id vdi) :: state.cleanup;
state.table <- (x.cls, x.id, Ref.string_of vdi) :: state.table
end
end
end else
warn "Skipping VDI %s as its SR was not imported." vdi_record.API.vDI_uuid
end


Expand Down

0 comments on commit 83cd558

Please sign in to comment.