proxmox-backup/src/api2/node/time.rs

113 lines
2.9 KiB
Rust
Raw Normal View History

use anyhow::{bail, format_err, Error};
use serde_json::{json, Value};
2020-04-16 08:01:59 +00:00
use proxmox::api::{api, Router, Permission};
use proxmox::tools::fs::{file_read_firstline, replace_file, CreateOptions};
2020-04-30 07:30:00 +00:00
use crate::config::acl::PRIV_SYS_MODIFY;
use crate::api2::types::*;
2019-01-23 14:14:14 +00:00
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());
}
2019-01-23 14:14:14 +00:00
// 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()),
}
2019-01-23 14:14:14 +00:00
}
2020-04-16 08:01:59 +00:00
#[api(
input: {
properties: {
node: {
schema: NODE_SCHEMA,
},
},
},
returns: {
description: "Returns server time and timezone.",
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,
},
}
},
access: {
permission: &Permission::Anybody,
},
)]
/// Read server time and time zone settings.
fn get_time(_param: Value) -> Result<Value, Error> {
let time = proxmox::tools::time::epoch_i64();
let tm = proxmox::tools::time::localtime(time)?;
let offset = tm.tm_gmtoff;
let localtime = time + offset;
2019-01-23 14:14:14 +00:00
Ok(json!({
2019-01-23 14:14:14 +00:00
"timezone": read_etc_localtime()?,
"time": time,
"localtime": localtime,
}))
}
2020-04-16 08:01:59 +00:00
#[api(
protected: true,
reload_timezone: true,
input: {
properties: {
node: {
schema: NODE_SCHEMA,
},
timezone: {
schema: TIME_ZONE_SCHEMA,
},
},
},
2020-04-30 07:30:00 +00:00
access: {
permission: &Permission::Privilege(&["system", "time"], PRIV_SYS_MODIFY, false),
},
2020-04-16 08:01:59 +00:00
)]
/// Set time zone
fn set_timezone(
2020-04-16 08:01:59 +00:00
timezone: String,
_param: Value,
) -> Result<Value, Error> {
let path = std::path::PathBuf::from(format!("/usr/share/zoneinfo/{}", timezone));
if !path.exists() {
bail!("No such timezone.");
}
replace_file("/etc/timezone", timezone.as_bytes(), CreateOptions::new())?;
let _ = std::fs::remove_file("/etc/localtime");
use std::os::unix::fs::symlink;
symlink(path, "/etc/localtime")?;
Ok(Value::Null)
}
2019-11-21 08:36:41 +00:00
pub const ROUTER: Router = Router::new()
2020-04-16 08:01:59 +00:00
.get(&API_METHOD_GET_TIME)
.put(&API_METHOD_SET_TIMEZONE);