diff --git a/doc/content/xapi/storage/sxm.md b/doc/content/xapi/storage/sxm.md index 8429f87321c..ee3b90276cc 100644 --- a/doc/content/xapi/storage/sxm.md +++ b/doc/content/xapi/storage/sxm.md @@ -450,8 +450,8 @@ but we've still got a bit of thinking to do: we sort the VDIs to copy based on a let compare_fun v1 v2 = let r = Int64.compare v1.size v2.size in if r = 0 then - let t1 = Date.to_float (Db.VDI.get_snapshot_time ~__context ~self:v1.vdi) in - let t2 = Date.to_float (Db.VDI.get_snapshot_time ~__context ~self:v2.vdi) in + let t1 = Date.to_unix_time (Db.VDI.get_snapshot_time ~__context ~self:v1.vdi) in + let t2 = Date.to_unix_time (Db.VDI.get_snapshot_time ~__context ~self:v2.vdi) in compare t1 t2 else r in let all_vdis = all_vdis |> List.sort compare_fun in diff --git a/ocaml/alerts/expiry_alert.ml b/ocaml/alerts/expiry_alert.ml index 1ea19844ba6..d2667ff35df 100644 --- a/ocaml/alerts/expiry_alert.ml +++ b/ocaml/alerts/expiry_alert.ml @@ -50,7 +50,7 @@ let all_messages rpc session_id = let message_body msg expiry = Printf.sprintf "%s%s" msg - (Date.to_string expiry) + (Date.to_rfc3339 expiry) let expired_message obj = Printf.sprintf "%s has expired." obj @@ -58,7 +58,7 @@ let expiring_message obj = Printf.sprintf "%s is expiring soon." obj let maybe_generate_alert now obj_description alert_conditions expiry = let remaining_days = - days_until_expiry (Date.to_float now) (Date.to_float expiry) + days_until_expiry (Date.to_unix_time now) (Date.to_unix_time expiry) in alert_conditions |> List.sort (fun (a, _) (b, _) -> compare a b) diff --git a/ocaml/idl/datamodel.ml b/ocaml/idl/datamodel.ml index 2efca2c2ce8..737ecc53b0f 100644 --- a/ocaml/idl/datamodel.ml +++ b/ocaml/idl/datamodel.ml @@ -217,9 +217,8 @@ module Session = struct session instance has is_local_superuser set, then the value of \ this field is undefined." ; field ~in_product_since:rel_george ~qualifier:DynamicRO - ~default_value:(Some (VDateTime (Date.of_float 0.))) - ~ty:DateTime "validation_time" - "time when session was last validated" + ~default_value:(Some (VDateTime Date.epoch)) ~ty:DateTime + "validation_time" "time when session was last validated" ; field ~in_product_since:rel_george ~qualifier:DynamicRO ~default_value:(Some (VString "")) ~ty:String "auth_user_sid" "the subject identifier of the user that was externally \ @@ -3895,9 +3894,11 @@ module VDI = struct ; { param_type= DateTime ; param_name= "snapshot_time" - ; param_doc= "Storage-specific config" + ; param_doc= + "Storage-specific config. When the timezone is missing, UTC is \ + assumed" ; param_release= tampa_release - ; param_default= Some (VDateTime Date.never) + ; param_default= Some (VDateTime Date.epoch) } ; { param_type= Ref _vdi @@ -4089,7 +4090,11 @@ module VDI = struct ~params: [ (Ref _vdi, "self", "The VDI to modify") - ; (DateTime, "value", "The snapshot time of this VDI.") + ; ( DateTime + , "value" + , "The snapshot time of this VDI. When the timezone is missing, UTC \ + is assumed" + ) ] ~flags:[`Session] ~doc:"Sets the snapshot time of this VDI." ~hide_from_docs:true ~allowed_roles:_R_LOCAL_ROOT_ONLY () @@ -4468,7 +4473,7 @@ module VDI = struct ~ty:(Set (Ref _vdi)) ~doc_tags:[Snapshots] "snapshots" "List pointing to all the VDIs snapshots." ; field ~in_product_since:rel_orlando - ~default_value:(Some (VDateTime Date.never)) ~qualifier:DynamicRO + ~default_value:(Some (VDateTime Date.epoch)) ~qualifier:DynamicRO ~ty:DateTime ~doc_tags:[Snapshots] "snapshot_time" "Date/time when this snapshot was created." ; field ~writer_roles:_R_VM_OP ~in_product_since:rel_orlando @@ -4752,7 +4757,7 @@ module VBD_metrics = struct uid _vbd_metrics ; namespace ~name:"io" ~contents:iobandwidth () ; field ~qualifier:DynamicRO ~ty:DateTime - ~default_value:(Some (VDateTime Date.never)) + ~default_value:(Some (VDateTime Date.epoch)) ~lifecycle: [ (Published, rel_rio, "") @@ -5511,7 +5516,11 @@ module VMPP = struct ~params: [ (Ref _vmpp, "self", "The protection policy") - ; (DateTime, "value", "the value to set") + ; ( DateTime + , "value" + , "When was the last backup was done. When the timezone is missing, \ + UTC is assumed" + ) ] () @@ -5521,7 +5530,11 @@ module VMPP = struct ~params: [ (Ref _vmpp, "self", "The protection policy") - ; (DateTime, "value", "the value to set") + ; ( DateTime + , "value" + , "When was the last archive was done. When the timezone is missing, \ + UTC is assumed" + ) ] () @@ -5669,7 +5682,7 @@ module VMPP = struct "true if this protection policy's backup is running" ; field ~lifecycle:removed ~qualifier:DynamicRO ~ty:DateTime "backup_last_run_time" "time of the last backup" - ~default_value:(Some (VDateTime (Date.of_float 0.))) + ~default_value:(Some (VDateTime Date.epoch)) ; field ~lifecycle:removed ~qualifier:StaticRO ~ty:archive_target_type "archive_target_type" "type of the archive target config" ~default_value:(Some (VEnum "none")) @@ -5693,7 +5706,7 @@ module VMPP = struct "true if this protection policy's archive is running" ; field ~lifecycle:removed ~qualifier:DynamicRO ~ty:DateTime "archive_last_run_time" "time of the last archive" - ~default_value:(Some (VDateTime (Date.of_float 0.))) + ~default_value:(Some (VDateTime Date.epoch)) ; field ~lifecycle:removed ~qualifier:DynamicRO ~ty:(Set (Ref _vm)) "VMs" "all VMs attached to this protection policy" ; field ~lifecycle:removed ~qualifier:StaticRO ~ty:Bool @@ -5782,7 +5795,11 @@ module VMSS = struct ~params: [ (Ref _vmss, "self", "The snapshot schedule") - ; (DateTime, "value", "the value to set") + ; ( DateTime + , "value" + , "When was the schedule was last run. When a timezone is missing, \ + UTC is assumed" + ) ] () @@ -5856,7 +5873,7 @@ module VMSS = struct ~default_value:(Some (VMap [])) ; field ~qualifier:DynamicRO ~ty:DateTime "last_run_time" "time of the last snapshot" - ~default_value:(Some (VDateTime (Date.of_float 0.))) + ~default_value:(Some (VDateTime Date.epoch)) ; field ~qualifier:DynamicRO ~ty:(Set (Ref _vm)) "VMs" "all VMs attached to this snapshot schedule" ] @@ -6311,7 +6328,10 @@ module Message = struct [ (cls, "cls", "The class of object") ; (String, "obj_uuid", "The uuid of the object") - ; (DateTime, "since", "The cutoff time") + ; ( DateTime + , "since" + , "The cutoff time. When the timezone is missing, UTC is assumed" + ) ] ~flags:[`Session] ~result:(Map (Ref _message, Record _message), "The relevant messages") @@ -6319,7 +6339,13 @@ module Message = struct let get_since = call ~name:"get_since" ~in_product_since:rel_orlando - ~params:[(DateTime, "since", "The cutoff time")] + ~params: + [ + ( DateTime + , "since" + , "The cutoff time. When the timezone is missing, UTC is assumed" + ) + ] ~flags:[`Session] ~result:(Map (Ref _message, Record _message), "The relevant messages") ~allowed_roles:_R_READ_ONLY () diff --git a/ocaml/idl/datamodel_certificate.ml b/ocaml/idl/datamodel_certificate.ml index bfbdd2b60b5..53c594fb941 100644 --- a/ocaml/idl/datamodel_certificate.ml +++ b/ocaml/idl/datamodel_certificate.ml @@ -59,10 +59,10 @@ let t = ~default_value:(Some (VRef null_ref)) "The host where the certificate is installed" ; field ~qualifier:StaticRO ~lifecycle ~ty:DateTime "not_before" - ~default_value:(Some (VDateTime Date.never)) + ~default_value:(Some (VDateTime Date.epoch)) "Date after which the certificate is valid" ; field ~qualifier:StaticRO ~lifecycle ~ty:DateTime "not_after" - ~default_value:(Some (VDateTime Date.never)) + ~default_value:(Some (VDateTime Date.epoch)) "Date before which the certificate is valid" ; field ~qualifier:StaticRO ~lifecycle: diff --git a/ocaml/idl/datamodel_host.ml b/ocaml/idl/datamodel_host.ml index b7d34350819..d48470f3a71 100644 --- a/ocaml/idl/datamodel_host.ml +++ b/ocaml/idl/datamodel_host.ml @@ -935,7 +935,9 @@ let create_params = ; { param_type= DateTime ; param_name= "last_software_update" - ; param_doc= "Date and time when the last software update was applied." + ; param_doc= + "Date and time when the last software update was applied. When the \ + timezone is missing, UTC is assumed" ; param_release= dundee_release ; param_default= Some (VDateTime Date.epoch) } @@ -2188,8 +2190,7 @@ let t = "tls_verification_enabled" ~default_value:(Some (VBool false)) "True if this host has TLS verifcation enabled" ; field ~qualifier:DynamicRO ~lifecycle:[] ~ty:DateTime - "last_software_update" - ~default_value:(Some (VDateTime (Date.of_float 0.0))) + "last_software_update" ~default_value:(Some (VDateTime Date.epoch)) "Date and time when the last software update was applied" ; field ~qualifier:DynamicRO ~lifecycle:[] ~ty:Bool ~default_value:(Some (VBool false)) "https_only" diff --git a/ocaml/idl/datamodel_types.ml b/ocaml/idl/datamodel_types.ml index 61893c99e01..67a6fdd4ea1 100644 --- a/ocaml/idl/datamodel_types.ml +++ b/ocaml/idl/datamodel_types.ml @@ -26,12 +26,12 @@ *) module Date = struct - open Xapi_stdext_date + module Date = Xapi_stdext_date.Date include Date - let iso8601_of_rpc rpc = Date.of_string (Rpc.string_of_rpc rpc) + let t_of_rpc rpc = Date.of_iso8601 (Rpc.string_of_rpc rpc) - let rpc_of_iso8601 date = Rpc.rpc_of_string (Date.to_string date) + let rpc_of_t date = Rpc.rpc_of_string (Date.to_rfc3339 date) end (* useful constants for product vsn tracking *) @@ -418,7 +418,7 @@ type api_value = | VInt of int64 | VFloat of float | VBool of bool - | VDateTime of Date.iso8601 + | VDateTime of Date.t | VEnum of string | VMap of (api_value * api_value) list | VSet of api_value list diff --git a/ocaml/idl/datamodel_types.mli b/ocaml/idl/datamodel_types.mli index 76ac814eb49..fbfb9e4a6f6 100644 --- a/ocaml/idl/datamodel_types.mli +++ b/ocaml/idl/datamodel_types.mli @@ -1,9 +1,9 @@ module Date : sig include module type of Xapi_stdext_date.Date - val iso8601_of_rpc : Rpc.t -> Xapi_stdext_date.Date.iso8601 + val t_of_rpc : Rpc.t -> Xapi_stdext_date.Date.t - val rpc_of_iso8601 : Xapi_stdext_date.Date.iso8601 -> Rpc.t + val rpc_of_t : Xapi_stdext_date.Date.t -> Rpc.t end val oss_since_303 : string option @@ -115,7 +115,7 @@ type api_value = | VInt of int64 | VFloat of float | VBool of bool - | VDateTime of Date.iso8601 + | VDateTime of Date.t | VEnum of string | VMap of (api_value * api_value) list | VSet of api_value list diff --git a/ocaml/idl/datamodel_values.ml b/ocaml/idl/datamodel_values.ml index 1b463d4b2e7..e270899b50f 100644 --- a/ocaml/idl/datamodel_values.ml +++ b/ocaml/idl/datamodel_values.ml @@ -40,7 +40,7 @@ let rec to_rpc v = | VBool b -> Rpc.Bool b | VDateTime d -> - Rpc.String (Date.to_string d) + Rpc.String (Date.to_rfc3339 d) | VEnum e -> Rpc.String e | VMap vvl -> @@ -94,7 +94,7 @@ let to_db v = | VBool false -> String "false" | VDateTime d -> - String (Date.to_string d) + String (Date.to_rfc3339 d) | VEnum e -> String e | VMap vvl -> @@ -117,7 +117,7 @@ let gen_empty_db_val t = | Bool -> Value.String "false" | DateTime -> - Value.String (Date.to_string Date.never) + Value.String Date.(to_rfc3339 epoch) | Enum (_, (enum_value, _) :: _) -> Value.String enum_value | Enum (_, []) -> diff --git a/ocaml/idl/datamodel_vm.ml b/ocaml/idl/datamodel_vm.ml index 96939c4d5e2..af7aa27b270 100644 --- a/ocaml/idl/datamodel_vm.ml +++ b/ocaml/idl/datamodel_vm.ml @@ -339,7 +339,11 @@ let update_snapshot_metadata = [ (Ref _vm, "vm", "The VM to update") ; (Ref _vm, "snapshot_of", "") - ; (DateTime, "snapshot_time", "") + ; ( DateTime + , "snapshot_time" + , "The timestamp the snapshot was taken. When a timezone is missing, \ + UTC is assumed" + ) ; (String, "transportable_snapshot_id", "") ] ~allowed_roles:_R_POOL_OP () @@ -2112,7 +2116,7 @@ let t = "List pointing to all the VM snapshots." ; field ~writer_roles:_R_VM_POWER_ADMIN ~qualifier:DynamicRO ~in_product_since:rel_orlando - ~default_value:(Some (VDateTime Date.never)) ~ty:DateTime + ~default_value:(Some (VDateTime Date.epoch)) ~ty:DateTime "snapshot_time" "Date/time when this snapshot was created." ; field ~writer_roles:_R_VM_POWER_ADMIN ~qualifier:DynamicRO ~in_product_since:rel_orlando ~default_value:(Some (VString "")) diff --git a/ocaml/idl/dune b/ocaml/idl/dune index 8d337c5c7f2..d971e6597df 100644 --- a/ocaml/idl/dune +++ b/ocaml/idl/dune @@ -45,11 +45,12 @@ (action (run %{x} -closed -markdown)) ) -(test - (name schematest) +(tests + (names schematest test_datetimes) (modes exe) - (modules schematest) + (modules schematest test_datetimes) (libraries + astring rpclib.core rpclib.json xapi_datamodel diff --git a/ocaml/idl/json_backend/gen_json.ml b/ocaml/idl/json_backend/gen_json.ml index 446eeb04b8f..5c8fc0da0ff 100644 --- a/ocaml/idl/json_backend/gen_json.ml +++ b/ocaml/idl/json_backend/gen_json.ml @@ -89,7 +89,7 @@ end = struct | VBool x -> string_of_bool x | VDateTime x -> - Date.to_string x + Date.to_rfc3339 x | VEnum x -> x | VMap x -> diff --git a/ocaml/idl/ocaml_backend/gen_api.ml b/ocaml/idl/ocaml_backend/gen_api.ml index 90fb78d39dc..5b18d603f4e 100644 --- a/ocaml/idl/ocaml_backend/gen_api.ml +++ b/ocaml/idl/ocaml_backend/gen_api.ml @@ -413,9 +413,9 @@ let gen_client_types highapi = "module Date = struct" ; " open Xapi_stdext_date" ; " include Date" - ; " let rpc_of_iso8601 x = DateTime (Date.to_string x)" - ; " let iso8601_of_rpc = function String x | DateTime x -> \ - Date.of_string x | _ -> failwith \"Date.iso8601_of_rpc\"" + ; " let rpc_of_t x = DateTime (Date.to_rfc3339 x)" + ; " let t_of_rpc = function String x | DateTime x -> Date.of_iso8601 \ + x | _ -> failwith \"Date.t_of_rpc\"" ; "end" ] ; [ diff --git a/ocaml/idl/ocaml_backend/gen_db_actions.ml b/ocaml/idl/ocaml_backend/gen_db_actions.ml index 23c3dc8a747..44542173fe9 100644 --- a/ocaml/idl/ocaml_backend/gen_db_actions.ml +++ b/ocaml/idl/ocaml_backend/gen_db_actions.ml @@ -69,7 +69,7 @@ let dm_to_string tys : O.Module.t = | DT.Bool -> "string_of_bool" | DT.DateTime -> - "Date.to_string" + "Date.to_rfc3339" | DT.Enum (_name, cs) -> let aux (c, _) = Printf.sprintf {|| %s -> "%s"|} (OU.constructor_of c) c @@ -119,7 +119,7 @@ let string_to_dm tys : O.Module.t = | DT.Bool -> "bool_of_string" | DT.DateTime -> - "fun x -> Date.of_string x" + "fun x -> Date.of_iso8601 x" | DT.Enum (name, cs) -> let aux (c, _) = "\"" ^ c ^ "\" -> " ^ OU.constructor_of c in "fun v -> match v with\n " diff --git a/ocaml/idl/ocaml_backend/gen_test.ml b/ocaml/idl/ocaml_backend/gen_test.ml index d9824961db0..abf251014f0 100644 --- a/ocaml/idl/ocaml_backend/gen_test.ml +++ b/ocaml/idl/ocaml_backend/gen_test.ml @@ -32,7 +32,7 @@ let rec gen_test_type highapi ty = | DT.Bool -> "true" | DT.DateTime -> - "(Date.of_string \"20120101T00:00:00Z\")" + "(Date.of_iso8601 \"20120101T00:00:00Z\")" | DT.Enum (_, (x, _) :: _) -> Printf.sprintf "(%s)" (OU.constructor_of x) | DT.Set (DT.Enum (_, y)) -> diff --git a/ocaml/idl/ocaml_backend/ocaml_utils.ml b/ocaml/idl/ocaml_backend/ocaml_utils.ml index 3a6436c67f4..7fe7fe063bc 100644 --- a/ocaml/idl/ocaml_backend/ocaml_utils.ml +++ b/ocaml/idl/ocaml_backend/ocaml_utils.ml @@ -128,7 +128,7 @@ let rec ocaml_of_ty = function | Bool -> "bool" | DateTime -> - "Date.iso8601" + "Date.t" | Set (Record x) -> alias_of_ty (Record x) ^ " list" | Set x -> diff --git a/ocaml/idl/test_datetimes.ml b/ocaml/idl/test_datetimes.ml new file mode 100644 index 00000000000..ab31f313e5d --- /dev/null +++ b/ocaml/idl/test_datetimes.ml @@ -0,0 +1,47 @@ +module DT = Datamodel_types + +let calls_with_datetime_params = + let get_messages DT.{name; messages; _} = + List.to_seq messages + |> Seq.map (fun msg -> + DT.{msg with msg_name= Printf.sprintf "%s.%s" name msg.msg_name} + ) + in + let with_datetimes DT.{msg_name; msg_params; _} = + let cursed_params = + List.filter_map + (fun param -> + if + param.DT.param_type = DT.DateTime + && not (Astring.String.is_infix ~affix:"UTC" param.param_doc) + then + Some (msg_name, param.param_name, param.param_doc) + else + None + ) + msg_params + in + if cursed_params <> [] then Some (List.to_seq cursed_params) else None + in + + Datamodel.all_system + |> List.to_seq + |> Seq.concat_map get_messages + |> Seq.filter_map with_datetimes + |> Seq.concat + +let () = + if not (Seq.is_empty calls_with_datetime_params) then ( + Printf.printf + "\x1b[31;1mERROR\x1b[0m: Found datetime parameters in calls without \ + proper documentation. It must mention that datetimes are assumed to \ + have UTC when they do not contain a timezone. Parameters found:\n" ; + calls_with_datetime_params + |> Seq.iter (fun (call_name, param_name, param_doc) -> + Printf.printf "%s (%s): %s\n" call_name param_name param_doc + ) ; + exit 1 + ) else + Printf.printf + "\x1b[32;1mOK\x1b[0m: All datetime parameters in calls have proper \ + documentation." diff --git a/ocaml/idl/test_datetimes.mli b/ocaml/idl/test_datetimes.mli new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ocaml/libs/clock/date.ml b/ocaml/libs/clock/date.ml index a4a43cde623..c668b0c1fb3 100644 --- a/ocaml/libs/clock/date.ml +++ b/ocaml/libs/clock/date.ml @@ -10,6 +10,8 @@ GNU Lesser General Public License for more details. *) +module L = Debug.Make (struct let name = __MODULE__ end) + let months = [| "Jan" @@ -28,22 +30,18 @@ let months = let days = [|"Sun"; "Mon"; "Tue"; "Wed"; "Thu"; "Fri"; "Sat"|] -type print_timezone = Empty | TZ of string - -(* we must store the print_type with iso8601 to handle the case where the local time zone is UTC *) -type t = Ptime.date * Ptime.time * print_timezone +(* iso8601 allows datetimes to not contain any timezone information. + Unfortunately we need to maintain this information because this means that + the timestamp cannot be converted back to a timestamp with UTC as a + reference. When serializing timezoneless timestamps, the timezone must be + avoided yet again. *) +type tz = int option -let utc = TZ "Z" +type t = {t: Ptime.t; tz: tz} -let of_dt print_type dt = - let date, time = dt in - (date, time, print_type) - -let to_dt (date, time, _) = (date, time) +let utc = Some 0 let best_effort_iso8601_to_rfc3339 x = - (* (a) add dashes - * (b) add UTC tz if no tz provided *) let x = try Scanf.sscanf x "%04d%02d%02dT%s" (fun y mon d rest -> @@ -60,30 +58,39 @@ let best_effort_iso8601_to_rfc3339 x = in match tz with | None | Some "" -> - (* the caller didn't specify a tz. we must try to add one so that ptime can at least attempt to parse *) - (Printf.sprintf "%sZ" x, Empty) - | Some tz -> - (x, TZ tz) + (* the caller didn't specify a tz, assume Coordinatel Universal Time *) + Printf.sprintf "%sZ" x + | Some _ -> + x let of_iso8601 x = - let rfc3339, print_timezone = best_effort_iso8601_to_rfc3339 x in + let rfc3339 = best_effort_iso8601_to_rfc3339 x in match Ptime.of_rfc3339 rfc3339 |> Ptime.rfc3339_error_to_msg with | Error _ -> invalid_arg (Printf.sprintf "%s: %s" __FUNCTION__ x) - | Ok (t, tz, _) -> ( - match tz with - | None | Some 0 -> - Ptime.to_date_time t |> of_dt print_timezone - | Some _ -> - invalid_arg (Printf.sprintf "%s: %s" __FUNCTION__ x) - ) - -let to_rfc3339 ((y, mon, d), ((h, min, s), _), print_type) = - match print_type with - | TZ tz -> - Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i%s" y mon d h min s tz - | Empty -> - Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i" y mon d h min s + | Ok (t, tz, _) -> + {t; tz} + +let print_tz tz_s = + match tz_s with + | None -> + "" + | Some 0 -> + "Z" + | Some tz -> + let tz_sign = if tz < 0 then '-' else '+' in + let all_tz_minutes = tz / 60 |> Int.abs in + let tz_h = all_tz_minutes / 60 in + let tz_min = all_tz_minutes mod 60 in + Printf.sprintf "%c%02d:%02d" tz_sign tz_h tz_min + +let to_rfc3339 {t; tz} = + (* Must be compatible with iso8601 as well. Because some client limitations, + the hyphens between year, month and day have to be absent + *) + let (y, mon, d), ((h, min, s), _) = Ptime.to_date_time ?tz_offset_s:tz t in + let tz = print_tz tz in + Printf.sprintf "%04i%02i%02iT%02i:%02i:%02i%s" y mon d h min s tz (* Extracted from tondering.dk/claus/cal/chrweek.php#calcdow *) let weekday ~year ~mon ~day = @@ -92,29 +99,25 @@ let weekday ~year ~mon ~day = let m = mon + (12 * a) - 2 in (day + y + (y / 4) - (y / 100) + (y / 400) + (31 * m / 12)) mod 7 -let to_rfc822 ((year, mon, day), ((h, min, s), _), print_type) = - let timezone = - match print_type with Empty | TZ "Z" -> "GMT" | TZ tz -> tz +let to_rfc822 {t; tz} = + let (year, mon, day), ((h, min, s), _) = + Ptime.to_date_time ?tz_offset_s:tz t in + let timezone = match print_tz tz with "Z" -> "GMT" | tz -> tz in let weekday = weekday ~year ~mon ~day in Printf.sprintf "%s, %d %s %d %02d:%02d:%02d %s" days.(weekday) day months.(mon - 1) year h min s timezone -let to_ptime_t t = - match to_dt t |> Ptime.of_date_time with - | Some t -> +let to_ptime = function + | {t; tz= None} as d -> + L.warn "%s: Date %s converted to POSIX time, but timezone is missing" + __FUNCTION__ (to_rfc3339 d) ; + t + | {t; tz= Some _} -> t - | None -> - let _, (_, offset), _ = t in - invalid_arg - (Printf.sprintf "%s: dt='%s', offset='%i' is invalid" __FUNCTION__ - (to_rfc3339 t) offset - ) - -let to_ptime = to_ptime_t -let of_ptime t = Ptime.to_date_time t |> of_dt utc +let of_ptime t = {t; tz= utc} let of_unix_time s = match Ptime.of_float_s s with @@ -123,24 +126,22 @@ let of_unix_time s = | Some t -> of_ptime t -let to_unix_time t = to_ptime_t t |> Ptime.to_float_s +let to_unix_time t = to_ptime t |> Ptime.to_float_s -let _localtime current_tz_offset t = - let tz_offset_s = current_tz_offset |> Option.value ~default:0 in - let localtime = t |> Ptime.to_date_time ~tz_offset_s |> of_dt Empty in - let _, (_, localtime_offset), _ = localtime in - if localtime_offset <> tz_offset_s then - invalid_arg - (Printf.sprintf "%s: offsets don't match. offset='%i', t='%s'" - __FUNCTION__ tz_offset_s (Ptime.to_rfc3339 t) - ) ; - localtime +let strip_tz tz t = + let t = + match tz with + | None -> + t + | Some tz -> + Ptime.Span.of_int_s tz |> Ptime.add_span t |> Option.value ~default:t + in + {t; tz= None} -let _localtime_string current_tz_offset t = - _localtime current_tz_offset t |> to_rfc3339 +let _localtime_string tz t = strip_tz tz t |> to_rfc3339 let localtime () = - _localtime (Ptime_clock.current_tz_offset_s ()) (Ptime_clock.now ()) + strip_tz (Ptime_clock.current_tz_offset_s ()) (Ptime_clock.now ()) let now () = of_ptime (Ptime_clock.now ()) @@ -152,19 +153,19 @@ let is_later ~than t = Ptime.is_later ~than:(to_ptime than) (to_ptime t) let diff a b = Ptime.diff (to_ptime a) (to_ptime b) -let compare_print_tz a b = +let compare_tz a b = match (a, b) with - | Empty, Empty -> + | None, None -> 0 - | TZ a_s, TZ b_s -> - String.compare a_s b_s - | Empty, TZ _ -> + | Some a_s, Some b_s -> + Int.compare a_s b_s + | None, Some _ -> -1 - | TZ _, Empty -> + | Some _, None -> 1 -let compare ((_, _, a_z) as a) ((_, _, b_z) as b) = +let compare a b = let ( ) a b = if a = 0 then b else a in - Ptime.compare (to_ptime a) (to_ptime b) compare_print_tz a_z b_z + Ptime.compare (to_ptime a) (to_ptime b) compare_tz a.tz b.tz -let eq x y = compare x y = 0 +let equal x y = if x == y then true else compare x y = 0 diff --git a/ocaml/libs/clock/date.mli b/ocaml/libs/clock/date.mli index 2a0123813b3..1ba0f19c9d9 100644 --- a/ocaml/libs/clock/date.mli +++ b/ocaml/libs/clock/date.mli @@ -12,24 +12,32 @@ * GNU Lesser General Public License for more details. *) -(** date-time with support for keeping timezone for ISO 8601 conversion *) +(** Nanosecond-precision POSIX timestamps, allows datetimes with unspecified + timezones. These are needed to produce and accept ISO 8601 datetimes without + timezones, but because the timezone is not known they do not share a common + point of time with any other timestamps they cannot be converted to unix + time, or be compared with other timestamps. All other timestamps have a + timezone attached to them, which will be used to serialize them to a + datetime string. This timezone is determined when creating a value and + cannot be changed. For timestamps created from datetime strings, the + timezone is maintained. For all other values UTC is used. *) type t (** Conversions *) val of_ptime : Ptime.t -> t -(** Convert ptime to time in UTC *) +(** Converts ptime to date *) val to_ptime : t -> Ptime.t (** Convert date/time to a ptime value: the number of seconds since 00:00:00 - UTC, 1 Jan 1970. Assumes the underlying {!t} is in UTC *) + UTC, 1 Jan 1970. When {!t} lacks a timezone, UTC is assumed *) val of_unix_time : float -> t (** Convert calendar time [x] (as returned by e.g. Unix.time), to time in UTC *) val to_unix_time : t -> float (** Convert date/time to a unix timestamp: the number of seconds since - 00:00:00 UTC, 1 Jan 1970. Assumes the underlying {!t} is in UTC *) + 00:00:00 UTC, 1 Jan 1970. When {!t} lacks a timezone, UTC is assumed *) val to_rfc822 : t -> string (** Convert date/time to email-formatted (RFC 822) string. *) @@ -39,38 +47,42 @@ val to_rfc3339 : t -> string the ISO 8601 format *) val of_iso8601 : string -> t -(** Convert ISO 8601 formatted string to a date/time value. Does not accept a - timezone annotated datetime - i.e. string must be UTC, and end with a Z *) +(** Convert ISO 8601 formatted string to a date/time value. Timezone can be + missing from the string, but that means some conversions will assume UTC, + which might be incorrect *) val epoch : t -(** 00:00:00 UTC, 1 Jan 1970, in UTC *) +(** 00:00:00 UTC, 1 Jan 1970 *) val now : unit -> t -(** Count the number of seconds passed since 00:00:00 UTC, 1 Jan 1970, in UTC *) +(** Count the number of seconds passed since 00:00:00 UTC, 1 Jan 1970 *) val _localtime_string : Ptime.tz_offset_s option -> Ptime.t -> string (** exposed for testing *) val localtime : unit -> t -(** Count the number of seconds passed since 00:00:00 UTC, 1 Jan 1970, in local - time *) +(** Local date time, the timezone is stripped. Do not use this call in new + code. *) (** Comparisons *) -val eq : t -> t -> bool -(** [eq a b] returns whether [a] and [b] are equal *) +val equal : t -> t -> bool +(** [equal a b] returns whether [a] and [b] are equal. Timestamps that are not + on UTC will only be equal to the values in their same memory position. *) val compare : t -> t -> int (** [compare a b] returns -1 if [a] is earlier than [b], 1 if [a] is later than - [b] or the ordering of the timezone printer *) + [b] or which timeone is sooner. When [a] or [b] lack a timezone, UTC is + assumed *) val is_earlier : than:t -> t -> bool (** [is_earlier ~than a] returns whether the timestamp [a] happens before - [than] *) + [than]. When [than] or [b] lack a timezone, UTC is assumed. *) val is_later : than:t -> t -> bool -(** [is_later ~than a] returns whether the timestamp [a] happens after [than] - *) +(** [is_later ~than a] returns whether the timestamp [a] happens after [than]. + When [than] or [b] lack a timezone, UTC is assumed. *) val diff : t -> t -> Ptime.Span.t -(** [diff a b] returns the span of time corresponding to [a - b] *) +(** [diff a b] returns the span of time corresponding to [a - b]. When [than] + or [b] lack a timezone, UTC is assumed. *) diff --git a/ocaml/libs/clock/dune b/ocaml/libs/clock/dune index 76285033f35..a2afef36460 100644 --- a/ocaml/libs/clock/dune +++ b/ocaml/libs/clock/dune @@ -8,6 +8,7 @@ mtime.clock.os (re_export ptime) ptime.clock.os + xapi-log ) ) diff --git a/ocaml/libs/clock/test_date.ml b/ocaml/libs/clock/test_date.ml index 78f673f635c..9318f44af54 100644 --- a/ocaml/libs/clock/test_date.ml +++ b/ocaml/libs/clock/test_date.ml @@ -10,6 +10,28 @@ let dash_time_str = "2020-04-07T08:28:32Z" let no_dash_utc_time_str = "20200407T08:28:32Z" +let best_effort_iso8601_to_rfc3339 x = + let x = + try + Scanf.sscanf x "%04d%02d%02dT%s" (fun y mon d rest -> + Printf.sprintf "%04d-%02d-%02dT%s" y mon d rest + ) + with _ -> x + in + let tz = + try + Scanf.sscanf x "%04d-%02d-%02dT%02d:%02d:%02d%s" (fun _ _ _ _ _ _ tz -> + Some tz + ) + with _ -> None + in + match tz with + | None | Some "" -> + (* the caller didn't specify a tz, use the Unqualified Local Time *) + Printf.sprintf "%s-00:00" x + | Some _ -> + x + let tests = let test_of_unix_time_invertible () = let non_int_time = 1586245987.70200706 in @@ -17,20 +39,24 @@ let tests = check_float "to_unix_time inverts of_unix_time" time (time |> of_unix_time |> to_unix_time) ; check_true "of_unix_time inverts to_unix_time" - @@ eq (time |> of_unix_time) + @@ equal (time |> of_unix_time) (time |> of_unix_time |> to_unix_time |> of_unix_time) in - let test_only_utc () = + let test_iso8601 () = let utc = "2020-12-20T18:10:19Z" in let _ = of_iso8601 utc in (* UTC is valid *) let non_utc = "2020-12-20T18:10:19+02:00" in - let exn = - Invalid_argument "Clock__Date.of_iso8601: 2020-12-20T18:10:19+02:00" + let _ = of_iso8601 non_utc in + () + in + let test_roundtrip_conversion () = + let non_utc = ["20201220T18:10:19+02:00"; "20201220T18:10:19-08:45"] in + let test spec = + let result = spec |> of_iso8601 |> to_rfc3339 in + Alcotest.(check string) "Roundtrip conversion be consistent" spec result in - Alcotest.check_raises "only UTC is accepted" exn (fun () -> - of_iso8601 non_utc |> ignore - ) + List.iter test non_utc in let test_ca333908 () = check_float "dash time and no dash time represent the same unix timestamp" @@ -41,7 +67,7 @@ let tests = check_string "to_rfc3339 inverts of_iso8601" no_dash_utc_time_str (no_dash_utc_time_str |> of_iso8601 |> to_rfc3339) ; check_true "of_iso8601 inverts to_rfc3339" - (eq + (equal (no_dash_utc_time_str |> of_iso8601) (no_dash_utc_time_str |> of_iso8601 |> to_rfc3339 |> of_iso8601) ) @@ -51,6 +77,21 @@ let tests = check_string "to_rfc3339 is backwards compatible" no_dash_utc_time_str (dash_time_str |> of_iso8601 |> to_rfc3339) in + let test_localtime () = + let time = localtime () in + match + time + |> to_rfc3339 + |> best_effort_iso8601_to_rfc3339 + |> Ptime.of_rfc3339 + |> Ptime.rfc3339_error_to_msg + with + | Ok (_, tz, _) -> + Alcotest.(check @@ option int) + "localtime generates a timestamp without timezone" None tz + | Error (`Msg msg) -> + Alcotest.failf "Unexpected error: %s" msg + in let test_localtime_string () = let[@warning "-8"] (Ok (t, _, _)) = Ptime.of_rfc3339 "2020-04-07T09:01:28Z" @@ -82,24 +123,33 @@ let tests = (String.contains localtime_string 'Z') in let test_xsi894 () = + let canonical = "20201210T17:19:20Z" in let missing_tz_no_dash = "20201210T17:19:20" in let missing_tz_dash = "2020-12-10T17:19:20" in - check_string "can process missing tz no dash" missing_tz_no_dash + check_string + "Timestamp without timezones nor dashes is accepted, gets converted to \ + UTC" + canonical (missing_tz_no_dash |> of_iso8601 |> to_rfc3339) ; - check_string "can process missing tz with dashes, but return without dashes" - missing_tz_no_dash - (missing_tz_dash |> of_iso8601 |> to_rfc3339) ; - check_float "to_unix_time assumes UTC" 1607620760. - (missing_tz_no_dash |> of_iso8601 |> to_unix_time) ; - let localtime' = localtime () in - check_string "to_rfc3339 inverts of_iso8601 for localtime" - (localtime' |> to_rfc3339) - (localtime' |> to_rfc3339 |> of_iso8601 |> to_rfc3339) + check_string + "Timestamp without timezones, and dashes is accepted, gets converted to \ + UTC" + canonical + (missing_tz_dash |> of_iso8601 |> to_rfc3339) in let test_email_date (unix_timestamp, expected) = let formatted = of_unix_time unix_timestamp |> to_rfc822 in check_string "String is properly RFC-822-formatted" expected formatted in + let test_no_timezone_to_unix () = + (* this is allowed, but it will print a warning to stdout *) + let missing_tz_no_dash = "20201210T17:19:20" in + let with_tz_no_dash = "20201210T17:19:20Z" in + let to_unix_time dt = dt |> of_iso8601 |> to_unix_time in + check_float "Datetime without timezone assumes it's in UTC" + (to_unix_time with_tz_no_dash) + (to_unix_time missing_tz_no_dash) + in let test_email_dates () = let dates = [ @@ -113,7 +163,8 @@ let tests = in [ ("test_of_unix_time_invertible", `Quick, test_of_unix_time_invertible) - ; ("test_only_utc", `Quick, test_only_utc) + ; ("test_only_utc", `Quick, test_iso8601) + ; ("Roundtrip conversion", `Quick, test_roundtrip_conversion) ; ("test_ca333908", `Quick, test_ca333908) ; ( "test_of_iso8601_invertible_when_no_dashes" , `Quick @@ -123,9 +174,14 @@ let tests = , `Quick , test_to_rfc3339_backwards_compatibility ) + ; ("localtime is printed without timezone", `Quick, test_localtime) ; ("test_localtime_string", `Quick, test_localtime_string) ; ("test_ca342171", `Quick, test_ca342171) - ; ("test_xsi894", `Quick, test_xsi894) + ; ("Parsing datetimes without timezones", `Quick, test_xsi894) + ; ( "Date w/o timezone to POSIX time conversion" + , `Quick + , test_no_timezone_to_unix + ) ; ("RFC 822 formatting", `Quick, test_email_dates) ] diff --git a/ocaml/libs/http-lib/xMLRPC.ml b/ocaml/libs/http-lib/xMLRPC.ml index a918f9b4e13..e9e425b976f 100644 --- a/ocaml/libs/http-lib/xMLRPC.ml +++ b/ocaml/libs/http-lib/xMLRPC.ml @@ -68,7 +68,7 @@ module To = struct let boolean b = value (box "boolean" [pcdata (if b then "1" else "0")]) let datetime s = - value (box "dateTime.iso8601" [pcdata (Xapi_stdext_date.Date.to_string s)]) + value (box "dateTime.iso8601" [pcdata (Xapi_stdext_date.Date.to_rfc3339 s)]) let double x = let txt = @@ -197,7 +197,7 @@ module From = struct let boolean = value (singleton ["boolean"] (( <> ) (Xml.PCData "0"))) let datetime x = - Xapi_stdext_date.Date.of_string + Xapi_stdext_date.Date.of_iso8601 (value (singleton ["dateTime.iso8601"] (pcdata id)) x) let double = value (singleton ["double"] (pcdata float_of_string)) diff --git a/ocaml/libs/http-lib/xMLRPC.mli b/ocaml/libs/http-lib/xMLRPC.mli index c8a7ca32af6..165f2e6ec52 100644 --- a/ocaml/libs/http-lib/xMLRPC.mli +++ b/ocaml/libs/http-lib/xMLRPC.mli @@ -59,7 +59,7 @@ module To : sig val boolean : bool -> xmlrpc (** Marshal a boolean. *) - val datetime : Xapi_stdext_date.Date.iso8601 -> xmlrpc + val datetime : Xapi_stdext_date.Date.t -> xmlrpc (** Marshal a date-time. *) val double : float -> xmlrpc @@ -98,7 +98,7 @@ module From : sig val boolean : xmlrpc -> bool (** Parse a boolean. *) - val datetime : xmlrpc -> Xapi_stdext_date.Date.iso8601 + val datetime : xmlrpc -> Xapi_stdext_date.Date.t (** Parse a date-time. *) val double : xmlrpc -> float diff --git a/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.ml b/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.ml index 45e9bba5efb..ef0f98ce13a 100644 --- a/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.ml +++ b/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.ml @@ -28,6 +28,8 @@ let rfc822_of_float = of_unix_time let rfc822_to_string = to_rfc822 +let eq = equal + type iso8601 = t type rfc822 = t diff --git a/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.mli b/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.mli index 62e894808bf..7fb29404306 100644 --- a/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.mli +++ b/ocaml/libs/xapi-stdext/lib/xapi-stdext-date/date.mli @@ -57,8 +57,8 @@ val localtime : unit -> t (** Comparisons *) -val eq : t -> t -> bool -(** [eq a b] returns whether [a] and [b] are equal *) +val equal : t -> t -> bool +(** [equal a b] returns whether [a] and [b] are equal *) val compare : t -> t -> int (** [compare a b] returns -1 if [a] is earlier than [b], 1 if [a] is later than @@ -77,29 +77,39 @@ val diff : t -> t -> Ptime.Span.t (** Deprecated bindings, these will be removed in a future release: *) +val eq : t -> t -> bool +[@@deprecated "Use Date.equal"] +(** [eq a b] returns whether [a] and [b] are equal *) + val rfc822_to_string : t -> string +[@@deprecated "Use Date.to_rfc822"] (** Same as {!to_rfc822} *) val rfc822_of_float : float -> t +[@@deprecated "Use Date.of_unix_time"] (** Same as {!of_unix_time} *) val of_float : float -> t +[@@deprecated "Use Date.of_unix_time"] (** Same as {!of_unix_time} *) val to_float : t -> float +[@@deprecated "Use Date.to_unix_time"] (** Same as {!to_unix_time} *) val to_string : t -> string +[@@deprecated "Use Date.to_rfc3339"] (** Same as {!to_rfc3339} *) val of_string : string -> t +[@@deprecated "Use Date.of_iso8601"] (** Same as {!of_iso8601} *) -val never : t +val never : t [@@deprecated "Use Date.epoch"] (** Same as {!epoch} *) (** Deprecated alias for {!t} *) -type iso8601 = t +type iso8601 = t [@@deprecated "Use Date.t"] (** Deprecated alias for {!t} *) -type rfc822 = t +type rfc822 = t [@@deprecated "Use Date.t"] diff --git a/ocaml/license/daily_license_check.ml b/ocaml/license/daily_license_check.ml index b107bfef755..3b6edecbb3e 100644 --- a/ocaml/license/daily_license_check.ml +++ b/ocaml/license/daily_license_check.ml @@ -13,7 +13,7 @@ let get_hosts all_license_params threshold = List.fold_left (fun acc (name_label, license_params) -> let expiry = List.assoc "expiry" license_params in - let expiry = Xapi_stdext_date.Date.(to_float (of_string expiry)) in + let expiry = Xapi_stdext_date.Date.(to_unix_time (of_iso8601 expiry)) in if expiry < threshold then name_label :: acc else @@ -23,7 +23,7 @@ let get_hosts all_license_params threshold = let check_license now pool_license_state all_license_params = let expiry = List.assoc "expiry" pool_license_state in - let expiry = Xapi_stdext_date.Date.(to_float (of_string expiry)) in + let expiry = Xapi_stdext_date.Date.(to_unix_time (of_iso8601 expiry)) in let days = days_to_expiry now expiry in if days <= 0. then Expired (get_hosts all_license_params now) diff --git a/ocaml/quicktest/qt.ml b/ocaml/quicktest/qt.ml index 7485cef15d4..3b6b7cd9743 100644 --- a/ocaml/quicktest/qt.ml +++ b/ocaml/quicktest/qt.ml @@ -100,9 +100,9 @@ module Time = struct let now () = Unix.gettimeofday () - let of_field = Xapi_stdext_date.Date.to_float + let of_field = Xapi_stdext_date.Date.to_unix_time - let pp t = Xapi_stdext_date.Date.of_float t |> Xapi_stdext_date.Date.to_string + let pp t = Xapi_stdext_date.Date.(of_unix_time t |> to_rfc3339) let check t ~after ~before = Alcotest.(check bool) @@ -269,7 +269,7 @@ module VDI = struct ; ( `Same , "snapshot_time" , fun vdi -> - vdi.API.vDI_snapshot_time |> Xapi_stdext_date.Date.to_string + vdi.API.vDI_snapshot_time |> Xapi_stdext_date.Date.to_rfc3339 ) ; (`Same, "virtual_size", fun vdi -> vdi.API.vDI_location) ] diff --git a/ocaml/quicktest/qt.mli b/ocaml/quicktest/qt.mli index 15dbb785f28..5ba4e8c68a0 100644 --- a/ocaml/quicktest/qt.mli +++ b/ocaml/quicktest/qt.mli @@ -34,7 +34,7 @@ module Time : sig val now : unit -> t - val of_field : Xapi_stdext_date.Date.iso8601 -> t + val of_field : Xapi_stdext_date.Date.t -> t val pp : t -> string diff --git a/ocaml/quicktest/quicktest_date.ml b/ocaml/quicktest/quicktest_date.ml index 7a7e6b7ba5e..19ff9153088 100644 --- a/ocaml/quicktest/quicktest_date.ml +++ b/ocaml/quicktest/quicktest_date.ml @@ -3,9 +3,7 @@ module Date = Xapi_stdext_date.Date let test_host_get_server_localtime rpc session_id () = let host = Client.Host.get_by_uuid ~rpc ~session_id ~uuid:Qt.localhost_uuid in - let (_ : Date.iso8601) = - Client.Host.get_server_localtime ~rpc ~session_id ~host - in + let (_ : Date.t) = Client.Host.get_server_localtime ~rpc ~session_id ~host in () let test_message_get_since rpc session_id () = @@ -14,7 +12,7 @@ let test_message_get_since rpc session_id () = Forkhelpers.execute_command_get_output "/bin/date" [Printf.sprintf "+%s" format'; "-d"; "yesterday"] in - let yesterday = String.trim stdout |> Date.of_string in + let yesterday = String.trim stdout |> Date.of_iso8601 in let (_ : ('a API.Ref.t * API.message_t) list) = Client.Message.get_since ~rpc ~session_id ~since:yesterday in @@ -25,6 +23,7 @@ let test_message_get_since rpc session_id () = ; "%Y-%m-%dT%H:%M:%S" ; "%Y%m%dT%H:%M:%SZ" ; "%Y%m%dT%H:%M:%S" + ; "%Y%m%dT%H:%M:%S-12:00" ] |> List.iter test_with_format diff --git a/ocaml/quicktest/quicktest_event.ml b/ocaml/quicktest/quicktest_event.ml index f844db3e72c..a99f71bf752 100644 --- a/ocaml/quicktest/quicktest_event.ml +++ b/ocaml/quicktest/quicktest_event.ml @@ -381,7 +381,7 @@ let event_message_test rpc session_id () = ) ; let messages = Client.Client.Message.get ~rpc ~session_id ~cls ~obj_uuid - ~since:Xapi_stdext_date.Date.never + ~since:Xapi_stdext_date.Date.epoch in let has_msg m = List.exists (fun (r, _) -> r = m) messages in Alcotest.(check bool) diff --git a/ocaml/quicktest/quicktest_vdi.ml b/ocaml/quicktest/quicktest_vdi.ml index a648495eced..a11e1b2ce05 100644 --- a/ocaml/quicktest/quicktest_vdi.ml +++ b/ocaml/quicktest/quicktest_vdi.ml @@ -139,7 +139,7 @@ let vdi_bad_introduce rpc session_id sr_info () = ~location:(Ref.string_of (Ref.make ())) ~xenstore_data:[] ~sm_config:[] ~managed:true ~virtual_size:0L ~physical_utilisation:0L ~metadata_of_pool:Ref.null - ~is_a_snapshot:false ~snapshot_time:Xapi_stdext_date.Date.never + ~is_a_snapshot:false ~snapshot_time:Xapi_stdext_date.Date.epoch ~snapshot_of:Ref.null in Alcotest.fail @@ -161,7 +161,7 @@ let vdi_bad_introduce rpc session_id sr_info () = ~other_config:[] ~location:vdir.API.vDI_location ~xenstore_data:[] ~sm_config:[] ~managed:true ~virtual_size:0L ~physical_utilisation:0L ~metadata_of_pool:Ref.null - ~is_a_snapshot:false ~snapshot_time:Xapi_stdext_date.Date.never + ~is_a_snapshot:false ~snapshot_time:Xapi_stdext_date.Date.epoch ~snapshot_of:Ref.null in Alcotest.fail diff --git a/ocaml/sdk-gen/csharp/gen_csharp_binding.ml b/ocaml/sdk-gen/csharp/gen_csharp_binding.ml index ff390468130..edaa3a7c7f9 100644 --- a/ocaml/sdk-gen/csharp/gen_csharp_binding.ml +++ b/ocaml/sdk-gen/csharp/gen_csharp_binding.ml @@ -1206,7 +1206,7 @@ and get_default_value_opt field = Printf.sprintf "DateTime.ParseExact(\"%s\", \"yyyyMMddTHH:mm:ssZ\", \ CultureInfo.InvariantCulture)" - (Date.to_string y) + (Date.to_rfc3339 y) ] | VEnum y -> [enum_of_wire y] diff --git a/ocaml/tests/alerts/test_alert_certificate_check.ml b/ocaml/tests/alerts/test_alert_certificate_check.ml index b35dcd362a5..ce84cc672d2 100644 --- a/ocaml/tests/alerts/test_alert_certificate_check.ml +++ b/ocaml/tests/alerts/test_alert_certificate_check.ml @@ -14,7 +14,7 @@ open Certificate_check -let date_of = Xapi_stdext_date.Date.of_string +let date_of = Xapi_stdext_date.Date.of_iso8601 let check_time = date_of "20200201T02:00:00Z" diff --git a/ocaml/tests/alerts/test_daily_license_check.ml b/ocaml/tests/alerts/test_daily_license_check.ml index 866830b1059..067d93288ce 100644 --- a/ocaml/tests/alerts/test_daily_license_check.ml +++ b/ocaml/tests/alerts/test_daily_license_check.ml @@ -37,7 +37,7 @@ let expiry = Alcotest.testable pp_expiry equals let check_time = - Xapi_stdext_date.Date.(to_float (of_string "20160601T04:00:00Z")) + Xapi_stdext_date.Date.(to_unix_time (of_iso8601 "20160601T04:00:00Z")) let test_expiry ((pool_license_state, all_license_params), expected) () = let result = check_license check_time pool_license_state all_license_params in diff --git a/ocaml/tests/alerts/test_expiry_alert.ml b/ocaml/tests/alerts/test_expiry_alert.ml index ece31122b78..2c3fa283be8 100644 --- a/ocaml/tests/alerts/test_expiry_alert.ml +++ b/ocaml/tests/alerts/test_expiry_alert.ml @@ -14,7 +14,7 @@ open Expiry_alert -let date_of = Xapi_stdext_date.Date.of_string +let date_of = Xapi_stdext_date.Date.of_iso8601 let test_expired = ("TEST_EXPIRED", 1L) diff --git a/ocaml/tests/common/test_common.ml b/ocaml/tests/common/test_common.ml index 1c1685f693d..293317518a4 100644 --- a/ocaml/tests/common/test_common.ml +++ b/ocaml/tests/common/test_common.ml @@ -296,7 +296,7 @@ let make_pool ~__context ~master ?(name_label = "") ?(name_description = "") ?(repository_proxy_username = "") ?(repository_proxy_password = Ref.null) ?(migration_compression = false) ?(coordinator_bias = true) ?(telemetry_uuid = Ref.null) ?(telemetry_frequency = `weekly) - ?(telemetry_next_collection = API.Date.never) + ?(telemetry_next_collection = API.Date.epoch) ?(last_update_sync = API.Date.epoch) ?(update_sync_frequency = `daily) ?(update_sync_day = 0L) ?(update_sync_enabled = false) ?(recommendations = []) () = @@ -393,7 +393,7 @@ let make_vdi ~__context ?(ref = Ref.make ()) ?(uuid = make_uuid ()) ?(read_only = false) ?(other_config = []) ?(storage_lock = false) ?(location = "") ?(managed = false) ?(missing = false) ?(parent = Ref.null) ?(xenstore_data = []) ?(sm_config = []) ?(is_a_snapshot = false) - ?(snapshot_of = Ref.null) ?(snapshot_time = API.Date.never) ?(tags = []) + ?(snapshot_of = Ref.null) ?(snapshot_time = API.Date.epoch) ?(tags = []) ?(allow_caching = true) ?(on_boot = `persist) ?(metadata_of_pool = Ref.make ()) ?(metadata_latest = true) ?(is_tools_iso = false) ?(cbt_enabled = false) () = @@ -516,9 +516,9 @@ let make_pool_update ~__context ?(ref = Ref.make ()) ?(uuid = make_uuid ()) let make_session ~__context ?(ref = Ref.make ()) ?(uuid = make_uuid ()) ?(this_host = Ref.null) ?(this_user = Ref.null) - ?(last_active = API.Date.never) ?(pool = false) ?(other_config = []) + ?(last_active = API.Date.epoch) ?(pool = false) ?(other_config = []) ?(is_local_superuser = false) ?(subject = Ref.null) - ?(validation_time = API.Date.never) ?(auth_user_sid = "") + ?(validation_time = API.Date.epoch) ?(auth_user_sid = "") ?(auth_user_name = "") ?(rbac_permissions = []) ?(parent = Ref.null) ?(originator = "test") ?(client_certificate = false) () = Db.Session.create ~__context ~ref ~uuid ~this_host ~this_user ~last_active diff --git a/ocaml/tests/test_client.ml b/ocaml/tests/test_client.ml index cdfa7690f79..1c3137721b8 100644 --- a/ocaml/tests/test_client.ml +++ b/ocaml/tests/test_client.ml @@ -13,7 +13,7 @@ let make_client_params ~__context = let rpc = Api_server.Server.dispatch_call req Unix.stdout in let session_id = let session_id = Ref.make () in - let now = Xapi_stdext_date.Date.of_float (Unix.time ()) in + let now = Xapi_stdext_date.Date.now () in let (_ : _ API.Ref.t) = Test_common.make_session ~__context ~ref:session_id ~this_host:(Helpers.get_localhost ~__context) diff --git a/ocaml/tests/test_pool_license.ml b/ocaml/tests/test_pool_license.ml index fbba9c74e36..aad9a145c11 100644 --- a/ocaml/tests/test_pool_license.ml +++ b/ocaml/tests/test_pool_license.ml @@ -29,22 +29,24 @@ let string_of_date_opt = function | None -> "None" | Some date -> - Printf.sprintf "Some %s" (Date.to_string date) + Printf.sprintf "Some %s" (Date.to_rfc3339 date) -let f2d = Date.of_float +let f2d = Date.of_unix_time -let f2d2s f = f |> Date.of_float |> Date.to_string +let f2d2s f = f |> Date.of_unix_time |> Date.to_rfc3339 let edition_to_int = [("edition1", 1); ("edition2", 2); ("edition3", 3)] module CompareDates = Generic.MakeStateless (struct module Io = struct - type input_t = Date.iso8601 option * Date.iso8601 option + type input_t = Date.t option * Date.t option type output_t = int let string_of_input_t = - Test_printers.(assoc_pair (option Date.to_string) (option Date.to_string)) + Test_printers.( + assoc_pair (option Date.to_rfc3339) (option Date.to_rfc3339) + ) let string_of_output_t = Test_printers.int end @@ -66,13 +68,13 @@ end) module PoolExpiryDate = Generic.MakeStateful (struct module Io = struct - type input_t = Date.iso8601 option list + type input_t = Date.t option list - type output_t = Date.iso8601 option + type output_t = Date.t option - let string_of_input_t = Test_printers.(list (option Date.to_string)) + let string_of_input_t = Test_printers.(list (option Date.to_rfc3339)) - let string_of_output_t = Test_printers.option Date.to_string + let string_of_output_t = Test_printers.option Date.to_rfc3339 end module State = Test_state.XapiDb @@ -86,7 +88,7 @@ module PoolExpiryDate = Generic.MakeStateful (struct | None -> [] | Some date -> - [("expiry", Date.to_string date)] + [("expiry", Date.to_rfc3339 date)] in let (_ : API.ref_host) = Test_common.make_host ~__context ~edition:"edition1" ~license_params @@ -201,10 +203,10 @@ module PoolLicenseState = Generic.MakeStateful (struct | None -> "never" | Some date -> - if date = Date.of_float License_check.never then + if date = Date.of_unix_time License_check.never then "never" else - Date.to_string date + Date.to_rfc3339 date in (pool_edition, pool_expiry) diff --git a/ocaml/tests/test_session.ml b/ocaml/tests/test_session.ml index 518dc221d72..4b441fc325b 100644 --- a/ocaml/tests/test_session.ml +++ b/ocaml/tests/test_session.ml @@ -1,8 +1,8 @@ module Date = Xapi_stdext_date.Date -let now = Date.of_string "2020-09-22T14:57:11Z" +let now = Date.of_iso8601 "2020-09-22T14:57:11Z" -let future = Date.of_string "2020-09-22T15:03:13Z" +let future = Date.of_iso8601 "2020-09-22T15:03:13Z" let fail_login ~__context ~uname ~originator ~now () = try diff --git a/ocaml/tests/test_updateinfo.ml b/ocaml/tests/test_updateinfo.ml index 6df2f0b2fba..6e05875e4f1 100644 --- a/ocaml/tests/test_updateinfo.ml +++ b/ocaml/tests/test_updateinfo.ml @@ -430,7 +430,7 @@ let fields_of_updateinfo = ) (list string) ; field "issued" - (fun (r : UpdateInfo.t) -> Xapi_stdext_date.Date.to_string r.issued) + (fun (r : UpdateInfo.t) -> Xapi_stdext_date.Date.to_rfc3339 r.issued) string ; field "severity" (fun (r : UpdateInfo.t) -> Severity.to_string r.severity) @@ -644,7 +644,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct ; update_type= "security" ; livepatches= [] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z" ; severity= Severity.High ; title= "title" } @@ -690,7 +690,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct ; update_type= "security" ; livepatches= [] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z" ; severity= Severity.High ; title= "title" } @@ -747,7 +747,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct ; update_type= "security" ; livepatches= [] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z" ; severity= Severity.High ; title= "title" } @@ -771,7 +771,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct ; update_type= "security" ; livepatches= [] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:50Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:50Z" ; severity= Severity.None ; title= "title" } @@ -828,7 +828,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct ; update_type= "security" ; livepatches= [] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z" ; severity= Severity.High ; title= "title" } @@ -852,7 +852,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct ; update_type= "security" ; livepatches= [] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:50Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:50Z" ; severity= Severity.None ; title= "title" } @@ -937,7 +937,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct ; update_type= "security" ; livepatches= [] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z" ; severity= Severity.High ; title= "title" } @@ -1034,7 +1034,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct ; update_type= "security" ; livepatches= [] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z" ; severity= Severity.High ; title= "title" } @@ -1112,7 +1112,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct } ] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z" ; severity= Severity.High ; title= "title" } @@ -1190,7 +1190,7 @@ module UpdateInfoOfXml = Generic.MakeStateless (struct } ] ; issued= - Xapi_stdext_date.Date.of_string "2023-05-12T08:37:49Z" + Xapi_stdext_date.Date.of_iso8601 "2023-05-12T08:37:49Z" ; severity= Severity.High ; title= "title" } diff --git a/ocaml/tests/test_xapi_db_upgrade.ml b/ocaml/tests/test_xapi_db_upgrade.ml index 6b488fec157..f14838ef6ab 100644 --- a/ocaml/tests/test_xapi_db_upgrade.ml +++ b/ocaml/tests/test_xapi_db_upgrade.ml @@ -38,14 +38,14 @@ let update_snapshots () = let a = T.make_vm ~__context ~name_label:"a" () in let a_snap = T.make_vm ~__context ~name_label:"a snap" () in Db.VM.set_snapshot_of ~__context ~self:a_snap ~value:a ; - Db.VM.set_snapshot_time ~__context ~self:a_snap ~value:(Date.of_float 1.) ; + Db.VM.set_snapshot_time ~__context ~self:a_snap ~value:(Date.of_unix_time 1.) ; let b = T.make_vm ~__context ~name_label:"b" () in let b_snap = T.make_vm ~__context ~name_label:"b snap" () in Db.VM.set_snapshot_of ~__context ~self:b_snap ~value:b ; - Db.VM.set_snapshot_time ~__context ~self:b_snap ~value:(Date.of_float 1.) ; + Db.VM.set_snapshot_time ~__context ~self:b_snap ~value:(Date.of_unix_time 1.) ; let b_snap2 = T.make_vm ~__context ~name_label:"b snap2" () in Db.VM.set_snapshot_of ~__context ~self:b_snap2 ~value:b ; - Db.VM.set_snapshot_time ~__context ~self:b_snap2 ~value:(Date.of_float 2.) ; + Db.VM.set_snapshot_time ~__context ~self:b_snap2 ~value:(Date.of_unix_time 2.) ; X.update_snapshots.fn ~__context ; let check_vm = Alcotest.check Alcotest_comparators.(ref ()) in (* a.parent = a_snap *) diff --git a/ocaml/xapi-cli-server/cli_operations.ml b/ocaml/xapi-cli-server/cli_operations.ml index 068309abaca..d0d981309da 100644 --- a/ocaml/xapi-cli-server/cli_operations.ml +++ b/ocaml/xapi-cli-server/cli_operations.ml @@ -1956,7 +1956,7 @@ let vdi_introduce printer rpc session_id params = let virtual_size = 0L and physical_utilisation = 0L in let metadata_of_pool = Ref.null in let is_a_snapshot = false in - let snapshot_time = Date.never in + let snapshot_time = Date.epoch in let snapshot_of = Ref.null in let vdi = Client.VDI.introduce ~rpc ~session_id ~uuid ~name_label ~name_description @@ -3210,7 +3210,7 @@ exception Multiple_failure of (string * string) list let format_message msg = Printf.sprintf "Message: time=%s priority=%Ld name='%s'" - (Date.to_string msg.API.message_timestamp) + (Date.to_rfc3339 msg.API.message_timestamp) msg.API.message_priority msg.API.message_name let wrap_op printer pri rpc session_id op e = @@ -3220,7 +3220,7 @@ let wrap_op printer pri rpc session_id op e = try Client.Message.get ~rpc ~session_id ~cls:`VM ~obj_uuid:(safe_get_field (field_lookup e.fields "uuid")) - ~since:(Date.of_float now) + ~since:(Date.of_unix_time now) with _ -> [] in List.iter @@ -5272,7 +5272,7 @@ let with_license_server_changes printer rpc session_id params hosts f = current_license_servers ; let alerts = Client.Message.get_since ~rpc ~session_id - ~since:(Date.of_float (now -. 1.)) + ~since:(Date.of_unix_time (now -. 1.)) in let print_if_checkout_error (ref, msg) = if @@ -6245,7 +6245,7 @@ let license_of_host rpc session_id host = let rstr = Features.of_assoc_list params in let expiry = if List.mem_assoc "expiry" params then - Date.to_float (Date.of_string (List.assoc "expiry" params)) + Date.to_unix_time (Date.of_iso8601 (List.assoc "expiry" params)) else 0. in @@ -6280,7 +6280,7 @@ let diagnostic_license_status printer rpc session_id _params = ; String.sub h.uuid 0 8 ; Features.to_compact_string h.rstr ; h.edition - ; Date.to_string (Date.of_float h.expiry) + ; Date.to_rfc3339 (Date.of_unix_time h.expiry) ; Printf.sprintf "%.1f" ((h.expiry -. now) /. (24. *. 60. *. 60.)) ] ) diff --git a/ocaml/xapi-cli-server/records.ml b/ocaml/xapi-cli-server/records.ml index 1e7393d377f..3798280d082 100644 --- a/ocaml/xapi-cli-server/records.ml +++ b/ocaml/xapi-cli-server/records.ml @@ -376,7 +376,7 @@ let message_record rpc session_id message = ~get:(fun () -> (x ()).API.message_obj_uuid) () ; make_field ~name:"timestamp" - ~get:(fun () -> Date.to_string (x ()).API.message_timestamp) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.message_timestamp) () ; make_field ~name:"body" ~get:(fun () -> (x ()).API.message_body) () ] @@ -749,10 +749,10 @@ let task_record rpc session_id task = ; make_field ~name:"type" ~get:(fun () -> (x ()).API.task_type) () ; make_field ~name:"result" ~get:(fun () -> (x ()).API.task_result) () ; make_field ~name:"created" - ~get:(fun () -> Date.to_string (x ()).API.task_created) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.task_created) () ; make_field ~name:"finished" - ~get:(fun () -> Date.to_string (x ()).API.task_finished) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.task_finished) () ; make_field ~name:"error_info" ~get:(fun () -> concat_with_semi (x ()).API.task_error_info) @@ -1447,11 +1447,11 @@ let pool_record rpc session_id pool = () ; make_field ~name:"telemetry-next-collection" ~get:(fun () -> - (x ()).API.pool_telemetry_next_collection |> Date.to_string + (x ()).API.pool_telemetry_next_collection |> Date.to_rfc3339 ) () ; make_field ~name:"last-update-sync" - ~get:(fun () -> Date.to_string (x ()).API.pool_last_update_sync) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.pool_last_update_sync) () ; make_field ~name:"update-sync-frequency" ~get:(fun () -> @@ -1550,7 +1550,7 @@ let vmss_record rpc session_id vmss = ) () ; make_field ~name:"last-run-time" - ~get:(fun () -> Date.to_string (x ()).API.vMSS_last_run_time) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.vMSS_last_run_time) () ; make_field ~name:"VMs" ~get:(fun () -> @@ -1842,7 +1842,7 @@ let vm_record rpc session_id vm = ~get:(fun () -> get_uuids_from_refs (x ()).API.vM_snapshots) () ; make_field ~name:"snapshot-time" - ~get:(fun () -> Date.to_string (x ()).API.vM_snapshot_time) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.vM_snapshot_time) () ; make_field ~name:"transportable-snapshot-id" ~hidden:true ~get:(fun () -> (x ()).API.vM_transportable_snapshot_id) @@ -2264,14 +2264,14 @@ let vm_record rpc session_id vm = ; make_field ~name:"start-time" ~get:(fun () -> Option.fold ~none:unknown_time - ~some:(fun m -> Date.to_string m.API.vM_metrics_start_time) + ~some:(fun m -> Date.to_rfc3339 m.API.vM_metrics_start_time) (xm ()) ) () ; make_field ~name:"install-time" ~get:(fun () -> Option.fold ~none:unknown_time - ~some:(fun m -> Date.to_string m.API.vM_metrics_install_time) + ~some:(fun m -> Date.to_rfc3339 m.API.vM_metrics_install_time) (xm ()) ) () @@ -2410,7 +2410,9 @@ let vm_record rpc session_id vm = ; make_field ~name:"guest-metrics-last-updated" ~get:(fun () -> Option.fold ~none:nid - ~some:(fun m -> Date.to_string m.API.vM_guest_metrics_last_updated) + ~some:(fun m -> + Date.to_rfc3339 m.API.vM_guest_metrics_last_updated + ) (xgm ()) ) () @@ -2611,7 +2613,7 @@ let host_crashdump_record rpc session_id host = ~get:(fun () -> get_uuid_from_ref (x ()).API.host_crashdump_host) () ; make_field ~name:"timestamp" - ~get:(fun () -> Date.to_string (x ()).API.host_crashdump_timestamp) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.host_crashdump_timestamp) () ; make_field ~name:"size" ~get:(fun () -> Int64.to_string (x ()).API.host_crashdump_size) @@ -3203,7 +3205,7 @@ let host_record rpc session_id host = ) () ; make_field ~name:"last-software-update" - ~get:(fun () -> Date.to_string (x ()).API.host_last_software_update) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.host_last_software_update) () ; make_field ~name:"latest-synced-updates-applied" ~get:(fun () -> @@ -3274,7 +3276,7 @@ let vdi_record rpc session_id vdi = ~get:(fun () -> get_uuids_from_refs (x ()).API.vDI_snapshots) () ; make_field ~name:"snapshot-time" - ~get:(fun () -> Date.to_string (x ()).API.vDI_snapshot_time) + ~get:(fun () -> Date.to_rfc3339 (x ()).API.vDI_snapshot_time) () ; make_field ~name:"allowed-operations" ~get:(fun () -> @@ -5118,7 +5120,7 @@ let cluster_host_record rpc session_id cluster_host = () ; make_field ~name:"last-update-live" ~get:(fun () -> - (x ()).API.cluster_host_last_update_live |> Date.to_string + (x ()).API.cluster_host_last_update_live |> Date.to_rfc3339 ) () ; make_field ~name:"allowed-operations" @@ -5184,10 +5186,10 @@ let certificate_record rpc session_id certificate = ~get:(fun () -> (x ()).API.certificate_host |> get_uuid_from_ref) () ; make_field ~name:"not-before" - ~get:(fun () -> (x ()).API.certificate_not_before |> Date.to_string) + ~get:(fun () -> (x ()).API.certificate_not_before |> Date.to_rfc3339) () ; make_field ~name:"not-after" - ~get:(fun () -> (x ()).API.certificate_not_after |> Date.to_string) + ~get:(fun () -> (x ()).API.certificate_not_after |> Date.to_rfc3339) () ; make_field ~name:"fingerprint" ~get:(fun () -> (x ()).API.certificate_fingerprint) diff --git a/ocaml/xapi-idl/storage/storage_interface.ml b/ocaml/xapi-idl/storage/storage_interface.ml index 4b3e03e48e9..f5bd93de60b 100644 --- a/ocaml/xapi-idl/storage/storage_interface.ml +++ b/ocaml/xapi-idl/storage/storage_interface.ml @@ -206,8 +206,7 @@ type vdi_info = { ; (* sm_config: workaround via XenAPI *) metadata_of_pool: string [@default ""] ; is_a_snapshot: bool [@default false] - ; snapshot_time: string - [@default Xapi_stdext_date.Date.to_string Xapi_stdext_date.Date.never] + ; snapshot_time: string [@default Xapi_stdext_date.Date.(to_rfc3339 epoch)] ; snapshot_of: Vdi.t [@default Vdi.of_string ""] ; (* managed: workaround via XenAPI *) read_only: bool [@default false] diff --git a/ocaml/xapi-storage-script/main.ml b/ocaml/xapi-storage-script/main.ml index 74ea3bb8d9f..cd6575bc9b3 100644 --- a/ocaml/xapi-storage-script/main.ml +++ b/ocaml/xapi-storage-script/main.ml @@ -1330,9 +1330,7 @@ let bind ~volume_script_dir = Volume_client.snapshot (volume_rpc ~dbg) dbg sr vdi ) >>>= fun response -> - let now = - Xapi_stdext_date.Date.(to_string (of_float (Unix.gettimeofday ()))) - in + let now = Xapi_stdext_date.Date.(to_rfc3339 (now ())) in set ~dbg ~sr ~vdi:response.Xapi_storage.Control.key ~key:_snapshot_time_key ~value:now >>>= fun () -> diff --git a/ocaml/xapi/certificates.ml b/ocaml/xapi/certificates.ml index fe66194cb0e..6e1c01b7be6 100644 --- a/ocaml/xapi/certificates.ml +++ b/ocaml/xapi/certificates.ml @@ -214,7 +214,7 @@ end = struct in (name, Ref.null, `ca, remove_obsoleted_copies) in - let date_of_ptime time = Date.of_float (Ptime.to_float_s time) in + let date_of_ptime time = Date.of_unix_time (Ptime.to_float_s time) in let dates_of_ptimes (a, b) = (date_of_ptime a, date_of_ptime b) in let not_before, not_after = dates_of_ptimes (X509.Certificate.validity certificate) diff --git a/ocaml/xapi/create_misc.ml b/ocaml/xapi/create_misc.ml index beb94f4751c..d329170fce6 100644 --- a/ocaml/xapi/create_misc.ml +++ b/ocaml/xapi/create_misc.ml @@ -280,7 +280,7 @@ and create_domain_zero_record ~__context ~domain_zero_ref (host_info : host_info ~scheduled_to_be_resident_on:Ref.null ~affinity:localhost ~suspend_VDI:Ref.null ~domid:0L ~domarch ~is_control_domain:true ~is_a_template:false ~is_default_template:false ~is_a_snapshot:false - ~snapshot_time:Date.never ~snapshot_of:Ref.null + ~snapshot_time:Date.epoch ~snapshot_of:Ref.null ~transportable_snapshot_id:"" ~snapshot_info:[] ~snapshot_metadata:"" ~parent:Ref.null ~other_config:[] ~blobs:[] ~xenstore_data:[] ~tags:[] ~user_version:1L ~ha_restart_priority:"" ~ha_always_run:false @@ -348,8 +348,8 @@ and create_domain_zero_metrics_record ~__context ~domain_zero_metrics_ref ~memory_actual:memory_constraints.target ~vCPUs_utilisation:(List.map (fun x -> (Int64.of_int x, 0.)) (mkints vcpus)) ~vCPUs_number:(Int64.of_int vcpus) ~vCPUs_CPU:[] ~vCPUs_params:[] - ~vCPUs_flags:[] ~state:[] ~start_time:Date.never ~install_time:Date.never - ~last_updated:Date.never ~other_config:[] ~hvm:false ~nomigrate:false + ~vCPUs_flags:[] ~state:[] ~start_time:Date.epoch ~install_time:Date.epoch + ~last_updated:Date.epoch ~other_config:[] ~hvm:false ~nomigrate:false ~nested_virt:false ~current_domain_type:Xapi_globs.domain_zero_domain_type and update_domain_zero_record ~__context ~domain_zero_ref (host_info : host_info) diff --git a/ocaml/xapi/db_gc_util.ml b/ocaml/xapi/db_gc_util.ml index 182eaac00df..7972aa28ed9 100644 --- a/ocaml/xapi/db_gc_util.ml +++ b/ocaml/xapi/db_gc_util.ml @@ -308,14 +308,14 @@ let timeout_tasks ~__context = let completed_old, completed_young = List.partition (fun (_, t) -> - Date.to_float t.Db_actions.task_finished < oldest_completed_time + Date.to_unix_time t.Db_actions.task_finished < oldest_completed_time ) completed_gcable in let pending_old, pending_young = List.partition (fun (_, t) -> - Date.to_float t.Db_actions.task_created < oldest_pending_time + Date.to_unix_time t.Db_actions.task_created < oldest_pending_time ) pending in @@ -360,8 +360,8 @@ let timeout_tasks ~__context = List.sort (fun (_, t1) (_, t2) -> compare - (Date.to_float t1.Db_actions.task_finished) - (Date.to_float t2.Db_actions.task_finished) + (Date.to_unix_time t1.Db_actions.task_finished) + (Date.to_unix_time t2.Db_actions.task_finished) ) completed in @@ -422,7 +422,7 @@ let timeout_sessions_common ~__context sessions limit session_group = List.map (fun (x, y) -> ( x - , Date.to_float y.Db_actions.session_last_active + , Date.to_unix_time y.Db_actions.session_last_active , y.Db_actions.session_uuid ) ) @@ -447,7 +447,7 @@ let timeout_sessions_common ~__context sessions limit session_group = debug "Session.destroy _ref=%s uuid=%s %s (last active %s): %s" (Ref.string_of s) uuid (Context.trackid_of_session (Some s)) - (Date.to_string (Date.of_float active)) + (Date.to_rfc3339 (Date.of_unix_time active)) doc ; Xapi_session.destroy_db_session ~__context ~self:s ) @@ -586,7 +586,7 @@ let timeout_alerts ~__context = let all_alerts = Db.Alert.get_all ~__context in let now = Unix.gettimeofday() in List.iter (fun alert -> - let alert_time = Date.to_float (Db.Alert.get_timestamp ~__context ~self:alert) in + let alert_time = Date.to_unix_time (Db.Alert.get_timestamp ~__context ~self:alert) in if now -. alert_time > Xapi_globs.alert_timeout then Db.Alert.destroy ~__context ~self:alert ) all_alerts diff --git a/ocaml/xapi/dbsync.ml b/ocaml/xapi/dbsync.ml index 5ee30bb39c8..875b406bb89 100644 --- a/ocaml/xapi/dbsync.ml +++ b/ocaml/xapi/dbsync.ml @@ -42,7 +42,7 @@ let create_host_metrics ~__context = Db.Host_metrics.create ~__context ~ref:r ~uuid:(Uuidx.to_string (Uuidx.make ())) ~live:false ~memory_total:0L ~memory_free:0L - ~last_updated:Xapi_stdext_date.Date.never ~other_config:[] ; + ~last_updated:Xapi_stdext_date.Date.epoch ~other_config:[] ; Db.Host.set_metrics ~__context ~self ~value:r ) ) diff --git a/ocaml/xapi/dbsync_master.ml b/ocaml/xapi/dbsync_master.ml index 8f8e6a582f8..31f235e7214 100644 --- a/ocaml/xapi/dbsync_master.ml +++ b/ocaml/xapi/dbsync_master.ml @@ -291,11 +291,10 @@ let ensure_vm_metrics_records_exist __context = let uuid = Uuidx.to_string (Uuidx.make ()) in Db.VM_metrics.create ~__context ~ref:m ~uuid ~vCPUs_number:0L ~vCPUs_utilisation:[] ~memory_actual:0L ~vCPUs_CPU:[] ~vCPUs_params:[] - ~vCPUs_flags:[] ~start_time:Xapi_stdext_date.Date.never - ~install_time:Xapi_stdext_date.Date.never ~state:[] - ~last_updated:(Xapi_stdext_date.Date.of_float 0.) - ~other_config:[] ~hvm:false ~nested_virt:false ~nomigrate:false - ~current_domain_type:`unspecified ; + ~vCPUs_flags:[] ~start_time:Xapi_stdext_date.Date.epoch + ~install_time:Xapi_stdext_date.Date.epoch ~state:[] + ~last_updated:Xapi_stdext_date.Date.epoch ~other_config:[] ~hvm:false + ~nested_virt:false ~nomigrate:false ~current_domain_type:`unspecified ; Db.VM.set_metrics ~__context ~self:vm ~value:m ) ) diff --git a/ocaml/xapi/dbsync_slave.ml b/ocaml/xapi/dbsync_slave.ml index 32ee7d44d21..3b90a3a05c3 100644 --- a/ocaml/xapi/dbsync_slave.ml +++ b/ocaml/xapi/dbsync_slave.ml @@ -73,12 +73,12 @@ let get_start_time () = let uptime = String.split ' ' uptime in let uptime = List.hd uptime in let uptime = float_of_string uptime in - let boot_time = Date.of_float (now -. uptime) in - debug " system booted at %s" (Date.to_string boot_time) ; + let boot_time = Date.of_unix_time (now -. uptime) in + debug " system booted at %s" (Date.to_rfc3339 boot_time) ; boot_time with e -> debug "Calculating boot time failed with '%s'" (ExnHelper.string_of_exn e) ; - Date.never + Date.epoch (* not sufficient just to fill in this data on create time [Xen caps may change if VT enabled in BIOS etc.] *) @@ -106,7 +106,9 @@ let refresh_localhost_info ~__context info = Db.Host.set_capabilities ~__context ~self:host ~value:caps ; Db.Host.set_address ~__context ~self:host ~value:(get_my_ip_addr ~__context) ; let boot_time_key = "boot_time" in - let boot_time_value = string_of_float (Date.to_float (get_start_time ())) in + let boot_time_value = + string_of_float (Date.to_unix_time (get_start_time ())) + in Db.Host.remove_from_other_config ~__context ~self:host ~key:boot_time_key ; Db.Host.add_to_other_config ~__context ~self:host ~key:boot_time_key ~value:boot_time_value ; diff --git a/ocaml/xapi/debug_populate.ml b/ocaml/xapi/debug_populate.ml index 0eb1a89581a..3c192509915 100644 --- a/ocaml/xapi/debug_populate.ml +++ b/ocaml/xapi/debug_populate.ml @@ -72,7 +72,7 @@ let rec make_vdis_and_vbds __context vmref i = let physical_utilisation = 1L in let metadata_of_pool = Ref.null in let is_a_snapshot = false in - let snapshot_time = Xapi_stdext_date.Date.never in + let snapshot_time = Xapi_stdext_date.Date.epoch in let snapshot_of = Ref.null in let sharable = false in let cbt_enabled = false in diff --git a/ocaml/xapi/export.ml b/ocaml/xapi/export.ml index 24589827bc8..a81ec647225 100644 --- a/ocaml/xapi/export.ml +++ b/ocaml/xapi/export.ml @@ -241,7 +241,7 @@ let make_vm ?(with_snapshot_metadata = false) ~preserve_power_state table ; API.vM_snapshots= (if with_snapshot_metadata then vm.API.vM_snapshots else []) ; API.vM_snapshot_time= - (if with_snapshot_metadata then vm.API.vM_snapshot_time else Date.never) + (if with_snapshot_metadata then vm.API.vM_snapshot_time else Date.epoch) ; API.vM_transportable_snapshot_id= ( if with_snapshot_metadata then vm.API.vM_transportable_snapshot_id diff --git a/ocaml/xapi/license_check.ml b/ocaml/xapi/license_check.ml index d34f2bd4526..e6df516f353 100644 --- a/ocaml/xapi/license_check.ml +++ b/ocaml/xapi/license_check.ml @@ -20,7 +20,7 @@ let never, _ = let get_expiry_date ~__context ~host = let license = Db.Host.get_license_params ~__context ~self:host in if List.mem_assoc "expiry" license then - Some (Xapi_stdext_date.Date.of_string (List.assoc "expiry" license)) + Some (Xapi_stdext_date.Date.of_iso8601 (List.assoc "expiry" license)) else None @@ -30,7 +30,7 @@ let check_expiry ~__context ~host = | None -> false (* No expiry date means no expiry :) *) | Some date -> - Unix.time () > Xapi_stdext_date.Date.to_float date + Unix.time () > Xapi_stdext_date.Date.to_unix_time date in if expired then raise (Api_errors.Server_error (Api_errors.license_expired, [])) diff --git a/ocaml/xapi/license_check.mli b/ocaml/xapi/license_check.mli index f970ff878df..610faaf9e0b 100644 --- a/ocaml/xapi/license_check.mli +++ b/ocaml/xapi/license_check.mli @@ -20,9 +20,7 @@ val never : float (** The expiry date that is considered to be "never". *) val get_expiry_date : - __context:Context.t - -> host:API.ref_host - -> Xapi_stdext_date.Date.iso8601 option + __context:Context.t -> host:API.ref_host -> Xapi_stdext_date.Date.t option (** Returns (Some date) if the host's license has an expiry date, * otherwise returns None. *) diff --git a/ocaml/xapi/message_forwarding.ml b/ocaml/xapi/message_forwarding.ml index 6ed0bc04d85..83d4ff26e24 100644 --- a/ocaml/xapi/message_forwarding.ml +++ b/ocaml/xapi/message_forwarding.ml @@ -1131,7 +1131,7 @@ functor let set_telemetry_next_collection ~__context ~self ~value = info "%s: pool='%s' value='%s'" __FUNCTION__ (pool_uuid ~__context self) - (Xapi_stdext_date.Date.to_string value) ; + (Xapi_stdext_date.Date.to_rfc3339 value) ; Local.Pool.set_telemetry_next_collection ~__context ~self ~value let reset_telemetry_uuid ~__context ~self = diff --git a/ocaml/xapi/monitor_master.ml b/ocaml/xapi/monitor_master.ml index bb4e6cf2e5b..ffad86ccd6c 100644 --- a/ocaml/xapi/monitor_master.ml +++ b/ocaml/xapi/monitor_master.ml @@ -70,8 +70,7 @@ let set_pif_metrics ~__context ~self ~vendor ~device ~carrier ~speed ~duplex Db.PIF_metrics.set_duplex ~__context ~self ~value:duplex ; if pmr.API.pIF_metrics_pci_bus_path <> pcibuspath then Db.PIF_metrics.set_pci_bus_path ~__context ~self ~value:pcibuspath ; - Db.PIF_metrics.set_last_updated ~__context ~self - ~value:(Date.of_float (Unix.gettimeofday ())) + Db.PIF_metrics.set_last_updated ~__context ~self ~value:(Date.now ()) (* Note that the following function is actually called on the slave most of the * time now but only when the PIF information changes. *) @@ -190,8 +189,8 @@ let update_pifs ~__context host pifs = ~uuid:(Uuidx.to_string (Uuidx.make ())) ~carrier:false ~device_name:"" ~vendor_name:"" ~device_id:"" ~vendor_id:"" ~speed:0L ~duplex:false ~pci_bus_path:"" - ~io_read_kbs:0. ~io_write_kbs:0. - ~last_updated:(Date.of_float 0.) ~other_config:[] ; + ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:Date.epoch + ~other_config:[] ; Db.PIF.set_metrics ~__context ~self:pifdev ~value:ref ; ref in diff --git a/ocaml/xapi/pool_periodic_update_sync.ml b/ocaml/xapi/pool_periodic_update_sync.ml index 5f1e502b2b4..45aacf82a9c 100644 --- a/ocaml/xapi/pool_periodic_update_sync.ml +++ b/ocaml/xapi/pool_periodic_update_sync.ml @@ -144,7 +144,7 @@ let rec update_sync () = with e -> let exc = Printexc.to_string e in warn "Periodic update sync failed with exception %s" exc ; - let now = Xapi_stdext_date.Date.(now () |> to_string) in + let now = Xapi_stdext_date.Date.(now () |> to_rfc3339) in let body = Printf.sprintf "Periodic update sync \ diff --git a/ocaml/xapi/storage_smapiv1.ml b/ocaml/xapi/storage_smapiv1.ml index 465b5d354b1..d8bf2cdc203 100644 --- a/ocaml/xapi/storage_smapiv1.ml +++ b/ocaml/xapi/storage_smapiv1.ml @@ -86,7 +86,7 @@ let vdi_info_of_vdi_rec __context vdi_rec = ; ty= Storage_utils.string_of_vdi_type vdi_rec.API.vDI_type ; metadata_of_pool= Ref.string_of vdi_rec.API.vDI_metadata_of_pool ; is_a_snapshot= vdi_rec.API.vDI_is_a_snapshot - ; snapshot_time= Date.to_string vdi_rec.API.vDI_snapshot_time + ; snapshot_time= Date.to_rfc3339 vdi_rec.API.vDI_snapshot_time ; snapshot_of= ( if Db.is_valid_ref __context vdi_rec.API.vDI_snapshot_of then Db.VDI.get_uuid ~__context ~self:vdi_rec.API.vDI_snapshot_of @@ -146,7 +146,7 @@ module SMAPIv1 : Server_impl = struct Server_helpers.exec_with_new_task "VDI.set_snapshot_time" ~subtask_of:(Ref.of_string dbg) (fun __context -> let vdi, _ = find_vdi ~__context sr vdi in - let snapshot_time = Date.of_string snapshot_time in + let snapshot_time = Date.of_iso8601 snapshot_time in Db.VDI.set_snapshot_time ~__context ~self:vdi ~value:snapshot_time ) @@ -761,7 +761,7 @@ module SMAPIv1 : Server_impl = struct (Db.VDI.get_other_config ~__context ~self:clonee) with _ -> Uuidx.(to_string (make ())) in - let snapshot_time = Date.of_float (Unix.gettimeofday ()) in + let snapshot_time = Date.now () in Db.VDI.set_name_label ~__context ~self ~value:vdi_info.name_label ; Db.VDI.set_name_description ~__context ~self ~value:vdi_info.name_description ; diff --git a/ocaml/xapi/storage_smapiv1_wrapper.ml b/ocaml/xapi/storage_smapiv1_wrapper.ml index 2efa9194168..7c5a6a97f43 100644 --- a/ocaml/xapi/storage_smapiv1_wrapper.ml +++ b/ocaml/xapi/storage_smapiv1_wrapper.ml @@ -90,7 +90,7 @@ let host_state_path = ref "/var/run/nonpersistent/xapi/storage.db" let indent x = " " ^ x -let string_of_date x = Date.to_string (Date.of_float x) +let string_of_date x = Date.to_rfc3339 (Date.of_unix_time x) let with_dbg ~name ~dbg f = Debug_info.with_dbg ~with_thread:true ~module_name:"SMAPIv1-Wrapper" ~name diff --git a/ocaml/xapi/taskHelper.ml b/ocaml/xapi/taskHelper.ml index 1f1d4fd7744..27e30ce3d39 100644 --- a/ocaml/xapi/taskHelper.ml +++ b/ocaml/xapi/taskHelper.ml @@ -44,7 +44,7 @@ let make ~__context ~http_other_config ?(description = "") ?session_id in let (_ : unit) = Db_actions.DB_Action.Task.create ~ref ~__context ~created:(Date.now ()) - ~finished:(Date.of_float 0.0) ~current_operations:[] ~_type:"" + ~finished:Date.epoch ~current_operations:[] ~_type:"" ~session:(Option.value ~default:Ref.null session_id) ~resident_on:!Xapi_globs.localhost_ref ~status:`pending ~result:"" ~progress:0. ~error_info:[] ~allowed_operations:[] diff --git a/ocaml/xapi/updateinfo.ml b/ocaml/xapi/updateinfo.ml index 375604cfe78..88e4a0cf0fc 100644 --- a/ocaml/xapi/updateinfo.ml +++ b/ocaml/xapi/updateinfo.ml @@ -562,7 +562,7 @@ module UpdateInfo = struct ; ("special-info", `String ui.spec_info) ; ("URL", `String ui.url) ; ("type", `String ui.update_type) - ; ("issued", `String (Xapi_stdext_date.Date.to_string ui.issued)) + ; ("issued", `String (Xapi_stdext_date.Date.to_rfc3339 ui.issued)) ; ("severity", `String (Severity.to_string ui.severity)) ; ( "livepatches" , `List (List.map (fun x -> LivePatch.to_json x) ui.livepatches) @@ -656,7 +656,7 @@ module UpdateInfo = struct match List.assoc_opt "date" attrs with | Some date -> ( try - Xapi_stdext_date.Date.of_string + Xapi_stdext_date.Date.of_iso8601 (Scanf.sscanf date "%04d-%02d-%02d %02d:%02d:%02d" (fun y mon d h m s -> diff --git a/ocaml/xapi/vpx.ml b/ocaml/xapi/vpx.ml index a1cd5924987..2871ad6486f 100644 --- a/ocaml/xapi/vpx.ml +++ b/ocaml/xapi/vpx.ml @@ -27,7 +27,7 @@ type jobInfo = { ; importInfo: importInfo } -type dateTime = Xapi_stdext_date.Date.iso8601 +type dateTime = Xapi_stdext_date.Date.t type jobInstance = { id: string @@ -221,12 +221,12 @@ let serverInfo_of_rpc r = } } -let rpc_of_dateTime v = Rpc.DateTime (Xapi_stdext_date.Date.to_string v) +let rpc_of_dateTime v = Rpc.DateTime (Xapi_stdext_date.Date.to_rfc3339 v) let dateTime_of_rpc r = match r with | Rpc.DateTime v -> - Xapi_stdext_date.Date.of_string v + Xapi_stdext_date.Date.of_iso8601 v | x -> rpc_type_error x "DateTime" "DateTime(datetime)" diff --git a/ocaml/xapi/xapi_blob.ml b/ocaml/xapi/xapi_blob.ml index 6be9cdd9abd..f483f8d7835 100644 --- a/ocaml/xapi/xapi_blob.ml +++ b/ocaml/xapi/xapi_blob.ml @@ -24,7 +24,7 @@ let create ~__context ~mime_type ~public = if mime_type = "" then "application/octet-stream" else mime_type in Db.Blob.create ~__context ~ref ~uuid:(Uuidx.to_string uuid) ~public - ~mime_type:mime_type' ~size:0L ~last_updated:Xapi_stdext_date.Date.never + ~mime_type:mime_type' ~size:0L ~last_updated:Xapi_stdext_date.Date.epoch ~name_label:"" ~name_description:"" ; ref @@ -212,7 +212,7 @@ let handler (req : Http.Request.t) s _ = in Db.Blob.set_size ~__context ~self ~value:size ; Db.Blob.set_last_updated ~__context ~self - ~value:(Xapi_stdext_date.Date.of_float (Unix.gettimeofday ())) + ~value:(Xapi_stdext_date.Date.of_unix_time (Unix.gettimeofday ())) | _ -> failwith "Unsupported method for BLOB" in diff --git a/ocaml/xapi/xapi_guest_agent.ml b/ocaml/xapi/xapi_guest_agent.ml index ffde9e7bf77..bd13e808ec8 100644 --- a/ocaml/xapi/xapi_guest_agent.ml +++ b/ocaml/xapi/xapi_guest_agent.ml @@ -329,7 +329,7 @@ let create_and_set_guest_metrics (lookup : string -> string option) ~pV_drivers_version:initial_gm.pv_drivers_version ~pV_drivers_up_to_date:pV_drivers_detected ~memory:[] ~disks:[] ~networks:initial_gm.networks ~pV_drivers_detected ~other:initial_gm.other - ~last_updated:(Date.of_float initial_gm.last_updated) + ~last_updated:(Date.of_unix_time initial_gm.last_updated) ~other_config:[] ~live:true ~can_use_hotplug_vbd:initial_gm.can_use_hotplug_vbd ~can_use_hotplug_vif:initial_gm.can_use_hotplug_vif ; @@ -469,7 +469,7 @@ let all (lookup : string -> string option) (list : string -> string list) (* if(guest_metrics_cached.memory <> memory) then Db.VM_guest_metrics.set_memory ~__context ~self:gm ~value:memory; *) Db.VM_guest_metrics.set_last_updated ~__context ~self:gm - ~value:(Date.of_float last_updated) ; + ~value:(Date.of_unix_time last_updated) ; if guest_metrics_cached.device_id <> device_id then if List.mem_assoc Xapi_globs.device_id_key_name device_id then ( let value = List.assoc Xapi_globs.device_id_key_name device_id in diff --git a/ocaml/xapi/xapi_ha.ml b/ocaml/xapi/xapi_ha.ml index 578788f8c9c..ddfbc357fb2 100644 --- a/ocaml/xapi/xapi_ha.ml +++ b/ocaml/xapi/xapi_ha.ml @@ -1463,7 +1463,7 @@ let rec propose_new_master_internal ~__context ~address ~manual = (Printf.sprintf "Already agreed to commit host address '%s' at %s ('%f' secs ago)" x - (Date.to_string (Date.of_float !proposed_master_time)) + (Date.to_rfc3339 (Date.of_unix_time !proposed_master_time)) diff ) | None -> diff --git a/ocaml/xapi/xapi_host.ml b/ocaml/xapi/xapi_host.ml index 897e8572e13..aa2f07e2fba 100644 --- a/ocaml/xapi/xapi_host.ml +++ b/ocaml/xapi/xapi_host.ml @@ -43,7 +43,7 @@ let take n xs = in loop n [] xs -let get_servertime ~__context ~host:_ = Date.of_float (Unix.gettimeofday ()) +let get_servertime ~__context ~host:_ = Date.now () let get_server_localtime ~__context ~host:_ = Date.localtime () @@ -1009,7 +1009,7 @@ let create ~__context ~uuid ~name_label ~name_description:_ ~hostname ~address let make_new_metrics_object ref = Db.Host_metrics.create ~__context ~ref ~uuid:(Uuidx.to_string (Uuidx.make ())) - ~live:false ~memory_total:0L ~memory_free:0L ~last_updated:Date.never + ~live:false ~memory_total:0L ~memory_free:0L ~last_updated:Date.epoch ~other_config:[] in let name_description = "Default install" and host = Ref.make () in @@ -1058,8 +1058,7 @@ let create ~__context ~uuid ~name_label ~name_description:_ ~hostname ~address ~latest_synced_updates_applied:`unknown ~pending_guidances_recommended:[] ~pending_guidances_full:[] ~last_update_hash:"" ; (* If the host we're creating is us, make sure its set to live *) - Db.Host_metrics.set_last_updated ~__context ~self:metrics - ~value:(Date.of_float (Unix.gettimeofday ())) ; + Db.Host_metrics.set_last_updated ~__context ~self:metrics ~value:(Date.now ()) ; Db.Host_metrics.set_live ~__context ~self:metrics ~value:host_is_us ; host diff --git a/ocaml/xapi/xapi_host.mli b/ocaml/xapi/xapi_host.mli index 0b61af641a2..8813f037b19 100644 --- a/ocaml/xapi/xapi_host.mli +++ b/ocaml/xapi/xapi_host.mli @@ -272,10 +272,9 @@ val sync_data : __context:Context.t -> host:API.ref_host -> unit val backup_rrds : __context:Context.t -> host:'b -> delay:float -> unit -val get_servertime : __context:'a -> host:'b -> Xapi_stdext_date.Date.iso8601 +val get_servertime : __context:'a -> host:'b -> Xapi_stdext_date.Date.t -val get_server_localtime : - __context:'a -> host:'b -> Xapi_stdext_date.Date.iso8601 +val get_server_localtime : __context:'a -> host:'b -> Xapi_stdext_date.Date.t val enable_binary_storage : __context:Context.t -> host:[`host] Ref.t -> unit diff --git a/ocaml/xapi/xapi_host_crashdump.ml b/ocaml/xapi/xapi_host_crashdump.ml index f16255e2c97..e8095ba6259 100644 --- a/ocaml/xapi/xapi_host_crashdump.ml +++ b/ocaml/xapi/xapi_host_crashdump.ml @@ -134,7 +134,7 @@ let resynchronise ~__context ~host = with _ -> (Unix.stat (Filename.concat crash_dir filename)).Unix.st_ctime in - let timestamp = Date.of_float timestamp in + let timestamp = Date.of_unix_time timestamp in let r = Ref.make () and uuid = Uuidx.to_string (Uuidx.make ()) in Db.Host_crashdump.create ~__context ~ref:r ~uuid ~other_config:[] ~host ~timestamp ~size ~filename diff --git a/ocaml/xapi/xapi_local_session.ml b/ocaml/xapi/xapi_local_session.ml index 148c776ca2f..7a5cf5f5070 100644 --- a/ocaml/xapi/xapi_local_session.ml +++ b/ocaml/xapi/xapi_local_session.ml @@ -14,11 +14,7 @@ (** Code to handle local sessions, used so that slaves can communicate even when the master is down. *) -type t = { - r: API.ref_session - ; pool: bool - ; last_active: Xapi_stdext_date.Date.iso8601 -} +type t = {r: API.ref_session; pool: bool; last_active: Xapi_stdext_date.Date.t} let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute @@ -31,13 +27,7 @@ let get_all ~__context = let create ~__context ~pool = let r = Ref.make () in - let session = - { - r - ; pool - ; last_active= Xapi_stdext_date.Date.of_float (Unix.gettimeofday ()) - } - in + let session = {r; pool; last_active= Xapi_stdext_date.Date.now ()} in with_lock m (fun () -> Hashtbl.replace table r session) ; r diff --git a/ocaml/xapi/xapi_local_session.mli b/ocaml/xapi/xapi_local_session.mli index dbba9a57a8b..c7859879990 100644 --- a/ocaml/xapi/xapi_local_session.mli +++ b/ocaml/xapi/xapi_local_session.mli @@ -13,11 +13,7 @@ *) (** Represents local sessions, for use in emergency mode *) -type t = { - r: API.ref_session - ; pool: bool - ; last_active: Xapi_stdext_date.Date.iso8601 -} +type t = {r: API.ref_session; pool: bool; last_active: Xapi_stdext_date.Date.t} val get_all : __context:Context.t -> API.ref_session list diff --git a/ocaml/xapi/xapi_message.ml b/ocaml/xapi/xapi_message.ml index 8d81bef3777..8bc43cc48e8 100644 --- a/ocaml/xapi/xapi_message.ml +++ b/ocaml/xapi/xapi_message.ml @@ -73,7 +73,7 @@ let to_xml output _ref gen message = ; tag "priority" [data (Int64.to_string message.API.message_priority)] ; tag "cls" [data (Record_util.cls_to_string message.API.message_cls)] ; tag "obj_uuid" [data message.API.message_obj_uuid] - ; tag "timestamp" [data (Date.to_string message.API.message_timestamp)] + ; tag "timestamp" [data (Date.to_rfc3339 message.API.message_timestamp)] ; tag "uuid" [data message.API.message_uuid] ; tag "body" [data message.API.message_body] ] @@ -96,7 +96,7 @@ let of_xml input = ; API.message_priority= 0L ; API.message_cls= `VM ; API.message_obj_uuid= "" - ; API.message_timestamp= Date.never + ; API.message_timestamp= Date.epoch ; API.message_body= "" ; API.message_uuid= "" } @@ -123,7 +123,8 @@ let of_xml input = | "obj_uuid" -> message := {!message with API.message_obj_uuid= dat} | "timestamp" -> - message := {!message with API.message_timestamp= Date.of_string dat} + message := + {!message with API.message_timestamp= Date.of_iso8601 dat} | "uuid" -> message := {!message with API.message_uuid= dat} | "body" -> @@ -342,7 +343,7 @@ let write ~__context ~_ref ~message = ) ) ; Unixext.mkdir_rec message_dir 0o700 ; - let timestamp = ref (Date.to_float message.API.message_timestamp) in + let timestamp = ref (Date.to_unix_time message.API.message_timestamp) in if message_exists () then Some (message_gen ()) else @@ -442,7 +443,7 @@ let create ~__context ~name ~priority ~cls ~obj_uuid ~body = ; API.message_priority= priority ; API.message_cls= cls ; API.message_obj_uuid= obj_uuid - ; API.message_timestamp= Date.of_float timestamp + ; API.message_timestamp= Date.of_unix_time timestamp ; API.message_body= body } in @@ -596,8 +597,8 @@ let get_real_inner dir filter name_filter = r else compare - (Date.to_float m2.API.message_timestamp) - (Date.to_float m1.API.message_timestamp) + (Date.to_unix_time m2.API.message_timestamp) + (Date.to_unix_time m1.API.message_timestamp) ) messages with _ -> [] @@ -631,16 +632,16 @@ let get ~__context ~cls ~obj_uuid ~since = (* Read in all the messages for a particular object *) let class_symlink = class_symlink cls obj_uuid in if not (check_uuid ~__context ~cls ~uuid:obj_uuid) then - raise (Api_errors.Server_error (Api_errors.uuid_invalid, [])) ; + raise Api_errors.(Server_error (uuid_invalid, [])) ; let msg = get_real_inner class_symlink - (fun msg -> Date.to_float msg.API.message_timestamp > Date.to_float since) + (fun msg -> Date.is_later msg.API.message_timestamp ~than:since) (fun _ -> true) in List.map (fun (_, b, c) -> (b, c)) msg let get_since ~__context ~since = - get_real message_dir (fun _ -> true) (Date.to_float since) + get_real message_dir (fun _ -> true) (Date.to_unix_time since) let get_since_for_events ~__context since = let cached_result = @@ -747,7 +748,7 @@ let repopulate_cache () = let last_256 = Listext.List.take 256 messages in in_memory_cache := last_256 ; let get_ts (ts, _, m) = - Printf.sprintf "%Ld (%s)" ts (Date.to_string m.API.message_timestamp) + Printf.sprintf "%Ld (%s)" ts (Date.to_rfc3339 m.API.message_timestamp) in debug "Constructing in-memory-cache: most length=%d" (List.length last_256) ; ( try diff --git a/ocaml/xapi/xapi_pif.ml b/ocaml/xapi/xapi_pif.ml index b6067a509de..56dff779240 100644 --- a/ocaml/xapi/xapi_pif.ml +++ b/ocaml/xapi/xapi_pif.ml @@ -412,7 +412,7 @@ let make_pif_metrics ~__context = Db.PIF_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid ~carrier:false ~device_name:"" ~vendor_name:"" ~device_id:"" ~vendor_id:"" ~speed:0L ~duplex:false ~pci_bus_path:"" ~io_read_kbs:0. ~io_write_kbs:0. - ~last_updated:(Date.of_float 0.) ~other_config:[] + ~last_updated:Date.epoch ~other_config:[] in metrics diff --git a/ocaml/xapi/xapi_pool.ml b/ocaml/xapi/xapi_pool.ml index 4fdefa0f8fb..49ea7194dc9 100644 --- a/ocaml/xapi/xapi_pool.ml +++ b/ocaml/xapi/xapi_pool.ml @@ -3127,10 +3127,10 @@ let get_license_state ~__context ~self:_ = | None -> "never" | Some date -> - if date = Date.of_float License_check.never then + if date = Date.of_unix_time License_check.never then "never" else - Date.to_string date + Date.to_rfc3339 date in [("edition", pool_edition); ("expiry", pool_expiry)] @@ -3285,7 +3285,7 @@ let alert_failed_login_attempts () = let now = Date.localtime () in let login_failures_between = Printf.sprintf "login failures between '%s' and last check" - (Date.to_string now) + (Date.to_rfc3339 now) in match Xapi_session.get_failed_login_stats () with | None -> @@ -3678,7 +3678,7 @@ let set_telemetry_next_collection ~__context ~self ~value = let err_msg = "Can't parse date and time for telemetry collection." in raise Api_errors.(Server_error (internal_error, [err_msg])) in - let ts = Date.to_string value in + let ts = Date.to_rfc3339 value in match Ptime.is_later dt_of_value ~than:dt_of_max_sched with | true -> raise Api_errors.(Server_error (telemetry_next_collection_too_late, [ts])) diff --git a/ocaml/xapi/xapi_pool.mli b/ocaml/xapi/xapi_pool.mli index 5fc33c66cad..9e74ea3f373 100644 --- a/ocaml/xapi/xapi_pool.mli +++ b/ocaml/xapi/xapi_pool.mli @@ -397,7 +397,7 @@ val set_https_only : val set_telemetry_next_collection : __context:Context.t -> self:API.ref_pool - -> value:Xapi_stdext_date.Date.iso8601 + -> value:Xapi_stdext_date.Date.t -> unit val reset_telemetry_uuid : __context:Context.t -> self:API.ref_pool -> unit diff --git a/ocaml/xapi/xapi_pool_license.ml b/ocaml/xapi/xapi_pool_license.ml index 5e69d64dee1..a37805127db 100644 --- a/ocaml/xapi/xapi_pool_license.ml +++ b/ocaml/xapi/xapi_pool_license.ml @@ -17,8 +17,8 @@ module D = Debug.Make (struct let name = "xapi_pool_license" end) open D (* Compare two date options, where None is always greater than (Some _) *) -let compare_dates (a : Xapi_stdext_date.Date.iso8601 option) - (b : Xapi_stdext_date.Date.iso8601 option) = +let compare_dates (a : Xapi_stdext_date.Date.t option) + (b : Xapi_stdext_date.Date.t option) = match (a, b) with | None, None -> 0 diff --git a/ocaml/xapi/xapi_pool_patch.ml b/ocaml/xapi/xapi_pool_patch.ml index 5988a1abc7c..72033070bc5 100644 --- a/ocaml/xapi/xapi_pool_patch.ml +++ b/ocaml/xapi/xapi_pool_patch.ml @@ -140,7 +140,7 @@ let get_patch_applied_to ~__context ~patch ~host = let write_patch_applied_db ~__context ?date ?(applied = true) ~self ~host () = let date = - Xapi_stdext_date.Date.of_float + Xapi_stdext_date.Date.of_unix_time (match date with Some d -> d | None -> Unix.gettimeofday ()) in match get_patch_applied_to ~__context ~patch:self ~host with diff --git a/ocaml/xapi/xapi_session.ml b/ocaml/xapi/xapi_session.ml index 43564278dda..72a0ff7c705 100644 --- a/ocaml/xapi/xapi_session.ml +++ b/ocaml/xapi/xapi_session.ml @@ -41,7 +41,7 @@ module AuthFail : sig val on_fail : __context:Context.t - -> now:Date.iso8601 + -> now:Date.t -> uname:string option -> originator:string option -> record:[< `log_only | `log_and_alert] @@ -85,7 +85,7 @@ end = struct type client_failed_attempts = { client: client ; num_failed_attempts: int - ; last_failed_attempt: Date.iso8601 + ; last_failed_attempt: Date.t } let up_to_3 xs x = @@ -103,7 +103,7 @@ end = struct |} (string_of_client x.client) x.num_failed_attempts - (Date.to_string x.last_failed_attempt) + (Date.to_rfc3339 x.last_failed_attempt) type stats = { total_num_failed_attempts: int @@ -143,7 +143,7 @@ end = struct val get : unit -> stats option (* returns the number of failures from this client since last call to [ get ] *) - val record_client : client -> now:Date.iso8601 -> int + val record_client : client -> now:Date.t -> int (* returns number of failures from unknown clients since last call to [ get ] *) val record_unknown : unit -> int @@ -159,7 +159,7 @@ end = struct ctr ) - type value = {num_failed_attempts: int; last_failed_attempt: Date.iso8601} + type value = {num_failed_attempts: int; last_failed_attempt: Date.t} let table = Hashtbl.create 10 @@ -247,7 +247,7 @@ let _record_login_failure ~__context ~now ~uname ~originator ~record f = let record_login_failure ~__context ~uname ~originator ~record f = Context.with_tracing ?originator ~__context __FUNCTION__ @@ fun __context -> - let now = Unix.time () |> Date.of_float in + let now = Date.now () in _record_login_failure ~__context ~now ~uname ~originator ~record f let get_failed_login_stats = AuthFail.get_stats_string @@ -448,11 +448,12 @@ let revalidate_external_session ~__context ~session = (* 2. has the external session expired/does it need revalidation? *) let session_last_validation_time = - Date.to_float (Db.Session.get_validation_time ~__context ~self:session) + Date.to_unix_time + (Db.Session.get_validation_time ~__context ~self:session) in - let now = Unix.time () in + let now = Date.now () in let session_needs_revalidation = - now + Date.to_unix_time now > session_last_validation_time +. session_lifespan +. random_lifespan in if session_needs_revalidation then ( @@ -528,7 +529,7 @@ let revalidate_external_session ~__context ~session = (* session passed revalidation, let's update its last revalidation time *) Db.Session.set_validation_time ~__context ~self:session - ~value:(Date.of_float now) ; + ~value:now ; debug "updated validation time for session %s, sid %s " (trackid session) authenticated_user_sid ; (* let's also update the session's subject ref *) @@ -634,12 +635,11 @@ let login_no_password_common ~__context ~uname ~originator ~host ~pool (trackid session_id) pool (match uname with None -> "" | Some u -> u) originator is_local_superuser auth_user_sid (trackid parent) ; + let now = Date.now () in Db.Session.create ~__context ~ref:session_id ~uuid ~this_user:user - ~this_host:host ~pool - ~last_active:(Date.of_float (Unix.time ())) - ~other_config:[] ~subject ~is_local_superuser ~auth_user_sid - ~validation_time:(Date.of_float (Unix.time ())) - ~auth_user_name ~rbac_permissions ~parent ~originator ~client_certificate ; + ~this_host:host ~pool ~last_active:now ~other_config:[] ~subject + ~is_local_superuser ~auth_user_sid ~validation_time:now ~auth_user_name + ~rbac_permissions ~parent ~originator ~client_certificate ; if not pool then Atomic.incr total_sessions ; Ref.string_of session_id diff --git a/ocaml/xapi/xapi_session.mli b/ocaml/xapi/xapi_session.mli index 853284f3c4c..c228fc3bfc5 100644 --- a/ocaml/xapi/xapi_session.mli +++ b/ocaml/xapi/xapi_session.mli @@ -87,7 +87,7 @@ val create_from_db_file : (* for unit testing *) val _record_login_failure : __context:Context.t - -> now:Xapi_stdext_date.Date.iso8601 + -> now:Xapi_stdext_date.Date.t -> uname:string option -> originator:string option -> record:[< `log_only | `log_and_alert] diff --git a/ocaml/xapi/xapi_sr.ml b/ocaml/xapi/xapi_sr.ml index fc7e5dd768a..d572660e72d 100644 --- a/ocaml/xapi/xapi_sr.ml +++ b/ocaml/xapi/xapi_sr.ml @@ -682,7 +682,7 @@ let update_vdis ~__context ~sr db_vdis vdi_infos = ~current_operations:[] ~allowed_operations:[] ~is_a_snapshot:vdi.is_a_snapshot ~snapshot_of:(find_vdi db_vdi_map vdi.snapshot_of) - ~snapshot_time:(Date.of_string vdi.snapshot_time) + ~snapshot_time:(Date.of_iso8601 vdi.snapshot_time) ~sR:sr ~virtual_size:vdi.virtual_size ~physical_utilisation:vdi.physical_utilisation ~_type:(try Storage_utils.vdi_type_of_string vdi.ty with _ -> `user) @@ -735,10 +735,10 @@ let update_vdis ~__context ~sr db_vdis vdi_infos = debug "%s is_a_snapshot <- %b" (Ref.string_of r) vi.is_a_snapshot ; Db.VDI.set_is_a_snapshot ~__context ~self:r ~value:vi.is_a_snapshot ) ; - if v.API.vDI_snapshot_time <> Date.of_string vi.snapshot_time then ( + if v.API.vDI_snapshot_time <> Date.of_iso8601 vi.snapshot_time then ( debug "%s snapshot_time <- %s" (Ref.string_of r) vi.snapshot_time ; Db.VDI.set_snapshot_time ~__context ~self:r - ~value:(Date.of_string vi.snapshot_time) + ~value:(Date.of_iso8601 vi.snapshot_time) ) ; let snapshot_of = find_vdi db_vdi_map vi.snapshot_of in if v.API.vDI_snapshot_of <> snapshot_of then ( diff --git a/ocaml/xapi/xapi_vbd.ml b/ocaml/xapi/xapi_vbd.ml index 4284523e2ba..0bd805e5a26 100644 --- a/ocaml/xapi/xapi_vbd.ml +++ b/ocaml/xapi/xapi_vbd.ml @@ -260,7 +260,7 @@ let create ~__context ~vM ~vDI ~device ~userdevice ~bootable ~mode ~_type let metrics = Ref.make () and metrics_uuid = Uuidx.to_string (Uuidx.make ()) in Db.VBD_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid - ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:(Date.of_float 0.) + ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:Date.epoch ~other_config:[] ; (* Enable the SM driver to specify a VBD backend kind for the VDI *) let other_config = diff --git a/ocaml/xapi/xapi_vbd_helpers.ml b/ocaml/xapi/xapi_vbd_helpers.ml index 3794d2c1fb7..c5a370df137 100644 --- a/ocaml/xapi/xapi_vbd_helpers.ml +++ b/ocaml/xapi/xapi_vbd_helpers.ml @@ -433,8 +433,7 @@ let copy ~__context ?vdi ~vm vbd = let metrics_uuid = Uuidx.to_string (Uuidx.make ()) in let vdi = Option.value ~default:all.API.vBD_VDI vdi in Db.VBD_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid - ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:(Date.of_float 0.) - ~other_config:[] ; + ~io_read_kbs:0. ~io_write_kbs:0. ~last_updated:Date.epoch ~other_config:[] ; Db.VBD.create ~__context ~ref:new_vbd ~uuid:vbd_uuid ~allowed_operations:[] ~current_operations:[] ~storage_lock:false ~vM:vm ~vDI:vdi ~empty:(all.API.vBD_empty || vdi = Ref.null) diff --git a/ocaml/xapi/xapi_vdi.mli b/ocaml/xapi/xapi_vdi.mli index 8e52daf8305..ff3e5a9e0ec 100644 --- a/ocaml/xapi/xapi_vdi.mli +++ b/ocaml/xapi/xapi_vdi.mli @@ -87,7 +87,7 @@ val pool_introduce : -> physical_utilisation:int64 -> metadata_of_pool:[`pool] API.Ref.t -> is_a_snapshot:bool - -> snapshot_time:API.Date.iso8601 + -> snapshot_time:API.Date.t -> snapshot_of:[`VDI] API.Ref.t -> cbt_enabled:bool -> [`VDI] Ref.t @@ -110,7 +110,7 @@ val db_introduce : -> physical_utilisation:int64 -> metadata_of_pool:[`pool] API.Ref.t -> is_a_snapshot:bool - -> snapshot_time:API.Date.iso8601 + -> snapshot_time:API.Date.t -> snapshot_of:[`VDI] API.Ref.t -> cbt_enabled:bool -> [`VDI] Ref.t @@ -208,7 +208,7 @@ val set_snapshot_of : __context:Context.t -> self:[`VDI] API.Ref.t -> value:[`VDI] API.Ref.t -> unit val set_snapshot_time : - __context:Context.t -> self:[`VDI] API.Ref.t -> value:API.Date.iso8601 -> unit + __context:Context.t -> self:[`VDI] API.Ref.t -> value:API.Date.t -> unit val set_metadata_of_pool : __context:Context.t diff --git a/ocaml/xapi/xapi_vif_helpers.ml b/ocaml/xapi/xapi_vif_helpers.ml index b7fd5eadd2d..4a469b84368 100644 --- a/ocaml/xapi/xapi_vif_helpers.ml +++ b/ocaml/xapi/xapi_vif_helpers.ml @@ -298,8 +298,7 @@ let create ~__context ~device ~network ~vM ~mAC ~mTU ~other_config and metrics_uuid = Uuidx.to_string (Uuidx.make ()) in Db.VIF_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid ~io_read_kbs:0. ~io_write_kbs:0. - ~last_updated:(Xapi_stdext_date.Date.of_float 0.) - ~other_config:[] ; + ~last_updated:Xapi_stdext_date.Date.epoch ~other_config:[] ; let (_ : unit) = Db.VIF.create ~__context ~ref ~uuid:(Uuidx.to_string uuid) ~current_operations:[] ~allowed_operations:[] ~reserved:false ~device diff --git a/ocaml/xapi/xapi_vm.ml b/ocaml/xapi/xapi_vm.ml index 3e54a277592..3acd99a763e 100644 --- a/ocaml/xapi/xapi_vm.ml +++ b/ocaml/xapi/xapi_vm.ml @@ -617,8 +617,8 @@ let create ~__context ~name_label ~name_description ~power_state ~user_version let current_domain_type = if suspended then domain_type else `unspecified in Db.VM_metrics.create ~__context ~ref:metrics ~uuid:metrics_uuid ~memory_actual:0L ~vCPUs_number:0L ~vCPUs_utilisation ~vCPUs_CPU:[] - ~vCPUs_params:[] ~vCPUs_flags:[] ~state:[] ~start_time:Date.never - ~install_time:Date.never ~last_updated:Date.never ~other_config:[] + ~vCPUs_params:[] ~vCPUs_flags:[] ~state:[] ~start_time:Date.epoch + ~install_time:Date.epoch ~last_updated:Date.epoch ~other_config:[] ~hvm:false ~nested_virt:false ~nomigrate:false ~current_domain_type ; let domain_type = if domain_type = `unspecified then @@ -652,7 +652,7 @@ let create ~__context ~name_label ~name_description ~power_state ~user_version ~power_state:_power_state ~allowed_operations:[] ~current_operations:[] ~blocked_operations:[] ~name_label ~name_description ~user_version ~is_a_template ~is_default_template:false ~transportable_snapshot_id:"" - ~is_a_snapshot:false ~snapshot_time:Date.never ~snapshot_of:Ref.null + ~is_a_snapshot:false ~snapshot_time:Date.epoch ~snapshot_of:Ref.null ~parent:Ref.null ~snapshot_info:[] ~snapshot_metadata:"" ~resident_on ~scheduled_to_be_resident_on ~affinity ~memory_overhead:0L ~memory_static_max ~memory_dynamic_max ~memory_target ~memory_dynamic_min diff --git a/ocaml/xapi/xapi_vm_clone.ml b/ocaml/xapi/xapi_vm_clone.ml index 46c1e310ac2..c2a5211d250 100644 --- a/ocaml/xapi/xapi_vm_clone.ml +++ b/ocaml/xapi/xapi_vm_clone.ml @@ -343,9 +343,9 @@ let copy_vm_record ?snapshot_info_record ~__context ~vm ~disk_op ~new_name ~snapshot_of:(if is_a_snapshot then vm else Ref.null) ~snapshot_time: ( if is_a_snapshot then - Date.of_float (Unix.gettimeofday ()) + Date.now () else - Date.never + Date.epoch ) ~snapshot_info: ( match snapshot_info_record with diff --git a/ocaml/xapi/xapi_vm_helpers.ml b/ocaml/xapi/xapi_vm_helpers.ml index 1c295235b3c..0387dee1952 100644 --- a/ocaml/xapi/xapi_vm_helpers.ml +++ b/ocaml/xapi/xapi_vm_helpers.ml @@ -79,9 +79,7 @@ let set_is_a_template ~__context ~self ~value = info "VM.set_is_a_template('%b')" value ; let m = Db.VM.get_metrics ~__context ~self in ( if not value then - try - Db.VM_metrics.set_install_time ~__context ~self:m - ~value:(Date.of_float (Unix.gettimeofday ())) + try Db.VM_metrics.set_install_time ~__context ~self:m ~value:(Date.now ()) with _ -> warn "Could not update VM install time because metrics object was missing" @@ -1413,19 +1411,19 @@ let copy_metrics ~__context ~vm = m ) ~start_time: - (Option.fold ~none:Date.never + (Option.fold ~none:Date.epoch ~some:(fun x -> x.Db_actions.vM_metrics_start_time) m ) ~install_time: - (Option.fold ~none:Date.never + (Option.fold ~none:Date.epoch ~some:(fun x -> x.Db_actions.vM_metrics_install_time) m ) ~state: (Option.fold ~none:[] ~some:(fun x -> x.Db_actions.vM_metrics_state) m) ~last_updated: - (Option.fold ~none:Date.never + (Option.fold ~none:Date.epoch ~some:(fun x -> x.Db_actions.vM_metrics_last_updated) m ) diff --git a/ocaml/xapi/xapi_vm_migrate.ml b/ocaml/xapi/xapi_vm_migrate.ml index 8208cf89880..677da6fe8f1 100644 --- a/ocaml/xapi/xapi_vm_migrate.ml +++ b/ocaml/xapi/xapi_vm_migrate.ml @@ -1370,10 +1370,10 @@ let migrate_send' ~__context ~vm ~dest ~live:_ ~vdi_map ~vif_map ~vgpu_map let r = Int64.compare v1.size v2.size in if r = 0 then let t1 = - Date.to_float (Db.VDI.get_snapshot_time ~__context ~self:v1.vdi) + Date.to_unix_time (Db.VDI.get_snapshot_time ~__context ~self:v1.vdi) in let t2 = - Date.to_float (Db.VDI.get_snapshot_time ~__context ~self:v2.vdi) + Date.to_unix_time (Db.VDI.get_snapshot_time ~__context ~self:v2.vdi) in compare t1 t2 else diff --git a/ocaml/xapi/xapi_vmss.ml b/ocaml/xapi/xapi_vmss.ml index 03badb83b60..d4a960cae81 100644 --- a/ocaml/xapi/xapi_vmss.ml +++ b/ocaml/xapi/xapi_vmss.ml @@ -228,7 +228,7 @@ let create ~__context ~name_label ~name_description ~enabled ~_type let uuid = Uuidx.to_string (Uuidx.make ()) in Db.VMSS.create ~__context ~ref ~uuid ~name_label ~name_description ~enabled ~_type ~retained_snapshots ~frequency ~schedule - ~last_run_time:(Xapi_stdext_date.Date.of_float 0.) ; + ~last_run_time:Xapi_stdext_date.Date.epoch ; ref let destroy_all_messages ~__context ~self = diff --git a/ocaml/xapi/xapi_xenops.ml b/ocaml/xapi/xapi_xenops.ml index 48c51740c77..f50e692a555 100644 --- a/ocaml/xapi/xapi_xenops.ml +++ b/ocaml/xapi/xapi_xenops.ml @@ -2282,14 +2282,16 @@ let update_vm ~__context id = Option.iter (fun (_, state) -> let metrics = Db.VM.get_metrics ~__context ~self in - let start_time = Date.of_float state.Vm.last_start_time in + let start_time = + Date.of_unix_time state.Vm.last_start_time + in if start_time <> Db.VM_metrics.get_start_time ~__context ~self:metrics then ( debug "xenopsd event: Updating VM %s last_start_time <- %s" id - (Date.to_string (Date.of_float state.Vm.last_start_time)) ; + Date.(to_rfc3339 (of_unix_time state.Vm.last_start_time)) ; Db.VM_metrics.set_start_time ~__context ~self:metrics ~value:start_time ; if @@ -2313,8 +2315,8 @@ let update_vm ~__context id = "VM %s guest metrics update time (%s) < VM start time \ (%s): deleting" id - (Date.to_string update_time) - (Date.to_string start_time) ; + (Date.to_rfc3339 update_time) + (Date.to_rfc3339 start_time) ; Xapi_vm_helpers.delete_guest_metrics ~__context ~self ; check_guest_agent () ) diff --git a/ocaml/xenopsd/lib/suspend_image.ml b/ocaml/xenopsd/lib/suspend_image.ml index 029224e7b06..e08cb53c268 100644 --- a/ocaml/xenopsd/lib/suspend_image.ml +++ b/ocaml/xenopsd/lib/suspend_image.ml @@ -42,7 +42,7 @@ module Xenops_record = struct [@@deriving sexp] let make ?vm_str ?xs_subtree () = - let time = Xapi_stdext_date.Date.(to_string (now ())) in + let time = Xapi_stdext_date.Date.(to_rfc3339 (now ())) in let word_size = Sys.word_size in {word_size; time; vm_str; xs_subtree} diff --git a/ocaml/xenopsd/lib/xenops_server.ml b/ocaml/xenopsd/lib/xenops_server.ml index 71ad563ed19..e65b929e1f4 100644 --- a/ocaml/xenopsd/lib/xenops_server.ml +++ b/ocaml/xenopsd/lib/xenops_server.ml @@ -1152,7 +1152,7 @@ module WorkerPool = struct let t' = Xenops_task.to_interface_task t in { id= t'.Task.id - ; ctime= t'.Task.ctime |> Date.of_float |> Date.to_string + ; ctime= t'.Task.ctime |> Date.of_unix_time |> Date.to_rfc3339 ; dbg= t'.Task.dbg ; subtasks= List.map diff --git a/ocaml/xenopsd/xc/memory_breakdown.ml b/ocaml/xenopsd/xc/memory_breakdown.ml index fae014a6ce3..54e739fe9aa 100644 --- a/ocaml/xenopsd/xc/memory_breakdown.ml +++ b/ocaml/xenopsd/xc/memory_breakdown.ml @@ -109,7 +109,7 @@ let xs_read_bytes_from_kib_key xs path = (** {2 Host fields} *) -let host_time _ = Date.to_string (Date.of_float (Unix.gettimeofday ())) +let host_time _ = Date.(to_rfc3339 (now ())) let host_total_bytes h = Int64.to_string diff --git a/ocaml/xenopsd/xc/memory_summary.ml b/ocaml/xenopsd/xc/memory_summary.ml index c63e495ccb4..e2abb80264d 100644 --- a/ocaml/xenopsd/xc/memory_summary.ml +++ b/ocaml/xenopsd/xc/memory_summary.ml @@ -55,7 +55,7 @@ let _ = in if not !hash then ( Printf.printf "%s %Ld %Ld" - (Date.to_string (Date.of_float (Unix.gettimeofday ()))) + Date.(to_rfc3339 (now ())) (total_pages ** one_page) (free_pages ** one_page) ; let domains = List.stable_sort (fun (a, _) (b, _) -> compare a b) domains diff --git a/quality-gate.sh b/quality-gate.sh index ab741ef3445..8e5a6ce8c26 100755 --- a/quality-gate.sh +++ b/quality-gate.sh @@ -40,7 +40,7 @@ mli-files () { } structural-equality () { - N=10 + N=11 EQ=$(git grep -r --count ' == ' -- '**/*.ml' ':!ocaml/sdk-gen/**/*.ml' | cut -d ':' -f 2 | paste -sd+ - | bc) if [ "$EQ" -eq "$N" ]; then echo "OK counted $EQ usages of ' == '"