mclu version 2
[mclu.git] / template.ml
1 (* mclu: Mini Cloud
2  * Copyright (C) 2014-2015 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *)
18
19 (* Templates. *)
20
21 open Utils
22
23 open Printf
24
25 let template_dir =
26   try Sys.getenv "MCLU_PATH"
27   with Not_found -> Config.pkgdatadir // "templates"
28
29 let templates () =
30   let files = Sys.readdir template_dir in
31   let files = Array.to_list files in
32   let files = List.map ((//) template_dir) files in
33   let files =
34     List.filter (fun name -> Filename.check_suffix name ".template") files in
35   List.map (
36     fun filename ->
37       let name = Filename.basename filename in
38       let name = Filename.chop_suffix name ".template" in
39       (name, filename)
40   ) files
41
42 let template_names () = List.map fst (templates ())
43
44 let run_template ~verbose filename subcmd args =
45   let cmd =
46     sprintf "%s %s %s" (quote filename) (quote subcmd)
47       (String.concat " " (List.map quote args)) in
48   if verbose then printf "%s\n%!" cmd;
49   let chan = Unix.open_process_in cmd in
50   let lines = ref [] in
51   (try while true do lines := input_line chan :: !lines done
52    with End_of_file -> ());
53   let lines = List.rev !lines in
54   let stat = Unix.close_process_in chan in
55   (match stat with
56   | Unix.WEXITED 0 -> Some lines
57   | Unix.WEXITED 2 -> None
58   | Unix.WEXITED i ->
59     eprintf "mclu: template '%s' subcmd '%s' exited with error %d\n"
60       filename subcmd i;
61     exit 1
62   | Unix.WSIGNALED i ->
63     eprintf "mclu: template '%s' subcmd '%s' killed by signal %d\n"
64       filename subcmd i;
65     exit 1
66   | Unix.WSTOPPED i ->
67     eprintf "mclu: template '%s' subcmd '%s' stopped by signal %d\n"
68       filename subcmd i;
69     exit 1
70   )
71
72 type template_info = {
73   base_image : string;
74   minimum_memory : int64 option;
75   recommended_memory : int64 option;
76   disk_bus : string option;
77   network_model : string option;
78 }
79
80 let probe ?(verbose = false) filename =
81   (* Check the template is a template. *)
82   (match run_template ~verbose filename "probe" [] with
83   | Some ["hello"] -> ()
84   | _ ->
85     eprintf "mclu: file %s is not an mclu template\n" filename;
86     exit 1
87   );
88
89   (* Probe for various properties. *)
90   let base_image =
91     match run_template ~verbose filename "base-image" [] with
92     | Some [answer] -> answer
93     | _ ->
94       eprintf "mclu: cannot parse '%s base-image'\n" filename;
95       exit 1 in
96   let minimum_memory =
97     match run_template ~verbose filename "minimum-memory" [] with
98     | Some [memory] ->
99       (try Some (bytes_of_human_size memory)
100        with Not_found ->
101          eprintf "mclu: cannot parse output of '%s minimum-memory'\n"
102            filename;
103          exit 1
104       );
105     | _ -> None in
106   let recommended_memory =
107     match run_template ~verbose filename "recommended-memory" [] with
108     | Some [memory] ->
109       (try Some (bytes_of_human_size memory)
110        with Not_found ->
111          eprintf "mclu: cannot parse output of '%s recommended-memory'\n"
112            filename;
113          exit 1
114       );
115     | _ -> None in
116   let disk_bus =
117     match run_template ~verbose filename "disk-bus" [] with
118     | Some [answer] -> Some answer
119     | _ -> None in
120   let network_model =
121     match run_template ~verbose filename "network-model" [] with
122     | Some [answer] -> Some answer
123     | _ -> None in
124
125   { base_image = base_image;
126     minimum_memory = minimum_memory;
127     recommended_memory = recommended_memory;
128     disk_bus = disk_bus;
129     network_model = network_model }