diff options
| author | Daniil Baturin <daniil@vyos.io> | 2025-09-18 12:32:18 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-18 12:32:18 +0100 |
| commit | 304e4d2a172fe1baf2c1df7f61b7a0a8e40f7d5d (patch) | |
| tree | 4a415189068819e7914ae1352a69abe08eb45c60 /src | |
| parent | 2da0981501a9bec8b69d29f1e52c10db90571aa4 (diff) | |
| parent | bca62a7bd1da4e78497fdce3882421609ce28c00 (diff) | |
| download | vyconf-304e4d2a172fe1baf2c1df7f61b7a0a8e40f7d5d.tar.gz vyconf-304e4d2a172fe1baf2c1df7f61b7a0a8e40f7d5d.zip | |
Merge pull request #31 from jestabro/interstitial-set
T7737: add analogue of configfs for config tree updates during commit
Diffstat (limited to 'src')
| -rw-r--r-- | src/commit.ml | 54 | ||||
| -rw-r--r-- | src/commit.mli | 7 | ||||
| -rw-r--r-- | src/message.ml | 4 | ||||
| -rw-r--r-- | src/message.mli | 2 | ||||
| -rw-r--r-- | src/session.ml | 98 | ||||
| -rw-r--r-- | src/session.mli | 24 | ||||
| -rw-r--r-- | src/vycall_client.ml | 3 | ||||
| -rw-r--r-- | src/vycall_pbt.ml | 72 | ||||
| -rw-r--r-- | src/vycall_pbt.mli | 6 | ||||
| -rw-r--r-- | src/vycli.ml | 10 | ||||
| -rw-r--r-- | src/vyconf_cli.ml | 10 | ||||
| -rw-r--r-- | src/vyconf_client.ml | 10 | ||||
| -rw-r--r-- | src/vyconf_client.mli | 2 | ||||
| -rw-r--r-- | src/vyconf_client_session.ml | 12 | ||||
| -rw-r--r-- | src/vyconf_pbt.ml | 362 | ||||
| -rw-r--r-- | src/vyconf_pbt.mli | 94 | ||||
| -rw-r--r-- | src/vyconfd.ml | 91 |
17 files changed, 687 insertions, 174 deletions
diff --git a/src/commit.ml b/src/commit.ml index 8913ceb..7b04c36 100644 --- a/src/commit.ml +++ b/src/commit.ml @@ -12,10 +12,20 @@ let tree_source_to_yojson = function | ADD -> `String "ADD" type status = { - success : bool; - out : string; + success : bool; + out : string; } [@@deriving to_yojson] +let default_status = { + success = true; + out = ""; +} + +let fail_status msg = + { success = false; + out = msg; + } + type node_data = { script_name: string; priority: int; @@ -39,6 +49,9 @@ let default_node_data = { type commit_data = { session_id: string; + session_pid: int32; + sudo_user: string; + user: string; dry_run: bool; atomic: bool; background: bool; @@ -49,21 +62,6 @@ type commit_data = { result : status; } [@@deriving to_yojson] -let default_commit_data = { - session_id = ""; - dry_run = false; - atomic = false; - background = false; - init = None; - node_list = []; - config_diff = CT.default; - config_result = CT.default; - result = { success = true; out = ""; }; -} - -let fail_status msg = - { success=false; out=msg } - let lex_order c1 c2 = let c = Vyos1x.Util.lex_order c1.path c2.path in match c with @@ -224,25 +222,31 @@ let config_result_update c_data n_data = let commit_update c_data = match c_data.init with | None -> - { default_commit_data with - init=Some (fail_status "commitd failure: no init status provided") + { c_data with + init = Some (fail_status "commitd failure: no init status provided") } | Some _ -> let func acc_data nd = match nd.reply with | None -> - { default_commit_data with - init=Some (fail_status"commitd failure: no reply status provided") + { c_data with + init = Some (fail_status "commitd failure: no reply status provided") } | Some _ -> config_result_update acc_data nd in List.fold_left func c_data c_data.node_list -let make_commit_data ?(dry_run=false) rt at wt id = +let make_commit_data ?(dry_run=false) rt at wt id pid sudo_user user = let diff = CD.diff_tree [] at wt in let del_list, add_list = calculate_priority_lists rt diff in - { default_commit_data with - session_id = id; + { session_id = id; + session_pid = pid; + sudo_user = sudo_user; + user = user; dry_run = dry_run; + atomic = false; + background = false; + init = None; config_diff = diff; config_result = CT.get_subtree diff ["inter"]; - node_list = del_list @ add_list; } + node_list = del_list @ add_list; + result = default_status; } diff --git a/src/commit.mli b/src/commit.mli index 01022ec..ee38768 100644 --- a/src/commit.mli +++ b/src/commit.mli @@ -17,6 +17,9 @@ type node_data = { type commit_data = { session_id: string; + session_pid: int32; + sudo_user: string; + user: string; dry_run: bool; atomic: bool; background: bool; @@ -33,9 +36,7 @@ val tree_source_to_yojson : tree_source -> [> `String of string ] val default_node_data : node_data -val default_commit_data : commit_data - -val make_commit_data : ?dry_run:bool -> Vyos1x.Reference_tree.t -> Vyos1x.Config_tree.t -> Vyos1x.Config_tree.t -> string -> commit_data +val make_commit_data : ?dry_run:bool -> Vyos1x.Reference_tree.t -> Vyos1x.Config_tree.t -> Vyos1x.Config_tree.t -> string -> int32 -> string -> string -> commit_data val calculate_priority_lists : Vyos1x.Reference_tree.t -> Vyos1x.Config_tree.t -> node_data list * node_data list diff --git a/src/message.ml b/src/message.ml index d4cc374..5b508eb 100644 --- a/src/message.ml +++ b/src/message.ml @@ -13,18 +13,14 @@ let read ic = let header = Bytes.create 4 in let%lwt () = Lwt_io.read_into_exactly ic header 0 4 in let length = EndianBytes.BigEndian.get_int32 header 0 |> Int32.to_int in - Lwt_log.debug (Printf.sprintf "Read length: %d\n" length) |> Lwt.ignore_result; if length < 0 then failwith (Printf.sprintf "Bad message length: %d" length) else let buffer = Bytes.create length in let%lwt () = Lwt_io.read_into_exactly ic buffer 0 length in - Lwt_log.debug (hexdump buffer |> Printf.sprintf "Read mesage: %s") |> Lwt.ignore_result; Lwt.return buffer let write oc msg = let length = Bytes.length msg in let length' = Int32.of_int length in - Lwt_log.debug (Printf.sprintf "Write length: %d\n" length) |> Lwt.ignore_result; - Lwt_log.debug (hexdump msg |> Printf.sprintf "Write message: %s") |> Lwt.ignore_result; if length' < 0l then failwith (Printf.sprintf "Bad message length: %d" length) else let header = Bytes.create 4 in let () = EndianBytes.BigEndian.set_int32 header 0 length' in diff --git a/src/message.mli b/src/message.mli index ec44c56..2d5baa7 100644 --- a/src/message.mli +++ b/src/message.mli @@ -1,3 +1,5 @@ val read : Lwt_io.input_channel -> bytes Lwt.t val write : Lwt_io.output_channel -> bytes -> unit Lwt.t + +val hexdump : bytes -> string diff --git a/src/session.ml b/src/session.ml index 5efc9f5..5f70feb 100644 --- a/src/session.ml +++ b/src/session.ml @@ -3,6 +3,7 @@ module IC = Vyos1x.Internal.Make(CT) module CC = Commitd_client.Commit module CD = Vyos1x.Config_diff module VT = Vyos1x.Vytree +module VL = Vyos1x.Vylist module RT = Vyos1x.Reference_tree module D = Directories module FP = FilePath @@ -12,6 +13,7 @@ exception Session_error of string type cfg_op = | CfgSet of string list * string option * CT.value_behaviour | CfgDelete of string list * string option + [@@deriving yojson] type world = { mutable running_config: CT.t; @@ -20,23 +22,34 @@ type world = { dirs: Directories.t } +type aux_op = { + script_name: string; + tag_value: string option; + changeset: cfg_op list; +} [@@deriving yojson] + + type session_data = { proposed_config : CT.t; modified: bool; conf_mode: bool; changeset: cfg_op list; + mutable aux_changeset: aux_op list; client_app: string; - user: string; client_pid: int32; + client_user: string; + client_sudo_user: string; } -let make world client_app user pid = { +let make world client_app sudo_user user pid = { proposed_config = world.running_config; modified = false; conf_mode = false; changeset = []; + aux_changeset = []; client_app = client_app; - user = user; + client_user = user; + client_sudo_user = sudo_user; client_pid = pid; } @@ -53,6 +66,10 @@ let string_of_op op = | None -> Printf.sprintf "delete %s" path_str | Some v -> Printf.sprintf "delete %s \"%s\"" path_str v) +let sprint_changeset ss = + let ss = List.map (fun x -> aux_op_to_yojson x) ss in + Yojson.Safe.to_string (`List ss) + let set_modified s = if s.modified = true then s else {s with modified = true} @@ -142,6 +159,51 @@ let delete w s path = let changeset' = update_delete w s.changeset path in { s with changeset = changeset' } +let aux_set w s path name tagval = + let _ = validate w s path in + let aux = s.aux_changeset in + let ident y = + if (y.script_name <> name || y.tag_value <> tagval) then false + else true + in + let op' = VL.find ident aux in + let changeset' = + match op' with + | None -> + update_set w [] path + | Some o -> + update_set w o.changeset path + in + let op = + { script_name = name; tag_value = tagval; changeset = changeset' } + in + let aux_changeset' = + VL.replace ~force:true ident op aux + in + s.aux_changeset <- aux_changeset' + +let aux_delete w s path name tagval = + let aux = s.aux_changeset in + let ident y = + if (y.script_name <> name || y.tag_value <> tagval) then false + else true + in + let op' = VL.find ident aux in + let changeset' = + match op' with + | None -> + update_delete w [] path + | Some o -> + update_delete w o.changeset path + in + let op = + { script_name = name; tag_value = tagval; changeset = changeset' } + in + let aux_changeset' = + VL.replace ~force:true ident op aux + in + s.aux_changeset <- aux_changeset' + let discard _w s = { s with changeset = []; } @@ -189,7 +251,7 @@ let save w s file = | Error e -> raise (Session_error (Printf.sprintf "Error saving config: %s" e)) | Ok () -> s -let prepare_commit ?(dry_run=false) w config id = +let prepare_commit ?(dry_run=false) w config id pid sudo_user user = let at = w.running_config in let rt = w.reference_tree in let vc = w.vyconf_config in @@ -205,7 +267,33 @@ let prepare_commit ?(dry_run=false) w config id = with Vyos1x.Internal.Write_error msg -> raise (Session_error msg) in - CC.make_commit_data ~dry_run:dry_run rt at config id + CC.make_commit_data ~dry_run:dry_run rt at config id pid sudo_user user + +let post_process_commit w s ((c_data: CC.commit_data), proposed_config) = + let ident n v y = + if (y.script_name <> n || y.tag_value <> v) then false + else true + in + let func (running, proposed) (n_data: CC.node_data) = + match n_data.reply with + | None -> (running, proposed) + | Some reply -> + match reply.success with + | false -> (running, proposed) + | true -> + begin + let post = + VL.find + (ident n_data.script_name n_data.tag_value) + s.aux_changeset + in + match post with + | None -> (running, proposed) + | Some p -> + (apply_changes w p.changeset running, apply_changes w p.changeset proposed) + end + in + List.fold_left func (c_data.config_result, proposed_config) c_data.node_list let get_config w s id = let at = w.running_config in diff --git a/src/session.mli b/src/session.mli index abe5165..a08f873 100644 --- a/src/session.mli +++ b/src/session.mli @@ -9,19 +9,29 @@ type world = { dirs: Directories.t } +type aux_op = { + script_name: string; + tag_value: string option; + changeset: cfg_op list; +} [@@deriving yojson] + type session_data = { proposed_config : Vyos1x.Config_tree.t; modified: bool; conf_mode: bool; changeset: cfg_op list; + mutable aux_changeset: aux_op list; client_app: string; - user: string; - client_pid: int32 + client_pid: int32; + client_user: string; + client_sudo_user: string; } exception Session_error of string -val make : world -> string -> string -> int32 -> session_data +val sprint_changeset : aux_op list -> string + +val make : world -> string -> string -> string -> int32 -> session_data val set_modified : session_data -> session_data @@ -33,6 +43,10 @@ val set : world -> session_data -> string list -> session_data val delete : world -> session_data -> string list -> session_data +val aux_set : world -> session_data -> string list -> string -> string option -> unit + +val aux_delete : world -> session_data -> string list -> string -> string option -> unit + val get_proposed_config : world -> session_data -> Vyos1x.Config_tree.t val discard : world -> session_data -> session_data @@ -55,7 +69,9 @@ val list_children : world -> session_data -> string list -> string list val string_of_op : cfg_op -> string -val prepare_commit : ?dry_run:bool -> world -> Vyos1x.Config_tree.t -> string -> Commitd_client.Commit.commit_data +val prepare_commit : ?dry_run:bool -> world -> Vyos1x.Config_tree.t -> string -> int32 -> string -> string -> Commitd_client.Commit.commit_data + +val post_process_commit : world -> session_data -> Commitd_client.Commit.commit_data * Vyos1x.Config_tree.t -> Vyos1x.Config_tree.t * Vyos1x.Config_tree.t val get_config : world -> session_data -> string -> string diff --git a/src/vycall_client.ml b/src/vycall_client.ml index 11bbe3f..515f5df 100644 --- a/src/vycall_client.ml +++ b/src/vycall_client.ml @@ -31,6 +31,9 @@ let call_to_node_data ((c: call), (nd: node_data)) = let commit_data_to_commit_proto cd = { session_id = cd.session_id; + session_pid = cd.session_pid; + sudo_user = cd.sudo_user; + user = cd.user; dry_run = cd.dry_run; atomic = cd.atomic; background = cd.background; diff --git a/src/vycall_pbt.ml b/src/vycall_pbt.ml index 715c453..89d2c67 100644 --- a/src/vycall_pbt.ml +++ b/src/vycall_pbt.ml @@ -14,6 +14,9 @@ type call = { type commit = { session_id : string; + session_pid : int32; + sudo_user : string; + user : string; dry_run : bool; atomic : bool; background : bool; @@ -43,6 +46,9 @@ let rec default_call let rec default_commit ?session_id:((session_id:string) = "") + ?session_pid:((session_pid:int32) = 0l) + ?sudo_user:((sudo_user:string) = "") + ?user:((user:string) = "") ?dry_run:((dry_run:bool) = false) ?atomic:((atomic:bool) = false) ?background:((background:bool) = false) @@ -50,6 +56,9 @@ let rec default_commit ?calls:((calls:call list) = []) () : commit = { session_id; + session_pid; + sudo_user; + user; dry_run; atomic; background; @@ -83,6 +92,9 @@ let default_call_mutable () : call_mutable = { type commit_mutable = { mutable session_id : string; + mutable session_pid : int32; + mutable sudo_user : string; + mutable user : string; mutable dry_run : bool; mutable atomic : bool; mutable background : bool; @@ -92,6 +104,9 @@ type commit_mutable = { let default_commit_mutable () : commit_mutable = { session_id = ""; + session_pid = 0l; + sudo_user = ""; + user = ""; dry_run = false; atomic = false; background = false; @@ -122,6 +137,9 @@ let rec pp_call fmt (v:call) = let rec pp_commit fmt (v:commit) = let pp_i fmt () = Pbrt.Pp.pp_record_field ~first:true "session_id" Pbrt.Pp.pp_string fmt v.session_id; + Pbrt.Pp.pp_record_field ~first:false "session_pid" Pbrt.Pp.pp_int32 fmt v.session_pid; + Pbrt.Pp.pp_record_field ~first:false "sudo_user" Pbrt.Pp.pp_string fmt v.sudo_user; + Pbrt.Pp.pp_record_field ~first:false "user" Pbrt.Pp.pp_string fmt v.user; Pbrt.Pp.pp_record_field ~first:false "dry_run" Pbrt.Pp.pp_bool fmt v.dry_run; Pbrt.Pp.pp_record_field ~first:false "atomic" Pbrt.Pp.pp_bool fmt v.atomic; Pbrt.Pp.pp_record_field ~first:false "background" Pbrt.Pp.pp_bool fmt v.background; @@ -167,21 +185,27 @@ let rec encode_pb_call (v:call) encoder = let rec encode_pb_commit (v:commit) encoder = Pbrt.Encoder.string v.session_id encoder; Pbrt.Encoder.key 1 Pbrt.Bytes encoder; + Pbrt.Encoder.int32_as_varint v.session_pid encoder; + Pbrt.Encoder.key 2 Pbrt.Varint encoder; + Pbrt.Encoder.string v.sudo_user encoder; + Pbrt.Encoder.key 3 Pbrt.Bytes encoder; + Pbrt.Encoder.string v.user encoder; + Pbrt.Encoder.key 4 Pbrt.Bytes encoder; Pbrt.Encoder.bool v.dry_run encoder; - Pbrt.Encoder.key 4 Pbrt.Varint encoder; - Pbrt.Encoder.bool v.atomic encoder; Pbrt.Encoder.key 5 Pbrt.Varint encoder; - Pbrt.Encoder.bool v.background encoder; + Pbrt.Encoder.bool v.atomic encoder; Pbrt.Encoder.key 6 Pbrt.Varint encoder; + Pbrt.Encoder.bool v.background encoder; + Pbrt.Encoder.key 7 Pbrt.Varint encoder; begin match v.init with | Some x -> Pbrt.Encoder.nested encode_pb_status x encoder; - Pbrt.Encoder.key 7 Pbrt.Bytes encoder; + Pbrt.Encoder.key 8 Pbrt.Bytes encoder; | None -> (); end; Pbrt.List_util.rev_iter_with (fun x encoder -> Pbrt.Encoder.nested encode_pb_call x encoder; - Pbrt.Encoder.key 8 Pbrt.Bytes encoder; + Pbrt.Encoder.key 9 Pbrt.Bytes encoder; ) v.calls encoder; () @@ -261,6 +285,9 @@ let rec decode_pb_commit d = let background_is_set = ref false in let atomic_is_set = ref false in let dry_run_is_set = ref false in + let user_is_set = ref false in + let sudo_user_is_set = ref false in + let session_pid_is_set = ref false in let session_id_is_set = ref false in while !continue__ do match Pbrt.Decoder.key d with @@ -272,39 +299,60 @@ let rec decode_pb_commit d = end | Some (1, pk) -> Pbrt.Decoder.unexpected_payload "Message(commit), field(1)" pk - | Some (4, Pbrt.Varint) -> begin - v.dry_run <- Pbrt.Decoder.bool d; dry_run_is_set := true; + | Some (2, Pbrt.Varint) -> begin + v.session_pid <- Pbrt.Decoder.int32_as_varint d; session_pid_is_set := true; + end + | Some (2, pk) -> + Pbrt.Decoder.unexpected_payload "Message(commit), field(2)" pk + | Some (3, Pbrt.Bytes) -> begin + v.sudo_user <- Pbrt.Decoder.string d; sudo_user_is_set := true; + end + | Some (3, pk) -> + Pbrt.Decoder.unexpected_payload "Message(commit), field(3)" pk + | Some (4, Pbrt.Bytes) -> begin + v.user <- Pbrt.Decoder.string d; user_is_set := true; end | Some (4, pk) -> Pbrt.Decoder.unexpected_payload "Message(commit), field(4)" pk | Some (5, Pbrt.Varint) -> begin - v.atomic <- Pbrt.Decoder.bool d; atomic_is_set := true; + v.dry_run <- Pbrt.Decoder.bool d; dry_run_is_set := true; end | Some (5, pk) -> Pbrt.Decoder.unexpected_payload "Message(commit), field(5)" pk | Some (6, Pbrt.Varint) -> begin - v.background <- Pbrt.Decoder.bool d; background_is_set := true; + v.atomic <- Pbrt.Decoder.bool d; atomic_is_set := true; end | Some (6, pk) -> Pbrt.Decoder.unexpected_payload "Message(commit), field(6)" pk - | Some (7, Pbrt.Bytes) -> begin - v.init <- Some (decode_pb_status (Pbrt.Decoder.nested d)); + | Some (7, Pbrt.Varint) -> begin + v.background <- Pbrt.Decoder.bool d; background_is_set := true; end | Some (7, pk) -> Pbrt.Decoder.unexpected_payload "Message(commit), field(7)" pk | Some (8, Pbrt.Bytes) -> begin - v.calls <- (decode_pb_call (Pbrt.Decoder.nested d)) :: v.calls; + v.init <- Some (decode_pb_status (Pbrt.Decoder.nested d)); end | Some (8, pk) -> Pbrt.Decoder.unexpected_payload "Message(commit), field(8)" pk + | Some (9, Pbrt.Bytes) -> begin + v.calls <- (decode_pb_call (Pbrt.Decoder.nested d)) :: v.calls; + end + | Some (9, pk) -> + Pbrt.Decoder.unexpected_payload "Message(commit), field(9)" pk | Some (_, payload_kind) -> Pbrt.Decoder.skip d payload_kind done; begin if not !background_is_set then Pbrt.Decoder.missing_field "background" end; begin if not !atomic_is_set then Pbrt.Decoder.missing_field "atomic" end; begin if not !dry_run_is_set then Pbrt.Decoder.missing_field "dry_run" end; + begin if not !user_is_set then Pbrt.Decoder.missing_field "user" end; + begin if not !sudo_user_is_set then Pbrt.Decoder.missing_field "sudo_user" end; + begin if not !session_pid_is_set then Pbrt.Decoder.missing_field "session_pid" end; begin if not !session_id_is_set then Pbrt.Decoder.missing_field "session_id" end; ({ session_id = v.session_id; + session_pid = v.session_pid; + sudo_user = v.sudo_user; + user = v.user; dry_run = v.dry_run; atomic = v.atomic; background = v.background; diff --git a/src/vycall_pbt.mli b/src/vycall_pbt.mli index f389302..fd39a0c 100644 --- a/src/vycall_pbt.mli +++ b/src/vycall_pbt.mli @@ -21,6 +21,9 @@ type call = { type commit = { session_id : string; + session_pid : int32; + sudo_user : string; + user : string; dry_run : bool; atomic : bool; background : bool; @@ -49,6 +52,9 @@ val default_call : val default_commit : ?session_id:string -> + ?session_pid:int32 -> + ?sudo_user:string -> + ?user:string -> ?dry_run:bool -> ?atomic:bool -> ?background:bool -> diff --git a/src/vycli.ml b/src/vycli.ml index 174d6f4..6b13bdd 100644 --- a/src/vycli.ml +++ b/src/vycli.ml @@ -68,7 +68,15 @@ let main socket op path out_format config_format = end | OpSetupSession -> let pid = Int32.of_int (Unix.getppid ()) in - let%lwt resp = setup_session client "vycli" pid in + let user = + try Sys.getenv "USER" + with Not_found -> "" + in + let sudo_user = + try Sys.getenv "SUDO_USER" + with Not_found -> "" + in + let%lwt resp = setup_session client "vycli" sudo_user user pid in begin match resp with | Ok c -> get_token c diff --git a/src/vyconf_cli.ml b/src/vyconf_cli.ml index 0d1535e..b2ee630 100644 --- a/src/vyconf_cli.ml +++ b/src/vyconf_cli.ml @@ -39,6 +39,14 @@ let in_cli_config_session () = let get_session () = let pid = Int32.of_int (Unix.getppid()) in + let user = + try Sys.getenv "USER" + with Not_found -> "" + in + let sudo_user = + try Sys.getenv "SUDO_USER" + with Not_found -> "" + in let socket = "/var/run/vyconfd.sock" in let config_format = config_format_of_string "curly" in let out_format = output_format_of_string "plain" in @@ -47,7 +55,7 @@ let get_session () = in let%lwt resp = session_of_pid client pid in match resp with - | Error _ -> setup_session client "vyconf_cli" pid + | Error _ -> setup_session client "vyconf_cli" sudo_user user pid | _ as c -> c |> Lwt.return let close_session () = diff --git a/src/vyconf_client.ml b/src/vyconf_client.ml index 05b5548..25b923f 100644 --- a/src/vyconf_client.ml +++ b/src/vyconf_client.ml @@ -53,10 +53,16 @@ let prompt client = let%lwt resp = do_request client req in Lwt.return resp -let setup_session ?(on_behalf_of=None) client client_app pid = +let setup_session ?(on_behalf_of=None) client client_app sudo_user user pid = if Option.is_some client.session then Lwt.return (Error "Client is already associated with a session") else let id = on_behalf_of |> (function None -> None | Some x -> (Some (Int32.of_int x))) in - let req = Setup_session {client_application=(Some client_app); on_behalf_of=id; client_pid=pid} in + let req = + Setup_session { client_application=(Some client_app); + on_behalf_of=id; + client_sudo_user=Some sudo_user; + client_user=Some user; + client_pid=pid; } + in let%lwt resp = do_request client req in match resp.status with | Success -> diff --git a/src/vyconf_client.mli b/src/vyconf_client.mli index 762495d..9c63652 100644 --- a/src/vyconf_client.mli +++ b/src/vyconf_client.mli @@ -8,7 +8,7 @@ val shutdown : t -> t Lwt.t val prompt : t -> Vyconf_connect.Vyconf_pbt.response Lwt.t -val setup_session : ?on_behalf_of:(int option) -> t -> string -> int32 -> (t, string) result Lwt.t +val setup_session : ?on_behalf_of:(int option) -> t -> string -> string -> string -> int32 -> (t, string) result Lwt.t val session_of_pid : t -> int32 -> (t, string) result Lwt.t diff --git a/src/vyconf_client_session.ml b/src/vyconf_client_session.ml index 93068fa..035f191 100644 --- a/src/vyconf_client_session.ml +++ b/src/vyconf_client_session.ml @@ -34,7 +34,17 @@ let call_op ?(out_format="plain") ?(config_format="curly") socket token op path match o with | OpSetupSession -> let pid = Int32.of_int (Unix.getppid ()) in - let%lwt resp = Vyconf_client.setup_session client "vyconf_client_session" pid in + let user = + try Sys.getenv "USER" + with Not_found -> "" + in + let sudo_user = + try Sys.getenv "SUDO_USER" + with Not_found -> "" + in + let%lwt resp = + Vyconf_client.setup_session client "vyconf_client_session" sudo_user user pid + in begin match resp with | Ok c -> Vyconf_client.get_token c diff --git a/src/vyconf_pbt.ml b/src/vyconf_pbt.ml index 913fcea..1fbbf75 100644 --- a/src/vyconf_pbt.ml +++ b/src/vyconf_pbt.ml @@ -14,14 +14,16 @@ type request_setup_session = { client_pid : int32; client_application : string option; on_behalf_of : int32 option; + client_user : string option; + client_sudo_user : string option; } type request_session_of_pid = { client_pid : int32; } -type request_session_update_pid = { - client_pid : int32; +type request_session_exists = { + dummy : int32 option; } type request_get_config = { @@ -45,6 +47,18 @@ type request_delete = { path : string list; } +type request_aux_set = { + path : string list; + script_name : string; + tag_value : string option; +} + +type request_aux_delete = { + path : string list; + script_name : string; + tag_value : string option; +} + type request_discard = { dummy : int32 option; } @@ -55,14 +69,14 @@ type request_session_changed = { type request_rename = { edit_level : string list; - from : string; - to_ : string; + source : string; + destination : string; } type request_copy = { edit_level : string list; - from : string; - to_ : string; + source : string; + destination : string; } type request_comment = { @@ -168,8 +182,10 @@ type request = | Discard of request_discard | Session_changed of request_session_changed | Session_of_pid of request_session_of_pid - | Session_update_pid of request_session_update_pid + | Session_exists of request_session_exists | Get_config of request_get_config + | Aux_set of request_aux_set + | Aux_delete of request_aux_delete type request_envelope = { token : string option; @@ -205,10 +221,14 @@ let rec default_request_setup_session ?client_pid:((client_pid:int32) = 0l) ?client_application:((client_application:string option) = None) ?on_behalf_of:((on_behalf_of:int32 option) = None) + ?client_user:((client_user:string option) = None) + ?client_sudo_user:((client_sudo_user:string option) = None) () : request_setup_session = { client_pid; client_application; on_behalf_of; + client_user; + client_sudo_user; } let rec default_request_session_of_pid @@ -217,10 +237,10 @@ let rec default_request_session_of_pid client_pid; } -let rec default_request_session_update_pid - ?client_pid:((client_pid:int32) = 0l) - () : request_session_update_pid = { - client_pid; +let rec default_request_session_exists + ?dummy:((dummy:int32 option) = None) + () : request_session_exists = { + dummy; } let rec default_request_get_config @@ -255,6 +275,26 @@ let rec default_request_delete path; } +let rec default_request_aux_set + ?path:((path:string list) = []) + ?script_name:((script_name:string) = "") + ?tag_value:((tag_value:string option) = None) + () : request_aux_set = { + path; + script_name; + tag_value; +} + +let rec default_request_aux_delete + ?path:((path:string list) = []) + ?script_name:((script_name:string) = "") + ?tag_value:((tag_value:string option) = None) + () : request_aux_delete = { + path; + script_name; + tag_value; +} + let rec default_request_discard ?dummy:((dummy:int32 option) = None) () : request_discard = { @@ -269,22 +309,22 @@ let rec default_request_session_changed let rec default_request_rename ?edit_level:((edit_level:string list) = []) - ?from:((from:string) = "") - ?to_:((to_:string) = "") + ?source:((source:string) = "") + ?destination:((destination:string) = "") () : request_rename = { edit_level; - from; - to_; + source; + destination; } let rec default_request_copy ?edit_level:((edit_level:string list) = []) - ?from:((from:string) = "") - ?to_:((to_:string) = "") + ?source:((source:string) = "") + ?destination:((destination:string) = "") () : request_copy = { edit_level; - from; - to_; + source; + destination; } let rec default_request_comment @@ -433,12 +473,16 @@ type request_setup_session_mutable = { mutable client_pid : int32; mutable client_application : string option; mutable on_behalf_of : int32 option; + mutable client_user : string option; + mutable client_sudo_user : string option; } let default_request_setup_session_mutable () : request_setup_session_mutable = { client_pid = 0l; client_application = None; on_behalf_of = None; + client_user = None; + client_sudo_user = None; } type request_session_of_pid_mutable = { @@ -449,12 +493,12 @@ let default_request_session_of_pid_mutable () : request_session_of_pid_mutable = client_pid = 0l; } -type request_session_update_pid_mutable = { - mutable client_pid : int32; +type request_session_exists_mutable = { + mutable dummy : int32 option; } -let default_request_session_update_pid_mutable () : request_session_update_pid_mutable = { - client_pid = 0l; +let default_request_session_exists_mutable () : request_session_exists_mutable = { + dummy = None; } type request_get_config_mutable = { @@ -499,6 +543,30 @@ let default_request_delete_mutable () : request_delete_mutable = { path = []; } +type request_aux_set_mutable = { + mutable path : string list; + mutable script_name : string; + mutable tag_value : string option; +} + +let default_request_aux_set_mutable () : request_aux_set_mutable = { + path = []; + script_name = ""; + tag_value = None; +} + +type request_aux_delete_mutable = { + mutable path : string list; + mutable script_name : string; + mutable tag_value : string option; +} + +let default_request_aux_delete_mutable () : request_aux_delete_mutable = { + path = []; + script_name = ""; + tag_value = None; +} + type request_discard_mutable = { mutable dummy : int32 option; } @@ -517,26 +585,26 @@ let default_request_session_changed_mutable () : request_session_changed_mutable type request_rename_mutable = { mutable edit_level : string list; - mutable from : string; - mutable to_ : string; + mutable source : string; + mutable destination : string; } let default_request_rename_mutable () : request_rename_mutable = { edit_level = []; - from = ""; - to_ = ""; + source = ""; + destination = ""; } type request_copy_mutable = { mutable edit_level : string list; - mutable from : string; - mutable to_ : string; + mutable source : string; + mutable destination : string; } let default_request_copy_mutable () : request_copy_mutable = { edit_level = []; - from = ""; - to_ = ""; + source = ""; + destination = ""; } type request_comment_mutable = { @@ -730,6 +798,8 @@ let rec pp_request_setup_session fmt (v:request_setup_session) = Pbrt.Pp.pp_record_field ~first:true "client_pid" Pbrt.Pp.pp_int32 fmt v.client_pid; Pbrt.Pp.pp_record_field ~first:false "client_application" (Pbrt.Pp.pp_option Pbrt.Pp.pp_string) fmt v.client_application; Pbrt.Pp.pp_record_field ~first:false "on_behalf_of" (Pbrt.Pp.pp_option Pbrt.Pp.pp_int32) fmt v.on_behalf_of; + Pbrt.Pp.pp_record_field ~first:false "client_user" (Pbrt.Pp.pp_option Pbrt.Pp.pp_string) fmt v.client_user; + Pbrt.Pp.pp_record_field ~first:false "client_sudo_user" (Pbrt.Pp.pp_option Pbrt.Pp.pp_string) fmt v.client_sudo_user; in Pbrt.Pp.pp_brk pp_i fmt () @@ -739,9 +809,9 @@ let rec pp_request_session_of_pid fmt (v:request_session_of_pid) = in Pbrt.Pp.pp_brk pp_i fmt () -let rec pp_request_session_update_pid fmt (v:request_session_update_pid) = +let rec pp_request_session_exists fmt (v:request_session_exists) = let pp_i fmt () = - Pbrt.Pp.pp_record_field ~first:true "client_pid" Pbrt.Pp.pp_int32 fmt v.client_pid; + Pbrt.Pp.pp_record_field ~first:true "dummy" (Pbrt.Pp.pp_option Pbrt.Pp.pp_int32) fmt v.dummy; in Pbrt.Pp.pp_brk pp_i fmt () @@ -776,6 +846,22 @@ let rec pp_request_delete fmt (v:request_delete) = in Pbrt.Pp.pp_brk pp_i fmt () +let rec pp_request_aux_set fmt (v:request_aux_set) = + let pp_i fmt () = + Pbrt.Pp.pp_record_field ~first:true "path" (Pbrt.Pp.pp_list Pbrt.Pp.pp_string) fmt v.path; + Pbrt.Pp.pp_record_field ~first:false "script_name" Pbrt.Pp.pp_string fmt v.script_name; + Pbrt.Pp.pp_record_field ~first:false "tag_value" (Pbrt.Pp.pp_option Pbrt.Pp.pp_string) fmt v.tag_value; + in + Pbrt.Pp.pp_brk pp_i fmt () + +let rec pp_request_aux_delete fmt (v:request_aux_delete) = + let pp_i fmt () = + Pbrt.Pp.pp_record_field ~first:true "path" (Pbrt.Pp.pp_list Pbrt.Pp.pp_string) fmt v.path; + Pbrt.Pp.pp_record_field ~first:false "script_name" Pbrt.Pp.pp_string fmt v.script_name; + Pbrt.Pp.pp_record_field ~first:false "tag_value" (Pbrt.Pp.pp_option Pbrt.Pp.pp_string) fmt v.tag_value; + in + Pbrt.Pp.pp_brk pp_i fmt () + let rec pp_request_discard fmt (v:request_discard) = let pp_i fmt () = Pbrt.Pp.pp_record_field ~first:true "dummy" (Pbrt.Pp.pp_option Pbrt.Pp.pp_int32) fmt v.dummy; @@ -791,16 +877,16 @@ let rec pp_request_session_changed fmt (v:request_session_changed) = let rec pp_request_rename fmt (v:request_rename) = let pp_i fmt () = Pbrt.Pp.pp_record_field ~first:true "edit_level" (Pbrt.Pp.pp_list Pbrt.Pp.pp_string) fmt v.edit_level; - Pbrt.Pp.pp_record_field ~first:false "from" Pbrt.Pp.pp_string fmt v.from; - Pbrt.Pp.pp_record_field ~first:false "to_" Pbrt.Pp.pp_string fmt v.to_; + Pbrt.Pp.pp_record_field ~first:false "source" Pbrt.Pp.pp_string fmt v.source; + Pbrt.Pp.pp_record_field ~first:false "destination" Pbrt.Pp.pp_string fmt v.destination; in Pbrt.Pp.pp_brk pp_i fmt () let rec pp_request_copy fmt (v:request_copy) = let pp_i fmt () = Pbrt.Pp.pp_record_field ~first:true "edit_level" (Pbrt.Pp.pp_list Pbrt.Pp.pp_string) fmt v.edit_level; - Pbrt.Pp.pp_record_field ~first:false "from" Pbrt.Pp.pp_string fmt v.from; - Pbrt.Pp.pp_record_field ~first:false "to_" Pbrt.Pp.pp_string fmt v.to_; + Pbrt.Pp.pp_record_field ~first:false "source" Pbrt.Pp.pp_string fmt v.source; + Pbrt.Pp.pp_record_field ~first:false "destination" Pbrt.Pp.pp_string fmt v.destination; in Pbrt.Pp.pp_brk pp_i fmt () @@ -944,8 +1030,10 @@ let rec pp_request fmt (v:request) = | Discard x -> Format.fprintf fmt "@[<hv2>Discard(@,%a)@]" pp_request_discard x | Session_changed x -> Format.fprintf fmt "@[<hv2>Session_changed(@,%a)@]" pp_request_session_changed x | Session_of_pid x -> Format.fprintf fmt "@[<hv2>Session_of_pid(@,%a)@]" pp_request_session_of_pid x - | Session_update_pid x -> Format.fprintf fmt "@[<hv2>Session_update_pid(@,%a)@]" pp_request_session_update_pid x + | Session_exists x -> Format.fprintf fmt "@[<hv2>Session_exists(@,%a)@]" pp_request_session_exists x | Get_config x -> Format.fprintf fmt "@[<hv2>Get_config(@,%a)@]" pp_request_get_config x + | Aux_set x -> Format.fprintf fmt "@[<hv2>Aux_set(@,%a)@]" pp_request_aux_set x + | Aux_delete x -> Format.fprintf fmt "@[<hv2>Aux_delete(@,%a)@]" pp_request_aux_delete x let rec pp_request_envelope fmt (v:request_envelope) = let pp_i fmt () = @@ -1008,6 +1096,18 @@ let rec encode_pb_request_setup_session (v:request_setup_session) encoder = Pbrt.Encoder.key 3 Pbrt.Varint encoder; | None -> (); end; + begin match v.client_user with + | Some x -> + Pbrt.Encoder.string x encoder; + Pbrt.Encoder.key 4 Pbrt.Bytes encoder; + | None -> (); + end; + begin match v.client_sudo_user with + | Some x -> + Pbrt.Encoder.string x encoder; + Pbrt.Encoder.key 5 Pbrt.Bytes encoder; + | None -> (); + end; () let rec encode_pb_request_session_of_pid (v:request_session_of_pid) encoder = @@ -1015,9 +1115,13 @@ let rec encode_pb_request_session_of_pid (v:request_session_of_pid) encoder = Pbrt.Encoder.key 1 Pbrt.Varint encoder; () -let rec encode_pb_request_session_update_pid (v:request_session_update_pid) encoder = - Pbrt.Encoder.int32_as_varint v.client_pid encoder; - Pbrt.Encoder.key 1 Pbrt.Varint encoder; +let rec encode_pb_request_session_exists (v:request_session_exists) encoder = + begin match v.dummy with + | Some x -> + Pbrt.Encoder.int32_as_varint x encoder; + Pbrt.Encoder.key 1 Pbrt.Varint encoder; + | None -> (); + end; () let rec encode_pb_request_get_config (v:request_get_config) encoder = @@ -1065,6 +1169,36 @@ let rec encode_pb_request_delete (v:request_delete) encoder = ) v.path encoder; () +let rec encode_pb_request_aux_set (v:request_aux_set) encoder = + Pbrt.List_util.rev_iter_with (fun x encoder -> + Pbrt.Encoder.string x encoder; + Pbrt.Encoder.key 1 Pbrt.Bytes encoder; + ) v.path encoder; + Pbrt.Encoder.string v.script_name encoder; + Pbrt.Encoder.key 2 Pbrt.Bytes encoder; + begin match v.tag_value with + | Some x -> + Pbrt.Encoder.string x encoder; + Pbrt.Encoder.key 3 Pbrt.Bytes encoder; + | None -> (); + end; + () + +let rec encode_pb_request_aux_delete (v:request_aux_delete) encoder = + Pbrt.List_util.rev_iter_with (fun x encoder -> + Pbrt.Encoder.string x encoder; + Pbrt.Encoder.key 1 Pbrt.Bytes encoder; + ) v.path encoder; + Pbrt.Encoder.string v.script_name encoder; + Pbrt.Encoder.key 2 Pbrt.Bytes encoder; + begin match v.tag_value with + | Some x -> + Pbrt.Encoder.string x encoder; + Pbrt.Encoder.key 3 Pbrt.Bytes encoder; + | None -> (); + end; + () + let rec encode_pb_request_discard (v:request_discard) encoder = begin match v.dummy with | Some x -> @@ -1088,9 +1222,9 @@ let rec encode_pb_request_rename (v:request_rename) encoder = Pbrt.Encoder.string x encoder; Pbrt.Encoder.key 1 Pbrt.Bytes encoder; ) v.edit_level encoder; - Pbrt.Encoder.string v.from encoder; + Pbrt.Encoder.string v.source encoder; Pbrt.Encoder.key 2 Pbrt.Bytes encoder; - Pbrt.Encoder.string v.to_ encoder; + Pbrt.Encoder.string v.destination encoder; Pbrt.Encoder.key 3 Pbrt.Bytes encoder; () @@ -1099,9 +1233,9 @@ let rec encode_pb_request_copy (v:request_copy) encoder = Pbrt.Encoder.string x encoder; Pbrt.Encoder.key 1 Pbrt.Bytes encoder; ) v.edit_level encoder; - Pbrt.Encoder.string v.from encoder; + Pbrt.Encoder.string v.source encoder; Pbrt.Encoder.key 2 Pbrt.Bytes encoder; - Pbrt.Encoder.string v.to_ encoder; + Pbrt.Encoder.string v.destination encoder; Pbrt.Encoder.key 3 Pbrt.Bytes encoder; () @@ -1360,12 +1494,18 @@ let rec encode_pb_request (v:request) encoder = | Session_of_pid x -> Pbrt.Encoder.nested encode_pb_request_session_of_pid x encoder; Pbrt.Encoder.key 27 Pbrt.Bytes encoder; - | Session_update_pid x -> - Pbrt.Encoder.nested encode_pb_request_session_update_pid x encoder; + | Session_exists x -> + Pbrt.Encoder.nested encode_pb_request_session_exists x encoder; Pbrt.Encoder.key 28 Pbrt.Bytes encoder; | Get_config x -> Pbrt.Encoder.nested encode_pb_request_get_config x encoder; Pbrt.Encoder.key 29 Pbrt.Bytes encoder; + | Aux_set x -> + Pbrt.Encoder.nested encode_pb_request_aux_set x encoder; + Pbrt.Encoder.key 30 Pbrt.Bytes encoder; + | Aux_delete x -> + Pbrt.Encoder.nested encode_pb_request_aux_delete x encoder; + Pbrt.Encoder.key 31 Pbrt.Bytes encoder; end let rec encode_pb_request_envelope (v:request_envelope) encoder = @@ -1460,6 +1600,16 @@ let rec decode_pb_request_setup_session d = end | Some (3, pk) -> Pbrt.Decoder.unexpected_payload "Message(request_setup_session), field(3)" pk + | Some (4, Pbrt.Bytes) -> begin + v.client_user <- Some (Pbrt.Decoder.string d); + end + | Some (4, pk) -> + Pbrt.Decoder.unexpected_payload "Message(request_setup_session), field(4)" pk + | Some (5, Pbrt.Bytes) -> begin + v.client_sudo_user <- Some (Pbrt.Decoder.string d); + end + | Some (5, pk) -> + Pbrt.Decoder.unexpected_payload "Message(request_setup_session), field(5)" pk | Some (_, payload_kind) -> Pbrt.Decoder.skip d payload_kind done; begin if not !client_pid_is_set then Pbrt.Decoder.missing_field "client_pid" end; @@ -1467,6 +1617,8 @@ let rec decode_pb_request_setup_session d = client_pid = v.client_pid; client_application = v.client_application; on_behalf_of = v.on_behalf_of; + client_user = v.client_user; + client_sudo_user = v.client_sudo_user; } : request_setup_session) let rec decode_pb_request_session_of_pid d = @@ -1489,25 +1641,23 @@ let rec decode_pb_request_session_of_pid d = client_pid = v.client_pid; } : request_session_of_pid) -let rec decode_pb_request_session_update_pid d = - let v = default_request_session_update_pid_mutable () in +let rec decode_pb_request_session_exists d = + let v = default_request_session_exists_mutable () in let continue__= ref true in - let client_pid_is_set = ref false in while !continue__ do match Pbrt.Decoder.key d with | None -> ( ); continue__ := false | Some (1, Pbrt.Varint) -> begin - v.client_pid <- Pbrt.Decoder.int32_as_varint d; client_pid_is_set := true; + v.dummy <- Some (Pbrt.Decoder.int32_as_varint d); end | Some (1, pk) -> - Pbrt.Decoder.unexpected_payload "Message(request_session_update_pid), field(1)" pk + Pbrt.Decoder.unexpected_payload "Message(request_session_exists), field(1)" pk | Some (_, payload_kind) -> Pbrt.Decoder.skip d payload_kind done; - begin if not !client_pid_is_set then Pbrt.Decoder.missing_field "client_pid" end; ({ - client_pid = v.client_pid; - } : request_session_update_pid) + dummy = v.dummy; + } : request_session_exists) let rec decode_pb_request_get_config d = let v = default_request_get_config_mutable () in @@ -1608,6 +1758,72 @@ let rec decode_pb_request_delete d = path = v.path; } : request_delete) +let rec decode_pb_request_aux_set d = + let v = default_request_aux_set_mutable () in + let continue__= ref true in + let script_name_is_set = ref false in + while !continue__ do + match Pbrt.Decoder.key d with + | None -> ( + v.path <- List.rev v.path; + ); continue__ := false + | Some (1, Pbrt.Bytes) -> begin + v.path <- (Pbrt.Decoder.string d) :: v.path; + end + | Some (1, pk) -> + Pbrt.Decoder.unexpected_payload "Message(request_aux_set), field(1)" pk + | Some (2, Pbrt.Bytes) -> begin + v.script_name <- Pbrt.Decoder.string d; script_name_is_set := true; + end + | Some (2, pk) -> + Pbrt.Decoder.unexpected_payload "Message(request_aux_set), field(2)" pk + | Some (3, Pbrt.Bytes) -> begin + v.tag_value <- Some (Pbrt.Decoder.string d); + end + | Some (3, pk) -> + Pbrt.Decoder.unexpected_payload "Message(request_aux_set), field(3)" pk + | Some (_, payload_kind) -> Pbrt.Decoder.skip d payload_kind + done; + begin if not !script_name_is_set then Pbrt.Decoder.missing_field "script_name" end; + ({ + path = v.path; + script_name = v.script_name; + tag_value = v.tag_value; + } : request_aux_set) + +let rec decode_pb_request_aux_delete d = + let v = default_request_aux_delete_mutable () in + let continue__= ref true in + let script_name_is_set = ref false in + while !continue__ do + match Pbrt.Decoder.key d with + | None -> ( + v.path <- List.rev v.path; + ); continue__ := false + | Some (1, Pbrt.Bytes) -> begin + v.path <- (Pbrt.Decoder.string d) :: v.path; + end + | Some (1, pk) -> + Pbrt.Decoder.unexpected_payload "Message(request_aux_delete), field(1)" pk + | Some (2, Pbrt.Bytes) -> begin + v.script_name <- Pbrt.Decoder.string d; script_name_is_set := true; + end + | Some (2, pk) -> + Pbrt.Decoder.unexpected_payload "Message(request_aux_delete), field(2)" pk + | Some (3, Pbrt.Bytes) -> begin + v.tag_value <- Some (Pbrt.Decoder.string d); + end + | Some (3, pk) -> + Pbrt.Decoder.unexpected_payload "Message(request_aux_delete), field(3)" pk + | Some (_, payload_kind) -> Pbrt.Decoder.skip d payload_kind + done; + begin if not !script_name_is_set then Pbrt.Decoder.missing_field "script_name" end; + ({ + path = v.path; + script_name = v.script_name; + tag_value = v.tag_value; + } : request_aux_delete) + let rec decode_pb_request_discard d = let v = default_request_discard_mutable () in let continue__= ref true in @@ -1647,8 +1863,8 @@ let rec decode_pb_request_session_changed d = let rec decode_pb_request_rename d = let v = default_request_rename_mutable () in let continue__= ref true in - let to__is_set = ref false in - let from_is_set = ref false in + let destination_is_set = ref false in + let source_is_set = ref false in while !continue__ do match Pbrt.Decoder.key d with | None -> ( @@ -1660,30 +1876,30 @@ let rec decode_pb_request_rename d = | Some (1, pk) -> Pbrt.Decoder.unexpected_payload "Message(request_rename), field(1)" pk | Some (2, Pbrt.Bytes) -> begin - v.from <- Pbrt.Decoder.string d; from_is_set := true; + v.source <- Pbrt.Decoder.string d; source_is_set := true; end | Some (2, pk) -> Pbrt.Decoder.unexpected_payload "Message(request_rename), field(2)" pk | Some (3, Pbrt.Bytes) -> begin - v.to_ <- Pbrt.Decoder.string d; to__is_set := true; + v.destination <- Pbrt.Decoder.string d; destination_is_set := true; end | Some (3, pk) -> Pbrt.Decoder.unexpected_payload "Message(request_rename), field(3)" pk | Some (_, payload_kind) -> Pbrt.Decoder.skip d payload_kind done; - begin if not !to__is_set then Pbrt.Decoder.missing_field "to_" end; - begin if not !from_is_set then Pbrt.Decoder.missing_field "from" end; + begin if not !destination_is_set then Pbrt.Decoder.missing_field "destination" end; + begin if not !source_is_set then Pbrt.Decoder.missing_field "source" end; ({ edit_level = v.edit_level; - from = v.from; - to_ = v.to_; + source = v.source; + destination = v.destination; } : request_rename) let rec decode_pb_request_copy d = let v = default_request_copy_mutable () in let continue__= ref true in - let to__is_set = ref false in - let from_is_set = ref false in + let destination_is_set = ref false in + let source_is_set = ref false in while !continue__ do match Pbrt.Decoder.key d with | None -> ( @@ -1695,23 +1911,23 @@ let rec decode_pb_request_copy d = | Some (1, pk) -> Pbrt.Decoder.unexpected_payload "Message(request_copy), field(1)" pk | Some (2, Pbrt.Bytes) -> begin - v.from <- Pbrt.Decoder.string d; from_is_set := true; + v.source <- Pbrt.Decoder.string d; source_is_set := true; end | Some (2, pk) -> Pbrt.Decoder.unexpected_payload "Message(request_copy), field(2)" pk | Some (3, Pbrt.Bytes) -> begin - v.to_ <- Pbrt.Decoder.string d; to__is_set := true; + v.destination <- Pbrt.Decoder.string d; destination_is_set := true; end | Some (3, pk) -> Pbrt.Decoder.unexpected_payload "Message(request_copy), field(3)" pk | Some (_, payload_kind) -> Pbrt.Decoder.skip d payload_kind done; - begin if not !to__is_set then Pbrt.Decoder.missing_field "to_" end; - begin if not !from_is_set then Pbrt.Decoder.missing_field "from" end; + begin if not !destination_is_set then Pbrt.Decoder.missing_field "destination" end; + begin if not !source_is_set then Pbrt.Decoder.missing_field "source" end; ({ edit_level = v.edit_level; - from = v.from; - to_ = v.to_; + source = v.source; + destination = v.destination; } : request_copy) let rec decode_pb_request_comment d = @@ -2133,8 +2349,10 @@ let rec decode_pb_request d = | Some (25, _) -> (Discard (decode_pb_request_discard (Pbrt.Decoder.nested d)) : request) | Some (26, _) -> (Session_changed (decode_pb_request_session_changed (Pbrt.Decoder.nested d)) : request) | Some (27, _) -> (Session_of_pid (decode_pb_request_session_of_pid (Pbrt.Decoder.nested d)) : request) - | Some (28, _) -> (Session_update_pid (decode_pb_request_session_update_pid (Pbrt.Decoder.nested d)) : request) + | Some (28, _) -> (Session_exists (decode_pb_request_session_exists (Pbrt.Decoder.nested d)) : request) | Some (29, _) -> (Get_config (decode_pb_request_get_config (Pbrt.Decoder.nested d)) : request) + | Some (30, _) -> (Aux_set (decode_pb_request_aux_set (Pbrt.Decoder.nested d)) : request) + | Some (31, _) -> (Aux_delete (decode_pb_request_aux_delete (Pbrt.Decoder.nested d)) : request) | Some (n, payload_kind) -> ( Pbrt.Decoder.skip d payload_kind; loop () diff --git a/src/vyconf_pbt.mli b/src/vyconf_pbt.mli index c9a7530..d63962e 100644 --- a/src/vyconf_pbt.mli +++ b/src/vyconf_pbt.mli @@ -21,14 +21,16 @@ type request_setup_session = { client_pid : int32; client_application : string option; on_behalf_of : int32 option; + client_user : string option; + client_sudo_user : string option; } type request_session_of_pid = { client_pid : int32; } -type request_session_update_pid = { - client_pid : int32; +type request_session_exists = { + dummy : int32 option; } type request_get_config = { @@ -52,6 +54,18 @@ type request_delete = { path : string list; } +type request_aux_set = { + path : string list; + script_name : string; + tag_value : string option; +} + +type request_aux_delete = { + path : string list; + script_name : string; + tag_value : string option; +} + type request_discard = { dummy : int32 option; } @@ -62,14 +76,14 @@ type request_session_changed = { type request_rename = { edit_level : string list; - from : string; - to_ : string; + source : string; + destination : string; } type request_copy = { edit_level : string list; - from : string; - to_ : string; + source : string; + destination : string; } type request_comment = { @@ -175,8 +189,10 @@ type request = | Discard of request_discard | Session_changed of request_session_changed | Session_of_pid of request_session_of_pid - | Session_update_pid of request_session_update_pid + | Session_exists of request_session_exists | Get_config of request_get_config + | Aux_set of request_aux_set + | Aux_delete of request_aux_delete type request_envelope = { token : string option; @@ -218,6 +234,8 @@ val default_request_setup_session : ?client_pid:int32 -> ?client_application:string option -> ?on_behalf_of:int32 option -> + ?client_user:string option -> + ?client_sudo_user:string option -> unit -> request_setup_session (** [default_request_setup_session ()] is the default value for type [request_setup_session] *) @@ -228,11 +246,11 @@ val default_request_session_of_pid : request_session_of_pid (** [default_request_session_of_pid ()] is the default value for type [request_session_of_pid] *) -val default_request_session_update_pid : - ?client_pid:int32 -> +val default_request_session_exists : + ?dummy:int32 option -> unit -> - request_session_update_pid -(** [default_request_session_update_pid ()] is the default value for type [request_session_update_pid] *) + request_session_exists +(** [default_request_session_exists ()] is the default value for type [request_session_exists] *) val default_request_get_config : ?dummy:int32 option -> @@ -265,6 +283,22 @@ val default_request_delete : request_delete (** [default_request_delete ()] is the default value for type [request_delete] *) +val default_request_aux_set : + ?path:string list -> + ?script_name:string -> + ?tag_value:string option -> + unit -> + request_aux_set +(** [default_request_aux_set ()] is the default value for type [request_aux_set] *) + +val default_request_aux_delete : + ?path:string list -> + ?script_name:string -> + ?tag_value:string option -> + unit -> + request_aux_delete +(** [default_request_aux_delete ()] is the default value for type [request_aux_delete] *) + val default_request_discard : ?dummy:int32 option -> unit -> @@ -279,16 +313,16 @@ val default_request_session_changed : val default_request_rename : ?edit_level:string list -> - ?from:string -> - ?to_:string -> + ?source:string -> + ?destination:string -> unit -> request_rename (** [default_request_rename ()] is the default value for type [request_rename] *) val default_request_copy : ?edit_level:string list -> - ?from:string -> - ?to_:string -> + ?source:string -> + ?destination:string -> unit -> request_copy (** [default_request_copy ()] is the default value for type [request_copy] *) @@ -438,8 +472,8 @@ val pp_request_setup_session : Format.formatter -> request_setup_session -> unit val pp_request_session_of_pid : Format.formatter -> request_session_of_pid -> unit (** [pp_request_session_of_pid v] formats v *) -val pp_request_session_update_pid : Format.formatter -> request_session_update_pid -> unit -(** [pp_request_session_update_pid v] formats v *) +val pp_request_session_exists : Format.formatter -> request_session_exists -> unit +(** [pp_request_session_exists v] formats v *) val pp_request_get_config : Format.formatter -> request_get_config -> unit (** [pp_request_get_config v] formats v *) @@ -456,6 +490,12 @@ val pp_request_set : Format.formatter -> request_set -> unit val pp_request_delete : Format.formatter -> request_delete -> unit (** [pp_request_delete v] formats v *) +val pp_request_aux_set : Format.formatter -> request_aux_set -> unit +(** [pp_request_aux_set v] formats v *) + +val pp_request_aux_delete : Format.formatter -> request_aux_delete -> unit +(** [pp_request_aux_delete v] formats v *) + val pp_request_discard : Format.formatter -> request_discard -> unit (** [pp_request_discard v] formats v *) @@ -546,8 +586,8 @@ val encode_pb_request_setup_session : request_setup_session -> Pbrt.Encoder.t -> val encode_pb_request_session_of_pid : request_session_of_pid -> Pbrt.Encoder.t -> unit (** [encode_pb_request_session_of_pid v encoder] encodes [v] with the given [encoder] *) -val encode_pb_request_session_update_pid : request_session_update_pid -> Pbrt.Encoder.t -> unit -(** [encode_pb_request_session_update_pid v encoder] encodes [v] with the given [encoder] *) +val encode_pb_request_session_exists : request_session_exists -> Pbrt.Encoder.t -> unit +(** [encode_pb_request_session_exists v encoder] encodes [v] with the given [encoder] *) val encode_pb_request_get_config : request_get_config -> Pbrt.Encoder.t -> unit (** [encode_pb_request_get_config v encoder] encodes [v] with the given [encoder] *) @@ -564,6 +604,12 @@ val encode_pb_request_set : request_set -> Pbrt.Encoder.t -> unit val encode_pb_request_delete : request_delete -> Pbrt.Encoder.t -> unit (** [encode_pb_request_delete v encoder] encodes [v] with the given [encoder] *) +val encode_pb_request_aux_set : request_aux_set -> Pbrt.Encoder.t -> unit +(** [encode_pb_request_aux_set v encoder] encodes [v] with the given [encoder] *) + +val encode_pb_request_aux_delete : request_aux_delete -> Pbrt.Encoder.t -> unit +(** [encode_pb_request_aux_delete v encoder] encodes [v] with the given [encoder] *) + val encode_pb_request_discard : request_discard -> Pbrt.Encoder.t -> unit (** [encode_pb_request_discard v encoder] encodes [v] with the given [encoder] *) @@ -654,8 +700,8 @@ val decode_pb_request_setup_session : Pbrt.Decoder.t -> request_setup_session val decode_pb_request_session_of_pid : Pbrt.Decoder.t -> request_session_of_pid (** [decode_pb_request_session_of_pid decoder] decodes a [request_session_of_pid] binary value from [decoder] *) -val decode_pb_request_session_update_pid : Pbrt.Decoder.t -> request_session_update_pid -(** [decode_pb_request_session_update_pid decoder] decodes a [request_session_update_pid] binary value from [decoder] *) +val decode_pb_request_session_exists : Pbrt.Decoder.t -> request_session_exists +(** [decode_pb_request_session_exists decoder] decodes a [request_session_exists] binary value from [decoder] *) val decode_pb_request_get_config : Pbrt.Decoder.t -> request_get_config (** [decode_pb_request_get_config decoder] decodes a [request_get_config] binary value from [decoder] *) @@ -672,6 +718,12 @@ val decode_pb_request_set : Pbrt.Decoder.t -> request_set val decode_pb_request_delete : Pbrt.Decoder.t -> request_delete (** [decode_pb_request_delete decoder] decodes a [request_delete] binary value from [decoder] *) +val decode_pb_request_aux_set : Pbrt.Decoder.t -> request_aux_set +(** [decode_pb_request_aux_set decoder] decodes a [request_aux_set] binary value from [decoder] *) + +val decode_pb_request_aux_delete : Pbrt.Decoder.t -> request_aux_delete +(** [decode_pb_request_aux_delete decoder] decodes a [request_aux_delete] binary value from [decoder] *) + val decode_pb_request_discard : Pbrt.Decoder.t -> request_discard (** [decode_pb_request_discard decoder] decodes a [request_discard] binary value from [decoder] *) diff --git a/src/vyconfd.ml b/src/vyconfd.ml index f1b1694..05cd693 100644 --- a/src/vyconfd.ml +++ b/src/vyconfd.ml @@ -29,9 +29,9 @@ let legacy_config_path = ref false (* Global data *) let sessions : (string, Session.session_data) Hashtbl.t = Hashtbl.create 10 -let commit_lock : string option ref = ref None +let commit_lock : int32 option ref = ref None -let conf_mode_lock : string option ref = ref None +let conf_mode_lock : int32 option ref = ref None (* Command line arguments *) let args = [ @@ -67,9 +67,18 @@ let make_session_token () = let setup_session world (req: request_setup_session) = let token = make_session_token () in let pid = req.client_pid in - let user = "unknown user" in + let user = + match req.client_user with + | None -> "" + | Some u -> u + in + let sudo_user = + match req.client_sudo_user with + | None -> "" + | Some u -> u + in let client_app = Option.value req.client_application ~default:"unknown client" in - let () = Hashtbl.add sessions token (Session.make world client_app user pid) in + let () = Hashtbl.add sessions token (Session.make world client_app sudo_user user pid) in {response_tmpl with output=(Some token)} let session_of_pid _world (req: request_session_of_pid) = @@ -77,15 +86,9 @@ let session_of_pid _world (req: request_session_of_pid) = let extant = find_session_by_pid pid in {response_tmpl with output=extant} -let session_update_pid _world token (req: request_session_update_pid) = - let pid = req.client_pid in +let session_exists _world token (_req: request_session_exists) = try - begin - let s = Hashtbl.find sessions token in - if s.client_pid <> pid then - let session = {s with client_pid=pid} in - Hashtbl.replace sessions token session - end; + let _ = Hashtbl.find sessions token in {response_tmpl with output=(Some token)} with Not_found -> {response_tmpl with status=Fail; output=None} @@ -100,14 +103,14 @@ let enter_conf_mode req token = let lock = !conf_mode_lock in let session = Hashtbl.find sessions token in match lock with - | Some user -> + | Some pid -> if req.override_exclusive then aux token session else {response_tmpl with status=Configuration_locked; - error=Some (Printf.sprintf "Configuration was locked by %s" user)} + error=Some (Printf.sprintf "Configuration was locked by %ld" pid)} | None -> - if req.exclusive then (conf_mode_lock := Some session.user; aux token session) + if req.exclusive then (conf_mode_lock := Some session.client_pid; aux token session) else aux token session let exit_conf_mode world token = @@ -207,6 +210,34 @@ let delete world token (req: request_delete) = response_tmpl with Session.Session_error msg -> {response_tmpl with status=Fail; error=(Some msg)} +let aux_set world token (req: request_aux_set) = + try + let () = (Lwt_log.debug @@ Printf.sprintf "[%s]\n" (Vyos1x.Util.string_of_list req.path)) |> Lwt.ignore_result in + let () = + Session.aux_set + world + (find_session token) + req.path + req.script_name + req.tag_value + in + response_tmpl + with Session.Session_error msg -> {response_tmpl with status=Fail; error=(Some msg)} + +let aux_delete world token (req: request_aux_delete) = + try + let () = (Lwt_log.debug @@ Printf.sprintf "[%s]\n" (Vyos1x.Util.string_of_list req.path)) |> Lwt.ignore_result in + let () = + Session.aux_delete + world + (find_session token) + req.path + req.script_name + req.tag_value + in + response_tmpl + with Session.Session_error msg -> {response_tmpl with status=Fail; error=(Some msg)} + let discard world token (_req: request_discard) = try let session = Session.discard world (find_session token) @@ -242,8 +273,15 @@ let commit world token (req: request_commit) = let s = find_session token in let proposed_config = Session.get_proposed_config world s in let req_dry_run = Option.value req.dry_run ~default:false in - - let commit_data = Session.prepare_commit ~dry_run:req_dry_run world proposed_config token + let commit_data = + Session.prepare_commit + ~dry_run:req_dry_run + world + proposed_config + token + s.client_pid + s.client_sudo_user + s.client_user in let%lwt received_commit_data = VC.do_commit commit_data in let%lwt result_commit_data = @@ -257,20 +295,27 @@ let commit world token (req: request_commit) = let res, out = init_data.success, init_data.out in + let () = + (Lwt_log.debug @@ Printf.sprintf "aux_changeset: %s" (Session.sprint_changeset s.aux_changeset)) |> Lwt.ignore_result + in match res with | false -> Lwt.return {response_tmpl with status=Internal_error; error=(Some out)} | true -> - (* partial commit *) if not req_dry_run then - world.Session.running_config <- result_commit_data.config_result; + let post_running, post_proposed = + Session.post_process_commit world s (result_commit_data, proposed_config) + in + world.Session.running_config <- post_running; let session = { s with changeset = Session.get_changeset world world.Session.running_config - proposed_config } - in Hashtbl.replace sessions token session; + post_proposed; + aux_changeset = []; } + in Hashtbl.replace sessions token session + else (); let success, msg_str = result_commit_data.result.success, result_commit_data.result.out @@ -320,7 +365,7 @@ let rec handle_connection world ic oc () = | _, Session_of_pid r -> session_of_pid world r | _, Reload_reftree r -> reload_reftree world r | None, _ -> {response_tmpl with status=Fail; output=(Some "Operation requires session token")} - | Some t, Session_update_pid r -> session_update_pid world t r + | Some t, Session_exists r -> session_exists world t r | Some t, Teardown _ -> teardown world t | Some t, Enter_configuration_mode r -> enter_conf_mode r t | Some t, Exit_configuration_mode -> exit_conf_mode world t @@ -332,6 +377,8 @@ let rec handle_connection world ic oc () = | Some t, Validate r -> validate world t r | Some t, Set r -> set world t r | Some t, Delete r -> delete world t r + | Some t, Aux_set r -> aux_set world t r + | Some t, Aux_delete r -> aux_delete world t r | Some t, Discard r -> discard world t r | Some t, Session_changed r -> session_changed world t r | Some t, Get_config r -> get_config world t r |
