summaryrefslogtreecommitdiff
blob: 5b7f58a7c1147daf63ba3560cb2c06cb273f5bca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
From e74d868b48d55dfb20f5a41ec20fbec93d8e5deb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= <edvin.torok@citrix.com>
Date: Tue, 11 May 2021 15:56:50 +0000
Subject: [PATCH 38/89] tools/oxenstored: validate config file before live
 update
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The configuration file can contain typos or various errors that could prevent
live update from succeeding (e.g. a flag only valid on a different version).
Unknown entries in the config file would be ignored on startup normally,
add a strict --config-test that live-update can use to check that the config file
is valid *for the new binary*.

For compatibility with running old code during live update recognize
--live --help as an equivalent to --config-test.

Signed-off-by: Edwin Török <edvin.torok@citrix.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
(cherry picked from commit e6f07052ce4a0f0b7d4dc522d87465efb2d9ee86)
---
 tools/ocaml/xenstored/parse_arg.ml | 26 ++++++++++++++++++++++++++
 tools/ocaml/xenstored/xenstored.ml | 11 +++++++++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/tools/ocaml/xenstored/parse_arg.ml b/tools/ocaml/xenstored/parse_arg.ml
index 7c0478e76a..5e4ca6f1f7 100644
--- a/tools/ocaml/xenstored/parse_arg.ml
+++ b/tools/ocaml/xenstored/parse_arg.ml
@@ -26,8 +26,14 @@ type config =
 	restart: bool;
 	live_reload: bool;
 	disable_socket: bool;
+	config_test: bool;
 }
 
+let get_config_filename config_file =
+	match config_file with
+	| Some name -> name
+	| None	    -> Define.default_config_dir ^ "/oxenstored.conf"
+
 let do_argv =
 	let pidfile = ref "" and tracefile = ref "" (* old xenstored compatibility *)
 	and domain_init = ref true
@@ -38,6 +44,8 @@ let do_argv =
 	and restart = ref false
 	and live_reload = ref false
 	and disable_socket = ref false
+	and config_test = ref false
+	and help = ref false
 	in
 
 	let speclist =
@@ -55,10 +63,27 @@ let do_argv =
 		  ("-T", Arg.Set_string tracefile, ""); (* for compatibility *)
 		  ("--restart", Arg.Set restart, "Read database on starting");
 		  ("--live", Arg.Set live_reload, "Read live dump on startup");
+		  ("--config-test", Arg.Set config_test, "Test validity of config file");
 		  ("--disable-socket", Arg.Unit (fun () -> disable_socket := true), "Disable socket");
+		  ("--help", Arg.Set help, "Display this list of options")
 		] in
 	let usage_msg = "usage : xenstored [--config-file <filename>] [--no-domain-init] [--help] [--no-fork] [--reraise-top-level] [--restart] [--disable-socket]" in
 	Arg.parse speclist (fun _ -> ()) usage_msg;
+	let () =
+		if !help then begin
+			if !live_reload then
+				(*
+				 * Transform --live --help into --config-test for backward compat with
+				 * running code during live update.
+				 * Caller will validate config and exit
+				 *)
+				config_test := true
+			else begin
+				Arg.usage_string speclist usage_msg |> print_endline;
+				exit 0
+			end
+		end
+	in
 	{
 		domain_init = !domain_init;
 		activate_access_log = !activate_access_log;
@@ -70,4 +95,5 @@ let do_argv =
 		restart = !restart;
 		live_reload = !live_reload;
 		disable_socket = !disable_socket;
+		config_test = !config_test;
 	}
diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml
index 4d5851c5cb..e2638a5af2 100644
--- a/tools/ocaml/xenstored/xenstored.ml
+++ b/tools/ocaml/xenstored/xenstored.ml
@@ -88,7 +88,7 @@ let default_pidfile = Paths.xen_run_dir ^ "/xenstored.pid"
 
 let ring_scan_interval = ref 20
 
-let parse_config filename =
+let parse_config ?(strict=false) filename =
 	let pidfile = ref default_pidfile in
 	let options = [
 		("merge-activate", Config.Set_bool Transaction.do_coalesce);
@@ -129,11 +129,12 @@ let parse_config filename =
 		("xenstored-port", Config.Set_string Domains.xenstored_port); ] in
 	begin try Config.read filename options (fun _ _ -> raise Not_found)
 	with
-	| Config.Error err -> List.iter (fun (k, e) ->
+	| Config.Error err as e -> List.iter (fun (k, e) ->
 		match e with
 		| "unknown key" -> eprintf "config: unknown key %s\n" k
 		| _             -> eprintf "config: %s: %s\n" k e
 		) err;
+		if strict then raise e
 	| Sys_error m -> eprintf "error: config: %s\n" m;
 	end;
 	!pidfile
@@ -358,6 +359,12 @@ let tweak_gc () =
 let () =
 	Printexc.set_uncaught_exception_handler Logging.fallback_exception_handler;
 	let cf = do_argv in
+	if cf.config_test then begin
+		let path = config_filename cf in
+		let _pidfile:string = parse_config ~strict:true path in
+		Printf.printf "Configuration valid at %s\n%!" path;
+		exit 0
+	end;
 	let pidfile =
 		if Sys.file_exists (config_filename cf) then
 			parse_config (config_filename cf)
-- 
2.40.0