summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/session.ml59
-rw-r--r--src/session.mli11
-rw-r--r--src/vyconfd.ml50
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