~ubuntu-branches/ubuntu/wily/marionnet/wily

« back to all changes in this revision

Viewing changes to disk.ml

  • Committer: Package Import Robot
  • Author(s): Lucas Nussbaum
  • Date: 2013-03-29 15:57:12 UTC
  • Revision ID: package-import@ubuntu.com-20130329155712-o0b9b96w8av68ktq
Tags: upstream-0.90.6+bzr407
ImportĀ upstreamĀ versionĀ 0.90.6+bzr407

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(* This file is part of marionnet
 
2
   Copyright (C) 2010  Jean-Vincent Loddo
 
3
   Copyright (C) 2010  UniversitĆ© Paris 13
 
4
 
 
5
   This program is free software: you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation, either version 2 of the License, or
 
8
   (at your option) any later version.
 
9
 
 
10
   This program is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
   GNU General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU General Public License
 
16
   along with this program.  If not, see <http://www.gnu.org/licenses/>. *)
 
17
 
 
18
open Gettext
 
19
 
 
20
(* `epithet' is almost a phantom type (almost because it is not abstract): *)
 
21
type 'a epithet = string
 
22
type variant = string
 
23
type filename = string
 
24
type dirname = string
 
25
type realpath = string
 
26
 
 
27
let string_of_epithet_kind =
 
28
  function
 
29
  | `distrib -> "distribution"
 
30
  | `variant -> "variant"
 
31
  | `kernel  -> "kernel"
 
32
  | _ -> assert false
 
33
 
 
34
class terminal_manager () =
 
35
 let hostxserver_name = "X HOST" in
 
36
 let xnest_name       = "X NEST" in
 
37
 let nox_name         = "No X" in
 
38
 object (self)
 
39
   method get_choice_list =
 
40
     [ hostxserver_name; xnest_name; nox_name ]
 
41
 
 
42
   method get_default = hostxserver_name
 
43
   method is_valid_choice x = List.mem x self#get_choice_list
 
44
   method is_hostxserver = ((=)hostxserver_name)
 
45
   method is_xnest       = ((=)xnest_name)
 
46
   method is_nox         = ((=)nox_name)
 
47
 end
 
48
 
 
49
 (** Read the given directory searching for names like [~prefix ^ "xxxxx"];
 
50
     return the list of epithets ["xxxxx"]. *)
 
51
let read_epithet_list ~prefix ~dir =
 
52
  let prefix_length = String.length prefix in
 
53
  let remove_prefix s = String.sub s prefix_length ((String.length s) - prefix_length) in
 
54
  let name_filter file_name =
 
55
    ((String.length file_name) > prefix_length) &&
 
56
    ((String.sub file_name 0 prefix_length) = prefix)
 
57
  in
 
58
  let xs =
 
59
    SysExtra.readdir_as_list
 
60
       ~only_not_directories:()
 
61
       ~name_filter
 
62
       ~name_converter:remove_prefix
 
63
       dir in
 
64
  Log.printf ~v:2 "Searching in %s:\n" dir;
 
65
  List.iter (fun x -> Log.printf ~v:2 " - found %s%s\n" prefix x) xs;
 
66
  xs
 
67
 
 
68
 
 
69
let machine_prefix = "machine-"
 
70
let router_prefix  = "router-"
 
71
let kernel_prefix  = "linux-"
 
72
 
 
73
let root_filesystem_searching_list = [
 
74
   Initialization.Path.filesystems;
 
75
   ]
 
76
 
 
77
let user_filesystem_searching_list = [
 
78
   Initialization.Path.user_filesystems;
 
79
   ]
 
80
 
 
81
(* In the order of priority: *)
 
82
let kernel_searching_list = [
 
83
   Initialization.Path.user_kernels;
 
84
   Initialization.Path.kernels;
 
85
   ]
 
86
 
 
87
module String_map = MapExtra.String_map
 
88
 
 
89
(* For a given choice the last binding with a directory will wins building the mapping.
 
90
   So we reverse the searching list: *)
 
91
let make_epithet_to_dir_mapping ~kind ?realpath ~prefix ~directory_searching_list () =
 
92
  Log.printf "Searching for a (%s) prefix: \"%s\"\n" (string_of_epithet_kind kind) prefix;
 
93
  let normalize_dir = match realpath with
 
94
   | None    -> (fun x -> Some x)
 
95
   | Some () -> (fun x -> UnixExtra.realpath x)
 
96
  in
 
97
  let searching_list = List.rev directory_searching_list in
 
98
  let xss =
 
99
     List.map
 
100
       (fun dir ->
 
101
          let epithet_list = read_epithet_list ~prefix ~dir in
 
102
          List.map (fun x -> (x, (normalize_dir dir))) epithet_list
 
103
        )
 
104
        searching_list
 
105
  in
 
106
  let yss = List.flatten xss in
 
107
  let yss = List.filter (fun (e,d)->d<>None) yss in
 
108
  let yss = List.map (function (e, Some dir)->(e,dir) | _ -> assert false) yss in
 
109
  (List.iter (function (e,d) -> Log.printf "* %s -> %s\n" e d) yss);
 
110
  String_map.of_list yss
 
111
 
 
112
 
 
113
(** epithet -> (variant list) * dir *)
 
114
let make_epithet_to_variant_list_and_dir_mapping ~prefix ~epithet_to_dir_mapping =
 
115
    String_map.mapi
 
116
      (fun epithet dir ->
 
117
        let dir = Printf.sprintf "%s/%s%s_variants" dir prefix epithet in
 
118
        ((read_epithet_list ~prefix:"" ~dir), dir)
 
119
      )
 
120
      epithet_to_dir_mapping
 
121
 
 
122
 
 
123
class type ['a] epithet_manager_object =
 
124
  object
 
125
    (* Constructor's arguments: *)
 
126
    method directory_searching_list : dirname list
 
127
    method prefix : string (* "machine-", "router-", "kernel-", "" (nothing for variants) *)
 
128
    (* Public interface: *)
 
129
    method get_epithet_list    : 'a epithet list
 
130
    method get_default_epithet : 'a epithet option
 
131
    method epithet_exists      : 'a epithet -> bool
 
132
    method realpath_of_epithet : 'a epithet -> realpath
 
133
    method resolve_epithet_symlink : 'a epithet -> 'a epithet
 
134
    (* Morally private methods: *)
 
135
    method epithets_of_filename : ?no_symlinks:unit -> filename -> ('a epithet) list
 
136
    method epithets_sharing_the_same_realpath_of : ?no_symlinks:unit -> ('a epithet) -> ('a epithet) list
 
137
    method filename_of_epithet : ('a epithet) -> filename
 
138
    method realpath_exists : string -> bool
 
139
    method filter : ('a epithet -> bool) -> unit
 
140
  end
 
141
 
 
142
 
 
143
class ['a] epithet_manager
 
144
  : ?default_epithet:('a epithet) ->
 
145
    ?filter:('a epithet->bool) ->
 
146
    kind: [> `distrib | `kernel | `variant ] ->
 
147
    directory_searching_list:string list ->
 
148
    prefix:string ->
 
149
    unit -> ['a] epithet_manager_object
 
150
  =
 
151
  fun
 
152
  ?(default_epithet="default")
 
153
  ?filter
 
154
  ~kind
 
155
  ~directory_searching_list
 
156
  ~prefix (* "machine-", "router-", "linux-", "" (for variants), ... *)
 
157
  ()
 
158
  ->
 
159
  let epithet_to_dir_mapping =
 
160
    make_epithet_to_dir_mapping ~kind ~realpath:() ~prefix ~directory_searching_list ()
 
161
  in
 
162
  (* Filter the list if required with the optional parameter `filter': *)
 
163
  let epithet_to_dir_mapping =
 
164
    match filter with
 
165
    | None   -> epithet_to_dir_mapping
 
166
    | Some f -> String_map.filter (fun epth _dir -> f epth) epithet_to_dir_mapping
 
167
  in
 
168
  object (self)
 
169
 
 
170
  (* The version stored in the object is the destructive (non-persistent)
 
171
     version of the same mapping: *)
 
172
  val mutable epithet_to_dir_mapping = epithet_to_dir_mapping
 
173
 
 
174
  (* Destructive filter application: *)
 
175
  method filter f =
 
176
    epithet_to_dir_mapping <- String_map.filter (fun epth _dir -> f epth) (epithet_to_dir_mapping)
 
177
 
 
178
  method directory_searching_list = directory_searching_list
 
179
  method prefix = prefix
 
180
 
 
181
  method get_epithet_list : 'a epithet list =
 
182
    String_map.domain epithet_to_dir_mapping
 
183
 
 
184
  method epithet_exists (epithet:'a epithet) : bool =
 
185
    String_map.mem epithet epithet_to_dir_mapping
 
186
 
 
187
  method (*private*) filename_of_epithet (epithet:'a epithet) =
 
188
    let dir = String_map.find epithet epithet_to_dir_mapping in
 
189
    (Printf.sprintf "%s/%s%s" dir prefix epithet)
 
190
 
 
191
  method realpath_of_epithet (epithet:'a epithet) : realpath =
 
192
    let filename = (self#filename_of_epithet epithet) in
 
193
    match (UnixExtra.realpath filename) with
 
194
    | Some x -> x
 
195
    | None   -> filename
 
196
 
 
197
  method (*private*) epithets_of_filename ?no_symlinks (filename:string) : ('a epithet) list =
 
198
    let realpath = Option.extract (UnixExtra.realpath filename) in
 
199
    let pred = match no_symlinks with
 
200
     | None    -> (fun e -> (self#realpath_of_epithet e) = realpath)
 
201
     | Some () ->
 
202
       (fun e ->
 
203
          (not (UnixExtra.is_symlink (self#filename_of_epithet e))) &&
 
204
          ((self#realpath_of_epithet e) = realpath))
 
205
    in
 
206
    (List.filter pred self#get_epithet_list)
 
207
 
 
208
  (* [machine-]default -> [machine-]debian-51426 *)
 
209
  method resolve_epithet_symlink (epithet:'a epithet) : 'a epithet =
 
210
   let filename = self#filename_of_epithet epithet in
 
211
   match UnixExtra.is_symlink filename with
 
212
   | false -> epithet
 
213
   | true  ->
 
214
      (match (self#epithets_of_filename ~no_symlinks:() filename) with
 
215
      | []            -> epithet
 
216
      | epithet'::_   -> epithet' (* we get the first *)
 
217
      )
 
218
 
 
219
  method epithets_sharing_the_same_realpath_of ?(no_symlinks:unit option) (epithet:'a epithet) : ('a epithet) list =
 
220
   let filename = self#filename_of_epithet epithet in
 
221
   self#epithets_of_filename ?no_symlinks filename
 
222
 
 
223
  method realpath_exists filename =
 
224
    let xs = List.map (self#filename_of_epithet) self#get_epithet_list in
 
225
    List.mem filename xs
 
226
 
 
227
  (* When a machine is created, we call this method to set a default epithet.*)
 
228
  method get_default_epithet : 'a epithet option =
 
229
    if self#epithet_exists default_epithet then (Some default_epithet) else
 
230
    let xs = self#get_epithet_list in
 
231
    match xs with
 
232
    | []   -> None
 
233
    | x::_ -> Some x (* We get the first as default... *)
 
234
 
 
235
end (* class epithet_manager *)
 
236
 
 
237
let get_and_parse_SUPPORTED_KERNELS (t : Configuration_files.t) : string -> (unit, string option) Either.t =
 
238
  let x = Configuration_files.get_string_list_variable "SUPPORTED_KERNELS" t in
 
239
  let brackets = (Str.regexp "^\\[\\(.*\\)\\]$") in
 
240
  let slashes  = (Str.regexp "^/\\(.*\\)/$") in
 
241
  let extract result =
 
242
    let (_,_,groups) = Option.extract result in
 
243
    List.hd groups
 
244
  in
 
245
  let rec loop acc = function
 
246
  | [] -> (List.rev acc)
 
247
  | x::xs when (StrExtra.First.matchingp brackets x) ->
 
248
      let brackets_content = extract (StrExtra.First.matching brackets x) in
 
249
      loop ((`Brackets brackets_content)::acc) xs
 
250
  | x::xs when (StrExtra.First.matchingp slashes x) ->
 
251
      let slashes_content = extract (StrExtra.First.matching slashes x) in
 
252
      loop ((`Slashes slashes_content)::acc) xs
 
253
  | x::xs ->
 
254
      loop ((`AString x)::acc) xs
 
255
  in
 
256
  let token_list : ([`Brackets of string | `Slashes of string | `AString of string] list) option =
 
257
    Option.map (loop []) x
 
258
  in
 
259
  let rec collapse_AString acc = function
 
260
  | [] -> List.rev acc
 
261
  | (`AString x)::(`AString y)::zs -> collapse_AString acc ((`AString (String.concat " " [x;y]))::zs)
 
262
  | x::ys -> collapse_AString (x::acc) ys
 
263
  in
 
264
  let token_list = Option.map (collapse_AString []) token_list in
 
265
  let rec parse acc = function
 
266
  | [] -> List.rev acc
 
267
  | (`Brackets x)::(`AString y)::zs -> parse (((`kernel_epithet x), Some y)::acc) zs
 
268
  | (`Brackets x)::zs               -> parse (((`kernel_epithet x), None)::acc) zs
 
269
  | (`Slashes x)::(`AString y)::zs  -> parse (((`kernel_regexpr (Str.regexp x)), Some y)::acc) zs
 
270
  | (`Slashes x)::zs                -> parse (((`kernel_regexpr (Str.regexp x)), None)::acc) zs
 
271
  | (`AString x)::_ ->
 
272
      let msg = Printf.sprintf "Parsing variable SUPPORTED_KERNELS: unexpected string `%s'" x in
 
273
      failwith msg
 
274
  in
 
275
  let parsing_result
 
276
    : ([> `kernel_epithet of string | `kernel_regexpr of Str.regexp ] * string option) list option
 
277
    = Option.map (parse []) token_list
 
278
  in
 
279
  let parsing_result_as_predicate_list : ((string -> bool) * string option) list option =
 
280
    let epithet_predicate_of = function
 
281
    | `kernel_epithet x -> ((=)x)
 
282
    | `kernel_regexpr r -> (StrExtra.First.matchingp r)
 
283
    in
 
284
    Option.map (List.map (fun (k,so) -> ((epithet_predicate_of k),so))) parsing_result
 
285
  in
 
286
  function epithet ->
 
287
    match parsing_result_as_predicate_list with
 
288
    | None -> Either.Right (None)  (* The epithet is ok, without special console options *)
 
289
    | Some pred_so_list ->
 
290
        begin
 
291
          match (ListExtra.search (fun (pred,so) -> pred epithet) pred_so_list) with
 
292
          | None -> Either.Left () (* The epithet will be not accepted *)
 
293
          | Some (_,options) -> Either.Right (options) (* The epithet is ok, may be with options *)
 
294
        end
 
295
  (* end of get_and_parse_SUPPORTED_KERNELS() *)
 
296
 
 
297
class virtual_machine_installations
 
298
  ?(user_filesystem_searching_list = user_filesystem_searching_list)
 
299
  ?(root_filesystem_searching_list = root_filesystem_searching_list)
 
300
  ?(kernel_searching_list=kernel_searching_list)
 
301
  ?(kernel_prefix = kernel_prefix)
 
302
  ?(kernel_default_epithet:[`kernel] epithet option)
 
303
  ?(filesystem_default_epithet:[`distrib] epithet option)
 
304
  ~prefix (* "machine-", "router-", ... *)
 
305
  () =
 
306
  (* The actual filesystem searching list is the merge of user (prioritary)
 
307
     and root lists: *)
 
308
  let filesystem_searching_list =
 
309
    List.append user_filesystem_searching_list root_filesystem_searching_list
 
310
  in
 
311
  let filter_exclude_names_ending_with_dot_conf x =
 
312
    not (StrExtra.First.matchingp (Str.regexp "[.]conf[~]?$") x)
 
313
  in
 
314
  (* The manager of all filesystem epithets: *)
 
315
  let filesystems : [`distrib] epithet_manager =
 
316
    new epithet_manager
 
317
        ~filter:filter_exclude_names_ending_with_dot_conf
 
318
        ~kind:`distrib
 
319
        ~prefix
 
320
        ~directory_searching_list:filesystem_searching_list
 
321
        ?default_epithet:filesystem_default_epithet
 
322
        ()
 
323
  in
 
324
  (* The manager of all kernel epithets: *)
 
325
  let kernels : [`kernel] epithet_manager =
 
326
    new epithet_manager
 
327
        ~filter:filter_exclude_names_ending_with_dot_conf
 
328
        ~kind:`kernel
 
329
        ~prefix:kernel_prefix
 
330
        ~directory_searching_list:kernel_searching_list
 
331
        ?default_epithet:kernel_default_epithet
 
332
        ()
 
333
  in
 
334
  (* The kit of managers (one per filesystem epithet) for variant epithets.
 
335
     This mapping is created from `filesystems#get_epithet_list' *)
 
336
  let filesystem_variants_mapping =
 
337
   let epithet_manager_of filesystem_epithet : [`variant] epithet_manager =
 
338
    begin
 
339
     let directory_searching_list_of e =
 
340
        List.map
 
341
          (fun dir -> Printf.sprintf "%s/%s%s_variants" dir prefix e)
 
342
          filesystem_searching_list
 
343
     in
 
344
     let directory_searching_list =
 
345
       let epithets = filesystems#epithets_sharing_the_same_realpath_of filesystem_epithet in
 
346
       let epithets = ListExtra.lift_to_the_top_positions ((=)filesystem_epithet) epithets in
 
347
       List.flatten (List.map directory_searching_list_of epithets)
 
348
     in
 
349
     new epithet_manager
 
350
        ~kind:`variant
 
351
        ~prefix:""
 
352
        ~directory_searching_list
 
353
       ()
 
354
    end
 
355
   in
 
356
   let assoc_list :  ([`distrib] epithet * [`variant] epithet_manager) list =
 
357
     List.map (fun e -> (e,epithet_manager_of e)) filesystems#get_epithet_list
 
358
   in
 
359
   String_map.of_list assoc_list
 
360
  in
 
361
  (* Now we build the mapping filesystem-epithet -> Configuration_files.t option *)
 
362
  let filesystem_config_mapping =
 
363
    let mill =
 
364
      fun filesystem_epithet ->
 
365
        let filename = filesystems#filename_of_epithet (filesystem_epithet) in
 
366
        let config_file = Printf.sprintf "%s.conf" (filename) in
 
367
        let result =
 
368
          match Sys.file_exists (config_file) with
 
369
          | false -> None
 
370
          | true  ->
 
371
              let () = Log.printf "configuration file found for \"%s\"\n" filesystem_epithet in
 
372
              let config =
 
373
                Configuration_files.make
 
374
                  ~dont_read_environment:()
 
375
                  ~file_names:[config_file]
 
376
                  ~variables:[ "MD5SUM"; "AUTHOR"; "DATE"; "MTIME"; "SUPPORTED_KERNELS"; "X11_SUPPORT"; ]
 
377
                  ()
 
378
              in
 
379
              Some (config)
 
380
        in
 
381
        result
 
382
    (* end mill () *)
 
383
    in
 
384
    String_map.of_list (List.map (fun e -> (e, mill e)) filesystems#get_epithet_list)
 
385
  in
 
386
  (* Now the mapping filesystem-epithet -> [(kernel1, console-options1); (kernel2, console-options2);...] option *)
 
387
  let filesystem_kernels_mapping =
 
388
    let mill =
 
389
      fun filesystem_epithet ->
 
390
        let config = String_map.find (filesystem_epithet) (filesystem_config_mapping) in
 
391
        Option.bind config
 
392
          (fun config_t ->
 
393
             try
 
394
               let filter : [`kernel] epithet -> (unit, string option) Either.t =
 
395
                  get_and_parse_SUPPORTED_KERNELS config_t
 
396
               in
 
397
               let ks = kernels#get_epithet_list in
 
398
               let ks = List.map (fun k -> (k, filter k)) ks in
 
399
               let ks = List.filter (fun (k,r) -> r <> Either.Left ()) ks in
 
400
               let ks = List.map (fun (k,r) -> (k, Either.extract r)) ks in
 
401
               let () =
 
402
                 Log.printf "Selected kernels for \"%s\": [%s]\n"
 
403
                   filesystem_epithet
 
404
                   (String.concat " " (List.map fst ks))
 
405
               in
 
406
               (Some ks)
 
407
             with Failure msg ->
 
408
                 let () = Log.printf "%s => \"%s\" config file ignored!\n" msg filesystem_epithet in
 
409
                 None)
 
410
    in
 
411
    String_map.of_list (List.map (fun e -> (e, mill e)) filesystems#get_epithet_list)
 
412
  in
 
413
  (* The manager for terminal (X support): *)
 
414
  let terminal_manager =
 
415
    new terminal_manager ()
 
416
  in
 
417
  object (self)
 
418
  method filesystem_searching_list = filesystem_searching_list
 
419
  method kernel_searching_list = kernel_searching_list
 
420
  method kernel_prefix = kernel_prefix
 
421
  method prefix = prefix
 
422
 
 
423
  method filesystems = filesystems
 
424
  method kernels = kernels
 
425
 
 
426
  method variants_of filesystem_epithet =
 
427
    String_map.find (filesystem_epithet) (filesystem_variants_mapping)
 
428
 
 
429
  (* Here, if we replace the first two lines of the following definition by:
 
430
    ---
 
431
    method supported_kernels_of (filesystem_epithet:[`distrib] epithet) : ([`kernel] epithet * (string option)) list =
 
432
    ---
 
433
    we obtain an error message about the method's type:
 
434
    [ `distrib ] epithet -> ('c epithet * string option) list where 'c is unbound *)
 
435
  method supported_kernels_of : [`distrib] epithet -> ([`kernel] epithet * (string option)) list =
 
436
    fun filesystem_epithet ->
 
437
      match String_map.find (filesystem_epithet) (filesystem_kernels_mapping) with
 
438
      | None    -> List.map (fun k -> (k,None)) kernels#get_epithet_list
 
439
      | Some ks -> ks
 
440
 
 
441
  (* Do not propose any filesystems which haven't at least one compatible installed kernel: *)
 
442
  initializer
 
443
    filesystems#filter
 
444
      (fun e -> (self#supported_kernels_of e)<>[])
 
445
 
 
446
  method get_kernel_console_arguments : [`distrib] epithet -> [`kernel] epithet -> string option =
 
447
    fun filesystem_epithet kernel_epithet ->
 
448
      try
 
449
        let ks = self#supported_kernels_of (filesystem_epithet) in
 
450
        List.assoc (kernel_epithet) ks
 
451
      with Not_found ->
 
452
        let () =
 
453
          Log.printf
 
454
            "Disk.virtual_machine_installations#get_kernel_console_arguments: couple (%s,%s) unknown!\n"
 
455
            (filesystem_epithet) (kernel_epithet)
 
456
        in None
 
457
 
 
458
  (** Terminal choices to handle uml machines.
 
459
      The list doesn't depend on the choosen distribution (in this version): *)
 
460
  method terminal_manager_of (_: [`distrib] epithet) = terminal_manager
 
461
 
 
462
  method root_export_dirname epithet =
 
463
    let root_dir = List.hd root_filesystem_searching_list in
 
464
    (Printf.sprintf "%s/%s%s_variants" root_dir prefix epithet)
 
465
 
 
466
  method user_export_dirname epithet =
 
467
    let user_dir = List.hd user_filesystem_searching_list in
 
468
    (Printf.sprintf "%s/%s%s_variants" user_dir prefix epithet)
 
469
 
 
470
  method check_filesystems_MTIME_consistency () =
 
471
    let check =
 
472
      fun filesystem_epithet ->
 
473
        let config = String_map.find (filesystem_epithet) (filesystem_config_mapping) in
 
474
        if config = None then () else (* continue: *)
 
475
        let mtime = Configuration_files.get_int_variable "MTIME" (Option.extract config) in
 
476
        Option.iter
 
477
          (fun expected_mtime ->
 
478
             let realpath = filesystems#realpath_of_epithet (filesystem_epithet) in
 
479
             let actual_mtime =
 
480
               int_of_float ((Unix.stat realpath).Unix.st_mtime)
 
481
             in
 
482
             if actual_mtime = expected_mtime then () else (* warning: *)
 
483
             let title = (s_ "Modification time (MTIME) inconsistency") in
 
484
             let message =
 
485
               Printf.sprintf
 
486
                 (f_ "The filesystem `%s%s' has the mtime %d, but the expected value was %d.\nPlease run the command:\n\n<tt><small>sudo touch -d @%d %s</small></tt>\n\nin order to fix this inconsistency. Otherwise, machines or routers with this filesystem defined in a project created elsewhere can not be restarted.")
 
487
                 (prefix) (filesystem_epithet) (actual_mtime) (expected_mtime) (expected_mtime) (realpath)
 
488
             in
 
489
             Simple_dialogs.warning title message ())
 
490
          mtime
 
491
    in
 
492
    List.iter (check) filesystems#get_epithet_list
 
493
 
 
494
end
 
495
 
 
496
let get_router_installations
 
497
  ?(user_filesystem_searching_list = user_filesystem_searching_list)
 
498
  ?(root_filesystem_searching_list = root_filesystem_searching_list)
 
499
  ?(kernel_searching_list=kernel_searching_list)
 
500
  ?(kernel_prefix = kernel_prefix)
 
501
  ?(kernel_default_epithet=Initialization.router_kernel_default_epithet)
 
502
  ?(filesystem_default_epithet=Initialization.router_filesystem_default_epithet)
 
503
  () =
 
504
     new virtual_machine_installations
 
505
       ~prefix:"router-"
 
506
       ~kernel_default_epithet
 
507
       ~filesystem_default_epithet
 
508
       ()
 
509
 
 
510
let get_machine_installations
 
511
  ?(user_filesystem_searching_list = user_filesystem_searching_list)
 
512
  ?(root_filesystem_searching_list = root_filesystem_searching_list)
 
513
  ?(kernel_searching_list=kernel_searching_list)
 
514
  ?(kernel_prefix = kernel_prefix)
 
515
  ?(kernel_default_epithet=Initialization.machine_kernel_default_epithet)
 
516
  ?(filesystem_default_epithet=Initialization.machine_filesystem_default_epithet)
 
517
  () =
 
518
     new virtual_machine_installations
 
519
       ~prefix:"machine-"
 
520
       ~kernel_default_epithet
 
521
       ~filesystem_default_epithet
 
522
       ()
 
523
 
 
524
let vm_installations_and_epithet_of_prefixed_filesystem prefixed_filesystem =
 
525
 try
 
526
  let p = String.index prefixed_filesystem '-' in
 
527
  let prefix = String.sub prefixed_filesystem 0 (p+1) in
 
528
  let epithet = String.sub prefixed_filesystem (p+1) ((String.length prefixed_filesystem)-(p+1)) in
 
529
  let vm_installations =
 
530
    (match prefix with
 
531
     | "machine-" -> get_machine_installations ()
 
532
     | "router-"  -> get_router_installations ()
 
533
     | _ -> (assert false)
 
534
     )
 
535
  in
 
536
  (vm_installations, epithet)
 
537
 with _ -> failwith (Printf.sprintf "vm_installations_and_epithet_of_prefixed_filesystem: %s" prefixed_filesystem)
 
538
 
 
539
let user_export_dirname_of_prefixed_filesystem prefixed_filesystem =
 
540
  let (vm_installations, epithet) =
 
541
    vm_installations_and_epithet_of_prefixed_filesystem prefixed_filesystem
 
542
  in
 
543
  vm_installations#user_export_dirname epithet
 
544
 
 
545
let root_export_dirname_of_prefixed_filesystem prefixed_filesystem =
 
546
  let (vm_installations, epithet) =
 
547
    vm_installations_and_epithet_of_prefixed_filesystem prefixed_filesystem
 
548
  in
 
549
  vm_installations#root_export_dirname epithet
 
550
 
 
551
 
 
552
module Make_and_check_installations (Unit:sig end) = struct
 
553
 
 
554
  let machines = get_machine_installations ()
 
555
  let routers  = get_router_installations ()
 
556
 
 
557
  let () = begin
 
558
    machines#check_filesystems_MTIME_consistency ();
 
559
    routers#check_filesystems_MTIME_consistency ();
 
560
    end
 
561
 
 
562
end (* Make_and_check_installations *)