mclu version 2
[mclu.git] / mclu_conf.ml
diff --git a/mclu_conf.ml b/mclu_conf.ml
new file mode 100644 (file)
index 0000000..7b955dd
--- /dev/null
@@ -0,0 +1,113 @@
+(* mclu: Mini Cloud
+ * Copyright (C) 2014-2015 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(* Parsing /etc/mclu.conf *)
+
+open Printf
+
+(* blank line *)
+let is_blank_line =
+  let rex = Pcre.regexp "^\\s*$" in
+  Pcre.pmatch ~rex
+
+(* comment *)
+let is_comment =
+  let rex = Pcre.regexp "^\\s*#" in
+  Pcre.pmatch ~rex
+
+(* [header] *)
+let is_header =
+  let rex = Pcre.regexp "^\\s*\\[(\\w+)\\]\\s*$" in
+  fun line ->
+    try
+      let subs = Pcre.exec ~rex line in
+      Some (Pcre.get_substring subs 1)
+    with
+      Not_found -> None
+
+let ws_rex = Pcre.regexp "\\s+"
+
+type node = {
+  hostname : string;
+  libvirt_uri : string;
+  mac_addr : string option;
+}
+
+let _nodes : node list ref = ref []
+
+let load_configuration config_file =
+  let chan =
+    try open_in config_file
+    with Sys_error msg ->
+      eprintf "mclu: %s: cannot open configuration file: %s\n" config_file msg;
+      exit 1 in
+  let rec loop section =
+    let line = input_line chan in
+    if is_blank_line line || is_comment line then
+      loop section
+    else (
+      match is_header line with
+      | Some "nodes" ->
+        loop `Nodes
+      | Some section ->
+        (* Ignore unknown sections and keep going. *)
+        printf "mclu: %s: warning: ignoring unknown section [%s]\n"
+          config_file section;
+        loop `Unknown
+      | None ->
+        (* How we parse lines within sections depends on the header. *)
+        match section with
+        | `Nodes ->
+          (* If we're in the [nodes] section, parse "hostname [key=value].." *)
+          (match Pcre.split ~rex:ws_rex line with
+          | [] -> assert false
+          | hostname :: defs ->
+            let node = {
+              hostname = hostname;
+              libvirt_uri = sprintf "qemu+ssh://root@%s/system" hostname;
+              mac_addr = None
+            } in
+            let node = List.fold_left (
+              fun node def ->
+                match Pcre.split ~pat:"=" ~max:2 def with
+                | ["mac"; value] -> { node with mac_addr = Some value }
+                | ["uri"; value] -> { node with libvirt_uri = value }
+                | [_] -> node           (* key with no value - ignore *)
+                | [_; _] -> node        (* unknown key=value - ignore *)
+                | _ -> assert false
+            ) node defs in
+            _nodes := node :: !_nodes;
+            loop section
+          )
+        | `Global
+        | `Unknown ->
+          (* Ignore the line. *)
+          printf "mclu: %s: warning: ignoring `%s'\n" config_file line;
+          loop section
+    )
+  in
+  (try
+     loop `Global
+   with End_of_file -> ()
+  );
+  close_in chan;
+
+  _nodes := List.rev !_nodes
+
+(* Get list of nodes. *)
+let nodes () = !_nodes