@@ -43,12 +43,20 @@ fn runtime_event_lock() -> anyhow::Result<fs_err::File> {
4343/// processes share it. This must be called before [`emit_runtime_event`].
4444/// Repeating the same configuration is allowed; changing it is rejected.
4545pub fn set_runtime_event_version ( version : EventLogVersion ) -> anyhow:: Result < ( ) > {
46+ let _lock = runtime_event_lock ( ) ?;
47+ set_runtime_event_version_file ( RUNTIME_EVENT_VERSION_FILE , version)
48+ }
49+
50+ fn set_runtime_event_version_file (
51+ path : impl AsRef < std:: path:: Path > ,
52+ version : EventLogVersion ,
53+ ) -> anyhow:: Result < ( ) > {
54+ let path = path. as_ref ( ) ;
4655 let value = match version {
4756 EventLogVersion :: V1 => "1" ,
4857 EventLogVersion :: V2 => "2" ,
4958 } ;
50- let _lock = runtime_event_lock ( ) ?;
51- match fs_err:: read_to_string ( RUNTIME_EVENT_VERSION_FILE ) {
59+ match fs_err:: read_to_string ( path) {
5260 Ok ( configured) => {
5361 anyhow:: ensure!(
5462 configured. trim( ) == value,
@@ -58,24 +66,62 @@ pub fn set_runtime_event_version(version: EventLogVersion) -> anyhow::Result<()>
5866 Ok ( ( ) )
5967 }
6068 Err ( err) if err. kind ( ) == std:: io:: ErrorKind :: NotFound => {
61- safe_write:: safe_write ( RUNTIME_EVENT_VERSION_FILE , value. as_bytes ( ) )
69+ safe_write:: safe_write ( path , value. as_bytes ( ) )
6270 . context ( "failed to write runtime event version" )
6371 }
6472 Err ( err) => Err ( err) . context ( "failed to read runtime event version" ) ,
6573 }
6674}
6775
6876fn runtime_event_version ( ) -> anyhow:: Result < EventLogVersion > {
69- let value = fs_err:: read_to_string ( RUNTIME_EVENT_VERSION_FILE )
70- . context ( "runtime event version is not configured" ) ?;
77+ runtime_event_version_file ( RUNTIME_EVENT_VERSION_FILE )
78+ }
79+
80+ fn runtime_event_version_file (
81+ path : impl AsRef < std:: path:: Path > ,
82+ ) -> anyhow:: Result < EventLogVersion > {
83+ let value = fs_err:: read_to_string ( path) . context (
84+ "runtime event version is not configured; complete dstack system setup before emitting events" ,
85+ ) ?;
7186 match value. trim ( ) {
7287 "1" => Ok ( EventLogVersion :: V1 ) ,
7388 "2" => Ok ( EventLogVersion :: V2 ) ,
7489 value => anyhow:: bail!( "invalid runtime event version: {value}" ) ,
7590 }
7691}
7792
78- /// Emit a dstack measured event using the legacy V1 digest format.
93+ #[ cfg( test) ]
94+ mod runtime_event_version_tests {
95+ use super :: * ;
96+
97+ fn temp_path ( name : & str ) -> std:: path:: PathBuf {
98+ std:: env:: temp_dir ( ) . join ( format ! ( "dstack-{name}-{}" , std:: process:: id( ) ) )
99+ }
100+
101+ #[ test]
102+ fn rejects_conflicting_runtime_event_version ( ) {
103+ let path = temp_path ( "event-version-conflict" ) ;
104+ let _ = fs_err:: remove_file ( & path) ;
105+ set_runtime_event_version_file ( & path, EventLogVersion :: V1 ) . unwrap ( ) ;
106+ set_runtime_event_version_file ( & path, EventLogVersion :: V1 ) . unwrap ( ) ;
107+ let err = set_runtime_event_version_file ( & path, EventLogVersion :: V2 ) . unwrap_err ( ) ;
108+ assert ! ( err. to_string( ) . contains( "already set to 1" ) ) ;
109+ let _ = fs_err:: remove_file ( path) ;
110+ }
111+
112+ #[ test]
113+ fn reports_unconfigured_runtime_event_version ( ) {
114+ let path = temp_path ( "event-version-missing" ) ;
115+ let _ = fs_err:: remove_file ( & path) ;
116+ let err = runtime_event_version_file ( path) . unwrap_err ( ) ;
117+ assert ! ( err. to_string( ) . contains( "complete dstack system setup" ) ) ;
118+ }
119+ }
120+
121+ /// Emit a dstack measured event using the system-configured digest format.
122+ ///
123+ /// The event-log append and platform-register extension are serialized by a
124+ /// system-wide file lock so their ordering cannot diverge across processes.
79125///
80126/// - TDX-family: RTMR3
81127/// - GCP TPM: SHA256 PCR14
0 commit comments