From 39e81829cdd0951c8ee7c41a4c493b4e01e889df Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Mon, 25 Feb 2013 14:17:10 +0000 Subject: [PATCH 01/10] CI-44: Add an extra field "originator" to session object. This is a key string used for distinguishing different API users sharing the same login name. Signed-off-by: Zheng Li --- ocaml/idl/datamodel.ml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ocaml/idl/datamodel.ml b/ocaml/idl/datamodel.ml index 120e059c58..4532eb556f 100644 --- a/ocaml/idl/datamodel.ml +++ b/ocaml/idl/datamodel.ml @@ -1188,7 +1188,9 @@ let session_login = call ~flags:[] ~versioned_params: [{param_type=String; param_name="uname"; param_doc="Username for login."; param_release=rio_release; param_default=None}; {param_type=String; param_name="pwd"; param_doc="Password for login."; param_release=rio_release; param_default=None}; - {param_type=String; param_name="version"; param_doc="Client API version."; param_release=miami_release; param_default=Some (VString "1.1")}] + {param_type=String; param_name="version"; param_doc="Client API version."; param_release=miami_release; param_default=Some (VString "1.1")}; + {param_type=String; param_name="originator"; param_doc="Key string for distinguishing different API users sharing the same login name."; param_release=clearwater_release; param_default=Some (VString "")} + ] ~errs:[Api_errors.session_authentication_failed] ~secret:true ~allowed_roles:_R_ALL (*any static role can try to create a user session*) @@ -3346,6 +3348,7 @@ let session = 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"; + field ~in_product_since:rel_clearwater ~qualifier:DynamicRO ~default_value:(Some(VString(""))) ~ty:String "originator" "a key string provided by a API user to distinguish itself from other users sharing the same login name"; ] () From 1ca62816cbdc1a3e02822c320d9d75fc917a3ef0 Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Wed, 6 Mar 2013 17:32:05 +0000 Subject: [PATCH 02/10] CI-44: Add the originator param to XAPI session creation Signed-off-by: Zheng Li --- ocaml/xapi/xapi_session.ml | 26 ++++++++++++++------------ ocaml/xapi/xapi_session.mli | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/ocaml/xapi/xapi_session.ml b/ocaml/xapi/xapi_session.ml index 6039ea2d80..fbe7792a45 100644 --- a/ocaml/xapi/xapi_session.ml +++ b/ocaml/xapi/xapi_session.ml @@ -266,9 +266,7 @@ let revalidate_all_sessions ~__context = )with e -> (*unexpected exception: we absorb it and print out a debug line *) debug "Unexpected exception while revalidating external sessions: %s" (ExnHelper.string_of_exn e) -(* XXX: only used internally by the code which grants the guest access to the API. - Needs to be protected by a proper access control system *) -let login_no_password ~__context ~uname ~host ~pool ~is_local_superuser ~subject ~auth_user_sid ~auth_user_name ~rbac_permissions = +let login_no_password_common ~__context ~uname ~originator ~host ~pool ~is_local_superuser ~subject ~auth_user_sid ~auth_user_name ~rbac_permissions = 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 *) @@ -282,22 +280,26 @@ let login_no_password ~__context ~uname ~host ~pool ~is_local_superuser ~subject (* 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 parent=%s" - (trackid session_id) pool (match uname with None->""|Some u->u) is_local_superuser auth_user_sid (trackid parent); + info "Session.create %s pool=%b uname=%s originator=%s is_local_superuser=%b auth_user_sid=%s parent=%s" + (trackid session_id) pool (match uname with None->""|Some u->u) originator 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 ~parent; + ~auth_user_name ~rbac_permissions ~parent ~originator; 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 *) let rpc = Helpers.make_rpc ~__context in ignore(Client.Session.get_uuid rpc session_id session_id); - session_id +(* XXX: only used internally by the code which grants the guest access to the API. + Needs to be protected by a proper access control system *) +let login_no_password ~__context ~uname ~host ~pool ~is_local_superuser ~subject ~auth_user_sid ~auth_user_name ~rbac_permissions = + login_no_password_common ~__context ~uname ~originator:"" ~host ~pool ~is_local_superuser ~subject ~auth_user_sid ~auth_user_name ~rbac_permissions + (** Cause the master to update the session last_active every 30s or so *) let consider_touching_session rpc session_id = let time = ref (Unix.gettimeofday ()) in @@ -354,13 +356,13 @@ let slave_local_login_with_password ~__context ~uname ~pwd = wipe_params_after_f - try and authenticate remotely, passing the supplied username/password to the external auth/directory service. (Note: see below for definition of 'authenticate remotely') 2. otherwise, Session.login_with_password will only attempt to authenticate against the local superuser credentials *) -let login_with_password ~__context ~uname ~pwd ~version = wipe_params_after_fn [pwd] (fun () -> +let login_with_password ~__context ~uname ~pwd ~version ~originator = wipe_params_after_fn [pwd] (fun () -> (* !!! Do something with the version number *) if (Context.preauth ~__context) then begin (* in this case, the context origin of this login request is a unix socket bound locally to a filename *) (* we trust requests from local unix filename sockets, so no need to authenticate them before login *) - login_no_password ~__context ~uname:(Some uname) ~host:(Helpers.get_localhost ~__context) + login_no_password_common ~__context ~uname:(Some uname) ~originator ~host:(Helpers.get_localhost ~__context) ~pool:false ~is_local_superuser:true ~subject:(Ref.null) ~auth_user_sid:"" ~auth_user_name:uname ~rbac_permissions:[] end @@ -372,7 +374,7 @@ let login_with_password ~__context ~uname ~pwd ~version = wipe_params_after_fn [ else begin do_local_auth uname pwd; debug "Successful local authentication user %s from %s" uname (Context.get_origin __context); - login_no_password ~__context ~uname:(Some uname) ~host:(Helpers.get_localhost ~__context) + login_no_password_common ~__context ~uname:(Some uname) ~originator ~host:(Helpers.get_localhost ~__context) ~pool:false ~is_local_superuser:true ~subject:(Ref.null) ~auth_user_sid:"" ~auth_user_name:uname ~rbac_permissions:[] end @@ -529,8 +531,8 @@ let login_with_password ~__context ~uname ~pwd ~version = wipe_params_after_fn [ debug "%s" msg; thread_delay_and_raise_error uname msg end - ) in - login_no_password ~__context ~uname:(Some uname) ~host:(Helpers.get_localhost ~__context) + ) in + login_no_password_common ~__context ~uname:(Some uname) ~originator ~host:(Helpers.get_localhost ~__context) ~pool:false ~is_local_superuser:false ~subject:subject ~auth_user_sid:subject_identifier ~auth_user_name:subject_name ~rbac_permissions end diff --git a/ocaml/xapi/xapi_session.mli b/ocaml/xapi/xapi_session.mli index cb87b199ed..fe80d37637 100644 --- a/ocaml/xapi/xapi_session.mli +++ b/ocaml/xapi/xapi_session.mli @@ -27,7 +27,7 @@ val consider_touching_session: (XMLRPC.xmlrpc -> XMLRPC.xmlrpc) -> API.ref_sessi val slave_login: __context:Context.t -> host:[ `host ] Ref.t -> psecret:string -> [ `session ] Ref.t val slave_local_login: __context:Context.t -> psecret:string -> API.ref_session val slave_local_login_with_password: __context:Context.t -> uname:string -> pwd:string -> API.ref_session -val login_with_password: __context:Context.t -> uname:string -> pwd:string -> version:'a -> [ `session ] Ref.t +val login_with_password: __context:Context.t -> uname:string ->pwd:string -> version:'a -> originator:string -> [ `session ] Ref.t val change_password: __context:Context.t -> old_pwd:string -> new_pwd:string -> unit val logout: __context:Context.t -> unit val local_logout: __context:Context.t -> unit From 2ea37e4f0873ae071befe5c26cc9d85ebeefff18 Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Mon, 11 Mar 2013 13:00:16 +0000 Subject: [PATCH 03/10] CI-44: update internal uses of login_with_password with the originator param Signed-off-by: Zheng Li --- ocaml/xapi/cli_operations.ml | 2 +- ocaml/xapi/xapi_cli.ml | 2 +- ocaml/xapi/xapi_http.ml | 4 ++-- ocaml/xapi/xapi_pool.ml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ocaml/xapi/cli_operations.ml b/ocaml/xapi/cli_operations.ml index 7b58aa8ce6..d1b9746ce0 100644 --- a/ocaml/xapi/cli_operations.ml +++ b/ocaml/xapi/cli_operations.ml @@ -2490,7 +2490,7 @@ let vm_migrate printer rpc session_id params = XML_protocol.rpc ~srcstr:"cli" ~dststr:"dst_xapi" ~transport:(SSL(SSL.make ~use_fork_exec_helper:false (), ip, 443)) ~http xml in let username = List.assoc "remote-username" params in let password = List.assoc "remote-password" params in - let remote_session = Client.Session.login_with_password remote_rpc username password "1.3" in + let remote_session = Client.Session.login_with_password remote_rpc username password "1.3" "" in finally (fun () -> let host, host_record = diff --git a/ocaml/xapi/xapi_cli.ml b/ocaml/xapi/xapi_cli.ml index 63b0cd78b4..cef5385014 100644 --- a/ocaml/xapi/xapi_cli.ml +++ b/ocaml/xapi/xapi_cli.ml @@ -68,7 +68,7 @@ let with_session ~local rpc u p session f = let session, logout = match local, session with | false, None -> - Client.Client.Session.login_with_password ~rpc ~uname:u ~pwd:p ~version:Xapi_globs.api_version_string, true + Client.Client.Session.login_with_password ~rpc ~uname:u ~pwd:p ~version:Xapi_globs.api_version_string ~originator:"cli", true | true, None -> Client.Client.Session.slave_local_login_with_password ~rpc ~uname:u ~pwd:p, true | _, Some session -> session, false in diff --git a/ocaml/xapi/xapi_http.ml b/ocaml/xapi/xapi_http.ml index a1fbe46b89..0051318419 100644 --- a/ocaml/xapi/xapi_http.ml +++ b/ocaml/xapi/xapi_http.ml @@ -144,7 +144,7 @@ let assert_credentials_ok realm ?(http_action=realm) ?(fn=Rbac.nofn) (req: Reque | Some (Http.Basic(username, password)) -> begin let session_id = try - Client.Session.login_with_password inet_rpc username password Xapi_globs.api_version_string + Client.Session.login_with_password inet_rpc username password Xapi_globs.api_version_string "" with _ -> raise (Http.Unauthorised realm) in Pervasiveext.finally @@ -181,7 +181,7 @@ let with_context ?(dummy=false) label (req: Request.t) (s: Unix.file_descr) f = | Some (Http.Basic(username, password)) -> begin try - Client.Session.login_with_password inet_rpc username password Xapi_globs.api_version_string, true + Client.Session.login_with_password inet_rpc username password Xapi_globs.api_version_string "", true with Api_errors.Server_error(code, params) when code = Api_errors.session_authentication_failed -> raise (Http.Unauthorised label) end diff --git a/ocaml/xapi/xapi_pool.ml b/ocaml/xapi/xapi_pool.ml index c3341f438b..d505fc9fc3 100644 --- a/ocaml/xapi/xapi_pool.ml +++ b/ocaml/xapi/xapi_pool.ml @@ -665,7 +665,7 @@ let join_common ~__context ~master_address ~master_username ~master_password ~fo a host that does not support pooling then an error will be thrown at this stage *) let rpc = rpc master_address in let session_id = - try Client.Session.login_with_password rpc master_username master_password Xapi_globs.api_version_string + try Client.Session.login_with_password rpc master_username master_password Xapi_globs.api_version_string "" with Http_client.Http_request_rejected _ | Http_client.Http_error _ -> raise (Api_errors.Server_error(Api_errors.pool_joining_host_service_failed, [])) in From acb4590d5bd2e6c97c5cf8031f7b367a32202867 Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Tue, 12 Mar 2013 11:06:13 +0000 Subject: [PATCH 04/10] CI-44: update external components and tests with the new originator param Signed-off-by: Zheng Li --- ocaml/events/event_listen.ml | 2 +- ocaml/graph/graph.ml | 2 +- ocaml/lvhdrt/lvhdrt.ml | 2 +- ocaml/lvhdrt/utils.ml | 4 ++-- ocaml/mpathalert/mpathalert.ml | 2 +- ocaml/multipathrt/alert_utils.ml | 2 +- ocaml/multipathrt/iscsi_utils.ml | 2 +- ocaml/multipathrt/multipathrt.ml | 2 +- ocaml/network/network_monitor_thread.ml | 2 +- ocaml/perftest/apiperf.ml | 2 +- ocaml/perftest/createpool.ml | 6 +++--- ocaml/perftest/perftest.ml | 4 ++-- ocaml/sm-cli/test.ml | 4 ++-- ocaml/toplevel/toplevelhelper.ml | 2 +- ocaml/vncproxy/vncproxy.ml | 2 +- ocaml/xapi/cancel_tests.ml | 2 +- ocaml/xapi/create_storage_main.ml | 2 +- ocaml/xapi/quicktest_common.ml | 2 +- ocaml/xe-cli/import_main.ml | 2 +- 19 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ocaml/events/event_listen.ml b/ocaml/events/event_listen.ml index 192b103273..2fb64c0e0f 100644 --- a/ocaml/events/event_listen.ml +++ b/ocaml/events/event_listen.ml @@ -41,7 +41,7 @@ let _ = Printf.printf "Connecting to Host: %s; Port: %d; Username: %s" !host !port !username; (* Interesting event stuff starts here: *) - let session_id = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.2" in + let session_id = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.2" ~originator:"event_listen" in Client.Event.register ~rpc ~session_id ~classes:["*"]; while true do let events = events_of_xmlrpc (Client.Event.next ~rpc ~session_id) in diff --git a/ocaml/graph/graph.ml b/ocaml/graph/graph.ml index 1196c54ed3..d25cea289b 100644 --- a/ocaml/graph/graph.ml +++ b/ocaml/graph/graph.ml @@ -142,7 +142,7 @@ let _ = "Display an object graph"; (* Interesting event stuff starts here: *) - let session_id = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.2" in + let session_id = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.2" ~originator:"graph" in let classes = List.filter (fun x -> List.mem x Datamodel.expose_get_all_messages_for) all_classes in List.iter (fun x -> if not(List.mem x classes) then failwith (Printf.sprintf "Class %s not available" x)) !wanted; diff --git a/ocaml/lvhdrt/lvhdrt.ml b/ocaml/lvhdrt/lvhdrt.ml index bec9ef02bd..c13a3948b6 100644 --- a/ocaml/lvhdrt/lvhdrt.ml +++ b/ocaml/lvhdrt/lvhdrt.ml @@ -39,7 +39,7 @@ let _ = (* Get a session *) let rpc = rpc_of_hostname !hostname in - let session = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.4" in + let session = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.4" ~originator:"lvhdrt" in try begin diff --git a/ocaml/lvhdrt/utils.ml b/ocaml/lvhdrt/utils.ml index 0b6cc9b1b5..183ab1a04c 100644 --- a/ocaml/lvhdrt/utils.ml +++ b/ocaml/lvhdrt/utils.ml @@ -334,7 +334,7 @@ let create_vdi_tree rpc session sr name_label size ?resize ?(pattern_type=1) pat let wait_for_fist rpc session sr ?(delay=90.0) fist = - let session2 = Client.Session.login_with_password rpc !Globs.username !Globs.password "1.4" in + let session2 = Client.Session.login_with_password rpc !Globs.username !Globs.password "1.4" "lvhdrt" in Client.Event.register rpc session2 ["sr"]; @@ -373,7 +373,7 @@ let wait_for_fist rpc session sr ?(delay=90.0) fist = * delay will be used if at least one VDI is not deleted (e.g. because it didn't * exist. *) let wait_for_vdi_deletion rpc session sr ?(delay=90.0) vdis = - let session2 = Client.Session.login_with_password rpc !Globs.username !Globs.password "1.4" in + let session2 = Client.Session.login_with_password rpc !Globs.username !Globs.password "1.4" "lvhdrt" in Client.Event.register rpc session2 ["vdi"]; debug "Registered for vdi events"; diff --git a/ocaml/mpathalert/mpathalert.ml b/ocaml/mpathalert/mpathalert.ml index 757f023cd3..2e6714c194 100644 --- a/ocaml/mpathalert/mpathalert.ml +++ b/ocaml/mpathalert/mpathalert.ml @@ -67,7 +67,7 @@ let to_string alert = let rec retry_with_session f rpc x = let session = let rec aux () = - try Client.Session.login_with_password ~rpc ~uname:"" ~pwd:"" ~version:"1.4" + try Client.Session.login_with_password ~rpc ~uname:"" ~pwd:"" ~version:"1.4" ~originator:"mpathalert" with _ -> Thread.delay !delay; aux () in aux () in try diff --git a/ocaml/multipathrt/alert_utils.ml b/ocaml/multipathrt/alert_utils.ml index 446f6582b7..0d631dd2f3 100644 --- a/ocaml/multipathrt/alert_utils.ml +++ b/ocaml/multipathrt/alert_utils.ml @@ -104,7 +104,7 @@ let check_path_counts entry max_paths current_paths = (* For all messages m matching the check_message predicate, execute f m *) let wait_for_alert rpc session ?(delay=180.0) check_message f = - let session2 = Client.Session.login_with_password rpc !Globs.username !Globs.password "1.4" in + let session2 = Client.Session.login_with_password rpc !Globs.username !Globs.password "1.4" "multipathrt"in Client.Event.register rpc session2 ["message"]; let finished = ref false in diff --git a/ocaml/multipathrt/iscsi_utils.ml b/ocaml/multipathrt/iscsi_utils.ml index b47eb6fdf9..dba5a6308f 100644 --- a/ocaml/multipathrt/iscsi_utils.ml +++ b/ocaml/multipathrt/iscsi_utils.ml @@ -160,7 +160,7 @@ let setup_iscsi_sr rpc session host iscsi_vm = (scsiid, sr) let wait_for_vm_to_run rpc session ?(delay=60.0) vm = - let session2 = Client.Session.login_with_password rpc !Globs.username !Globs.password "1.4" in + let session2 = Client.Session.login_with_password rpc !Globs.username !Globs.password "1.4" "multipathrt" in Client.Event.register rpc session2 ["vm"]; let finished = ref false in diff --git a/ocaml/multipathrt/multipathrt.ml b/ocaml/multipathrt/multipathrt.ml index 27103e82db..853dc96ecb 100644 --- a/ocaml/multipathrt/multipathrt.ml +++ b/ocaml/multipathrt/multipathrt.ml @@ -37,7 +37,7 @@ let _ = (* Get a session *) let rpc = rpc_of_hostname !hostname in - let session = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.4" in + let session = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.4" ~originator:"multipathrt" in try begin match !tc with diff --git a/ocaml/network/network_monitor_thread.ml b/ocaml/network/network_monitor_thread.ml index 4b2999795d..930306c969 100644 --- a/ocaml/network/network_monitor_thread.ml +++ b/ocaml/network/network_monitor_thread.ml @@ -34,7 +34,7 @@ let send_bond_change_alert dev interfaces message = let ifaces = String.concat "+" (List.sort String.compare interfaces) in let module XenAPI = Client.Client in let session_id = XenAPI.Session.login_with_password - ~rpc:xapi_rpc ~uname:"" ~pwd:"" ~version:"1.4" in + ~rpc:xapi_rpc ~uname:"" ~pwd:"" ~version:"1.4" ~originator:"networkd" in Pervasiveext.finally (fun _ -> let obj_uuid = Util_inventory.lookup Util_inventory._installation_uuid in diff --git a/ocaml/perftest/apiperf.ml b/ocaml/perftest/apiperf.ml index 2bc80413ed..3d8841be20 100644 --- a/ocaml/perftest/apiperf.ml +++ b/ocaml/perftest/apiperf.ml @@ -153,7 +153,7 @@ let _ = if not !master && !slave_limit = 0 then failwith "Must provide either -master or -slaves argument"; - let session = Client.Session.login_with_password rpc "root" "xenroot" "1.2" in + let session = Client.Session.login_with_password rpc "root" "xenroot" "1.2" "perftest" in finally (fun () -> let hosts = Client.Host.get_all rpc session in diff --git a/ocaml/perftest/createpool.ml b/ocaml/perftest/createpool.ml index 01c7083cdc..bdf3dee21b 100644 --- a/ocaml/perftest/createpool.ml +++ b/ocaml/perftest/createpool.ml @@ -248,7 +248,7 @@ let create_sdk_pool session_id sdkname pool_name key ipbase = if firstboot.(i) then true else begin let rpc = remoterpc ip in try - let s = Client.Session.login_with_password rpc "root" "xensource" "1.1" in + let s = Client.Session.login_with_password rpc "root" "xensource" "1.1" "perftest" in finally (fun () -> let host = List.hd (Client.Host.get_all rpc s) in (* only one host because it hasn't joined the pool yet *) @@ -282,7 +282,7 @@ let create_sdk_pool session_id sdkname pool_name key ipbase = let host_uuids = Array.mapi (fun i vm -> let n = i + 1 in let rpc = remoterpc (Printf.sprintf "192.168.%d.%d" pool.ipbase n) in - let s = Client.Session.login_with_password rpc "root" "xensource" "1.1" in + let s = Client.Session.login_with_password rpc "root" "xensource" "1.1" "perftest" in let h = List.hd (Client.Host.get_all rpc s) in let u = Client.Host.get_uuid rpc s h in debug "Setting name of host %d" n; @@ -295,7 +295,7 @@ let create_sdk_pool session_id sdkname pool_name key ipbase = ) hosts in let poolrpc = remoterpc (Printf.sprintf "192.168.%d.1" pool.ipbase) in - let poolses = Client.Session.login_with_password poolrpc "root" "xensource" "1.1" in + let poolses = Client.Session.login_with_password poolrpc "root" "xensource" "1.1" "perftest" in let vpool=List.hd (Client.Pool.get_all poolrpc poolses) in Client.Pool.add_to_other_config poolrpc poolses vpool "scenario" pool_name; diff --git a/ocaml/perftest/perftest.ml b/ocaml/perftest/perftest.ml index c9f0f47916..e90546e129 100644 --- a/ocaml/perftest/perftest.ml +++ b/ocaml/perftest/perftest.ml @@ -95,7 +95,7 @@ let _ = List.iter (fun x -> debug "* %s" x) lines | _ -> - let session = Client.Session.login_with_password rpc "root" "xenroot" "1.2" in + let session = Client.Session.login_with_password rpc "root" "xenroot" "1.2" "perftest" in let (_: API.string_to_string_map) = get_metadata rpc session in finally (fun () -> @@ -111,7 +111,7 @@ let _ = debug ~out:stderr "Not yet implemented ... "; | "run" -> let newrpc = if pool.Scenario.sdk then remoterpc (Printf.sprintf "192.168.%d.1" !ipbase) else rpc in - let session = if pool.Scenario.sdk then Client.Session.login_with_password newrpc "root" "xensource" "1.2" else session in + let session = if pool.Scenario.sdk then Client.Session.login_with_password newrpc "root" "xensource" "1.2" "perftest" else session in finally (fun () -> marshall pool (get_metadata newrpc session) (Tests.run newrpc session !key !run_all !iter)) (fun () -> if pool.Scenario.sdk then Client.Session.logout newrpc session) diff --git a/ocaml/sm-cli/test.ml b/ocaml/sm-cli/test.ml index faaf714a71..099f7ff360 100644 --- a/ocaml/sm-cli/test.ml +++ b/ocaml/sm-cli/test.ml @@ -342,10 +342,10 @@ let _ = rxtransport := (TCP (!host2, 80)); rtransport := (TCP (!host2, 80)); - let localsession = XapiClient.Session.login_with_password xrpc !username !password "1.0" in + let localsession = XapiClient.Session.login_with_password xrpc !username !password "1.0" "sm-cli" in session := Ref.string_of localsession; - let remotesession = XapiClient.Session.login_with_password rxrpc !username !password "1.0" in + let remotesession = XapiClient.Session.login_with_password rxrpc !username !password "1.0" "sm-cli" in rsession := Ref.string_of remotesession; let url = Printf.sprintf "http://%s/services/SM?session_id=%s" !host !session in diff --git a/ocaml/toplevel/toplevelhelper.ml b/ocaml/toplevel/toplevelhelper.ml index 7b12d8844b..d92f58f4ab 100644 --- a/ocaml/toplevel/toplevelhelper.ml +++ b/ocaml/toplevel/toplevelhelper.ml @@ -24,4 +24,4 @@ let rpc xml = open Client let init_session username password = - Client.Session.login_with_password ~rpc ~uname:username ~pwd:password ~version:"1.2" + Client.Session.login_with_password ~rpc ~uname:username ~pwd:password ~version:"1.2" ~originator:"toplevel" diff --git a/ocaml/vncproxy/vncproxy.ml b/ocaml/vncproxy/vncproxy.ml index 6f2df86000..e8861b42f7 100644 --- a/ocaml/vncproxy/vncproxy.ml +++ b/ocaml/vncproxy/vncproxy.ml @@ -73,7 +73,7 @@ let _ = with _ -> List.hd (Client.VM.get_by_name_label rpc session_id vm) in - let session_id = Client.Session.login_with_password rpc !username !password "1.1" in + let session_id = Client.Session.login_with_password rpc !username !password "1.1" "vncproxy" in finally (fun () -> let vm = find_vm rpc session_id !vm in diff --git a/ocaml/xapi/cancel_tests.ml b/ocaml/xapi/cancel_tests.ml index 2f0cead070..f1132454d7 100644 --- a/ocaml/xapi/cancel_tests.ml +++ b/ocaml/xapi/cancel_tests.ml @@ -402,7 +402,7 @@ let _ = "Test VM lifecycle cancellation leaves the system in a valid state"; let rpc = make_rpc () in - let session_id = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.2" in + let session_id = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.2" ~originator:"cancel_tests" in finally (fun () -> match Client.VM.get_by_name_label ~rpc ~session_id ~label:!vm with diff --git a/ocaml/xapi/create_storage_main.ml b/ocaml/xapi/create_storage_main.ml index a0b9fe6018..72c443d389 100644 --- a/ocaml/xapi/create_storage_main.ml +++ b/ocaml/xapi/create_storage_main.ml @@ -31,6 +31,6 @@ let _ = let http = xmlrpc ~version:"1.0" "/" in let rpc xml = XML_protocol.rpc ~transport:(TCP(!host, !port)) ~http xml in let session_id = Client.Session.login_with_password ~rpc - ~uname:!username ~pwd:!password ~version:Xapi_globs.api_version_string in + ~uname:!username ~pwd:!password ~version:Xapi_globs.api_version_string ~originator:"" in create_storage_localhost rpc session_id; Client.Session.logout ~rpc ~session_id diff --git a/ocaml/xapi/quicktest_common.ml b/ocaml/xapi/quicktest_common.ml index 8c546feadc..db23e55224 100644 --- a/ocaml/xapi/quicktest_common.ml +++ b/ocaml/xapi/quicktest_common.ml @@ -156,7 +156,7 @@ let rpc = ref rpc_unix_domain let using_unix_domain_socket = ref true let init_session username password = - Client.Session.login_with_password ~rpc:!rpc ~uname:username ~pwd:password ~version:Xapi_globs.api_version_string + Client.Session.login_with_password ~rpc:!rpc ~uname:username ~pwd:password ~version:Xapi_globs.api_version_string ~originator:"quick_test" let get_pool session_id = let pool = Client.Pool.get_all !rpc session_id in diff --git a/ocaml/xe-cli/import_main.ml b/ocaml/xe-cli/import_main.ml index cae563a42e..d2393a8e57 100644 --- a/ocaml/xe-cli/import_main.ml +++ b/ocaml/xe-cli/import_main.ml @@ -51,7 +51,7 @@ let _ = let path = !path in if path = "" then failwith "Must supply an XVA path (file or directory) as an argument"; - let session_id: API.ref_session = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password in + let session_id: API.ref_session = Client.Session.login_with_password ~rpc ~uname:!username ~pwd:!password ~version:"1.2" ~originator:"cli" in let send_fn = match Import.classify path with | Zurich -> stream_from_xva_dir path From 385406ccec4731f66a3b7fb0615ea8f46d740bd0 Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Tue, 12 Mar 2013 11:32:22 +0000 Subject: [PATCH 05/10] CI-44: Add max_sessions_per_originator config Signed-off-by: Zheng Li --- ocaml/xapi/xapi_globs.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ocaml/xapi/xapi_globs.ml b/ocaml/xapi/xapi_globs.ml index cfef47b4c6..2ac583d979 100644 --- a/ocaml/xapi/xapi_globs.ml +++ b/ocaml/xapi/xapi_globs.ml @@ -234,6 +234,9 @@ let max_tasks = 200 (* We must allow for more sessions than running tasks *) let max_sessions = max_tasks * 2 +(* For sessions with specified originator, their session limits are counted independently. *) +let max_sessions_per_originator = 50 + (* The Unix.time that represents the maximum time in the future that a 32 bit time can cope with *) let the_future = 2147483647.0 From 25d25364d4b7655e5caa09e3dd4e66b69feb1a56 Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Tue, 12 Mar 2013 11:51:18 +0000 Subject: [PATCH 06/10] CI-44: update session create/destory rbac audit functions Based on some previous patches from Thomas Sanders. Signed-off-by: Zheng Li --- ocaml/idl/ocaml_backend/rbac_audit.ml | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/ocaml/idl/ocaml_backend/rbac_audit.ml b/ocaml/idl/ocaml_backend/rbac_audit.ml index b092e9fbb3..b57852216d 100644 --- a/ocaml/idl/ocaml_backend/rbac_audit.ml +++ b/ocaml/idl/ocaml_backend/rbac_audit.ml @@ -538,27 +538,32 @@ let denied ~__context ~session_id ~action ~permission ?args () = audit_line_of __context session_id "DENIED" "" "" action permission ?args () ) -let session_destroy ~__context ~session_id = -(* - (* this is currently only creating spam in the audit log *) - let action="session.destroy" in - allowed_ok ~__context ~session_id ~action ~permission:action () -*) - () - -let session_create ~__context ~session_id ~uname = +let session_create_or_destroy ~create ~__context ~session_id ~uname = wrap (fun () -> let session_rec = DB_Action.Session.get_record ~__context ~self:session_id in let s_is_intrapool = session_rec.API.session_pool in let s_is_lsu = session_rec.API.session_is_local_superuser in (* filters out intra-pool logins to avoid spamming the audit log *) if (not s_is_intrapool) && (not s_is_lsu) then ( - let action="session.create" in + let action = (if create then "session.create" else "session.destroy") in + let originator = session_rec.API.session_originator in let sexpr_of_args = - (get_sexpr_arg "uname" (match uname with None->""|Some u->u) "" ""):: + (get_sexpr_arg "originator" originator "" ""):: [] in + let sexpr_of_args = + if create then + (get_sexpr_arg "uname" (match uname with None->""|Some u->u) "" ""):: + sexpr_of_args + else + sexpr_of_args + in allowed_post_fn_ok ~__context ~session_id ~action ~sexpr_of_args ~permission:action () ) ) +let session_destroy ~__context ~session_id = + session_create_or_destroy ~uname:None ~create:false ~__context ~session_id + +let session_create ~__context ~session_id ~uname = + session_create_or_destroy ~create:true ~__context ~session_id ~uname From 8c7b147c4d3479eb916dd8dbd3955a48fd3c1e49 Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Tue, 12 Mar 2013 13:23:59 +0000 Subject: [PATCH 07/10] CI-44: it seems making better sense to expire tasks before sessions Signed-off-by: Zheng Li --- ocaml/xapi/db_gc.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ocaml/xapi/db_gc.ml b/ocaml/xapi/db_gc.ml index d7ee923d7e..e87868c29b 100644 --- a/ocaml/xapi/db_gc.ml +++ b/ocaml/xapi/db_gc.ml @@ -470,8 +470,8 @@ let single_pass () = "PGPUs", gc_PGPUs; "Host patches", gc_Host_patches; "Host CPUs", gc_host_cpus; - "Sessions", timeout_sessions; "Tasks", timeout_tasks; + "Sessions", timeout_sessions; "Messages", gc_messages; (* timeout_alerts; *) (* CA-29253: wake up all blocked clients *) From 26de5d5fadafdd51488493893087dbf411d9887d Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Tue, 12 Mar 2013 17:22:10 +0000 Subject: [PATCH 08/10] CI-44: add max_sessions_per_user_name config variable Signed-off-by: Zheng Li --- ocaml/xapi/xapi_globs.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ocaml/xapi/xapi_globs.ml b/ocaml/xapi/xapi_globs.ml index 2ac583d979..791ab3e399 100644 --- a/ocaml/xapi/xapi_globs.ml +++ b/ocaml/xapi/xapi_globs.ml @@ -237,6 +237,9 @@ let max_sessions = max_tasks * 2 (* For sessions with specified originator, their session limits are counted independently. *) let max_sessions_per_originator = 50 +(* For sessions with specifiied user name (non-root), their session limit are counted independently *) +let max_sessions_per_user_name = 50 + (* The Unix.time that represents the maximum time in the future that a 32 bit time can cope with *) let the_future = 2147483647.0 From 6059070ddedf50acd3560892d1f88bfafe3414ee Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Tue, 12 Mar 2013 17:23:14 +0000 Subject: [PATCH 09/10] CI-44: expire sessions based on username/originator specific quota Based on some previous patches by Thomas Sanders. The current algorithm is implemented as follows: * For sessions with their own auth_user_name (other than "root"/""), they will use their independent session quota (Xapi_globs.max_sessions_per_user_name) grouped by their auth_user_name. This can happen in following cases: - The session creator uses an external authentication method where the username is not the default - The session creator is logged in as local super user (hence no username/password authentication required) but still chooses to pass an independent username argument in purpose (e.g. vmpr, sm) * Sessions without independent auth_user_name (e.g. without RBAC, most external API users will have to share the same super user login) can still distiguish themselves using the new "originator" param during session creation. For sessions created with the optional "originator" argument, they will use their independent session quota (Xapi_globs.max_sessions_per_originator) grouped by their originator key. * All the rest sessions are in the common session pool, as before, sharing the default session quota (Xapi_globs.max_sessions). Among them, internal sessions will have higher prioirty than the external ones. Signed-off-by: Zheng Li --- ocaml/xapi/db_gc.ml | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/ocaml/xapi/db_gc.ml b/ocaml/xapi/db_gc.ml index e87868c29b..668a301ebe 100644 --- a/ocaml/xapi/db_gc.ml +++ b/ocaml/xapi/db_gc.ml @@ -221,7 +221,7 @@ let check_host_liveness ~__context = let task_status_is_completed task_status = (task_status=`success) || (task_status=`failure) || (task_status=`cancelled) -let timeout_sessions_common ~__context sessions = +let timeout_sessions_common ~__context sessions limit session_group = let unused_sessions = List.filter (fun (x, _) -> let rec is_session_unused s = @@ -243,19 +243,18 @@ let timeout_sessions_common ~__context sessions = ) 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 + let disposable_sessions = List.map (fun (x, y) -> x, Date.to_float y.Db_actions.session_last_active, y.Db_actions.session_uuid) unused_sessions in (* Definitely invalidate sessions last used long ago *) let threshold_time = Unix.time () -. !Xapi_globs.inactive_session_timeout in let young, old = List.partition (fun (_, y, _) -> y > threshold_time) disposable_sessions in (* If there are too many young sessions then we need to delete the oldest *) let lucky, unlucky = - if List.length young <= Xapi_globs.max_sessions + if List.length young <= limit then young, [] (* keep them all *) else (* Need to reverse sort by last active and drop the oldest *) - List.chop Xapi_globs.max_sessions (List.sort (fun (_,a, _) (_,b, _) -> compare b a) young) in + List.chop limit (List.sort (fun (_,a, _) (_,b, _) -> compare b a) young) in let cancel doc sessions = List.iter (fun (s, active, uuid) -> @@ -264,19 +263,31 @@ let timeout_sessions_common ~__context sessions = ) sessions in (* Only the 'lucky' survive: the 'old' and 'unlucky' are destroyed *) if unlucky <> [] - then debug "Number of disposable sessions in database (%d/%d) exceeds limit (%d): will delete the oldest" (List.length disposable_sessions) (List.length sessions) Xapi_globs.max_sessions; + then debug "Number of disposable sessions in database (%d/%d) exceeds limit (%d): will delete the oldest" (List.length disposable_sessions) (List.length sessions) limit; cancel "Timed out session because of its age" old; cancel "Timed out session because max number of sessions was exceeded" unlucky let timeout_sessions ~__context = - let all_sessions = - Db.Session.get_internal_records_where ~__context ~expr:Db_filter_types.True - in - let (intrapool_sessions, normal_sessions) = - List.partition (fun (_, y) -> y.Db_actions.session_pool) all_sessions - in begin - timeout_sessions_common ~__context normal_sessions; - timeout_sessions_common ~__context intrapool_sessions; + let all_sessions = Db.Session.get_internal_records_where ~__context ~expr:Db_filter_types.True in + let pool_sessions, nonpool_sessions = List.partition (fun (_, s) -> s.Db_actions.session_pool) all_sessions in + let use_root_auth_name s = s.Db_actions.session_auth_user_name = "" || s.Db_actions.session_auth_user_name = "root" in + let anon_sessions, named_sessions = List.partition (fun (_, s) -> s.Db_actions.session_originator = "" && use_root_auth_name s) nonpool_sessions in + let session_groups = Hashtbl.create 37 in + List.iter (function (_, s) as rs -> + let key = if use_root_auth_name s then `Orig s.Db_actions.session_originator else `Name s.Db_actions.session_auth_user_name in + let current_sessions = + try Hashtbl.find session_groups key + with Not_found -> [] in + Hashtbl.replace session_groups key (rs :: current_sessions) + ) named_sessions; + begin + Hashtbl.iter + (fun key ss -> match key with + | `Orig orig -> timeout_sessions_common ~__context ss Xapi_globs.max_sessions_per_originator ("originator:"^orig) + | `Name name -> timeout_sessions_common ~__context ss Xapi_globs.max_sessions_per_user_name ("username:"^name)) + session_groups; + timeout_sessions_common ~__context anon_sessions Xapi_globs.max_sessions "external"; + timeout_sessions_common ~__context pool_sessions Xapi_globs.max_sessions "internal"; end let probation_pending_tasks = Hashtbl.create 53 From c7ae2c6a04fc4f2a986d66df760fcf9537f52865 Mon Sep 17 00:00:00 2001 From: Zheng Li Date: Tue, 16 Apr 2013 13:32:19 +0000 Subject: [PATCH 10/10] Bump API version number ... due to the incompatible change on the Session.login_with_password signature etc. Xapi_globs.xencenter_min_verstring is kept unchanged and should probably wait until XenCenter changes get in. Signed-off-by: Zheng Li --- ocaml/idl/xenenterpriseapi-coversheet.tex | 4 ++-- ocaml/xapi/xapi_globs.ml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ocaml/idl/xenenterpriseapi-coversheet.tex b/ocaml/idl/xenenterpriseapi-coversheet.tex index 676d6ad0c3..55f1d5b54f 100644 --- a/ocaml/idl/xenenterpriseapi-coversheet.tex +++ b/ocaml/idl/xenenterpriseapi-coversheet.tex @@ -17,9 +17,9 @@ \newcommand{\releasestatement}{} %% Document revision -\newcommand{\revstring}{API Revision 1.10} +\newcommand{\revstring}{API Revision 2.0} %% Document authors \newcommand{\docauthors}{ } -\newcommand{\legalnotice}{Copyright \copyright{} 2006-2012 Citrix Systems, Inc. All Rights Reserved.} +\newcommand{\legalnotice}{Copyright \copyright{} 2006-2013 Citrix Systems, Inc. All Rights Reserved.} diff --git a/ocaml/xapi/xapi_globs.ml b/ocaml/xapi/xapi_globs.ml index 791ab3e399..3f48e89381 100644 --- a/ocaml/xapi/xapi_globs.ml +++ b/ocaml/xapi/xapi_globs.ml @@ -35,8 +35,8 @@ let version_minor = Version.xapi_version_minor let xapi_user_agent = "xapi/"^(string_of_int version_major)^"."^(string_of_int version_minor) (* api version *) -let api_version_major = 1L -let api_version_minor = 10L +let api_version_major = 2L +let api_version_minor = 0L let api_version_string = Printf.sprintf "%Ld.%Ld" api_version_major api_version_minor let api_version_vendor = "XenSource" @@ -49,7 +49,7 @@ let tools_version = ref tools_version_none (* client min/max version range *) let xencenter_min_verstring = "1.10" -let xencenter_max_verstring = "1.10" +let xencenter_max_verstring = "2.0" (* linux pack vsn key in host.software_version (used for a pool join restriction *) let linux_pack_vsn_key = "xs:linux"