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 = '

XenServer Management API

' - 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"]]