Skip to content

Commit 98c16bd

Browse files
thomassamatthiasgoergens
authored andcommitted
CA-32077 Gracefully handle missing /etc/xensource-inventory file
xapi was failing nastily on start-up if the xensource-inventory file was missing. Now it generates a minimal one if none exists. This does not include a build number, so version.ml now falls back to using a build number from the Make environment if one is not available from the inventory, i.e. it falls back to the behaviour from before Matthias's commit for CA-43574 (build number from xensource-inventory). Signed-off-by: Thomas Sanders <[email protected]>
1 parent 066da3d commit 98c16bd

File tree

3 files changed

+58
-46
lines changed

3 files changed

+58
-46
lines changed

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ import-v6:
7878
version:
7979
echo "(* This file is autogenerated. Grep for e17512ce-ba7c-11df-887b-0026b9799147 (random uuid) to see where it comes from. ;o) *)" > ocaml/util/version.ml
8080
echo "let hg_id = \"$(shell hg id | sed -r 's/(.+)\s.*/\1/g')\"" >> ocaml/util/version.ml
81-
echo "let hostname = \"$(shell hostname)\"" >> ocaml/util/version.ml
82-
echo "let date = \"$(shell date -u +%Y-%m-%d)\"" >> ocaml/util/version.ml
81+
echo "let hostname = \"$(shell hostname)\"" >> ocaml/util/version.ml
82+
echo "let date = \"$(shell date -u +%Y-%m-%d)\"" >> ocaml/util/version.ml
8383
echo "let product_version = \"$(PRODUCT_VERSION)\"" >> ocaml/util/version.ml
8484
echo "let product_version_text = \"$(PRODUCT_VERSION_TEXT)\"" >> ocaml/util/version.ml
8585
echo "let product_version_text_short = \"$(PRODUCT_VERSION_TEXT_SHORT)\"" >> ocaml/util/version.ml
86-
echo "let product_brand = \"$(PRODUCT_BRAND)\"" >> ocaml/util/version.ml
87-
echo "let build_number = Util_inventory.lookup \"BUILD_NUMBER\" (* \"$(BUILD_NUMBER)\" *)" >> ocaml/util/version.ml
86+
echo "let product_brand = \"$(PRODUCT_BRAND)\"" >> ocaml/util/version.ml
87+
echo "let build_number = Util_inventory.lookup ~default:\"$(BUILD_NUMBER)\" \"BUILD_NUMBER\"" >> ocaml/util/version.ml
8888

8989
.PHONY: clean
9090
clean:

ocaml/util/util_inventory.ml

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(*
2-
* Copyright (C) 2006-2009 Citrix Systems Inc.
2+
* Copyright (C) 2006-2010 Citrix Systems Inc.
33
*
44
* This program is free software; you can redistribute it and/or modify
55
* it under the terms of the GNU Lesser General Public License as published
@@ -20,10 +20,33 @@ open Threadext
2020
module D = Debug.Debugger(struct let name="xapi" end)
2121
open D
2222

23+
let inventory_filename = Util_globs_inventory.inventory_filename
24+
25+
(* Keys which must exist: *)
26+
let _installation_uuid = "INSTALLATION_UUID"
27+
let _control_domain_uuid = "CONTROL_DOMAIN_UUID"
28+
let _management_interface = "MANAGEMENT_INTERFACE"
29+
30+
(* Optional keys: *)
31+
let _current_interfaces = "CURRENT_INTERFACES"
32+
let _oem_manufacturer = "OEM_MANUFACTURER"
33+
let _oem_model = "OEM_MODEL"
34+
let _oem_build_number = "OEM_BUILD_NUMBER"
35+
let _machine_serial_number = "MACHINE_SERIAL_NUMBER"
36+
let _machine_serial_name = "MACHINE_SERIAL_NAME"
37+
2338
let loaded_inventory = ref false
2439
let inventory = Hashtbl.create 10
2540
let inventory_m = Mutex.create ()
2641

42+
(* Compute the minimum necessary inventory file contents *)
43+
let minimum_default_entries () =
44+
let host_uuid = Uuid.string_of_uuid (Uuid.make_uuid ()) in
45+
let dom0_uuid = Uuid.string_of_uuid (Uuid.make_uuid ()) in
46+
[ _installation_uuid, host_uuid;
47+
_control_domain_uuid, dom0_uuid;
48+
_management_interface, "" ]
49+
2750
(* trim any quotes off the ends *)
2851
let strip_quotes v =
2952
if String.length v >= 2
@@ -39,15 +62,25 @@ let parse_inventory_entry line =
3962
Some (k, strip_quotes ++ String.strip String.isspace $ v)
4063
| _ -> None
4164

65+
let string_of_table h =
66+
let lines = List.fold_left (fun acc (k, v) ->
67+
Printf.sprintf "%s='%s'\n" k v :: acc) [] h in
68+
String.concat "" lines
69+
4270
let read_inventory_contents () =
71+
if not (Sys.file_exists inventory_filename) then begin
72+
warn "%s does not exist: generating a minimal one" inventory_filename;
73+
Unixext.write_string_to_file inventory_filename (
74+
string_of_table (minimum_default_entries ()))
75+
end;
4376
(* Perhaps we should blank the old inventory before we read the new one?
4477
What is the desired behaviour? *)
4578
Unixext.file_lines_iter (fun line ->
4679
match parse_inventory_entry line with
4780
| Some (k, v) -> Hashtbl.add inventory k v
4881
| None -> warn
4982
"Failed to parse line from xensource-inventory file: %s" line)
50-
Util_globs_inventory.inventory_filename;
83+
inventory_filename;
5184
loaded_inventory := true
5285

5386
let read_inventory () = Mutex.execute inventory_m read_inventory_contents
@@ -57,18 +90,19 @@ let reread_inventory () = Mutex.execute inventory_m (fun () ->
5790

5891
exception Missing_inventory_key of string
5992

60-
let lookup key =
61-
if not (!loaded_inventory) then read_inventory();
62-
if not (Hashtbl.mem inventory key)
63-
then raise (Missing_inventory_key key);
64-
Hashtbl.find inventory key
93+
let lookup ?default key =
94+
(if not (!loaded_inventory) then read_inventory());
95+
if (Hashtbl.mem inventory key)
96+
then
97+
Hashtbl.find inventory key
98+
else
99+
match default with
100+
| None -> raise (Missing_inventory_key key)
101+
| Some v -> v
65102

66103
let flush_to_disk_locked () =
67-
let lines = Hashtbl.fold
68-
(fun k v acc -> Printf.sprintf "%s='%s'\n" k v :: acc)
69-
inventory [] in
70-
Unixext.write_string_to_file Util_globs_inventory.inventory_filename
71-
$ String.concat "" lines
104+
let h = Hashtbl.fold (fun k v acc -> (k, v) :: acc) inventory [] in
105+
Unixext.write_string_to_file inventory_filename (string_of_table h)
72106

73107
let update key value = Mutex.execute inventory_m (fun () ->
74108
Hashtbl.clear inventory;
@@ -81,25 +115,3 @@ let remove key = Mutex.execute inventory_m (fun () ->
81115
read_inventory_contents ();
82116
Hashtbl.remove inventory key;
83117
flush_to_disk_locked ())
84-
85-
let _product_brand = "PRODUCT_BRAND"
86-
let _product_name = "PRODUCT_NAME"
87-
let _product_version = "PRODUCT_VERSION='0.5.1'"
88-
let _build_number = "BUILD_NUMBER"
89-
let _kernel_version = "KERNEL_VERSION"
90-
let _xen_version = "XEN_VERSION"
91-
let _installation_date = "INSTALLATION_DATE"
92-
let _default_sr = "DEFAULT_SR"
93-
let _primary_disk = "PRIMARY_DISK"
94-
let _backup_partition = "BACKUP_PARTITION"
95-
let _installation_uuid = "INSTALLATION_UUID"
96-
let _default_sr_physdevs = "DEFAULT_SR_PHYSDEVS"
97-
let _control_domain_uuid = "CONTROL_DOMAIN_UUID"
98-
let _management_interface = "MANAGEMENT_INTERFACE"
99-
let _current_interfaces = "CURRENT_INTERFACES"
100-
let _dom0_mem = "DOM0_MEM"
101-
let _oem_manufacturer = "OEM_MANUFACTURER"
102-
let _oem_model = "OEM_MODEL"
103-
let _oem_build_number = "OEM_BUILD_NUMBER"
104-
let _machine_serial_number = "MACHINE_SERIAL_NUMBER"
105-
let _machine_serial_name = "MACHINE_SERIAL_NAME"

ocaml/util/util_inventory.mli

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(*
2-
* Copyright (C) 2006-2009 Citrix Systems Inc.
2+
* Copyright (C) 2006-2010 Citrix Systems Inc.
33
*
44
* This program is free software; you can redistribute it and/or modify
55
* it under the terms of the GNU Lesser General Public License as published
@@ -25,9 +25,9 @@ val read_inventory: unit -> unit
2525
(** Clears the copy of the inventory file in memory and reads the file from disk. *)
2626
val reread_inventory: unit -> unit
2727

28-
(** Return the value of key [key] in the inventory file. Throws {!Missing_inventory_key}
29-
* if the key does not exist. *)
30-
val lookup: string -> string
28+
(** Return the value of key [key] in the inventory file. If the key does not exist,
29+
* returns the default if supplied, or throws {!Missing_inventory_key} otherwise. *)
30+
val lookup: ?default:string -> string -> string
3131

3232
(** Remove the key with the given name from the inventory file, if it exists. *)
3333
val remove: string -> unit
@@ -40,6 +40,9 @@ val update: string -> string -> unit
4040
val parse_inventory_entry: string -> (string * string) option
4141

4242
(* Keys defined in Geneva *)
43+
(** UUID of the Host object in the xapi database *)
44+
val _installation_uuid : string
45+
(*
4346
(** Brand name, such as "XenServer" *)
4447
val _product_brand : string
4548
@@ -70,15 +73,12 @@ val _primary_disk : string
7073
(** Device path of backup partition *)
7174
val _backup_partition : string
7275
73-
(** UUID of the Host object in the xapi database *)
74-
val _installation_uuid : string
75-
7676
(** Device path of the default SR used for local storage *)
7777
val _default_sr_physdevs : string
7878
7979
(** Memory size of dom0 (?) *)
8080
val _dom0_mem : string
81-
81+
*)
8282

8383
(* Keys defined in Rio *)
8484
(** UUID of the control domain (dom0) *)

0 commit comments

Comments
 (0)