1+ mod setup;
2+
13use anyhow:: Result ;
2- use feos_proto:: {
3- host_service:: host_service_server:: HostServiceServer ,
4- image_service:: image_service_server:: ImageServiceServer ,
5- vm_service:: vm_service_server:: VmServiceServer ,
6- } ;
7- use feos_utils:: filesystem:: mount_virtual_filesystems;
8- use feos_utils:: host:: info:: is_running_on_vm;
9- use feos_utils:: host:: memory:: configure_hugepages;
10- use feos_utils:: network:: { configure_network_devices, configure_sriov} ;
11- use host_service:: {
12- api:: HostApiHandler , dispatcher:: HostServiceDispatcher , Command as HostCommand , RestartSignal ,
13- } ;
14- use image_service:: {
15- api:: ImageApiHandler , dispatcher:: ImageServiceDispatcher , filestore:: FileStore ,
16- worker:: Orchestrator , IMAGE_DIR , IMAGE_SERVICE_SOCKET ,
17- } ;
4+ use host_service:: RestartSignal ;
5+ use image_service:: IMAGE_SERVICE_SOCKET ;
186use log:: { error, info, warn} ;
19- use nix:: libc;
207use nix:: unistd:: Uid ;
8+ use setup:: * ;
219use std:: env;
22- use std:: ffi:: CString ;
23- use std:: os:: unix:: ffi:: OsStringExt ;
24- use std:: os:: unix:: fs:: PermissionsExt ;
25- use std:: path:: Path ;
26- use tokio:: fs:: { self , File } ;
27- use tokio:: { net:: UnixListener , sync:: mpsc} ;
10+ use tokio:: { fs, net:: UnixListener , sync:: mpsc} ;
2811use tokio_stream:: wrappers:: UnixListenerStream ;
2912use tonic:: transport:: Server ;
30- use vm_service:: {
31- api:: VmApiHandler , dispatcher:: VmServiceDispatcher , Command as VmCommand , DEFAULT_VM_DB_URL ,
32- VM_API_SOCKET_DIR , VM_CONSOLE_DIR ,
33- } ;
34-
35- const VFS_NUM : u32 = 125 ;
36- const HUGEPAGES_NUM : u32 = 1024 ;
3713
3814pub async fn run_server ( restarted_after_upgrade : bool ) -> Result < ( ) > {
3915 println ! (
@@ -51,7 +27,7 @@ pub async fn run_server(restarted_after_upgrade: bool) -> Result<()> {
5127
5228 let log_handle = feos_utils:: feos_logger:: Builder :: new ( )
5329 . filter_level ( log:: LevelFilter :: Info )
54- . max_history ( 100 )
30+ . max_history ( 150 )
5531 . init ( )
5632 . expect ( "Failed to initialize feos_logger" ) ;
5733
@@ -61,119 +37,21 @@ pub async fn run_server(restarted_after_upgrade: bool) -> Result<()> {
6137
6238 if !restarted_after_upgrade {
6339 if std:: process:: id ( ) == 1 {
64- info ! ( "MAIN: Performing first-boot initialization..." ) ;
65- info ! ( "MAIN: Mounting virtual filesystems..." ) ;
66- mount_virtual_filesystems ( ) ;
67-
68- info ! ( "MAIN: Configuring hugepages..." ) ;
69- if let Err ( e) = configure_hugepages ( HUGEPAGES_NUM ) . await {
70- warn ! ( "Failed to configure hugepages: {e}" ) ;
71- }
72-
73- let is_on_vm = is_running_on_vm ( ) . await . unwrap_or_else ( |e| {
74- error ! ( "Error checking VM status: {e}" ) ;
75- false // Default to false in case of error
76- } ) ;
77-
78- info ! ( "MAIN: Configuring network devices..." ) ;
79- if let Some ( ( delegated_prefix, delegated_prefix_length) ) = configure_network_devices ( )
80- . await
81- . expect ( "could not configure network devices" )
82- {
83- info ! ( "MAIN: Delegated prefix: {delegated_prefix}/{delegated_prefix_length}" ) ;
84- }
85-
86- if !is_on_vm {
87- info ! ( "configuring sriov..." ) ;
88- if let Err ( e) = configure_sriov ( VFS_NUM ) . await {
89- warn ! ( "failed to configure sriov: {e}" )
90- }
91- }
40+ perform_first_boot_initialization ( ) . await ?;
9241 }
9342 } else {
9443 info ! ( "MAIN: Skipping one-time initialization on restart after upgrade." ) ;
9544 }
9645
97- dotenvy:: dotenv ( ) . ok ( ) ;
98-
99- let db_url = env:: var ( "DATABASE_URL" ) . unwrap_or_else ( |_| {
100- info ! ( "MAIN: DATABASE_URL not set, using default '{DEFAULT_VM_DB_URL}'" ) ;
101- DEFAULT_VM_DB_URL . to_string ( )
102- } ) ;
103- if let Some ( db_path_str) = db_url. strip_prefix ( "sqlite:" ) {
104- let db_path = Path :: new ( db_path_str) ;
105- if let Some ( db_dir) = db_path. parent ( ) {
106- info ! (
107- "MAIN: Ensuring database directory '{}' exists..." ,
108- db_dir. display( )
109- ) ;
110- fs:: create_dir_all ( db_dir) . await ?;
111- }
112- if !db_path. exists ( ) {
113- info ! (
114- "MAIN: Database file does not exist, creating at '{}'..." ,
115- db_path. display( )
116- ) ;
117- File :: create ( db_path) . await ?;
118- }
119- }
46+ let db_url = setup_database ( ) . await ?;
12047
12148 let ( restart_tx, mut restart_rx) = mpsc:: channel :: < RestartSignal > ( 1 ) ;
12249
123- info ! ( "MAIN: Ensuring VM socket directory '{VM_API_SOCKET_DIR}' exists..." ) ;
124- fs:: create_dir_all ( VM_API_SOCKET_DIR ) . await ?;
125- info ! ( "MAIN: Directory check complete. Path '{VM_API_SOCKET_DIR}' is ready." ) ;
50+ let vm_service = initialize_vm_service ( & db_url) . await ?;
12651
127- info ! ( "MAIN: Ensuring VM console directory '{VM_CONSOLE_DIR}' exists..." ) ;
128- fs:: create_dir_all ( VM_CONSOLE_DIR ) . await ?;
129- info ! ( "MAIN: Directory check complete. Path '{VM_CONSOLE_DIR}' is ready." ) ;
52+ let host_service = initialize_host_service ( restart_tx. clone ( ) , log_handle) ;
13053
131- let ( vm_tx, vm_rx) = mpsc:: channel :: < VmCommand > ( 32 ) ;
132- let vm_dispatcher = VmServiceDispatcher :: new ( vm_rx, & db_url) . await ?;
133- tokio:: spawn ( async move {
134- vm_dispatcher. run ( ) . await ;
135- } ) ;
136- let vm_api_handler = VmApiHandler :: new ( vm_tx) ;
137- let vm_service = VmServiceServer :: new ( vm_api_handler) ;
138- info ! ( "MAIN: VM Service is configured." ) ;
139-
140- let ( host_tx, host_rx) = mpsc:: channel :: < HostCommand > ( 32 ) ;
141- let host_dispatcher = HostServiceDispatcher :: new ( host_rx, restart_tx. clone ( ) , log_handle) ;
142- tokio:: spawn ( async move {
143- host_dispatcher. run ( ) . await ;
144- } ) ;
145- let host_api_handler = HostApiHandler :: new ( host_tx) ;
146- let host_service = HostServiceServer :: new ( host_api_handler) ;
147- info ! ( "MAIN: Host Service is configured." ) ;
148-
149- info ! ( "MAIN: Ensuring image directory '{IMAGE_DIR}' exists..." ) ;
150- fs:: create_dir_all ( IMAGE_DIR ) . await ?;
151- info ! ( "MAIN: Directory check complete. Path '{IMAGE_DIR}' is ready." ) ;
152-
153- let filestore_actor = FileStore :: new ( ) ;
154- let filestore_tx = filestore_actor. get_command_sender ( ) ;
155- tokio:: spawn ( async move {
156- filestore_actor. run ( ) . await ;
157- } ) ;
158- info ! ( "MAIN: FileStore actor for Image Service has been started." ) ;
159-
160- let orchestrator_actor = Orchestrator :: new ( filestore_tx) ;
161- let orchestrator_tx = orchestrator_actor. get_command_sender ( ) ;
162- tokio:: spawn ( async move {
163- orchestrator_actor. run ( ) . await ;
164- } ) ;
165- info ! ( "MAIN: Orchestrator actor for Image Service has been started." ) ;
166-
167- let grpc_dispatcher = ImageServiceDispatcher :: new ( orchestrator_tx) ;
168- let grpc_dispatcher_tx = grpc_dispatcher. get_command_sender ( ) ;
169- tokio:: spawn ( async move {
170- grpc_dispatcher. run ( ) . await ;
171- } ) ;
172- info ! ( "MAIN: gRPC Dispatcher for Image Service has been started." ) ;
173-
174- let image_api_handler = ImageApiHandler :: new ( grpc_dispatcher_tx) ;
175- let image_service = ImageServiceServer :: new ( image_api_handler) ;
176- info ! ( "MAIN: Image Service is configured." ) ;
54+ let image_service = initialize_image_service ( ) . await ?;
17755
17856 let tcp_addr = "[::]:1337" . parse ( ) . unwrap ( ) ;
17957 let tcp_server = Server :: builder ( )
@@ -203,58 +81,9 @@ pub async fn run_server(restarted_after_upgrade: bool) -> Result<()> {
20381 }
20482 } ,
20583 Some ( RestartSignal ( new_binary_path) ) = restart_rx. recv( ) => {
206- info!( "MAIN: Upgrade signal received. New binary at {new_binary_path:?}. Preparing to execv." ) ;
207-
208- let current_exe = match std:: env:: current_exe( ) {
209- Ok ( path) => path,
210- Err ( e) => panic!( "FATAL: Could not get current executable path: {e}" ) ,
211- } ;
212- info!( "MAIN: Current binary is at {:?}" , & current_exe) ;
213-
214- let rename_result = std:: fs:: rename( & new_binary_path, & current_exe) ;
215-
216- match rename_result {
217- Ok ( _) => {
218- info!( "MAIN: Successfully replaced on-disk binary via atomic rename." ) ;
219- }
220- Err ( e) if e. raw_os_error( ) == Some ( libc:: EXDEV ) => {
221- info!( "MAIN: Cross-device link detected. Falling back to copy-then-rename strategy." ) ;
222- let staging_path = current_exe. with_extension( "staging" ) ;
223- if let Err ( copy_err) = std:: fs:: copy( & new_binary_path, & staging_path) {
224- error!( "CRITICAL: Failed to copy new binary to staging path {:?}: {}. Aborting upgrade." , & staging_path, copy_err) ;
225- return Ok ( ( ) ) ;
226- }
227- if let Err ( perm_err) = std:: fs:: set_permissions( & staging_path, std:: fs:: Permissions :: from_mode( 0o755 ) ) {
228- error!( "CRITICAL: Failed to set permissions on staged binary {:?}: {}. Aborting upgrade." , & staging_path, perm_err) ;
229- let _ = std:: fs:: remove_file( & staging_path) ;
230- return Ok ( ( ) ) ;
231- }
232- if let Err ( final_rename_err) = std:: fs:: rename( & staging_path, & current_exe) {
233- error!( "CRITICAL: Failed to perform final atomic rename from {:?}: {}. Aborting upgrade." , & staging_path, final_rename_err) ;
234- let _ = std:: fs:: remove_file( & staging_path) ;
235- return Ok ( ( ) ) ;
236- }
237- let _ = std:: fs:: remove_file( & new_binary_path) ;
238- info!( "MAIN: Successfully replaced on-disk binary via copy-then-rename." ) ;
239- }
240- Err ( e) => {
241- error!( "CRITICAL: Failed to rename new binary into place with an unexpected error: {e}. Aborting upgrade." ) ;
242- return Ok ( ( ) ) ;
243- }
244- }
245-
246- let mut args: Vec <String > = std:: env:: args( ) . collect( ) ;
247- let restart_flag = "--restarted-after-upgrade" ;
248- if !args. contains( & restart_flag. to_string( ) ) {
249- args. push( restart_flag. to_string( ) ) ;
84+ if let Err ( e) = handle_upgrade( & new_binary_path) {
85+ error!( "Upgrade failed: {e}" ) ;
25086 }
251-
252- let cstr_args: Vec <CString > = args. into_iter( ) . map( |arg| CString :: new( arg) . unwrap( ) ) . collect( ) ;
253- let cstr_path = CString :: new( current_exe. into_os_string( ) . into_vec( ) ) . unwrap( ) ;
254-
255- info!( "MAIN: Executing new binary with arguments: {:?}" , & cstr_args) ;
256- let Err ( e) = nix:: unistd:: execv( & cstr_path, & cstr_args) ;
257- panic!( "FATAL: execv failed after replacing binary: {e}" ) ;
25887 }
25988 } ;
26089
0 commit comments