[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-API] [PATCH 1 of 3] CA-34933: For each host, cache the session used communicating within the pool



# HG changeset patch
# User Thomas Gazagnaire <thomas.gazagnaire@xxxxxxxxxx>
# Date 1260283362 0
# Node ID 2acddc1fa6a2fb77b1534a1089b28e4ba4412520
# Parent  1f49f00797faf725de371513be573e0ca0badb26
CA-34933: For each host, cache the session used communicating within the pool.

Signed-off-by: Thomas Gazagnaire <thomas.gazagnaire@xxxxxxxxxx>

diff -r 1f49f00797fa -r 2acddc1fa6a2 ocaml/idl/ocaml_backend/context.ml
--- a/ocaml/idl/ocaml_backend/context.ml        Fri Dec 04 16:04:36 2009 +0000
+++ b/ocaml/idl/ocaml_backend/context.ml        Tue Dec 08 14:42:42 2009 +0000
@@ -45,6 +45,11 @@
   match x.session_id with
     | None -> failwith "Could not find a session_id"
     | Some x -> x
+
+let has_session_id x =
+       match x.session_id with
+       | None -> false
+       | Some _ -> true
 
 let forwarded_task ctx =
   ctx.forwarded_task  
diff -r 1f49f00797fa -r 2acddc1fa6a2 ocaml/idl/ocaml_backend/context.mli
--- a/ocaml/idl/ocaml_backend/context.mli       Fri Dec 04 16:04:36 2009 +0000
+++ b/ocaml/idl/ocaml_backend/context.mli       Tue Dec 08 14:42:42 2009 +0000
@@ -48,6 +48,7 @@
 (** [session_of_t __context] returns the session id stored in [__context]. In 
case there is no session id in this
     context, it fails with [Failure "Could not find a session_id"]. *)
 val get_session_id : t -> API.ref_session
+val has_session_id : t -> bool
 
 (** [get_task_id __context] returns the task id stored in [__context]. Such a 
task can be either a task stored in 
     database or a tempory task (also called dummy). *)
diff -r 1f49f00797fa -r 2acddc1fa6a2 ocaml/xapi/helpers.ml
--- a/ocaml/xapi/helpers.ml     Fri Dec 04 16:04:36 2009 +0000
+++ b/ocaml/xapi/helpers.ml     Tue Dec 08 14:42:42 2009 +0000
@@ -94,47 +94,43 @@
       (* Slave has to go back to master via network *)
       Xmlrpcclient.do_secure_xml_rpc 
        ~subtask_of
-  ~use_stunnel_cache:true
+       ~use_stunnel_cache:true
     ~version:"1.1" ~host:(Pool_role.get_master_address ())
     ~port:!Xapi_globs.https_port ~path:"/" xml 
     (* No auth needed over unix domain socket *)
 
+let do_internal_login ~__context =
+       let login =
+               if Pool_role.is_master () then
+                       (fun () ->
+                                if Context.has_session_id __context && 
Db.Session.get_pool ~__context ~self:(Context.get_session_id __context) then
+                                        Context.get_session_id __context
+                                else begin
+                                        let rpc = make_rpc ~__context in
+                                        let session_id = 
Client.Client.Session.slave_login rpc (get_localhost ~__context) 
!Xapi_globs.pool_secret in
+                                        debug "local login done";
+                                        session_id
+                                end)
+               else
+                       (fun () ->
+                                let rpc = make_rpc ~__context in
+                                let session_id = 
Client.Client.Session.slave_login rpc (get_localhost ~__context) 
!Xapi_globs.pool_secret in
+                                debug "slave login done";
+                                session_id) in
+       Xapi_globs.get_internal_session login
+
+let with_cached_session ~__context fn =
+       try fn (do_internal_login ~__context)
+       with Api_errors.Server_error (error,_) as e when error = 
Api_errors.session_authentication_failed ->
+               Xapi_globs.reset_internal_session_cache ();
+               debug "remote client call finished with exception %s; cleaning 
the session cache" (Printexc.to_string e);
+               raise e
+
 (** Log into pool master using the client code, call a function
     passing it the rpc function and session id, logout when finished. *)
 let call_api_functions ~__context f =
-  let rpc = make_rpc ~__context in
-  let () = debug "logging into master" in
-  (* If we're the master then our existing session may be a client one without 
'pool' flag set, so
-     we consider making a new one. If we're a slave then our existing session 
(if we have one) must
-     have the 'pool' flag set because it would have been created for us in the 
message forwarding layer
-     in the master, so we just re-use it. [If we haven't got an existing 
session in our context then
-     we always make a new one *)
-  let require_explicit_logout = ref false in
-  let do_master_login () =
-    let session = Client.Client.Session.slave_login rpc (get_localhost 
~__context) !Xapi_globs.pool_secret in
-      require_explicit_logout := true;
-      session 
-  in
-  let session_id =
-      try
-        if Pool_role.is_master() then 
-      begin
-        let session_id = Context.get_session_id __context in
-          if Db.Session.get_pool ~__context ~self:session_id 
-          then session_id
-          else do_master_login ()
-      end 
-      else Context.get_session_id __context
-      with _ -> 
-      do_master_login ()
-  in
-  let () = debug "login done" in
-  finally 
-    (fun () -> f rpc session_id) 
-    (fun () ->
-       debug "remote client call finished; logging out";
-       if !require_explicit_logout 
-      then Client.Client.Session.logout rpc session_id)
+       let rpc = make_rpc ~__context in
+       with_cached_session ~__context (fun session_id ->  f rpc session_id)
 
 let call_emergency_mode_functions hostname f = 
   let rpc xml = Xmlrpcclient.do_secure_xml_rpc ~version:"1.0" ~host:hostname
diff -r 1f49f00797fa -r 2acddc1fa6a2 ocaml/xapi/message_forwarding.ml
--- a/ocaml/xapi/message_forwarding.ml  Fri Dec 04 16:04:36 2009 +0000
+++ b/ocaml/xapi/message_forwarding.ml  Tue Dec 08 14:42:42 2009 +0000
@@ -191,11 +191,8 @@
     ~port:!Xapi_globs.https_port ~path:"/" xml
 
 let call_slave_with_session remote_rpc_fn __context host (task_opt: 
API.ref_task option) f =
-  let session_id = Xapi_session.login_no_password ~__context ~uname:None ~host 
~pool:true ~is_local_superuser:true ~subject:(Ref.null) ~auth_user_sid:"" 
~rbac_permissions:[] in
   let hostname = Db.Host.get_address ~__context ~self:host in
-  Pervasiveext.finally
-    (fun ()->f session_id (remote_rpc_fn __context hostname task_opt))
-    (fun ()->Server_helpers.exec_with_new_task ~session_id "local logout in 
message forwarder" (fun __context -> Xapi_session.logout ~__context))
+  Helpers.with_cached_session ~__context (fun session_id -> f session_id 
(remote_rpc_fn __context hostname task_opt))
 
 let call_slave_with_local_session remote_rpc_fn __context host (task_opt: 
API.ref_task option) f =
   let hostname = Db.Host.get_address ~__context ~self:host in
diff -r 1f49f00797fa -r 2acddc1fa6a2 ocaml/xapi/xapi.ml
--- a/ocaml/xapi/xapi.ml        Fri Dec 04 16:04:36 2009 +0000
+++ b/ocaml/xapi/xapi.ml        Tue Dec 08 14:42:42 2009 +0000
@@ -394,8 +394,7 @@
             debug "Master claims he has no record of us being a slave";
             Xapi_host.set_emergency_mode_error 
Api_errors.host_unknown_to_master [ localhost_uuid ];
             Some Permanent
-        | `ok -> 
-            None
+        | `ok -> None
       )
   with 
   | Api_errors.Server_error(code, params) when code = 
Api_errors.session_authentication_failed ->
diff -r 1f49f00797fa -r 2acddc1fa6a2 ocaml/xapi/xapi_globs.ml
--- a/ocaml/xapi/xapi_globs.ml  Fri Dec 04 16:04:36 2009 +0000
+++ b/ocaml/xapi/xapi_globs.ml  Tue Dec 08 14:42:42 2009 +0000
@@ -15,6 +15,7 @@
 (** A central location for settings related to xapi *)
  
 open Stringext
+open Threadext
 open Printf
 
 (* xapi process returns this code on exit when it wants to be restarted *)
@@ -22,6 +23,19 @@
 
 let pool_secret_path = "/etc/xensource/ptoken"
 let pool_secret = ref ""
+let internal_session : [`session] Ref.t option ref = ref None
+
+let internal_session_mutex = Mutex.create ()
+let get_internal_session login_fn =
+       Mutex.execute internal_session_mutex (fun () ->
+               match !internal_session with
+               | None ->
+                         let session = login_fn () in
+                         internal_session := Some session;
+                         session
+               | Some session -> session)
+let reset_internal_session_cache () =
+       Mutex.execute internal_session_mutex (fun () -> internal_session := 
None)
 
 let localhost_ref : [`host] Ref.t ref = ref Ref.null
 
6 files changed, 52 insertions(+), 40 deletions(-)
ocaml/idl/ocaml_backend/context.ml  |    5 ++
ocaml/idl/ocaml_backend/context.mli |    1 
ocaml/xapi/helpers.ml               |   64 ++++++++++++++++-------------------
ocaml/xapi/message_forwarding.ml    |    5 --
ocaml/xapi/xapi.ml                  |    3 -
ocaml/xapi/xapi_globs.ml            |   14 +++++++


Attachment: xen-api.hg-3.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.