# 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 +++++++
xen-api.hg-3.patch
Description: Text Data
_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
|