# HG changeset patch # User Marcus Granado # Date 1274449016 -3600 # Node ID 093a35d8808a40adf8468d185944c5131dcc165b # Parent a402deb8e3cfdccc5fd3383d7fb96a76a07917a2 CA-34933: do not kill sessions children of sessions with running tasks Signed-off-by: Marcus Granado diff -r a402deb8e3cf -r 093a35d8808a ocaml/idl/datamodel.ml --- a/ocaml/idl/datamodel.ml +++ b/ocaml/idl/datamodel.ml @@ -2859,6 +2859,7 @@ field ~in_product_since:rel_midnight_ride ~qualifier:DynamicRO ~default_value:(Some(VString(""))) ~ty:String "auth_user_name" "the subject name of the user that was externally authenticated. If a session instance has is_local_superuser set, then the value of this field is undefined."; field ~in_product_since:rel_midnight_ride ~qualifier:StaticRO ~default_value:(Some(VSet [])) ~ty:(Set(String)) "rbac_permissions" "list with all RBAC permissions for this session"; field ~in_product_since:rel_midnight_ride ~qualifier:DynamicRO ~ty:(Set(Ref _task)) "tasks" "list of tasks created using the current session"; + field ~in_product_since:rel_midnight_ride ~qualifier:StaticRO ~default_value:(Some (VRef (Ref.string_of Ref.null))) ~ty:(Ref _session) "parent" "references the parent session that created this session"; ] () diff -r a402deb8e3cf -r 093a35d8808a ocaml/xapi/db_gc.ml --- a/ocaml/xapi/db_gc.ml +++ b/ocaml/xapi/db_gc.ml @@ -207,7 +207,27 @@ (task_status=`success) || (task_status=`failure) || (task_status=`cancelled) let timeout_sessions_common ~__context sessions = - let unused_sessions = List.filter (fun (_, y) -> List.for_all (fun t -> task_status_is_completed (Db.Task.get_status ~__context ~self:t)) y.Db_actions.session_tasks) sessions in + let unused_sessions = List.filter + (fun (x, _) -> + let rec is_session_unused s = + if (s=Ref.null) then true (* top of session tree *) + else + try (* if no session s, assume default value true=unused *) + let tasks = (Db.Session.get_tasks ~__context ~self:s) in + let parent = (Db.Session.get_parent ~__context ~self:s) in + (List.for_all + (fun t -> task_status_is_completed + (* task might not exist anymore, assume completed in this case *) + (try Db.Task.get_status ~__context ~self:t with _->`success) + ) + tasks + ) + && (is_session_unused parent) + with _->true + in is_session_unused x + ) + sessions + in let disposable_sessions = unused_sessions in (* Only keep a list of (ref, last_active, uuid) *) let disposable_sessions = List.map (fun (x, y) -> x, Date.to_float y.Db_actions.session_last_active, y.Db_actions.session_uuid) disposable_sessions in diff -r a402deb8e3cf -r 093a35d8808a ocaml/xapi/xapi_session.ml --- a/ocaml/xapi/xapi_session.ml +++ b/ocaml/xapi/xapi_session.ml @@ -136,7 +136,7 @@ (* CP-982: create tracking id in log files to link username to actions *) info "Session.destroy %s" (trackid self); Rbac_audit.session_destroy ~__context ~session_id:self; - Db.Session.destroy ~__context ~self; + (try Db.Session.destroy ~__context ~self; with _->()); Rbac.destroy_session_permissions_tbl ~session_id:self (* CP-703: ensure that activate sessions are invalidated in a bounded time *) @@ -271,6 +271,7 @@ let session_id = Ref.make () in let uuid = Uuid.to_string (Uuid.make_uuid ()) in let user = Ref.null in (* always return a null reference to the deprecated user object *) + let parent = try Context.get_session_id __context with _ -> Ref.null in (*match uname with (* the user object is deprecated in favor of subject *) Some uname -> Helpers.get_user ~__context uname | None -> Ref.null in*) @@ -280,14 +281,14 @@ (* see also task creation in context.ml *) (* CP-982: promote tracking debug line to info status *) (* CP-982: create tracking id in log files to link username to actions *) - info "Session.create %s pool=%b uname=%s is_local_superuser=%b auth_user_sid=%s" - (trackid session_id) pool (match uname with None->""|Some u->u) is_local_superuser auth_user_sid; + info "Session.create %s pool=%b uname=%s is_local_superuser=%b auth_user_sid=%s parent=%s" + (trackid session_id) pool (match uname with None->""|Some u->u) is_local_superuser auth_user_sid (trackid parent); Db.Session.create ~__context ~ref:session_id ~uuid ~this_user:user ~this_host:host ~pool:pool ~last_active:(Date.of_float (Unix.time ())) ~other_config:[] ~subject:subject ~is_local_superuser:is_local_superuser ~auth_user_sid ~validation_time:(Date.of_float (Unix.time ())) - ~auth_user_name ~rbac_permissions; + ~auth_user_name ~rbac_permissions ~parent; Rbac_audit.session_create ~__context ~session_id ~uname; (* At this point, the session is created, but with an incorrect time *) (* Force the time to be updated by calling an API function with this session *)