(&self, cid: u32, event: &str, body: String)
| 900 | } |
| 901 | |
| 902 | pub(crate) fn vm_event_report(&self, cid: u32, event: &str, body: String) -> Result<()> { |
| 903 | info!(cid, event, "VM event"); |
| 904 | if body.len() > 1024 * 4 { |
| 905 | error!("Event body too large, skipping"); |
| 906 | return Ok(()); |
| 907 | } |
| 908 | let mut state = self.lock(); |
| 909 | let Some(vm) = state.vms.values_mut().find(|vm| vm.config.cid == cid) else { |
| 910 | bail!("VM not found"); |
| 911 | }; |
| 912 | vm.state.events.push_back(pb::GuestEvent { |
| 913 | event: event.into(), |
| 914 | body: body.clone(), |
| 915 | timestamp: SystemTime::now() |
| 916 | .duration_since(SystemTime::UNIX_EPOCH) |
| 917 | .unwrap_or_default() |
| 918 | .as_millis() as u64, |
| 919 | }); |
| 920 | while vm.state.events.len() > self.config.event_buffer_size { |
| 921 | vm.state.events.pop_front(); |
| 922 | } |
| 923 | match event { |
| 924 | "boot.progress" => { |
| 925 | vm.state.boot_progress = body; |
| 926 | } |
| 927 | "boot.error" => { |
| 928 | vm.state.boot_error = body; |
| 929 | } |
| 930 | "shutdown.progress" => { |
| 931 | if body == "powering off" { |
| 932 | self.set_started(&vm.config.manifest.id, false)?; |
| 933 | } |
| 934 | vm.state.shutdown_progress = body; |
| 935 | } |
| 936 | "instance.info" => { |
| 937 | let workdir = VmWorkDir::new(vm.config.workdir.clone()); |
| 938 | let instancd_info_path = workdir.instance_info_path(); |
| 939 | safe_write::safe_write(&instancd_info_path, &body)?; |
| 940 | } |
| 941 | _ => { |
| 942 | error!("Guest reported unknown event: {event}"); |
| 943 | } |
| 944 | } |
| 945 | Ok(()) |
| 946 | } |
| 947 | |
| 948 | pub(crate) fn compose_file_path(&self, id: &str) -> PathBuf { |
| 949 | self.shared_dir(id).join(APP_COMPOSE) |
no test coverage detected