|
1 | 1 | use std::fmt::Debug; |
2 | 2 |
|
3 | | -use anyhow::{Context, Result}; |
| 3 | +use anyhow::{bail, Context, Result}; |
4 | 4 | use bollard::{container::ListContainersOptions, Docker}; |
5 | 5 | use cmd_lib::{run_cmd as cmd, run_fun}; |
6 | 6 | use dstack_guest_agent_rpc::worker_server::WorkerRpc as _; |
@@ -122,15 +122,48 @@ impl GuestApiRpc for GuestApiHandler { |
122 | 122 | .write(true) |
123 | 123 | .open(BACKUP_LOCK_FILE) |
124 | 124 | .context("Failed to create backup lock file, there is another backup in progress")?; |
| 125 | + // Run /dstack/hooks/pre-backup if it exists |
| 126 | + let pre_backup_hook = "/dstack/hooks/pre-backup"; |
| 127 | + if is_exe(pre_backup_hook) { |
| 128 | + let status = tokio::process::Command::new(pre_backup_hook) |
| 129 | + .spawn() |
| 130 | + .context("Failed to run pre-backup hook")? |
| 131 | + .wait() |
| 132 | + .await |
| 133 | + .context("Failed to run pre-backup hook")?; |
| 134 | + if !status.success() { |
| 135 | + bail!("Failed to run pre-backup hook"); |
| 136 | + } |
| 137 | + } |
125 | 138 | Ok(()) |
126 | 139 | } |
127 | 140 |
|
128 | 141 | async fn post_backup(self) -> Result<()> { |
129 | 142 | fs::remove_file(BACKUP_LOCK_FILE).context("Failed to remove backup lock file")?; |
| 143 | + let post_backup_hook = "/dstack/hooks/post-backup"; |
| 144 | + if is_exe(post_backup_hook) { |
| 145 | + let status = tokio::process::Command::new(post_backup_hook) |
| 146 | + .spawn() |
| 147 | + .context("Failed to run post-backup hook")? |
| 148 | + .wait() |
| 149 | + .await |
| 150 | + .context("Failed to run post-backup hook")?; |
| 151 | + if !status.success() { |
| 152 | + bail!("Failed to run post-backup hook"); |
| 153 | + } |
| 154 | + } |
130 | 155 | Ok(()) |
131 | 156 | } |
132 | 157 | } |
133 | 158 |
|
| 159 | +fn is_exe(path: &str) -> bool { |
| 160 | + use std::os::unix::fs::PermissionsExt; |
| 161 | + let Ok(metadata) = fs::metadata(path) else { |
| 162 | + return false; |
| 163 | + }; |
| 164 | + metadata.is_file() && metadata.permissions().mode() & 0o111 != 0 |
| 165 | +} |
| 166 | + |
134 | 167 | pub(crate) async fn list_containers() -> Result<ListContainersResponse> { |
135 | 168 | let docker = Docker::connect_with_defaults().context("Failed to connect to Docker")?; |
136 | 169 | let containers = docker |
|
0 commit comments