Permalink
Browse files

[CA-60540] Fix forced SR/VDI import.

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...
1 parent 63cbdf7 commit 83cd558967845a885ef0ae792a8dd8b5113ad433 @johnelse committed Jul 6, 2011
Showing with 38 additions and 33 deletions.
  1. +38 −33 ocaml/xapi/import.ml
View
@@ -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 *)
@@ -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

0 comments on commit 83cd558

Please sign in to comment.