# HG changeset patch # User Mike McClurg # Date 1294163490 0 # Node ID 4ae59c40f32bea8ae9ddf9b03f484a203ab874b0 # Parent 0f6aebc5e54b3c26124d5d7957edc11bb4bbfaff [mq]: CA-47366-Remove-lvhd_stop_using_these_vdis_and_call_script diff --git a/ocaml/idl/datamodel.ml b/ocaml/idl/datamodel.ml --- a/ocaml/idl/datamodel.ml +++ b/ocaml/idl/datamodel.ml @@ -4421,20 +4421,6 @@ ~allowed_roles:_R_POOL_OP () - let sr_lvhd_stop_using_these_vdis_and_call_script = call - ~name:"lvhd_stop_using_these_vdis_and_call_script" - ~in_oss_since:None - ~in_product_since:rel_george - ~params:[Set(Ref _vdi), "vdis", "The VDIs to stop using"; - String, "plugin", "Name of the plugin script to call"; - String, "fn", "Name of the function within the script to call"; - Map(String, String), "args", "Arguments to pass to the script"] - ~result:(String, "output from the lvhd script hook") - ~doc:"Pauses active VBDs associated with the given VDIs and prevents other VDIs becoming active; then calls a script and unwinds" - ~hide_from_docs:true - ~allowed_roles:_R_POOL_OP - () - (** A storage repository. Note we overide default create/destroy methods with our own here... *) let storage_repository = create_obj ~in_db:true ~in_product_since:rel_rio ~in_oss_since:oss_since_303 ~internal_deprecated_since:None ~persist:PersistEverything ~gen_constructor_destructor:false ~name:_sr ~descr:"A storage repository" @@ -4447,7 +4433,6 @@ sr_create_new_blob; sr_set_physical_size; sr_set_virtual_allocation; sr_set_physical_utilisation; sr_assert_can_host_ha_statefile; - sr_lvhd_stop_using_these_vdis_and_call_script; ] ~contents: ([ uid _sr; diff --git a/ocaml/lvhdrt/OMakefile b/ocaml/lvhdrt/OMakefile --- a/ocaml/lvhdrt/OMakefile +++ b/ocaml/lvhdrt/OMakefile @@ -4,7 +4,7 @@ IEXE=install -m 755 -o root -g root -OCamlProgram(lvhdrt, lvhdrt lvhdrt_exceptions utils globs fists tc_8670 tc_8682 tc_8699 tc_8700 tc_8707 tc_8713 tc_8766 tc_8775) +OCamlProgram(lvhdrt, lvhdrt lvhdrt_exceptions utils globs fists tc_8670 tc_8682 tc_8699 tc_8700 tc_8707 tc_8766 tc_8775) .PHONY: clean diff --git a/ocaml/lvhdrt/lvhdrt.ml b/ocaml/lvhdrt/lvhdrt.ml --- a/ocaml/lvhdrt/lvhdrt.ml +++ b/ocaml/lvhdrt/lvhdrt.ml @@ -47,7 +47,6 @@ | 8682 -> Tc_8682.run rpc session | 8700 -> Tc_8700.run rpc session | 8707 -> Tc_8707.run rpc session - | 8713 -> Tc_8713.run rpc session | 8766 -> Tc_8766.run rpc session | 8775 -> Tc_8775.run rpc session | _ -> failwith "Unknown test case!" diff --git a/ocaml/lvhdrt/tc_8713.ml b/ocaml/lvhdrt/tc_8713.ml deleted file mode 100644 --- a/ocaml/lvhdrt/tc_8713.ml +++ /dev/null @@ -1,216 +0,0 @@ -(* - * Copyright (C) 2006-2009 Citrix Systems Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; version 2.1 only. with the special - * exception on linking described in file LICENSE. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - *) -open Threadext -open Client -open Lvhdrt_exceptions - -let trash_vdi_plugin = "lvhdrt-trash-vdi" -let test_runtime = 60. *. 60. *. 2. - -module Background_thread = struct - type t = { - m: Mutex.t; - mutable shutting_down: bool; - mutable t: Thread.t option; - mutable iterations: int; - } - let make one_iteration_fn = - let repeat_until_shutting_down state f = - while Mutex.execute state.m (fun () -> not state.shutting_down) do - begin - try - f (); - with e -> - Mutex.execute state.m (fun () -> state.shutting_down <- true); - raise e - end; - state.iterations <- state.iterations + 1; - done in - let state = { m = Mutex.create (); - shutting_down = false; - t = None; - iterations = 0 } in - let t = Thread.create (fun () -> repeat_until_shutting_down state one_iteration_fn) () in - state.t <- Some t; - state - let stopping state = Mutex.execute state.m (fun () -> state.shutting_down) - let stop state = - Mutex.execute state.m (fun () -> state.shutting_down <- true); - Opt.iter Thread.join state.t; - state.t <- None; - state.iterations -end - -let stdout_m = Mutex.create () - -let debug (fmt: ('a , unit, string, unit) format4) = - (* Convert calendar time, x, to tm in UTC *) - let of_float x = - let time = Unix.gmtime x in - Printf.sprintf "%04d%02d%02dT%02d:%02d:%02dZ" - (time.Unix.tm_year+1900) - (time.Unix.tm_mon+1) - time.Unix.tm_mday - time.Unix.tm_hour - time.Unix.tm_min - time.Unix.tm_sec in - - Mutex.execute stdout_m - (fun () -> - Printf.kprintf (fun s -> Printf.printf "%s [%d] %s\n" (of_float (Unix.gettimeofday ())) (Thread.id (Thread.self ())) s; flush stdout) fmt - ) - -(* Plug a disk into dom0 then unplug and clean up *) -let vbd_plug_unplug rpc session_id vdi () = - debug "test: vbd_plug_unplug vdi = %s" (Ref.string_of vdi); - Utils.with_attached_vdi rpc session_id vdi - (fun _ _ -> () -(* - debug "sleeping for 5s to give the other thread a chance"; - Thread.delay 5. -*) - ) - -let clone_delete rpc session_id vdi () = - debug "test: clone_delete vdi = %s" (Ref.string_of vdi); - let vdi' = Client.VDI.clone rpc session_id vdi [] in - Client.VDI.destroy rpc session_id vdi' - -let snapshot_delete rpc session_id vdi () = - debug "test: snapshot_delete vdi = %s" (Ref.string_of vdi); - let vdi' = Client.VDI.snapshot rpc session_id vdi [] in - Client.VDI.destroy rpc session_id vdi' - -let resize rpc session_id vdi () = - debug "test: resize vdi = %s" (Ref.string_of vdi); - let virtual_size = Client.VDI.get_virtual_size rpc session_id vdi in - Client.VDI.resize rpc session_id vdi (Int64.add virtual_size 1L) - -let scan rpc session_id vdi () = - let sr = Client.VDI.get_SR rpc session_id vdi in - debug "test: scan sr = %s" (Ref.string_of sr); - Client.SR.scan rpc session_id sr - -let pbd_unplug_plug rpc session_id vdi () = - let sr = Client.VDI.get_SR rpc session_id vdi in - debug "test: pbd_unplug_plug sr = %s" (Ref.string_of sr); - List.iter - (fun pbd -> - Client.PBD.unplug rpc session_id pbd; - Client.PBD.plug rpc session_id pbd) - (Client.SR.get_PBDs rpc session_id sr) - -let suspend_vm rpc session_id vm = - let start = Unix.gettimeofday () in - let limit = 20. *. 60. in - let finished = ref false in - while Unix.gettimeofday () -. start < limit && not(!finished) do - try - debug "attempting suspend"; - Client.VM.suspend rpc session_id vm; - finished := true; - with Api_errors.Server_error(code, params) when code = Api_errors.vm_missing_pv_drivers -> - debug "test: suspend_vm waiting for PV drivers"; - Thread.delay 1. - done; - if not !finished then failwith "Failed to detect PV drivers after %.0f seconds" limit - -let vm_start_unstart rpc session_id vm () = - debug "test: vm_start_unstart vm = %s" (Ref.string_of vm); - Client.VM.start rpc session_id vm false false; - suspend_vm rpc session_id vm; - Client.VM.resume rpc session_id vm false false; - Client.VM.hard_shutdown rpc session_id vm - -let do_everything rpc session_id vm vdi () = - vbd_plug_unplug rpc session_id vdi (); - clone_delete rpc session_id vdi (); - snapshot_delete rpc session_id vdi (); - resize rpc session_id vdi (); - scan rpc session_id vdi (); - pbd_unplug_plug rpc session_id vdi (); - vm_start_unstart rpc session_id vm () - -let total_trashings = ref 0 - -let trash_untrash_vdi rpc session_id vdi = - debug "calling SR.lvhd_stop_using_these_vdis_and_call_script with vdi = %s" (Ref.string_of vdi); - let vdi_uuid = Client.VDI.get_uuid rpc session_id vdi in - Thread.delay 0.1; - try - match Client.SR.lvhd_stop_using_these_vdis_and_call_script rpc session_id [ vdi ] trash_vdi_plugin "main" [ "vdi-uuid", vdi_uuid ] with - | "LV inactive" -> - debug "Ignoring glitch: LV currently inactive" - | "Data restored" -> - debug "Successful LV manipulation"; - incr total_trashings - with Api_errors.Server_error(code, params) as e -> - let pause_and_ignore = List.mem code [ Api_errors.sr_no_pbds (* concurrent PBD.unplug; plug loops *) ] in - debug "Caught %s [ %s ] %s" code (String.concat "; " params) (if pause_and_ignore then "-- ignoring" else "-- FATAL"); - if pause_and_ignore - then Thread.delay 5. - else raise e - -let run rpc session = - Random.self_init(); - - (* Make sure the plugin actually exists *) - begin - try - ignore (Client.SR.lvhd_stop_using_these_vdis_and_call_script rpc session [ ] trash_vdi_plugin "main" [ ]) - with - | Api_errors.Server_error(code, params) when code = Api_errors.xenapi_missing_plugin -> - raise (Test_error (Printf.sprintf "ERROR: you must install the plugin %s" trash_vdi_plugin)) - | Api_errors.Server_error(code, params) when code = Api_errors.xenapi_plugin_failure -> - debug "Precheck: %s plugin detected" trash_vdi_plugin - end; - - let master = Utils.get_master rpc session in - - (* Find an LVHD SR *) - let sr = Utils.find_lvhd_sr rpc session in - debug "Using LVHD SR: %s" (Ref.string_of sr); - - Utils.with_sacrificial_vm rpc session - (fun vm -> - debug "Will use VM: %s" (Ref.string_of vm); - (* Choose one of the VM's disks *) - let vbds = Client.VM.get_VBDs rpc session vm in - let nonempty_vbds = List.filter (fun x -> not (Client.VBD.get_empty rpc session x)) vbds in - if nonempty_vbds = [] then failwith "VM appears to have no non-empty VBDs"; - let vdi = Client.VBD.get_VDI rpc session (List.hd nonempty_vbds) in - debug "Will use VDI: %s" (Ref.string_of vdi); - - let number_trash_iterations = ref 0 in - - let start = Unix.gettimeofday () in - let background_loop = Background_thread.make (do_everything rpc session vm vdi) in - Pervasiveext.finally - (fun () -> - while Unix.gettimeofday () -. start < test_runtime && not (Background_thread.stopping background_loop) do - trash_untrash_vdi rpc session vdi; - incr number_trash_iterations; - Thread.delay 0.1; -(* - Thread.delay 5. -*) - done - ) - (fun () -> - let iterations = Background_thread.stop background_loop in - debug "After %.2f seconds the background thread completed %d iterations and the VDI was stopped %d times" (Unix.gettimeofday () -. start) iterations !number_trash_iterations; - debug " of which, %d performed the VHD manipulation" !total_trashings - ) - ); - debug "Test passed" diff --git a/ocaml/xapi/message_forwarding.ml b/ocaml/xapi/message_forwarding.ml --- a/ocaml/xapi/message_forwarding.ml +++ b/ocaml/xapi/message_forwarding.ml @@ -2652,93 +2652,6 @@ info "SR.create_new_blob: SR = '%s'" (sr_uuid ~__context sr); Local.SR.create_new_blob ~__context ~sr ~name ~mime_type - let with_many_vdis ~__context ~vdis ~doc ~op f = - let task_id = Ref.string_of (Context.get_task_id __context) in - let vdis_marked = ref [] in - - (* NB since we acquire locks on multiple VDIs we wait until all locks are released before waking up any - other threads *) - let unmark_all reason = - List.iter - (log_exn_ignore ~doc:("unmarking VDI: " ^ reason) - (fun self -> - if Db.is_valid_ref self then begin - Db.VDI.remove_from_current_operations ~__context ~self ~key:task_id; - Early_wakeup.broadcast (Datamodel._vdi, Ref.string_of self); - end)) - !vdis_marked in - - let signal_all () = - List.iter (fun self -> Early_wakeup.broadcast (Datamodel._vdi, Ref.string_of self)) !vdis_marked in - - retry_with_global_lock ~__context ~doc - (fun () -> - begin - (* If there is an unplug in progress then backoff (hard failure will be thrown in Xapi_pbd.unplug) *) - if vdis <> [] then - let sr = Db.VDI.get_SR ~__context ~self:(List.hd vdis) in - if Helpers.i_am_srmaster ~__context ~sr then - let current_ops = List.map snd (Db.SR.get_current_operations ~__context ~self:sr) in - if List.mem `unplug current_ops then raise (Api_errors.Server_error(Api_errors.other_operation_in_progress, [ Datamodel._sr; Ref.string_of sr ])) - end; - try - List.iter (fun vdi -> - try - Xapi_vdi.assert_operation_valid ~__context ~self:vdi ~op; - Db.VDI.add_to_current_operations ~__context ~self:vdi ~key:task_id ~value:op; - vdis_marked := vdi :: !vdis_marked - (* save time by not updating the allowed operations: this should be a transient operation *) - with - | Db_exn.DBCache_NotFound ("missing row", "VDI", reference) as e -> - let should_skip = reference = (Ref.string_of vdi) in - debug "SR.lvhd_stop_using_these_vdis_and_call_script: Caught %s for VDI %s; %s" (ExnHelper.string_of_exn e) (Ref.string_of vdi) - (if should_skip then "skipping" else "re-raising"); (* CA-26217 *) - if not should_skip then raise e - | e -> - debug "SR.lvhd_stop_using_these_vdis_and_call_script: Caught %s while handling VDI %s" (ExnHelper.string_of_exn e) (Ref.string_of vdi); - raise e - ) vdis - with e -> - (* Failed so unmarking those marked so far *) - unmark_all ("handling transient locking failure during " ^ doc); - (* Signal at the end when all locks have been released *) - signal_all (); - raise e - ); - (* All requested VDIs are now marked and the global heap lock has been released *) - finally - (fun () -> f !vdis_marked) - (fun () -> - with_global_lock - (fun () -> - unmark_all ("releasing all locks after " ^ doc); - (* Signal at the end when all locks have been released *) - signal_all () - )) - - let lvhd_stop_using_these_vdis_and_call_script ~__context ~vdis ~plugin ~fn ~args = - info "SR.lvhd_stop_using_these_vdis_and_call_script: vdis = [ %s ]; plugin = '%s'; fn = '%s'; args = [ %s ]" - (String.concat "; " (List.map (vdi_uuid ~__context) vdis)) - plugin fn - (String.concat "; " (List.map (fun (k, v) -> k ^ ", " ^ v) args)); - let local_fn = Local.SR.lvhd_stop_using_these_vdis_and_call_script ~vdis ~plugin ~fn ~args in - with_many_vdis ~__context ~vdis ~doc:"SR.lvhd_stop_using_these_vdis_and_call_script" ~op:`blocked - (fun vdis -> - - (* Sanity check: all VDIs should be in the same SR *) - let srs = Listext.List.setify (List.concat (List.map (fun vdi -> try [ Db.VDI.get_SR ~__context ~self:vdi ] with _ -> []) vdis)) in - if List.length srs > 1 - then failwith "VDIs must all be in the same SR"; - (* If the list of VDIs is empty then we run the function locally *) - if srs = [] - then local_fn ~__context - else - let sr = List.hd srs in - forward_sr_op ~local_fn ~__context ~self:sr - (fun session_id rpc -> - Client.SR.lvhd_stop_using_these_vdis_and_call_script ~rpc ~session_id ~vdis ~plugin ~fn ~args - ) - ) end module VDI = struct diff --git a/ocaml/xapi/quicktest.ml b/ocaml/xapi/quicktest.ml --- a/ocaml/xapi/quicktest.ml +++ b/ocaml/xapi/quicktest.ml @@ -414,12 +414,7 @@ (* Give the background thread a chance to start *) Thread.delay 1.5; (* Verify that the function 'test' can be called in the script *) - - while Unix.gettimeofday () -. start < 30. do - let start' = Unix.gettimeofday () in - let result = Client.SR.lvhd_stop_using_these_vdis_and_call_script !rpc session_id vdis "echo" "main" [ ] in - debug test (Printf.sprintf "lvhd-script-hook tool %.2f seconds; output was: %s" (Unix.gettimeofday () -. start') result); - done; + Thread.join t; debug test (Printf.sprintf "Meanwhile background thread executed %d conflicting operations" !total_bg_ops); success test diff --git a/ocaml/xapi/xapi_globs.ml b/ocaml/xapi/xapi_globs.ml --- a/ocaml/xapi/xapi_globs.ml +++ b/ocaml/xapi/xapi_globs.ml @@ -541,9 +541,6 @@ (** Pool.other_config key which, when set to the value "true", enables generation of METADATA_LUN_{HEALTHY_BROKEN} alerts *) let redo_log_alert_key = "metadata_lun_alerts" -(** Called from the SR.lvhd_stop_using_these_vdis_and_call_script *) -let lvhd_script_hook = "lvhd-script-hook" - (** Mutex for the external authentication in pool *) (* CP-825: Serialize execution of pool-enable-extauth and pool-disable-extauth *) let serialize_pool_enable_disable_extauth = Mutex.create() diff --git a/ocaml/xapi/xapi_sr.ml b/ocaml/xapi/xapi_sr.ml --- a/ocaml/xapi/xapi_sr.ml +++ b/ocaml/xapi/xapi_sr.ml @@ -433,29 +433,3 @@ let blob = Xapi_blob.create ~__context ~mime_type in Db.SR.add_to_blobs ~__context ~self:sr ~key:name ~value:blob; blob - -let lvhd_stop_using_these_vdis_and_call_script ~__context ~vdis ~plugin ~fn ~args = - (* Sanity check: all VDIs should be in the same SR *) - let srs = List.setify (List.concat (List.map (fun vdi -> try [ Db.VDI.get_SR ~__context ~self:vdi ] with _ -> []) vdis)) in - if List.length srs > 1 - then failwith "VDIs must all be in the same SR"; - (* If vdis = [] then srs = []. Otherwise vdis <> [] and len(srs) = 1 *) - if List.length srs = 1 then begin - Sm.assert_pbd_is_plugged ~__context ~sr:(List.hd srs); - if not (Helpers.i_am_srmaster ~__context ~sr:(List.hd srs)) - then failwith "I am not the SRmaster"; (* should never happen *) - end; - - (* Find all the VBDs with currently_attached = true. We rely on logic in the master forwarding layer - to guarantee that no other VBDs may become currently_attached = true. *) - let localhost = Helpers.get_localhost ~__context in - Helpers.call_api_functions ~__context - (fun rpc session_id -> - Sm.with_all_vbds_paused ~__context ~vdis - (fun () -> - Client.Host.call_plugin rpc session_id localhost - plugin - fn - args - ) - )