Skip to content

Commit ec90b9e

Browse files
committed
fde: sync time to system before call cdh if run in aliyun ecs
Signed-off-by: Kun Lai <[email protected]>
1 parent b31f927 commit ec90b9e

File tree

5 files changed

+110
-7
lines changed

5 files changed

+110
-7
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ libc = "0.2.161"
2626
liblmod = "0.2.0"
2727
loopdev-3 = {git = "https://github.com/stratis-storage/loopdev-3.git", tag = "loopdev-3-v0.5.1"}
2828
mnt = "0.3.1"
29-
nix = {version = "0.29.0", features = ["ioctl", "feature"]}
29+
nix = {version = "0.29.0", features = ["ioctl", "feature", "time"]}
3030
num_cpus = "1.16.0"
3131
ordermap = "0.5.6"
3232
protobuf = {version = "~3.4.0", optional = true}
3333
rand = {version = "0.8.5", features = ["std_rng"]}
3434
reqwest = {version = "0.12.9", default-features = false, features = ["rustls-tls"]}
35+
rsntp = "4.0.0"
3536
scopeguard = "1.2.0"
3637
serde = {version = "1.0", features = ["derive"]}
3738
serde_json = {version = "1", optional = true}

cryptpilot.spec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
%global debug_package %{nil}
2-
%define release_num 4
2+
%define release_num 5
33

44
Name: cryptpilot
55
Version: 0.2.5
@@ -139,6 +139,10 @@ fi
139139

140140

141141
%changelog
142+
* Mon Jul 7 2025 Kun Lai <[email protected]> - 0.2.5-5
143+
- fde: sync time to system before call cdh if run in aliyun ecs.
144+
- fde: add timeout fetching config from cloudinit.
145+
142146
* Wed Jul 2 2025 Kun Lai <[email protected]> - 0.2.5-4
143147
- Fix "Failed to load kernel module 'nbd'" when used in docker container.
144148

src/cmd/boot_service/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod copy_config;
22
pub mod initrd_state;
33
pub mod metadata;
4+
pub mod time_sync;
45

56
use std::path::Path;
67

@@ -47,15 +48,12 @@ impl super::Command for BootServiceCommand {
4748
async fn run(&self) -> Result<()> {
4849
match &self.boot_service_options.stage {
4950
BootStage::InitrdFdeBeforeSysroot => {
51+
time_sync::sync_time_to_system().await?;
52+
5053
setup_volumes_required_by_fde()
5154
.await
5255
.context("Failed to setup volumes required by FDE")?;
5356
}
54-
BootStage::SystemVolumesAutoOpen => {
55-
setup_user_provided_volumes(&self.boot_service_options)
56-
.await
57-
.context("Failed to setup volumes user provided automatically")?;
58-
}
5957
BootStage::InitrdFdeAfterSysroot => {
6058
let measure = AutoDetectMeasure::new().await;
6159
if let Err(e) = measure
@@ -70,6 +68,11 @@ impl super::Command for BootServiceCommand {
7068
.await
7169
.context("Failed to setup mounts required by FDE")?;
7270
}
71+
BootStage::SystemVolumesAutoOpen => {
72+
setup_user_provided_volumes(&self.boot_service_options)
73+
.await
74+
.context("Failed to setup volumes user provided automatically")?;
75+
}
7376
}
7477

7578
tracing::info!("Everything have been completed, exit now");

src/cmd/boot_service/time_sync.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use anyhow::{Context, Result};
2+
use rsntp::AsyncSntpClient;
3+
use tokio::net::TcpStream;
4+
5+
use std::time::Duration;
6+
7+
async fn check_is_aliyun_ecs() -> bool {
8+
matches!(
9+
tokio::time::timeout(
10+
Duration::from_secs(5),
11+
TcpStream::connect(("100.100.100.200", 80)),
12+
)
13+
.await,
14+
Ok(Ok(_))
15+
)
16+
}
17+
18+
async fn get_time_from_ntp() -> Result<Duration> {
19+
// Use the ntp server here: https://help.aliyun.com/zh/ecs/user-guide/alibaba-cloud-ntp-server#1d2319ae414lc
20+
let mut client = AsyncSntpClient::new();
21+
client.set_timeout(Duration::from_secs(10));
22+
let result = client.synchronize("ntp.cloud.aliyuncs.com").await?;
23+
let unix_timetamp_utc = result.datetime().unix_timestamp()?;
24+
Ok(unix_timetamp_utc)
25+
}
26+
27+
pub async fn sync_time_to_system() -> Result<()> {
28+
let is_ecs = check_is_aliyun_ecs().await;
29+
if !is_ecs {
30+
tracing::debug!("Not a Aliyun ECS instance, skip syncing system time");
31+
return Ok(());
32+
} else {
33+
tracing::info!("Aliyun ECS instance detected, sync system time now");
34+
35+
let unix_timetamp_utc = get_time_from_ntp()
36+
.await
37+
.context("Failed to get time from NTP server")?;
38+
tracing::info!(?unix_timetamp_utc, "Got UNIX timestamp from NTP server");
39+
40+
// Note CAP_SYS_TIME is required to set system time
41+
nix::time::clock_settime(
42+
nix::time::ClockId::CLOCK_REALTIME,
43+
nix::sys::time::TimeSpec::from_duration(unix_timetamp_utc),
44+
)
45+
.context("Failed to set system time")?;
46+
}
47+
48+
Ok(())
49+
}
50+
51+
#[cfg(test)]
52+
pub mod tests {
53+
54+
#[allow(unused_imports)]
55+
use super::*;
56+
use anyhow::Result;
57+
58+
#[tokio::test(flavor = "multi_thread", worker_threads = 10)]
59+
async fn test_time() -> Result<()> {
60+
let is_ecs = check_is_aliyun_ecs().await;
61+
if !is_ecs {
62+
/* Skip */
63+
return Ok(());
64+
} else {
65+
let unix_timetamp_utc = get_time_from_ntp()
66+
.await
67+
.context("Failed to get time from NTP server")?;
68+
69+
println!("Got: {unix_timetamp_utc:?}");
70+
let current_sys_time = Duration::from(nix::time::clock_gettime(
71+
nix::time::ClockId::CLOCK_REALTIME,
72+
)?);
73+
74+
let diff = if current_sys_time >= unix_timetamp_utc {
75+
current_sys_time - unix_timetamp_utc
76+
} else {
77+
unix_timetamp_utc - current_sys_time
78+
};
79+
assert!(diff <= Duration::from_secs(10));
80+
81+
Ok(())
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)