diff options
| author | Daniil Baturin <daniil@vyos.io> | 2025-11-03 13:44:19 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-03 13:44:19 +0000 |
| commit | 2482e3f1a073cd9bd3cc260d0cbb4b8b38bd58f7 (patch) | |
| tree | 8eab6df656276e2ccea49682f5cf402861931583 /src | |
| parent | 304e4d2a172fe1baf2c1df7f61b7a0a8e40f7d5d (diff) | |
| parent | f372408dc6fb5b98d1f0d28bc334d8a5b8016c11 (diff) | |
| download | vyconf-2482e3f1a073cd9bd3cc260d0cbb4b8b38bd58f7.tar.gz vyconf-2482e3f1a073cd9bd3cc260d0cbb4b8b38bd58f7.zip | |
Merge pull request #34 from jestabro/restart-from-cache
T7980: cache running config on commit completion and add option --reload-active-config
Diffstat (limited to 'src')
| -rw-r--r-- | src/session.ml | 60 | ||||
| -rw-r--r-- | src/session.mli | 6 | ||||
| -rw-r--r-- | src/startup.ml | 16 | ||||
| -rw-r--r-- | src/startup.mli | 2 | ||||
| -rw-r--r-- | src/vyconfd.ml | 59 |
5 files changed, 111 insertions, 32 deletions
diff --git a/src/session.ml b/src/session.ml index 5f70feb..f5fff2f 100644 --- a/src/session.ml +++ b/src/session.ml @@ -251,23 +251,51 @@ 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 pid sudo_user user = - let at = w.running_config in - let rt = w.reference_tree in +let write_running_cache w = let vc = w.vyconf_config in - let () = - try - IC.write_internal at (FP.concat vc.session_dir vc.running_cache) - with - Vyos1x.Internal.Write_error msg -> raise (Session_error msg) - in - let () = - try - IC.write_internal config (FP.concat vc.session_dir vc.session_cache) - with - Vyos1x.Internal.Write_error msg -> raise (Session_error msg) - in - CC.make_commit_data ~dry_run:dry_run rt at config id pid sudo_user user + try + let () = + IC.write_internal_atomic + w.running_config + (FP.concat vc.session_dir vc.running_cache); + in Ok () + with + Vyos1x.Internal.Write_error msg -> + let msg = + Printf.sprintf "Write error caching running config: %s" msg + in Error msg + +let write_session_cache w config = + let vc = w.vyconf_config in + try + let () = + IC.write_internal + config + (FP.concat vc.session_dir vc.session_cache); + in Ok () + with + Vyos1x.Internal.Write_error msg -> + let msg = + Printf.sprintf "Write error caching session config: %s" msg + in Error msg + +let prepare_commit ?(dry_run=false) w s config id = + let opt_running = write_running_cache w in + let opt_session = write_session_cache w config in + match opt_running, opt_session with + | Ok (), Ok () -> + Ok (CC.make_commit_data + ~dry_run:dry_run + w.reference_tree + w.running_config + config + id + s.client_pid + s.client_sudo_user + s.client_user) + | Error msg, Ok () -> Error msg + | Ok (), Error msg -> Error msg + | Error msg1, Error msg2 -> Error (Printf.sprintf "%s\n %s" msg1 msg2) let post_process_commit w s ((c_data: CC.commit_data), proposed_config) = let ident n v y = diff --git a/src/session.mli b/src/session.mli index a08f873..1750f6c 100644 --- a/src/session.mli +++ b/src/session.mli @@ -69,7 +69,11 @@ 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 -> int32 -> string -> string -> Commitd_client.Commit.commit_data +val write_running_cache : world -> (unit, string) result + +val write_session_cache : world -> Vyos1x.Config_tree.t -> (unit, string) result + +val prepare_commit : ?dry_run:bool -> world -> session_data -> Vyos1x.Config_tree.t -> string -> (Commitd_client.Commit.commit_data, string) result val post_process_commit : world -> session_data -> Commitd_client.Commit.commit_data * Vyos1x.Config_tree.t -> Vyos1x.Config_tree.t * Vyos1x.Config_tree.t diff --git a/src/startup.ml b/src/startup.ml index 20882cb..e8b2639 100644 --- a/src/startup.ml +++ b/src/startup.ml @@ -94,6 +94,16 @@ let load_config_failsafe main fallback = | Error msg -> panic (Printf.sprintf "Failed to load fallback config %s: %s, exiting" fallback msg) end +module IC = Vyos1x.Internal.Make(Vyos1x.Config_tree) + +let load_config_cache cache_file = + try + let cached_config = IC.read_internal cache_file in + log_info @@ Printf.sprintf "Reading active config from %s" cache_file; + Ok cached_config + with Vyos1x.Internal.Read_error msg -> + Error (Printf.sprintf "Failed to load active config %s: %s, exiting" cache_file msg) + (* Load interface definitions from a directory into a reference tree *) let load_interface_definitions dir = let open Vyos1x.Reference_tree in @@ -111,11 +121,11 @@ let load_interface_definitions dir = | Error msg -> Error msg end with Bad_interface_definition msg -> Error msg -module I = Vyos1x.Internal.Make(Vyos1x.Reference_tree) +module IR = Vyos1x.Internal.Make(Vyos1x.Reference_tree) let read_reference_tree file = try - let reftree = I.read_internal file in + let reftree = IR.read_internal file in log_info @@ Printf.sprintf "Reading interface definitions from %s" file; Ok reftree - with Sys_error msg -> Error msg + with Vyos1x.Internal.Read_error msg -> Error msg diff --git a/src/startup.mli b/src/startup.mli index 1415953..41c6251 100644 --- a/src/startup.mli +++ b/src/startup.mli @@ -14,6 +14,8 @@ val create_server : (Lwt_unix.file_descr * Lwt_unix.sockaddr -> unit Lwt.t) -> Lwt_unix.file_descr -> unit -> 'a Lwt.t +val load_config_cache : string -> (Vyos1x.Config_tree.t, string) result + val load_config_failsafe : string -> string -> Vyos1x.Config_tree.t val load_interface_definitions : string -> (Vyos1x.Reference_tree.t, string) result diff --git a/src/vyconfd.ml b/src/vyconfd.ml index 05cd693..a0fe76d 100644 --- a/src/vyconfd.ml +++ b/src/vyconfd.ml @@ -25,6 +25,7 @@ let config_file = ref defaults.config_file let basepath = ref "/" let log_file = ref None let legacy_config_path = ref false +let reload_active_config = ref false (* Global data *) let sessions : (string, Session.session_data) Hashtbl.t = Hashtbl.create 10 @@ -43,6 +44,7 @@ let args = [ ("--version", Arg.Unit (fun () -> print_endline @@ Version.version_info (); exit 0), "Print version and exit"); ("--legacy-config-path", Arg.Unit (fun () -> legacy_config_path := true), (Printf.sprintf "Load config file from legacy path %s" defaults.legacy_config_path)); + ("--reload-active-config", Arg.Unit (fun () -> reload_active_config := true), "Reload active config file"); ] let usage = "Usage: " ^ Sys.argv.(0) ^ " [options]" @@ -274,16 +276,13 @@ let commit world token (req: request_commit) = 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 - s.client_pid - s.client_sudo_user - s.client_user + Session.prepare_commit ~dry_run:req_dry_run world s proposed_config token in - let%lwt received_commit_data = VC.do_commit commit_data in + match commit_data with + | Error msg -> + Lwt.return {response_tmpl with status=Internal_error; error=(Some msg)} + | Ok c_data -> + let%lwt received_commit_data = VC.do_commit c_data in let%lwt result_commit_data = Lwt.return (CC.commit_update received_commit_data) in @@ -314,12 +313,25 @@ let commit world token (req: request_commit) = world.Session.running_config post_proposed; aux_changeset = []; } - in Hashtbl.replace sessions token session + in + Hashtbl.replace sessions token session else (); - let success, msg_str = + let write_msg = + if not req_dry_run then + match Session.write_running_cache world with + | Ok () -> "" + | Error msg -> msg + else "" + in + let success, result_msg = result_commit_data.result.success, result_commit_data.result.out in + let msg_str = + match write_msg with + | "" -> result_msg + | _ -> Printf.sprintf "%s\n %s" result_msg write_msg + in match success with | true -> Lwt.return {response_tmpl with status=Success; output=(Some msg_str)} | false -> Lwt.return {response_tmpl with status=Fail; output=(Some msg_str)} @@ -426,6 +438,14 @@ let read_reference_tree file = | Ok r -> r | Error s -> Startup.panic s +let init_write_cache world = + (* initial cache of running config; this will be unnecessary once + vyconfd is started at boot *) + let res = Session.write_running_cache world in + match res with + | Ok _ -> () + | Error msg -> (Lwt_log.error msg) |> Lwt.ignore_result + let make_world config dirs = let open Session in (* the reference_tree json file is generated at vyos-1x build time *) @@ -446,8 +466,23 @@ let () = | false -> (FP.concat vc.config_dir vc.primary_config) in let failsafe_config = (FP.concat vc.config_dir vc.fallback_config) in + let restart_cache = (FP.concat vc.session_dir vc.running_cache) in let config = - Startup.load_config_failsafe primary_config failsafe_config + match !reload_active_config with + | true -> let res = Startup.load_config_cache restart_cache in + begin + match res with + | Ok c -> c + | Error msg -> + let () = (Lwt_log.error msg) |> Lwt.ignore_result in + Startup.load_config_failsafe primary_config failsafe_config + end + | false -> Startup.load_config_failsafe primary_config failsafe_config in let world = Session.{world with running_config=config} in + let () = + match !reload_active_config with + | true -> () + | false -> init_write_cache world + in Lwt_main.run @@ main_loop !basepath world () |
