mirror of
https://git.proxmox.com/git/proxmox
synced 2025-06-06 06:02:36 +00:00
system-config-api: add functions to read/write time and timezone
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
parent
751b578d6e
commit
770c5dbd03
@ -19,9 +19,10 @@ serde_json = { workspace = true }
|
|||||||
|
|
||||||
proxmox-sys = { workspace = true, optional = true }
|
proxmox-sys = { workspace = true, optional = true }
|
||||||
proxmox-schema = { workspace = true, features = ["api-macro", "api-types"] }
|
proxmox-schema = { workspace = true, features = ["api-macro", "api-types"] }
|
||||||
|
proxmox-time = { workspace = true, optional = true }
|
||||||
proxmox-product-config = { workspace = true, optional = true }
|
proxmox-product-config = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "proxmox-product-config/default" ]
|
default = [ "proxmox-product-config/default" ]
|
||||||
impl = [ "dep:proxmox-sys", "proxmox-product-config/impl"]
|
impl = [ "dep:proxmox-sys", "dep:proxmox-time", "proxmox-product-config/impl"]
|
@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use proxmox_schema::api;
|
use proxmox_schema::api;
|
||||||
use proxmox_schema::api_types::IP_FORMAT;
|
use proxmox_schema::api_types::IP_FORMAT;
|
||||||
|
use proxmox_schema::api_types::TIME_ZONE_SCHEMA;
|
||||||
use proxmox_schema::Schema;
|
use proxmox_schema::Schema;
|
||||||
use proxmox_schema::StringSchema;
|
use proxmox_schema::StringSchema;
|
||||||
|
|
||||||
@ -80,7 +81,6 @@ pub struct ResolvConfWithDigest {
|
|||||||
pub digest: ConfigDigest,
|
pub digest: ConfigDigest,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[api()]
|
#[api()]
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
@ -93,3 +93,28 @@ pub enum DeletableResolvConfProperty {
|
|||||||
/// Delete third nameserver entry
|
/// Delete third nameserver entry
|
||||||
Dns3,
|
Dns3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
properties: {
|
||||||
|
timezone: {
|
||||||
|
schema: TIME_ZONE_SCHEMA,
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
type: i64,
|
||||||
|
description: "Seconds since 1970-01-01 00:00:00 UTC.",
|
||||||
|
minimum: 1_297_163_644,
|
||||||
|
},
|
||||||
|
localtime: {
|
||||||
|
type: i64,
|
||||||
|
description: "Seconds since 1970-01-01 00:00:00 UTC. (local time)",
|
||||||
|
minimum: 1_297_163_644,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)]
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
/// Server time and timezone.
|
||||||
|
pub struct ServerTimeInfo {
|
||||||
|
pub timezone: String,
|
||||||
|
pub time: i64,
|
||||||
|
pub localtime: i64,
|
||||||
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
mod api_types;
|
mod api_types;
|
||||||
|
pub use api_types::ServerTimeInfo;
|
||||||
pub use api_types::{DeletableResolvConfProperty, ResolvConf, ResolvConfWithDigest};
|
pub use api_types::{DeletableResolvConfProperty, ResolvConf, ResolvConfWithDigest};
|
||||||
pub use api_types::{
|
pub use api_types::{
|
||||||
FIRST_DNS_SERVER_SCHEMA, SEARCH_DOMAIN_SCHEMA, SECOND_DNS_SERVER_SCHEMA,
|
FIRST_DNS_SERVER_SCHEMA, SEARCH_DOMAIN_SCHEMA, SECOND_DNS_SERVER_SCHEMA,
|
||||||
@ -6,6 +7,7 @@ pub use api_types::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "impl")]
|
#[cfg(feature = "impl")]
|
||||||
mod resolv_conf;
|
pub mod resolv_conf;
|
||||||
|
|
||||||
#[cfg(feature = "impl")]
|
#[cfg(feature = "impl")]
|
||||||
pub use resolv_conf::*;
|
pub mod time;
|
||||||
|
55
proxmox-system-config-api/src/time.rs
Normal file
55
proxmox-system-config-api/src/time.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use anyhow::{bail, format_err, Error};
|
||||||
|
|
||||||
|
use proxmox_product_config::replace_system_config;
|
||||||
|
use proxmox_sys::fs::file_read_firstline;
|
||||||
|
|
||||||
|
use crate::api_types::ServerTimeInfo;
|
||||||
|
|
||||||
|
pub fn read_etc_localtime() -> Result<String, Error> {
|
||||||
|
// use /etc/timezone
|
||||||
|
if let Ok(line) = file_read_firstline("/etc/timezone") {
|
||||||
|
return Ok(line.trim().to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise guess from the /etc/localtime symlink
|
||||||
|
let link = std::fs::read_link("/etc/localtime")
|
||||||
|
.map_err(|err| format_err!("failed to guess timezone - {}", err))?;
|
||||||
|
|
||||||
|
let link = link.to_string_lossy();
|
||||||
|
match link.rfind("/zoneinfo/") {
|
||||||
|
Some(pos) => Ok(link[(pos + 10)..].to_string()),
|
||||||
|
None => Ok(link.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_timezone(timezone: String) -> Result<(), Error> {
|
||||||
|
let path = std::path::PathBuf::from(format!("/usr/share/zoneinfo/{}", timezone));
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
bail!("No such timezone.");
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_system_config("/etc/timezone", timezone.as_bytes())?;
|
||||||
|
|
||||||
|
let _ = std::fs::remove_file("/etc/localtime");
|
||||||
|
|
||||||
|
use std::os::unix::fs::symlink;
|
||||||
|
symlink(path, "/etc/localtime")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read server time and time zone settings.
|
||||||
|
pub fn get_server_time_info() -> Result<ServerTimeInfo, Error> {
|
||||||
|
let time = proxmox_time::epoch_i64();
|
||||||
|
let tm = proxmox_time::localtime(time)?;
|
||||||
|
let offset = tm.tm_gmtoff;
|
||||||
|
|
||||||
|
let localtime = time + offset;
|
||||||
|
|
||||||
|
Ok(ServerTimeInfo {
|
||||||
|
timezone: read_etc_localtime()?,
|
||||||
|
time: time,
|
||||||
|
localtime: localtime,
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user