diff --git a/ocaml/tests/test_updateinfo.ml b/ocaml/tests/test_updateinfo.ml
index 2adb7c9d2db..6df2f0b2fba 100644
--- a/ocaml/tests/test_updateinfo.ml
+++ b/ocaml/tests/test_updateinfo.ml
@@ -442,7 +442,11 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
module Io = struct
type input_t = string
- type output_t = ((string * UpdateInfo.t) list, exn) result
+ type output_t =
+ ( UpdateInfo.api_ver_t option * (UpdateInfo.id_t * UpdateInfo.t) list
+ , exn
+ )
+ result
let string_of_input_t s = s
@@ -451,7 +455,10 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
str "%a"
Dump.(
result
- ~ok:(list (pair string (record @@ fields_of_updateinfo)))
+ ~ok:
+ (pair (option string)
+ (list (pair string (record @@ fields_of_updateinfo)))
+ )
~error:exn
)
)
@@ -472,13 +479,22 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
, Error Api_errors.(Server_error (invalid_updateinfo_xml, []))
)
; (* No update in updateinfo.xml *)
- ({|
+ ( {|
- |}, Ok [])
+ |}
+ , Ok (None, [])
+ )
+ ; (* No update in updateinfo.xml, but with xapi-api-version *)
+ ( {|
+
+
+ |}
+ , Error Api_errors.(Server_error (invalid_updateinfo_xml, []))
+ )
; (* Missing update_type *)
( {|
-
+
UPDATE-0000
title
@@ -494,7 +510,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
)
; (* Missing id *)
( {|
-
+
title
summary
@@ -509,7 +525,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
)
; (* Missing summary *)
( {|
-
+
UPDATE-0000
title
@@ -524,7 +540,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
)
; (* Missing description *)
( {|
-
+
UPDATE-0000
title
@@ -537,35 +553,37 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= ""
- ; guidance=
- [
- (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= ""
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Duplicate update ID *)
( {|
-
+
UPDATE-0000
title
@@ -588,7 +606,99 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Error Api_errors.(Server_error (invalid_updateinfo_xml, []))
)
+ ; (* Single update, without xapi-api-version *)
+ ( {|
+
+
+ UPDATE-0000
+ title
+ summary
+ description
+ special information
+ https://update.details.info
+
+
+ High
+
+
+ |}
+ , Ok
+ ( None
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ ; severity= Severity.High
+ ; title= "title"
+ }
+ )
+ ]
+ )
+ )
; (* Single update *)
+ ( {|
+
+
+ UPDATE-0000
+ title
+ summary
+ description
+ special information
+ https://update.details.info
+
+
+ High
+
+
+ |}
+ , Ok
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ ; severity= Severity.High
+ ; title= "title"
+ }
+ )
+ ]
+ )
+ )
+ ; (* Two updates, without xapi-api-version *)
( {|
@@ -602,39 +712,76 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
High
+
+ UPDATE-0001
+ title
+ summary
+ description
+ special information
+ https://update.details.info
+
+
+ None
+
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
- ; severity= Severity.High
- ; title= "title"
- }
- )
- ]
+ ( None
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ ; severity= Severity.High
+ ; title= "title"
+ }
+ )
+ ; ( "UPDATE-0001"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0001"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:50Z"
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Two updates *)
( {|
-
+
UPDATE-0000
title
@@ -660,60 +807,62 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
- ; severity= Severity.High
- ; title= "title"
- }
- )
- ; ( "UPDATE-0001"
- , UpdateInfo.
- {
- id= "UPDATE-0001"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:50Z"
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ ; severity= Severity.High
+ ; title= "title"
+ }
+ )
+ ; ( "UPDATE-0001"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0001"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:50Z"
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Single update with deprecated guidances only *)
( {|
-
+
UPDATE-0000
title
@@ -747,56 +896,58 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities=
- [
- Applicability.
- {
- name= "xsconsole"
- ; arch= "x86_64"
- ; inequality= Some Gte
- ; epoch= None
- ; version= "10.1.0"
- ; release= "25"
- }
- ; Applicability.
- {
- name= "xsconsole"
- ; arch= "x86_64"
- ; inequality= Some Lt
- ; epoch= None
- ; version= "10.1.0"
- ; release= "25"
- }
- ]
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
- ; severity= Severity.High
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities=
+ [
+ Applicability.
+ {
+ name= "xsconsole"
+ ; arch= "x86_64"
+ ; inequality= Some Gte
+ ; epoch= None
+ ; version= "10.1.0"
+ ; release= "25"
+ }
+ ; Applicability.
+ {
+ name= "xsconsole"
+ ; arch= "x86_64"
+ ; inequality= Some Lt
+ ; epoch= None
+ ; version= "10.1.0"
+ ; release= "25"
+ }
+ ]
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ ; severity= Severity.High
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Single update with unknown guidance *)
( {|
-
+
UPDATE-0000
title
@@ -842,56 +993,58 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Recommended, [RebootHost])
- ; (Full, [RebootHost; RestartVM])
- ; (Mandatory, [RebootHost])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities=
- [
- Applicability.
- {
- name= "xsconsole"
- ; arch= "x86_64"
- ; inequality= Some Gte
- ; epoch= None
- ; version= "10.1.0"
- ; release= "25"
- }
- ; Applicability.
- {
- name= "xsconsole"
- ; arch= "x86_64"
- ; inequality= Some Lt
- ; epoch= None
- ; version= "10.1.0"
- ; release= "25"
- }
- ]
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
- ; severity= Severity.High
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Recommended, [RebootHost])
+ ; (Full, [RebootHost; RestartVM])
+ ; (Mandatory, [RebootHost])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities=
+ [
+ Applicability.
+ {
+ name= "xsconsole"
+ ; arch= "x86_64"
+ ; inequality= Some Gte
+ ; epoch= None
+ ; version= "10.1.0"
+ ; release= "25"
+ }
+ ; Applicability.
+ {
+ name= "xsconsole"
+ ; arch= "x86_64"
+ ; inequality= Some Lt
+ ; epoch= None
+ ; version= "10.1.0"
+ ; release= "25"
+ }
+ ]
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ ; severity= Severity.High
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Single update with livepatches and livepatch guidance *)
( {|
-
+
UPDATE-0000
title
@@ -916,58 +1069,60 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Livepatch, [RestartToolstack])
- ; (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches=
- [
- LivePatch.
- {
- component= Kernel
- ; base_build_id=
- "8346194f2e98a228f5a595b13ecabd43a99fada0"
- ; base_version= "4.19.19"
- ; base_release= "8.0.19.xs8"
- ; to_version= "4.19.19"
- ; to_release= "8.0.21.xs8"
- }
- ; LivePatch.
- {
- component= Kernel
- ; base_build_id=
- "9346194f2e98a228f5a595b13ecabd43a99fada0"
- ; base_version= "4.19.19"
- ; base_release= "8.0.20.xs8"
- ; to_version= "4.19.19"
- ; to_release= "8.0.21.xs8"
- }
- ]
- ; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
- ; severity= Severity.High
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Livepatch, [RestartToolstack])
+ ; (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches=
+ [
+ LivePatch.
+ {
+ component= Kernel
+ ; base_build_id=
+ "8346194f2e98a228f5a595b13ecabd43a99fada0"
+ ; base_version= "4.19.19"
+ ; base_release= "8.0.19.xs8"
+ ; to_version= "4.19.19"
+ ; to_release= "8.0.21.xs8"
+ }
+ ; LivePatch.
+ {
+ component= Kernel
+ ; base_build_id=
+ "9346194f2e98a228f5a595b13ecabd43a99fada0"
+ ; base_version= "4.19.19"
+ ; base_release= "8.0.20.xs8"
+ ; to_version= "4.19.19"
+ ; to_release= "8.0.21.xs8"
+ }
+ ]
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ ; severity= Severity.High
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Single update with livepatches and unknown livepatch guidance *)
( {|
-
+
UPDATE-0000
title
@@ -992,58 +1147,60 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Livepatch, [RebootHost])
- ; (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches=
- [
- LivePatch.
- {
- component= Kernel
- ; base_build_id=
- "8346194f2e98a228f5a595b13ecabd43a99fada0"
- ; base_version= "4.19.19"
- ; base_release= "8.0.19.xs8"
- ; to_version= "4.19.19"
- ; to_release= "8.0.21.xs8"
- }
- ; LivePatch.
- {
- component= Kernel
- ; base_build_id=
- "9346194f2e98a228f5a595b13ecabd43a99fada0"
- ; base_version= "4.19.19"
- ; base_release= "8.0.20.xs8"
- ; to_version= "4.19.19"
- ; to_release= "8.0.21.xs8"
- }
- ]
- ; issued=
- Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
- ; severity= Severity.High
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Livepatch, [RebootHost])
+ ; (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches=
+ [
+ LivePatch.
+ {
+ component= Kernel
+ ; base_build_id=
+ "8346194f2e98a228f5a595b13ecabd43a99fada0"
+ ; base_version= "4.19.19"
+ ; base_release= "8.0.19.xs8"
+ ; to_version= "4.19.19"
+ ; to_release= "8.0.21.xs8"
+ }
+ ; LivePatch.
+ {
+ component= Kernel
+ ; base_build_id=
+ "9346194f2e98a228f5a595b13ecabd43a99fada0"
+ ; base_version= "4.19.19"
+ ; base_release= "8.0.20.xs8"
+ ; to_version= "4.19.19"
+ ; to_release= "8.0.21.xs8"
+ }
+ ]
+ ; issued=
+ Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z"
+ ; severity= Severity.High
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Single update with livepatch guidance but empty livepatch *)
( {|
-
+
UPDATE-0000
title
@@ -1064,35 +1221,37 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Livepatch, [RestartDeviceModel])
- ; (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Livepatch, [RestartDeviceModel])
+ ; (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Single update with valid livepatches *)
( {|
-
+
UPDATE-0000
title
@@ -1115,47 +1274,49 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Livepatch, [RestartToolstack])
- ; (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches=
- [
- LivePatch.
- {
- component= Kernel
- ; base_build_id=
- "9346194f2e98a228f5a595b13ecabd43a99fada0"
- ; base_version= "4.19.19"
- ; base_release= "8.0.20.xs8"
- ; to_version= "4.19.19"
- ; to_release= "8.0.21.xs8"
- }
- ]
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Livepatch, [RestartToolstack])
+ ; (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches=
+ [
+ LivePatch.
+ {
+ component= Kernel
+ ; base_build_id=
+ "9346194f2e98a228f5a595b13ecabd43a99fada0"
+ ; base_version= "4.19.19"
+ ; base_release= "8.0.20.xs8"
+ ; to_version= "4.19.19"
+ ; to_release= "8.0.21.xs8"
+ }
+ ]
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* Single update with invalid livepatches *)
( {|
-
+
UPDATE-0000
title
@@ -1178,35 +1339,37 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "description"
- ; guidance=
- [
- (Livepatch, [RestartToolstack])
- ; (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "description"
+ ; guidance=
+ [
+ (Livepatch, [RestartToolstack])
+ ; (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* guidance in new format: empty guidance *)
( {|
-
+
UPDATE-0000
title
@@ -1227,35 +1390,37 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "empty guidance"
- ; guidance=
- [
- (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "empty guidance"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* guidance in new format only: empty guidance *)
( {|
-
+
UPDATE-0000
title
@@ -1273,35 +1438,37 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "guidance in new format only: empty guidance"
- ; guidance=
- [
- (Mandatory, [])
- ; (Recommended, [])
- ; (Full, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "guidance in new format only: empty guidance"
+ ; guidance=
+ [
+ (Mandatory, [])
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* guidance in new format: empty mandatory and full *)
( {|
-
+
UPDATE-0000
title
@@ -1326,35 +1493,37 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "empty mandatory and full"
- ; guidance=
- [
- (Full, [])
- ; (Mandatory, [])
- ; (Recommended, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "empty mandatory and full"
+ ; guidance=
+ [
+ (Full, [])
+ ; (Mandatory, [])
+ ; (Recommended, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* guidance in new format: mandatory only *)
( {|
-
+
UPDATE-0000
title
@@ -1381,37 +1550,39 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "mandatory only"
- ; guidance=
- [
- ( Mandatory
- , [RestartDeviceModel; EvacuateHost; RestartToolstack]
- )
- ; (Recommended, [])
- ; (Full, [])
- ; (Livepatch, [])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "mandatory only"
+ ; guidance=
+ [
+ ( Mandatory
+ , [RestartDeviceModel; EvacuateHost; RestartToolstack]
+ )
+ ; (Recommended, [])
+ ; (Full, [])
+ ; (Livepatch, [])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* guidance in new format: mandatory, recommended, full and livepatch *)
( {|
-
+
UPDATE-0000
title
@@ -1445,35 +1616,37 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "mandatory, recommended, full and livepatch"
- ; guidance=
- [
- (Full, [RebootHost])
- ; (Livepatch, [RestartDeviceModel])
- ; (Recommended, [EvacuateHost])
- ; (Mandatory, [RestartToolstack])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "mandatory, recommended, full and livepatch"
+ ; guidance=
+ [
+ (Full, [RebootHost])
+ ; (Livepatch, [RestartDeviceModel])
+ ; (Recommended, [EvacuateHost])
+ ; (Mandatory, [RestartToolstack])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
; (* guidance in new format: mandatory, recommended, full and livepatch *)
( {|
-
+
UPDATE-0000
title
@@ -1507,31 +1680,33 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct
|}
, Ok
- [
- ( "UPDATE-0000"
- , UpdateInfo.
- {
- id= "UPDATE-0000"
- ; summary= "summary"
- ; description= "RestartVM in mandatory"
- ; guidance=
- [
- (Full, [RebootHost])
- ; (Livepatch, [RestartDeviceModel])
- ; (Recommended, [EvacuateHost])
- ; (Mandatory, [RestartVM])
- ]
- ; guidance_applicabilities= []
- ; spec_info= "special information"
- ; url= "https://update.details.info"
- ; update_type= "security"
- ; livepatches= []
- ; issued= Xapi_stdext_date.Date.epoch
- ; severity= Severity.None
- ; title= "title"
- }
- )
- ]
+ ( Some "2.23"
+ , [
+ ( "UPDATE-0000"
+ , UpdateInfo.
+ {
+ id= "UPDATE-0000"
+ ; summary= "summary"
+ ; description= "RestartVM in mandatory"
+ ; guidance=
+ [
+ (Full, [RebootHost])
+ ; (Livepatch, [RestartDeviceModel])
+ ; (Recommended, [EvacuateHost])
+ ; (Mandatory, [RestartVM])
+ ]
+ ; guidance_applicabilities= []
+ ; spec_info= "special information"
+ ; url= "https://update.details.info"
+ ; update_type= "security"
+ ; livepatches= []
+ ; issued= Xapi_stdext_date.Date.epoch
+ ; severity= Severity.None
+ ; title= "title"
+ }
+ )
+ ]
+ )
)
]
end)
diff --git a/ocaml/xapi/repository.ml b/ocaml/xapi/repository.ml
index 95007999782..d798246d0b0 100644
--- a/ocaml/xapi/repository.ml
+++ b/ocaml/xapi/repository.ml
@@ -298,7 +298,7 @@ let get_applied_livepatches_of_host updates_of_host =
let is_livepatchable ~__context repository applied_livepatches_of_host =
let updates_info =
- parse_updateinfo ~__context ~self:repository ~check:false
+ parse_updateinfo ~__context ~self:repository ~check:false |> snd
in
List.exists
(fun lp ->
@@ -562,7 +562,7 @@ let get_pool_updates_in_json ~__context ~hosts =
set_available_updates ~__context |> ignore ;
let repository_name = get_repository_name ~__context ~self:repository in
- let updates_info =
+ let api_ver, updates_info =
parse_updateinfo ~__context ~self:repository ~check:true
in
let updates_of_hosts, ids_of_updates =
@@ -579,12 +579,17 @@ let get_pool_updates_in_json ~__context ~hosts =
|> List.map (fun upd_id -> List.assoc upd_id updates_info)
|> List.map (prune_updateinfo_for_livepatches lps)
in
- `Assoc
- [
- ("hosts", `List (List.map HostUpdates.to_json updates_of_hosts))
- ; ("updates", `List (List.map UpdateInfo.to_json updateinfo_list))
- ; ("hash", `String (Db.Repository.get_hash ~__context ~self:repository))
- ]
+ let f x =
+ Option.fold ~none:x
+ ~some:(fun api_ver -> ("xapi-api-version", `String api_ver) :: x)
+ api_ver
+ in
+ [
+ ("hosts", `List (List.map HostUpdates.to_json updates_of_hosts))
+ ; ("updates", `List (List.map UpdateInfo.to_json updateinfo_list))
+ ; ("hash", `String (Db.Repository.get_hash ~__context ~self:repository))
+ ]
+ |> fun x -> `Assoc (f x)
with
| Api_errors.(Server_error (code, _)) as e
when code <> Api_errors.internal_error ->
@@ -787,7 +792,7 @@ let apply_updates ~__context ~host ~hash =
raise Api_errors.(Server_error (updateinfo_hash_mismatch, [])) ;
with_pool_repositories (fun () ->
let updates_info =
- parse_updateinfo ~__context ~self:repository ~check:true
+ parse_updateinfo ~__context ~self:repository ~check:true |> snd
in
let updates_of_hosts =
if Helpers.is_pool_master ~__context ~host then (
diff --git a/ocaml/xapi/updateinfo.ml b/ocaml/xapi/updateinfo.ml
index 092af683232..375604cfe78 100644
--- a/ocaml/xapi/updateinfo.ml
+++ b/ocaml/xapi/updateinfo.ml
@@ -531,8 +531,10 @@ end
module UpdateInfo = struct
(** The [guidance] deprecates [rec_guidance], [abs_guidance] and [livepatch_guidance] *)
+ type id_t = string
+
type t = {
- id: string
+ id: id_t
; summary: string
; description: string
; guidance: GuidanceInUpdateInfo.t
@@ -546,6 +548,8 @@ module UpdateInfo = struct
; title: string
}
+ type api_ver_t = string
+
let guidance_to_string o =
Option.value (Option.map Guidance.to_string o) ~default:""
@@ -605,94 +609,106 @@ module UpdateInfo = struct
Option.value (List.assoc_opt kind updateinfo.guidance) ~default:[]
let of_xml = function
- | Xml.Element ("updates", _, children) ->
- List.filter_map
- (fun n ->
- match n with
- | Xml.Element ("update", attr, update_nodes) ->
- let ty =
- match List.assoc_opt "type" attr with
- | Some ty ->
- ty
- | None ->
- ""
- in
- let ui =
- List.fold_left
- (fun acc node ->
- match node with
- | Xml.Element ("id", _, [Xml.PCData v]) ->
- {acc with id= v}
- | Xml.Element ("url", _, [Xml.PCData v]) ->
- {acc with url= v}
- | Xml.Element ("special_info", _, [Xml.PCData v]) ->
- {acc with spec_info= v}
- | Xml.Element ("summary", _, [Xml.PCData v]) ->
- {acc with summary= v}
- | Xml.Element ("description", _, [Xml.PCData v]) ->
- {acc with description= v}
- | Xml.Element ("guidance", _, guidance_blocks) ->
- {
- acc with
- guidance=
- GuidanceInUpdateInfo.of_xml guidance_blocks
- }
- | Xml.Element ("guidance_applicabilities", _, apps) ->
- {
- acc with
- guidance_applicabilities=
- List.filter_map Applicability.of_xml apps
- }
- | Xml.Element ("livepatches", _, livepatches) ->
- {acc with livepatches= LivePatch.of_xml livepatches}
- | Xml.Element ("issued", attr, _) ->
- let issued =
- match List.assoc_opt "date" attr with
- | Some date -> (
- try
- Xapi_stdext_date.Date.of_string
- (Scanf.sscanf date
- "%04d-%02d-%02d %02d:%02d:%02d"
- (fun y mon d h m s ->
- Printf.sprintf
- "%04i%02i%02iT%02i:%02i:%02iZ" y mon d
- h m s
- )
- )
- with e ->
- (* The error should not block update. Ingore it
- and set "issued" as epoch. *)
- warn "%s" (ExnHelper.string_of_exn e) ;
- Xapi_stdext_date.Date.epoch
- )
- | None ->
- Xapi_stdext_date.Date.epoch
- in
- {acc with issued}
- | Xml.Element ("severity", _, [Xml.PCData v]) -> (
- try {acc with severity= Severity.of_string v}
- with e ->
- (* The error should not block update. Ingore it. *)
- warn "%s" (ExnHelper.string_of_exn e) ;
- acc
+ | Xml.Element ("updates", attrs, children) -> (
+ let api_ver = List.assoc_opt "xapi-api-version" attrs in
+ let uis =
+ List.filter_map
+ (fun n ->
+ match n with
+ | Xml.Element ("update", attrs, update_nodes) ->
+ let ty =
+ match List.assoc_opt "type" attrs with
+ | Some ty ->
+ ty
+ | None ->
+ ""
+ in
+ let ui =
+ List.fold_left
+ (fun acc node ->
+ match node with
+ | Xml.Element ("id", _, [Xml.PCData v]) ->
+ {acc with id= v}
+ | Xml.Element ("url", _, [Xml.PCData v]) ->
+ {acc with url= v}
+ | Xml.Element ("special_info", _, [Xml.PCData v]) ->
+ {acc with spec_info= v}
+ | Xml.Element ("summary", _, [Xml.PCData v]) ->
+ {acc with summary= v}
+ | Xml.Element ("description", _, [Xml.PCData v]) ->
+ {acc with description= v}
+ | Xml.Element ("guidance", _, guidance_blocks) ->
+ {
+ acc with
+ guidance=
+ GuidanceInUpdateInfo.of_xml guidance_blocks
+ }
+ | Xml.Element ("guidance_applicabilities", _, apps) ->
+ {
+ acc with
+ guidance_applicabilities=
+ List.filter_map Applicability.of_xml apps
+ }
+ | Xml.Element ("livepatches", _, livepatches) ->
+ {acc with livepatches= LivePatch.of_xml livepatches}
+ | Xml.Element ("issued", attrs, _) ->
+ let issued =
+ match List.assoc_opt "date" attrs with
+ | Some date -> (
+ try
+ Xapi_stdext_date.Date.of_string
+ (Scanf.sscanf date
+ "%04d-%02d-%02d %02d:%02d:%02d"
+ (fun y mon d h m s ->
+ Printf.sprintf
+ "%04i%02i%02iT%02i:%02i:%02iZ" y mon
+ d h m s
+ )
+ )
+ with e ->
+ (* The error should not block update. Ingore it
+ and set "issued" as epoch. *)
+ warn "%s" (ExnHelper.string_of_exn e) ;
+ Xapi_stdext_date.Date.epoch
+ )
+ | None ->
+ Xapi_stdext_date.Date.epoch
+ in
+ {acc with issued}
+ | Xml.Element ("severity", _, [Xml.PCData v]) -> (
+ try {acc with severity= Severity.of_string v}
+ with e ->
+ (* The error should not block update. Ingore it. *)
+ warn "%s" (ExnHelper.string_of_exn e) ;
+ acc
+ )
+ | Xml.Element ("title", _, [Xml.PCData v]) ->
+ {acc with title= v}
+ | _ ->
+ acc
)
- | Xml.Element ("title", _, [Xml.PCData v]) ->
- {acc with title= v}
- | _ ->
- acc
- )
- {default with update_type= ty}
- update_nodes
- |> assert_valid_updateinfo
- in
- debug "updateinfo: %s" (to_string ui) ;
- Some ui
- | _ ->
- None
- )
- children
- |> assert_no_dup_update_id
- |> List.map (fun updateinfo -> (updateinfo.id, updateinfo))
+ {default with update_type= ty}
+ update_nodes
+ |> assert_valid_updateinfo
+ in
+ debug "updateinfo: %s" (to_string ui) ;
+ Some ui
+ | _ ->
+ None
+ )
+ children
+ |> assert_no_dup_update_id
+ |> List.map (fun updateinfo -> (updateinfo.id, updateinfo))
+ in
+ match (api_ver, uis) with
+ | Some v, [] ->
+ error
+ "Unexpected xapi-api-version: %s when there is no updates at all"
+ v ;
+ raise Api_errors.(Server_error (invalid_updateinfo_xml, []))
+ | _, _ ->
+ (api_ver, uis)
+ )
| _ ->
error "Failed to parse updateinfo.xml: missing " ;
raise Api_errors.(Server_error (invalid_updateinfo_xml, []))
diff --git a/ocaml/xapi/updateinfo.mli b/ocaml/xapi/updateinfo.mli
index 7a348db598c..8948d778d23 100644
--- a/ocaml/xapi/updateinfo.mli
+++ b/ocaml/xapi/updateinfo.mli
@@ -143,8 +143,10 @@ end
(** The metadata of one update in updateinfo. *)
module UpdateInfo : sig
+ type id_t = string
+
type t = {
- id: string
+ id: id_t
; summary: string
; description: string
; guidance: GuidanceInUpdateInfo.t
@@ -158,13 +160,15 @@ module UpdateInfo : sig
; title: string
}
+ type api_ver_t = string
+
val to_json : t -> Yojson.Basic.t
val guidance_to_string : Guidance.t option -> string
- val of_xml : Xml.xml -> (string * t) list
+ val of_xml : Xml.xml -> api_ver_t option * (id_t * t) list
- val of_xml_file : string -> (string * t) list
+ val of_xml_file : string -> api_ver_t option * (id_t * t) list
val get_guidances_of_kind : kind:Guidance.kind -> t -> Guidance.t list
end