forked from xapi-project/xen-api
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util_inventory.ml
119 lines (102 loc) · 3.82 KB
/
util_inventory.ml
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
(*
* Copyright (C) 2006-2010 Citrix Systems Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* 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 Lesser General Public License for more details.
*)
(* Code to parse the XenSource inventory file *)
open Pervasiveext
open Stringext
open Threadext
module D = Debug.Debugger(struct let name="xapi" end)
open D
let inventory_filename = Util_globs_inventory.inventory_filename
(* Keys which must exist: *)
let _installation_uuid = "INSTALLATION_UUID"
let _control_domain_uuid = "CONTROL_DOMAIN_UUID"
let _management_interface = "MANAGEMENT_INTERFACE"
let _build_number = "BUILD_NUMBER"
(* Optional keys: *)
let _current_interfaces = "CURRENT_INTERFACES"
let _oem_manufacturer = "OEM_MANUFACTURER"
let _oem_model = "OEM_MODEL"
let _oem_build_number = "OEM_BUILD_NUMBER"
let _machine_serial_number = "MACHINE_SERIAL_NUMBER"
let _machine_serial_name = "MACHINE_SERIAL_NAME"
let loaded_inventory = ref false
let inventory = Hashtbl.create 10
let inventory_m = Mutex.create ()
(* Compute the minimum necessary inventory file contents *)
let minimum_default_entries () =
let host_uuid = Uuid.string_of_uuid (Uuid.make_uuid ()) in
let dom0_uuid = Uuid.string_of_uuid (Uuid.make_uuid ()) in
[ _installation_uuid, host_uuid;
_control_domain_uuid, dom0_uuid;
_management_interface, "";
_build_number, "0" ]
(* trim any quotes off the ends *)
let strip_quotes v =
if String.length v >= 2
&& v.[0] = '\''
&& v.[String.length v - 1] = '\''
then String.sub v 1 (String.length v - 2)
else v
let parse_inventory_entry line =
match String.split ~limit:2 '=' line with
| [k; v] ->
(* trim whitespace *)
Some (k, strip_quotes ++ String.strip String.isspace $ v)
| _ -> None
let string_of_table h =
let lines = List.fold_left (fun acc (k, v) ->
Printf.sprintf "%s='%s'\n" k v :: acc) [] h in
String.concat "" lines
let read_inventory_contents () =
if not (Sys.file_exists inventory_filename) then begin
warn "%s does not exist: generating a minimal one" inventory_filename;
Unixext.write_string_to_file inventory_filename (
string_of_table (minimum_default_entries ()))
end;
(* Perhaps we should blank the old inventory before we read the new one?
What is the desired behaviour? *)
Unixext.file_lines_iter (fun line ->
match parse_inventory_entry line with
| Some (k, v) -> Hashtbl.add inventory k v
| None -> warn
"Failed to parse line from inventory file: %s" line)
inventory_filename;
loaded_inventory := true
let read_inventory () = Mutex.execute inventory_m read_inventory_contents
let reread_inventory () = Mutex.execute inventory_m (fun () ->
Hashtbl.clear inventory;
read_inventory_contents ())
exception Missing_inventory_key of string
let lookup ?default key =
(if not (!loaded_inventory) then read_inventory());
if (Hashtbl.mem inventory key)
then
Hashtbl.find inventory key
else
match default with
| None -> raise (Missing_inventory_key key)
| Some v -> v
let flush_to_disk_locked () =
let h = Hashtbl.fold (fun k v acc -> (k, v) :: acc) inventory [] in
Unixext.write_string_to_file inventory_filename (string_of_table h)
let update key value = Mutex.execute inventory_m (fun () ->
Hashtbl.clear inventory;
read_inventory_contents ();
Hashtbl.replace inventory key value;
flush_to_disk_locked ())
let remove key = Mutex.execute inventory_m (fun () ->
Hashtbl.clear inventory;
read_inventory_contents ();
Hashtbl.remove inventory key;
flush_to_disk_locked ())