diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/session.ml | 59 | ||||
| -rw-r--r-- | src/session.mli | 11 | ||||
| -rw-r--r-- | src/vyconfd.ml | 50 |
3 files changed, 120 insertions, 0 deletions
diff --git a/src/session.ml b/src/session.ml index 03c5f91..44feb8f 100644 --- a/src/session.ml +++ b/src/session.ml @@ -34,6 +34,7 @@ type session_data = { conf_mode: bool; changeset: cfg_op list; mutable aux_changeset: aux_op list; + edit_level: string list; client_app: string; client_pid: int32; client_user: string; @@ -45,6 +46,7 @@ let make _world client_app sudo_user user pid = { conf_mode = false; changeset = []; aux_changeset = []; + edit_level = []; client_app = client_app; client_user = user; client_sudo_user = sudo_user; @@ -262,6 +264,63 @@ let aux_delete w s path name tagval = let discard _w s = { s with changeset = []; } +let edit_env_str s = + (* To maintain consistency with classic CLI, we return env variable for + PS1 on changes to edit level. + *) + let ps1 = + match s.edit_level with + | [] -> + "[edit]\\n\\u@\\H${VRF:+(vrf:$VRF)}${NETNS:+(ns:$NETNS)}# " + | _ as p -> + Printf.sprintf + "[edit %s]\\n\\u@\\H${VRF:+(vrf:$VRF)}${NETNS:+(ns:$NETNS)}# " + (Vyos1x.Util.string_of_list p) + in + Printf.sprintf "export PS1='%s';" ps1 + +let set_edit_level w s path = + let current_level = s.edit_level in + let new_level = current_level @ path in + let result = RT.allowed_edit_level w.reference_tree new_level in + match result with + | Ok () -> + let c = get_proposed_config w s in + let s' = + if not ((VT.exists[@alert "-exn"]) c path) then + set w s path + else s + in + let session = { s' with edit_level = new_level; } in + session, (edit_env_str session) + | Error msg -> + raise (Session_error msg) + +let set_edit_level_up w s = + let current_level = s.edit_level in + let new_level = + if Vyos1x.Util.is_empty current_level then + current_level + else + let up = Vyos1x.Util.drop_last current_level in + match RT.allowed_edit_level w.reference_tree up with + | Ok () -> up + | Error _ -> (* tag_value *) + Vyos1x.Util.drop_last up + in + let session = { s with edit_level = new_level; } + in session, (edit_env_str session) + +let get_edit_level _w s = + Vyos1x.Util.string_of_list s.edit_level + +let reset_edit_level _w s = + let session = { s with edit_level = []; } + in session, (edit_env_str session) + +let edit_level_root _w s = + Vyos1x.Util.is_empty s.edit_level + let session_changed w s = (* structural equality test requires consistent ordering, which is * practised, but may be unreliable; test actual difference diff --git a/src/session.mli b/src/session.mli index cb3f37a..757bc18 100644 --- a/src/session.mli +++ b/src/session.mli @@ -20,6 +20,7 @@ type session_data = { conf_mode: bool; changeset: cfg_op list; mutable aux_changeset: aux_op list; + edit_level: string list; client_app: string; client_pid: int32; client_user: string; @@ -50,6 +51,16 @@ val get_proposed_config : world -> session_data -> Vyos1x.Config_tree.t val discard : world -> session_data -> session_data +val set_edit_level : world -> session_data -> string list -> session_data * string + +val set_edit_level_up : world -> session_data -> session_data * string + +val get_edit_level : world -> session_data -> string + +val reset_edit_level : world -> session_data -> session_data * string + +val edit_level_root : world -> session_data -> bool + val session_changed : world -> session_data -> bool val load : world -> session_data -> string -> bool -> session_data diff --git a/src/vyconfd.ml b/src/vyconfd.ml index c09c4f4..ed84978 100644 --- a/src/vyconfd.ml +++ b/src/vyconfd.ml @@ -362,6 +362,51 @@ let reload_reftree world (_req: request_reload_reftree) = {response_tmpl with status=Success} | Error s -> {response_tmpl with status=Fail; error=(Some s)} +let set_edit_level world token (req: request_set_edit_level) = + let s = find_session token in + try + let session, edit_env = + Session.set_edit_level world s req.path + in + Hashtbl.replace sessions token session; + {response_tmpl with output=(Some edit_env)} + with Session.Session_error msg -> + {response_tmpl with status=Fail; error=(Some msg)} + +let set_edit_level_up world token (_req: request_set_edit_level_up) = + let s = find_session token in + try + let session, edit_env = + Session.set_edit_level_up world s + in + Hashtbl.replace sessions token session; + {response_tmpl with output=(Some edit_env)} + with Session.Session_error msg -> + {response_tmpl with status=Fail; error=(Some msg)} + +let reset_edit_level world token (_req: request_reset_edit_level) = + let s = find_session token in + try + let session, edit_env = + Session.reset_edit_level world s + in + Hashtbl.replace sessions token session; + {response_tmpl with output=(Some edit_env)} + with Session.Session_error msg -> + {response_tmpl with status=Fail; error=(Some msg)} + +let get_edit_level world token (_req: request_get_edit_level) = + let s = find_session token in + try + let edit_env = Session.get_edit_level world s in + {response_tmpl with output=(Some edit_env)} + with Session.Session_error msg -> + {response_tmpl with status=Fail; error=(Some msg)} + +let edit_level_root world token (_req: request_edit_level_root) = + if Session.edit_level_root world (find_session token) then response_tmpl + else {response_tmpl with status=Fail} + let send_response oc resp = let enc = Pbrt.Encoder.create () in let%lwt () = encode_pb_response resp enc |> return in @@ -413,6 +458,11 @@ let rec handle_connection world ic oc () = | Some t, Merge r -> merge world t r | Some t, Save r -> save world t r | Some t, Show_sessions r -> show_sessions world t r + | Some t, Set_edit_level r -> set_edit_level world t r + | Some t, Set_edit_level_up r -> set_edit_level_up world t r + | Some t, Reset_edit_level r -> reset_edit_level world t r + | Some t, Get_edit_level r -> get_edit_level world t r + | Some t, Edit_level_root r -> edit_level_root world t r | _ -> failwith "Unimplemented" ) |> Lwt.return end |
