diff --git a/Makefile b/Makefile
index d32926b3efc..993f999a5ea 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ build: setup.data
doc: setup.data build
$(SETUP) -doc $(DOCFLAGS)
- ./jsapi.native -destdir _build/ocaml/doc
+ ./jsapi.native -destdir _build/ocaml/doc -templdir ocaml/doc/templates
test: setup.data build
$(SETUP) -test $(TESTFLAGS)
@@ -95,5 +95,4 @@ install: setup.data rbac_static.csv
mkdir -p $(DESTDIR)$(DOCDIR)/html/xenserver
cp -r -L _build/ocaml/doc/api $(DESTDIR)$(DOCDIR)/html/xenserver
cd ocaml/doc && cp *.js *.html *.css *.png $(DESTDIR)$(DOCDIR)/html/xenserver
- cp ocaml/doc/xenserver/* $(DESTDIR)$(DOCDIR)/html/xenserver
-
+ cp _build/ocaml/doc/branding.js $(DESTDIR)$(DOCDIR)/html/xenserver/branding.js
diff --git a/_oasis b/_oasis
index 71ec9716c8c..2dc4ab15f8c 100644
--- a/_oasis
+++ b/_oasis
@@ -424,7 +424,8 @@ Executable jsapi
xapi-consts,
stdext,
uuid,
- gzip
+ gzip,
+ mustache
############################################################################
diff --git a/ocaml/doc/branding.js b/ocaml/doc/branding.js
deleted file mode 100644
index 81da0b1d37d..00000000000
--- a/ocaml/doc/branding.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2006-2009 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.
- */
-
-function make_title() {
- document.write('
Xapi Documentation');
-}
-
-function make_header(t) {
- if (t == 'apidoc')
- title = 'Xapi – XenAPI Documentation';
- else if (t == 'codedoc')
- title = 'Xapi – OCaml Code Documentation';
- else
- title = 'Xapi – Documentation';
-
- html = ''
- document.getElementById('header').innerHTML = html;
-}
-
-first_release = 'midnight-ride';
-
-function get_release_name(s)
-{
- switch (s) {
- case 'rio':
- case 'miami':
- case 'symc':
- case 'orlando':
- case 'orlando-update-1':
- case 'george':
- case 'midnight-ride':
- return 'XCP 0.5';
- case 'cowley':
- return 'XCP 1.0';
- case 'boston':
- return 'XCP 1.5';
- case 'tampa':
- return 'XCP 1.6';
- case 'clearwater':
- return 'XenServer 6.2';
- case 'vgpu-tech-preview':
- return 'XenServer 6.2 vGPU preview';
- case 'vgpu-productisation':
- return 'XenServer 6.2 SP1';
- case 'clearwater-felton':
- return 'XenServer 6.2 SP1 Hotfix 4';
- case 'clearwater-whetstone':
- return 'XenServer 6.2 SP1 Hotfix 11';
- case 'creedence':
- return 'XenServer 6.5';
- case 'cream':
- return 'XenServer 6.5 SP1';
- case 'dundee':
- return 'XenServer 7.0';
- case 'ely':
- return 'XenServer 7.1';
- default:
- return (s + ' (unreleased)');
- }
-}
-
diff --git a/ocaml/doc/jsapi.ml b/ocaml/doc/jsapi.ml
index b0dae63c058..0994aaed52d 100644
--- a/ocaml/doc/jsapi.ml
+++ b/ocaml/doc/jsapi.ml
@@ -12,6 +12,8 @@
* GNU Lesser General Public License for more details.
*)
+open Stdext
+open Pervasiveext
open Datamodel_types
type change_t = lifecycle_change * string * string
@@ -19,10 +21,12 @@ and changes_t = change_t list
[@@deriving rpc]
let destdir = ref "."
+let templdir = ref ""
let parse_args () =
Arg.parse [
"-destdir", Arg.Set_string destdir, "the destination directory for the generated files";
+ "-templdir", Arg.Set_string templdir, "the directory with the template (mustache) files";
]
(fun x-> Printf.printf "Ignoring anonymous argument %s" x)
("Generates documentation for the datamodel classes. See -help.")
@@ -48,14 +52,14 @@ let generate_files destdir =
let changes_in_release rel =
let search_obj obj =
- let changes = List.filter (fun (transition, release, doc) -> release = rel) obj.obj_lifecycle in
+ let changes = List.filter (fun (transition, release, doc) -> release = code_name_of_release rel) obj.obj_lifecycle in
let obj_changes : changes_t =
List.map (fun (transition, release, doc) ->
(transition, obj.name, if doc = "" && transition = Published then obj.description else doc)
) changes in
let changes_for_msg m =
- let changes = List.filter (fun (transition, release, doc) -> release = rel) m.msg_lifecycle in
+ let changes = List.filter (fun (transition, release, doc) -> release = code_name_of_release rel) m.msg_lifecycle in
List.map (fun (transition, release, doc) ->
(transition, m.msg_name, if doc = "" && transition = Published then m.msg_doc else doc)
) changes
@@ -64,7 +68,7 @@ let generate_files destdir =
let msg_changes : changes_t = List.fold_left (fun l m -> l @ (changes_for_msg m)) [] msgs in
let changes_for_field f =
- let changes = List.filter (fun (transition, release, doc) -> release = rel) f.lifecycle in
+ let changes = List.filter (fun (transition, release, doc) -> release = code_name_of_release rel) f.lifecycle in
let field_name = String.concat "_" f.full_name in
List.map (fun (transition, release, doc) ->
(transition, field_name, if doc = "" && transition = Published then f.field_description else doc)
@@ -83,14 +87,37 @@ let generate_files destdir =
"{'cls': '" ^ obj.name ^ "', 'obj_changes': " ^ Jsonrpc.to_string (rpc_of_changes_t obj_changes) ^ ", 'field_changes': " ^ Jsonrpc.to_string (rpc_of_changes_t field_changes) ^ ", 'msg_changes': " ^ Jsonrpc.to_string (rpc_of_changes_t msg_changes) ^ "}"
in
let release_info = String.concat ", " (List.map search_obj objs) in
- let fname = rel ^ ".json" in
+ let fname = (code_name_of_release rel) ^ ".json" in
Stdext.Unixext.write_string_to_file (Filename.concat api_dir fname) ("release_info = [" ^ release_info ^ "]")
in
List.iter changes_in_release release_order;
- let release_list = String.concat ", " (List.map (fun s -> "'" ^ s ^ "'") release_order) in
+ let release_list = String.concat ", " (List.map (fun s -> "'" ^ (code_name_of_release s) ^ "'") release_order) in
Stdext.Unixext.write_string_to_file (Filename.concat api_dir "releases.json") ("releases = [" ^ release_list ^ "]")
+let json_releases =
+ let json_of_rel x = `O [
+ "code_name", `String (code_name_of_release x);
+ "version_major", `Float (float_of_int x.version_major);
+ "version_minor", `Float (float_of_int x.version_minor);
+ "branding", `String x.branding;
+ ]
+ in
+ `O [ "releases", `A (List.map json_of_rel release_order) ]
+
+let render_template template_file json output_file =
+ let templ = Stdext.Unixext.string_of_file template_file |> Mustache.of_string in
+ let rendered = Mustache.render templ json in
+ let out_chan = open_out output_file in
+ finally (fun () -> output_string out_chan rendered)
+ (fun () -> close_out out_chan)
+
+let populate_releases templates_dir dest_dir=
+ let inpath x = Filename.concat templates_dir x in
+ let outpath x = Filename.concat dest_dir x in
+ let render (infile, outfile) = render_template (inpath infile) json_releases (outpath outfile) in
+ [ "branding.mustache", "branding.js"] |> List.iter render
let _ =
parse_args ();
- generate_files !destdir
\ No newline at end of file
+ generate_files !destdir;
+ populate_releases !templdir !destdir
diff --git a/ocaml/doc/xenserver/branding.js b/ocaml/doc/templates/branding.mustache
similarity index 51%
rename from ocaml/doc/xenserver/branding.js
rename to ocaml/doc/templates/branding.mustache
index 2095f961822..3924445efe5 100644
--- a/ocaml/doc/xenserver/branding.js
+++ b/ocaml/doc/templates/branding.mustache
@@ -24,49 +24,14 @@ function make_header(t) {
first_release = 'rio';
-function get_release_name(s)
-{
+function get_release_name(s) {
switch (s) {
- case 'rio':
- return 'XenServer 4.0';
- case 'miami':
- return 'XenServer 4.1';
- case 'symc':
- return 'XenServer 4.1.1';
- case 'orlando':
- return 'XenServer 5.0';
- case 'orlando-update-1':
- return 'XenServer 5.0 Update 1';
- case 'george':
- return 'XenServer 5.5';
- case 'midnight-ride':
- return 'XenServer 5.6';
- case 'cowley':
- return 'XenServer 5.6 FP1';
- case 'boston':
- return 'XenServer 6.0';
- case 'tampa':
- return 'XenServer 6.1';
- case 'clearwater':
- return 'XenServer 6.2';
- case 'vgpu-tech-preview':
- return 'XenServer 6.2 vGPU preview';
- case 'vgpu-productisation':
- return 'XenServer 6.2 SP1';
- case 'clearwater-felton':
- return 'XenServer 6.2 SP1 Hotfix 4';
- case 'clearwater-whetstone':
- return 'XenServer 6.2 SP1 Hotfix 11';
- case 'creedence':
- return 'XenServer 6.5';
- case 'cream':
- return 'XenServer 6.5 SP1';
- case 'dundee':
- return 'XenServer 7.0';
- case 'ely':
- return 'XenServer 7.1';
- default:
- return 'Unreleased';
- }
+{{#releases}}
+ case '{{code_name}}':
+ return '{{branding}}';
+{{/releases}}
+ default:
+ return 'Unreleased';
+ }
}
diff --git a/ocaml/idl/datamodel.ml b/ocaml/idl/datamodel.ml
index 74f2cb5ddd0..7fe0ed395f2 100644
--- a/ocaml/idl/datamodel.ml
+++ b/ocaml/idl/datamodel.ml
@@ -215,8 +215,6 @@ let _R_ALL = _R_READ_ONLY
let errors = Hashtbl.create 10
let messages = Hashtbl.create 10
-exception UnspecifiedRelease
-
let get_oss_releases in_oss_since =
match in_oss_since with
None -> []
@@ -227,7 +225,8 @@ let get_product_releases in_product_since =
let rec go_through_release_order rs =
match rs with
[] -> raise UnspecifiedRelease
- | x::xs -> if x=in_product_since then "closed"::x::xs else go_through_release_order xs
+ | x::xs when code_name_of_release x = in_product_since -> "closed"::in_product_since::(List.map code_name_of_release xs)
+ | x::xs -> go_through_release_order xs
in go_through_release_order release_order
let falcon_release =
@@ -236,8 +235,8 @@ let falcon_release =
; internal_deprecated_since=None
}
-let dundee_plus_release =
- { internal = get_product_releases rel_dundee_plus
+let ely_release =
+ { internal = get_product_releases rel_ely
; opensource=get_oss_releases None
; internal_deprecated_since=None
}
@@ -303,37 +302,37 @@ let cowley_release =
}
let midnight_ride_release =
- { internal=get_product_releases "midnight-ride"
+ { internal=get_product_releases rel_midnight_ride
; opensource=get_oss_releases None
; internal_deprecated_since=None
}
let george_release =
- { internal=get_product_releases "george"
+ { internal=get_product_releases rel_george
; opensource=get_oss_releases None
; internal_deprecated_since=None
}
let orlando_release =
- { internal=get_product_releases "orlando"
+ { internal=get_product_releases rel_orlando
; opensource=get_oss_releases None
; internal_deprecated_since=None
}
let miami_symc_release =
- { internal=get_product_releases "symc"
+ { internal=get_product_releases rel_symc
; opensource=get_oss_releases None
; internal_deprecated_since=None
}
let miami_release =
- { internal=get_product_releases "miami"
+ { internal=get_product_releases rel_miami
; opensource=get_oss_releases None
; internal_deprecated_since=None
}
let rio_release =
- { internal=get_product_releases "rio"
+ { internal=get_product_releases rel_rio
; opensource=get_oss_releases (Some "3.0.3")
; internal_deprecated_since=None
}
@@ -3219,7 +3218,7 @@ let host_call_plugin = call
let host_has_extension = call
~name:"has_extension"
- ~in_product_since:rel_dundee_plus
+ ~in_product_since:rel_ely
~doc:"Return true if the extension is available on the host"
~params:[Ref _host, "host", "The host";
String, "name", "The name of the API call";]
@@ -3229,7 +3228,7 @@ let host_has_extension = call
let host_call_extension = call
~name:"call_extension"
- ~in_product_since:rel_dundee_plus
+ ~in_product_since:rel_ely
~custom_marshaller:true
~doc:"Call a XenAPI extension on this host"
~params:[Ref _host, "host", "The host";
@@ -4555,7 +4554,7 @@ let host_emergency_ha_disable = call ~flags:[`Session]
~in_oss_since:None
~in_product_since:rel_orlando
~versioned_params:
- [{param_type=Bool; param_name="soft"; param_doc="Disable HA temporarily, revert upon host reboot or further changes, idempotent"; param_release=dundee_plus_release; param_default=Some(VBool false)};
+ [{param_type=Bool; param_name="soft"; param_doc="Disable HA temporarily, revert upon host reboot or further changes, idempotent"; param_release=ely_release; param_default=Some(VBool false)};
]
~doc:"This call disables HA on the local host. This should only be used with extreme care."
~allowed_roles:_R_POOL_OP
@@ -5064,7 +5063,7 @@ let host =
field ~qualifier:RW ~in_product_since:rel_tampa ~default_value:(Some (VMap [])) ~ty:(Map (String, String)) "guest_VCPUs_params" "VCPUs params to apply to all resident guests";
field ~qualifier:RW ~in_product_since:rel_cream ~default_value:(Some (VEnum "enabled")) ~ty:host_display "display" "indicates whether the host is configured to output its console to a physical display device";
field ~qualifier:DynamicRO ~in_product_since:rel_cream ~default_value:(Some (VSet [VInt 0L])) ~ty:(Set (Int)) "virtual_hardware_platform_versions" "The set of versions of the virtual hardware platform that the host can offer to its guests";
- field ~qualifier:DynamicRO ~default_value:(Some (VRef null_ref)) ~in_product_since:rel_dundee_plus ~ty:(Ref _vm) "control_domain" "The control domain (domain 0)";
+ field ~qualifier:DynamicRO ~default_value:(Some (VRef null_ref)) ~in_product_since:rel_ely ~ty:(Ref _vm) "control_domain" "The control domain (domain 0)";
field ~qualifier:DynamicRO ~lifecycle:[Published, rel_ely, ""] ~ty:(Set (Ref _pool_update)) ~ignore_foreign_key:true "updates_requiring_reboot" "List of updates which require reboot";
field ~qualifier:DynamicRO ~lifecycle:[Published, rel_falcon, ""] ~ty:(Set (Ref _feature)) "features" "List of features available on this host"
])
@@ -9256,7 +9255,7 @@ let vgpu_type =
()
module PVS_site = struct
- let lifecycle = [Prototyped, rel_dundee_plus, ""]
+ let lifecycle = [Prototyped, rel_ely, ""]
let introduce = call
~name:"introduce"
@@ -9342,7 +9341,7 @@ end
let pvs_site = PVS_site.obj
module PVS_server = struct
- let lifecycle = [Prototyped, rel_dundee_plus, ""]
+ let lifecycle = [Prototyped, rel_ely, ""]
let introduce = call
~name:"introduce"
@@ -9411,7 +9410,7 @@ end
let pvs_server = PVS_server.obj
module PVS_proxy = struct
- let lifecycle = [Prototyped, rel_dundee_plus, ""]
+ let lifecycle = [Prototyped, rel_ely, ""]
let status = Enum ("pvs_proxy_status", [
"stopped", "The proxy is not currently running";
diff --git a/ocaml/idl/datamodel_types.ml b/ocaml/idl/datamodel_types.ml
index 41a88212dd3..bd0d840e12d 100644
--- a/ocaml/idl/datamodel_types.ml
+++ b/ocaml/idl/datamodel_types.ml
@@ -54,42 +54,152 @@ let rel_creedence = "creedence"
let rel_cream = "cream"
let rel_indigo = "indigo"
let rel_dundee = "dundee"
-let rel_dundee_plus = "dundee-plus"
let rel_ely = "ely"
let rel_falcon = "falcon"
-let release_order =
- [ rel_rio
- ; rel_miami
- ; rel_symc
- ; rel_orlando
- ; rel_orlando_update_1
- ; rel_george
- ; rel_midnight_ride
- ; rel_cowley
- ; rel_boston
- ; rel_tampa
- ; rel_clearwater
- ; rel_vgpu_tech_preview
- ; rel_vgpu_productisation
- ; rel_clearwater_felton
- ; rel_clearwater_whetstone
- ; rel_creedence
- ; rel_cream
- ; rel_indigo
- ; rel_dundee
- ; rel_dundee_plus
- ; rel_ely
- ; rel_falcon
+type api_release = {
+ code_name: string option;
+ version_major: int;
+ version_minor: int;
+ branding: string;
+}
+
+let release_order_full = [{
+ code_name = Some rel_rio;
+ version_major = 1;
+ version_minor = 1;
+ branding = "XenServer 4.0";
+ }; {
+ code_name = Some rel_miami;
+ version_major = 1;
+ version_minor = 2;
+ branding = "XenServer 4.1";
+ }; {
+ code_name = Some rel_symc;
+ version_major = 1;
+ version_minor = 2;
+ branding = "XenServer 4.1.1";
+ }; {
+ code_name = Some rel_orlando;
+ version_major = 1;
+ version_minor = 3;
+ branding = "XenServer 5.0";
+ }; {
+ code_name = Some rel_orlando_update_1;
+ version_major = 1;
+ version_minor = 3;
+ branding = "XenServer 5.0 Update 1";
+ }; {
+ code_name = None;
+ version_major = 1;
+ version_minor = 4;
+ branding = "Unreleased";
+ }; {
+ code_name = None;
+ version_major = 1;
+ version_minor = 5;
+ branding = "XenServer 5.0 update 3";
+ }; {
+ code_name = Some rel_george;
+ version_major = 1;
+ version_minor = 6;
+ branding = "XenServer 5.5";
+ }; {
+ code_name = Some rel_midnight_ride;
+ version_major = 1;
+ version_minor = 7;
+ branding = "XenServer 5.6";
+ }; {
+ code_name = Some rel_cowley;
+ version_major = 1;
+ version_minor = 8;
+ branding = "XenServer 5.6 FP1";
+ }; {
+ code_name = Some rel_boston;
+ version_major = 1;
+ version_minor = 9;
+ branding = "XenServer 6.0";
+ }; {
+ code_name = Some rel_tampa;
+ version_major = 1;
+ version_minor = 10;
+ branding = "XenServer 6.1";
+ }; {
+ code_name = Some rel_clearwater;
+ version_major = 2;
+ version_minor = 0;
+ branding = "XenServer 6.2";
+ }; {
+ code_name = Some rel_vgpu_tech_preview;
+ version_major = 2;
+ version_minor = 0;
+ branding = "XenServer 6.2 SP1 Tech-Preview";
+ }; {
+ code_name = Some rel_vgpu_productisation;
+ version_major = 2;
+ version_minor = 1;
+ branding = "XenServer 6.2 SP1";
+ }; {
+ code_name = Some rel_clearwater_felton;
+ version_major = 2;
+ version_minor = 2;
+ branding = "XenServer 6.2 SP1 Hotfix 4";
+ }; {
+ code_name = Some rel_clearwater_whetstone;
+ version_major = 2;
+ version_minor = 2;
+ branding = "XenServer 6.2 SP1 Hotfix 11";
+ }; {
+ code_name = Some rel_creedence;
+ version_major = 2;
+ version_minor = 3;
+ branding = "XenServer 6.5";
+ }; {
+ code_name = Some rel_cream;
+ version_major = 2;
+ version_minor = 4;
+ branding = "XenServer 6.5 SP1";
+ }; {
+ code_name = Some rel_indigo;
+ version_major = 2;
+ version_minor = 4;
+ branding = "XenServer 6.5 SP1 Hotfix 31";
+ }; {
+ code_name = Some rel_dundee;
+ version_major = 2;
+ version_minor = 5;
+ branding = "XenServer 7.0";
+ }; {
+ code_name = Some rel_ely;
+ version_major = 2;
+ version_minor = 6;
+ branding = "XenServer 7.1";
+ }; {
+ code_name = Some rel_falcon;
+ version_major = 2;
+ version_minor = 7;
+ branding = "XenServer 7.2";
+ };
]
+let release_order =
+ List.filter (fun x -> x.code_name <> None) release_order_full
+
exception Unknown_release of string
+exception UnspecifiedRelease
+
+let code_name_of_release x =
+ match x.code_name with
+ | Some r -> r
+ | None -> raise UnspecifiedRelease
+
(* ordering function on releases *)
let release_leq x y =
let rec posn_in_list i x l =
match l with
[] -> raise (Unknown_release x)
- | r::rs -> if r=x then i else posn_in_list (i+1) x rs in
+ | r::rs when code_name_of_release r = x -> i
+ | r::rs-> posn_in_list (i+1) x rs in
(posn_in_list 0 x release_order) <= (posn_in_list 0 y release_order)
(** Types of object fields. Accessor functions are generated for each field automatically according to its type and qualifiers. *)
diff --git a/ocaml/idl/dm_api.ml b/ocaml/idl/dm_api.ml
index beadc1bd8b5..54b4e0a5fe7 100644
--- a/ocaml/idl/dm_api.ml
+++ b/ocaml/idl/dm_api.ml
@@ -233,7 +233,7 @@ let check api emergency_calls =
[] -> sofar
| "closed"::xs -> find_smallest sofar xs (* closed is not a real release, so skip it *)
| x::xs -> if release_lt x sofar then find_smallest x xs else find_smallest sofar xs in
- find_smallest (getlast release_order) releases in
+ find_smallest (getlast release_order |> code_name_of_release) releases in
let rec check_vsns max_release_sofar ps =
match ps with
[] -> true
diff --git a/ocaml/idl/json_backend/gen_json.ml b/ocaml/idl/json_backend/gen_json.ml
index ce70cc4e1fa..b1011268e9e 100644
--- a/ocaml/idl/json_backend/gen_json.ml
+++ b/ocaml/idl/json_backend/gen_json.ml
@@ -257,7 +257,7 @@ let compare_changes (a_t, a_n, _, a_k) (b_t, b_n, _, b_k) =
let releases objs =
let changes_in_release rel =
let search_obj obj =
- let changes = List.filter (fun (transition, release, doc) -> release = rel) obj.obj_lifecycle in
+ let changes = List.filter (fun (transition, release, doc) -> release = code_name_of_release rel) obj.obj_lifecycle in
let obj_changes =
List.map (fun (transition, release, doc) ->
transition,
@@ -267,7 +267,7 @@ let releases objs =
) changes in
let changes_for_msg m =
- let changes = List.filter (fun (transition, release, doc) -> release = rel) m.msg_lifecycle in
+ let changes = List.filter (fun (transition, release, doc) -> release = code_name_of_release rel) m.msg_lifecycle in
List.map (fun (transition, release, doc) ->
transition,
obj.name ^ "." ^ m.msg_name,
@@ -280,7 +280,7 @@ let releases objs =
let msg_changes = List.fold_left (fun l m -> l @ (changes_for_msg m)) [] msgs in
let changes_for_field f =
- let changes = List.filter (fun (transition, release, doc) -> release = rel) f.lifecycle in
+ let changes = List.filter (fun (transition, release, doc) -> release = code_name_of_release rel) f.lifecycle in
let field_name = String.concat "_" f.full_name in
List.map (fun (transition, release, doc) ->
transition,
@@ -302,7 +302,7 @@ let releases objs =
in
JArray (List.map search_obj objs |> List.flatten |> List.sort compare_changes |> List.map jobject_of_change)
in
- let release_info = JObject (List.map (fun rel -> rel, changes_in_release rel) release_order) in
+ let release_info = JObject (List.map (fun rel -> code_name_of_release rel, changes_in_release rel) release_order) in
Stdext.Unixext.write_string_to_file ("release_info.json") (string_of_json 0 release_info)
let _ =
diff --git a/opam b/opam
index f6bdd8296a8..7a4606eb86f 100644
--- a/opam
+++ b/opam
@@ -52,6 +52,7 @@ depends: [
"pci"
"sha"
"xapi-xenopsd"
+ "mustache"
]
depexts: [
[["centos"] ["pam-devel"]]