@@ -14,7 +14,7 @@ use actix_web::{
1414use datastore:: { serialize_scalar, Committed , FilesystemDataStore , Key , KeyType , Value } ;
1515use error:: Result ;
1616use http:: StatusCode ;
17- use log:: info;
17+ use log:: { debug , info} ;
1818use model:: ephemeral_storage:: { Bind , Init } ;
1919use model:: generator:: { RawSettingsGenerator , Strength } ;
2020use model:: { ConfigurationFiles , Model , Report , Services , Settings } ;
@@ -137,6 +137,7 @@ where
137137 . route ( "/prepare-update" , web:: post ( ) . to ( prepare_update) )
138138 . route ( "/activate-update" , web:: post ( ) . to ( activate_update) )
139139 . route ( "/deactivate-update" , web:: post ( ) . to ( deactivate_update) )
140+ . route ( "/network/configure" , web:: post ( ) . to ( configure_network) )
140141 . route (
141142 "/ephemeral-storage/init" ,
142143 web:: post ( ) . to ( initialize_ephemeral_storage) ,
@@ -687,6 +688,44 @@ async fn reboot() -> Result<HttpResponse> {
687688 Ok ( HttpResponse :: NoContent ( ) . finish ( ) )
688689}
689690
691+ /// Configures network settings by writing invoking netdog commit.
692+ /// The configuration will be applied at next boot - a reboot is required for changes to take effect.
693+ async fn configure_network ( body : web:: Bytes ) -> Result < HttpResponse > {
694+ debug ! ( "Configuring network settings" ) ;
695+
696+ // Convert the body bytes to a UTF-8 string
697+ let content = String :: from_utf8 ( body. to_vec ( ) ) . context ( error:: NetworkConfigContentSnafu ) ?;
698+
699+ info ! ( "Invoking netdog commit to validate and write network configuration" ) ;
700+
701+ // Validate and write net.toml using netdog commit
702+ let validation_result = std:: process:: Command :: new ( "/usr/bin/netdog" )
703+ . arg ( "commit" )
704+ . stdin ( std:: process:: Stdio :: piped ( ) )
705+ . stdout ( std:: process:: Stdio :: piped ( ) )
706+ . stderr ( std:: process:: Stdio :: piped ( ) )
707+ . spawn ( )
708+ . and_then ( |mut child| {
709+ use std:: io:: Write ;
710+ if let Some ( stdin) = child. stdin . as_mut ( ) {
711+ stdin. write_all ( content. as_bytes ( ) ) ?;
712+ }
713+ child. wait_with_output ( )
714+ } )
715+ . context ( error:: NetworkConfigValidationSnafu ) ?;
716+
717+ if !validation_result. status . success ( ) {
718+ let stderr = String :: from_utf8_lossy ( & validation_result. stderr ) ;
719+ error ! (
720+ "netdog commit failed: network configuration validation failed: {}" ,
721+ stderr
722+ ) ;
723+ return error:: NetworkConfigInvalidSnafu { stderr } . fail ( ) ;
724+ }
725+
726+ Ok ( HttpResponse :: NoContent ( ) . finish ( ) )
727+ }
728+
690729/// Gets the set of report types supported by this host.
691730async fn list_reports ( ) -> Result < ReportListResponse > {
692731 // Add each report to list response when adding a new handler
@@ -965,6 +1004,9 @@ impl ResponseError for error::Error {
9651004 InvalidPrefix { .. } => StatusCode :: BAD_REQUEST ,
9661005 DeserializeJson { .. } => StatusCode :: BAD_REQUEST ,
9671006 InvalidKeyPair { .. } => StatusCode :: BAD_REQUEST ,
1007+ NetworkConfigContent { .. } => StatusCode :: BAD_REQUEST ,
1008+ NetworkConfigValidation { .. } => StatusCode :: BAD_REQUEST ,
1009+ NetworkConfigInvalid { .. } => StatusCode :: BAD_REQUEST ,
9681010
9691011 // 404 Not Found
9701012 MissingData { .. } => StatusCode :: NOT_FOUND ,
0 commit comments