Skip to content

Commit

Permalink
CA-87324: simulate VBD eject/insert as plug/unplug in xapi rather tha…
Browse files Browse the repository at this point in the history
…n xenopsd

Simulating this in xenopsd leads to states where a VDI has been
ejected but the device is still 'active' and therefore 'currently_attached=true'
Although this is self-consistent, it confuses xapi and the regression
tests using the XenAPI. Instead we fall back to transforming eject into
unplug and insert into plug at the XenAPI level.

Signed-off-by: David Scott <dave.scott@eu.citrix.com>
  • Loading branch information
David Scott committed Jul 31, 2012
1 parent c1393ff commit ad120a3
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 38 deletions.
87 changes: 56 additions & 31 deletions ocaml/xapi/xapi_xenops.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1840,37 +1840,6 @@ let md_of_vbd ~__context ~self =
let vm = Db.VBD.get_VM ~__context ~self in
MD.of_vbd ~__context ~vm:(Db.VM.get_record ~__context ~self:vm) ~vbd:(Db.VBD.get_record ~__context ~self)

let vbd_eject ~__context ~self =
transform_xenops_exn ~__context
(fun () ->
let vm = Db.VBD.get_VM ~__context ~self in
assert_resident_on ~__context ~self:vm;
let vbd = md_of_vbd ~__context ~self in
info "xenops: VBD.eject %s.%s" (fst vbd.Vbd.id) (snd vbd.Vbd.id);
let dbg = Context.string_of_task __context in
Client.VBD.eject dbg vbd.Vbd.id |> sync_with_task __context;
Events_from_xenopsd.wait dbg ();
Events_from_xapi.wait ~__context ~self:vm;
assert (Db.VBD.get_empty ~__context ~self);
assert (Db.VBD.get_VDI ~__context ~self = Ref.null)
)

let vbd_insert ~__context ~self ~vdi =
transform_xenops_exn ~__context
(fun () ->
let vm = Db.VBD.get_VM ~__context ~self in
assert_resident_on ~__context ~self:vm;
let vbd = md_of_vbd ~__context ~self in
let disk = disk_of_vdi ~__context ~self:vdi |> Opt.unbox in
info "xenops: VBD.insert %s.%s %s" (fst vbd.Vbd.id) (snd vbd.Vbd.id) (disk |> rpc_of_disk |> Jsonrpc.to_string);
let dbg = Context.string_of_task __context in
Client.VBD.insert dbg vbd.Vbd.id disk |> sync_with_task __context;
Events_from_xenopsd.wait dbg ();
Events_from_xapi.wait ~__context ~self:vm;
assert (not(Db.VBD.get_empty ~__context ~self));
assert (Db.VBD.get_VDI ~__context ~self = vdi)
)

let vbd_plug ~__context ~self =
transform_xenops_exn ~__context
(fun () ->
Expand Down Expand Up @@ -1911,6 +1880,62 @@ let vbd_unplug ~__context ~self force =
assert (not(Db.VBD.get_currently_attached ~__context ~self))
)

let vbd_eject_hvm ~__context ~self =
transform_xenops_exn ~__context
(fun () ->
let vm = Db.VBD.get_VM ~__context ~self in
assert_resident_on ~__context ~self:vm;
let vbd = md_of_vbd ~__context ~self in
info "xenops: VBD.eject %s.%s" (fst vbd.Vbd.id) (snd vbd.Vbd.id);
let dbg = Context.string_of_task __context in
Client.VBD.eject dbg vbd.Vbd.id |> sync_with_task __context;
Events_from_xenopsd.wait dbg ();
Events_from_xapi.wait ~__context ~self:vm;
assert (Db.VBD.get_empty ~__context ~self);
assert (Db.VBD.get_VDI ~__context ~self = Ref.null)
)

let vbd_insert_hvm ~__context ~self ~vdi =
transform_xenops_exn ~__context
(fun () ->
let vm = Db.VBD.get_VM ~__context ~self in
assert_resident_on ~__context ~self:vm;
let vbd = md_of_vbd ~__context ~self in
let disk = disk_of_vdi ~__context ~self:vdi |> Opt.unbox in
info "xenops: VBD.insert %s.%s %s" (fst vbd.Vbd.id) (snd vbd.Vbd.id) (disk |> rpc_of_disk |> Jsonrpc.to_string);
let dbg = Context.string_of_task __context in
Client.VBD.insert dbg vbd.Vbd.id disk |> sync_with_task __context;
Events_from_xenopsd.wait dbg ();
Events_from_xapi.wait ~__context ~self:vm;
assert (not(Db.VBD.get_empty ~__context ~self));
assert (Db.VBD.get_VDI ~__context ~self = vdi)
)

let ejectable ~__context ~self =
let dbg = Context.string_of_task __context in
let vm = Db.VBD.get_VM ~__context ~self in
let id = Db.VM.get_uuid ~__context ~self:vm in
let _, state = Client.VM.stat dbg id in
state.Vm.hvm

let vbd_eject ~__context ~self =
if ejectable ~__context ~self
then vbd_eject_hvm ~__context ~self
else begin
vbd_unplug ~__context ~self false;
Db.VBD.set_empty ~__context ~self ~value:true;
Db.VBD.set_VDI ~__context ~self ~value:Ref.null;
end

let vbd_insert ~__context ~self ~vdi =
if ejectable ~__context ~self
then vbd_insert_hvm ~__context ~self ~vdi
else begin
Db.VBD.set_VDI ~__context ~self ~value:vdi;
Db.VBD.set_empty ~__context ~self ~value:false;
vbd_plug ~__context ~self
end

let md_of_vif ~__context ~self =
let vm = Db.VIF.get_VM ~__context ~self in
MD.of_vif ~__context ~vm:(Db.VM.get_record ~__context ~self:vm) ~vif:(Db.VIF.get_record ~__context ~self)
Expand Down
10 changes: 3 additions & 7 deletions ocaml/xenops/xenops_server_xen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1677,13 +1677,9 @@ module VBD = struct
(fun xc xs frontend_domid hvm ->
let (device: Device_common.device) = device_by_id xc xs vm Device_common.Vbd Oldest (id_of vbd) in

if not hvm
then unplug task vm vbd false
else begin
let device_number = device_number_of_device device in
Device.Vbd.media_eject ~xs ~device_number frontend_domid;
xs.Xs.rm (vdi_path_of_device ~xs device);
end;
let device_number = device_number_of_device device in
Device.Vbd.media_eject ~xs ~device_number frontend_domid;
xs.Xs.rm (vdi_path_of_device ~xs device);
Storage.dp_destroy task (Storage.id_of (frontend_domid_of_device device) vbd.Vbd.id)
) Oldest vm

Expand Down

0 comments on commit ad120a3

Please sign in to comment.