@@ -5,6 +5,8 @@ use crate::entity_manager::server::EntityStoreServer;
55use crate :: entity_manager:: server:: EntityStoreServerConfig ;
66use crate :: http_server:: actor:: HttpServerBuilder ;
77use crate :: http_server:: actor:: HttpServerConfig ;
8+ use crate :: operation_workflows:: install_service_workflows;
9+ use crate :: operation_workflows:: EntityStoreClient ;
810use crate :: operation_workflows:: OperationConfig ;
911use crate :: operation_workflows:: WorkflowActorBuilder ;
1012use crate :: restart_manager:: builder:: RestartManagerBuilder ;
@@ -35,6 +37,7 @@ use tedge_actors::Sequential;
3537use tedge_actors:: ServerActorBuilder ;
3638use tedge_actors:: ServerConfig ;
3739use tedge_api:: entity_store:: EntityRegistrationMessage ;
40+ use tedge_api:: file_transfer_url:: EntityStoreUrls ;
3841use tedge_api:: file_transfer_url:: FileTransferUrls ;
3942use tedge_api:: mqtt_topics:: DeviceTopicId ;
4043use tedge_api:: mqtt_topics:: EntityTopicId ;
@@ -43,6 +46,8 @@ use tedge_api::mqtt_topics::OperationType;
4346use tedge_api:: mqtt_topics:: Service ;
4447use tedge_api:: mqtt_topics:: ServiceTopicId ;
4548use tedge_api:: path:: DataDir ;
49+ use tedge_api:: service_command:: ActionCapabilities ;
50+ use tedge_api:: service_command:: TEDGE_SERVICE_ACTIONS ;
4651use tedge_api:: EntityStore ;
4752use tedge_config:: tedge_toml:: TEdgeConfigReaderService ;
4853use tedge_config_ext:: ConfigPublisherBuilder ;
@@ -52,6 +57,7 @@ use tedge_config_manager::ConfigManagerOptions;
5257use tedge_downloader_ext:: DownloaderActor ;
5358use tedge_file_system_ext:: FsWatchActorBuilder ;
5459use tedge_health_ext:: HealthMonitorBuilder ;
60+ use tedge_http_ext:: HttpActor ;
5561use tedge_log_manager:: LogManagerBuilder ;
5662use tedge_log_manager:: LogManagerConfig ;
5763use tedge_log_manager:: LogManagerOptions ;
@@ -85,6 +91,8 @@ pub(crate) struct AgentConfig {
8591 pub service_topic_id : ServiceTopicId ,
8692 pub mqtt_topic_root : Arc < str > ,
8793 pub file_transfer_urls : FileTransferUrls ,
94+ pub entity_store_urls : EntityStoreUrls ,
95+ pub http_client_tls_config : rustls:: ClientConfig ,
8896 pub service : TEdgeConfigReaderService ,
8997 pub identity : Option < Identity > ,
9098 pub cloud_root_certs : CloudHttpConfig ,
@@ -139,6 +147,8 @@ impl AgentConfig {
139147 . with_session_name ( mqtt_session_name) ;
140148
141149 let file_transfer_urls = tedge_config. http . file_transfer_urls ( ) ;
150+ let entity_store_urls = tedge_config. http . entity_store_urls ( ) ;
151+ let http_client_tls_config = tedge_config. http . client_tls_config ( ) ?;
142152
143153 // HTTP config
144154 let data_dir = tedge_config. data_root ( ) ;
@@ -221,6 +231,8 @@ impl AgentConfig {
221231 mqtt_device_topic_id,
222232 service_topic_id,
223233 file_transfer_urls,
234+ entity_store_urls,
235+ http_client_tls_config,
224236 identity,
225237 cloud_root_certs,
226238 is_sudo_enabled,
@@ -281,6 +293,8 @@ impl Agent {
281293 ShellExecuteBuilder :: try_new ( & self . config . operations_dir ) . await ?;
282294 }
283295
296+ install_service_workflows ( & self . config . operations_dir ) . await ?;
297+
284298 // Inotify actor
285299 let mut fs_watch_actor_builder = FsWatchActorBuilder :: new ( ) ;
286300
@@ -301,6 +315,67 @@ impl Agent {
301315 let mut uploader_actor_builder =
302316 UploaderActor :: new ( self . config . identity , self . config . cloud_root_certs ) . builder ( ) ;
303317
318+ let device_topic_id = self . config . mqtt_device_topic_id . clone ( ) ;
319+ let mqtt_schema = MqttSchema :: with_root ( self . config . mqtt_topic_root . to_string ( ) ) ;
320+
321+ // TODO: replace with a call to entity store when we stop assuming default MQTT schema
322+ let is_main_device = device_topic_id == EntityTopicId :: default_main_device ( ) ;
323+ let entity_store = if is_main_device {
324+ info ! ( "Running as a main device, starting File Transfer Service" ) ;
325+
326+ let state_dir = agent_state_dir ( & self . config . state_dir , & self . config . config_dir ) ;
327+ let state_dir = state_dir. path ( ) ;
328+ let clean_start = self . config . entity_store_clean_start ;
329+ let telemetry_cache_size = 0 ; // Agent need not cache any data messages, the mapper would
330+
331+ let main_device = EntityRegistrationMessage :: main_device ( None ) ;
332+ let entity_store = EntityStore :: with_main_device (
333+ mqtt_schema. clone ( ) ,
334+ main_device,
335+ telemetry_cache_size,
336+ state_dir,
337+ clean_start,
338+ ) ?;
339+ let entity_store_server_config =
340+ EntityStoreServerConfig :: new ( mqtt_schema. clone ( ) , self . config . entity_auto_register ) ;
341+ let entity_store_server = EntityStoreServer :: new (
342+ entity_store_server_config,
343+ entity_store,
344+ & mut mqtt_actor_builder,
345+ ) ;
346+ let mut entity_store_actor_builder =
347+ ServerActorBuilder :: new ( entity_store_server, & ServerConfig :: default ( ) , Sequential ) ;
348+ mqtt_actor_builder. connect_mapped_sink (
349+ entity_manager:: server:: subscriptions ( & mqtt_schema) ,
350+ & entity_store_actor_builder,
351+ |message| {
352+ Some ( RequestEnvelope {
353+ request : EntityStoreRequest :: MqttMessage ( message) ,
354+ reply_to : Box :: new ( NullSender ) ,
355+ } )
356+ } ,
357+ ) ;
358+
359+ let entity_store = EntityStoreClient :: local ( & mut entity_store_actor_builder) ;
360+
361+ let file_transfer_server_builder = HttpServerBuilder :: try_bind (
362+ self . config . http_config ,
363+ & mut entity_store_actor_builder,
364+ )
365+ . await ?;
366+
367+ runtime. spawn ( file_transfer_server_builder) . await ?;
368+ runtime. spawn ( entity_store_actor_builder) . await ?;
369+ entity_store
370+ } else {
371+ info ! ( "Running as a child device: File Transfer Service disabled" ) ;
372+ let mut http_actor = HttpActor :: new ( self . config . http_client_tls_config ) . builder ( ) ;
373+ let entity_store =
374+ EntityStoreClient :: remote ( self . config . entity_store_urls , & mut http_actor) ;
375+ runtime. spawn ( http_actor) . await ?;
376+ entity_store
377+ } ;
378+
304379 // Software update actor
305380 let mut software_update_builder = SoftwareManagerBuilder :: new ( self . config . sw_update_config ) ;
306381
@@ -312,19 +387,18 @@ impl Agent {
312387 & mut fs_watch_actor_builder,
313388 & mut downloader_actor_builder,
314389 & mut uploader_actor_builder,
390+ entity_store,
315391 ) ;
316392 workflow_actor_builder. register_builtin_operation ( & mut restart_actor_builder) ;
317393 workflow_actor_builder. register_builtin_operation ( & mut software_update_builder) ;
318394
319395 // Health actor
320396 // TODO: take a user-configurable service topic id
321- let device_topic_id = self . config . mqtt_device_topic_id . clone ( ) ;
322397 let service_topic_id = self . config . service_topic_id . clone ( ) ;
323398 let service = Service {
324399 service_topic_id : service_topic_id. clone ( ) ,
325400 device_topic_id : DeviceTopicId :: new ( device_topic_id. clone ( ) ) ,
326401 } ;
327- let mqtt_schema = MqttSchema :: with_root ( self . config . mqtt_topic_root . to_string ( ) ) ;
328402
329403 let twin_manager_config = TwinManagerConfig :: new (
330404 self . config . config_dir . root ( ) . to_path_buf ( ) ,
@@ -347,7 +421,8 @@ impl Agent {
347421 & mut mqtt_actor_builder,
348422 & mqtt_schema,
349423 & self . config . service ,
350- ) ;
424+ )
425+ . with_action_capabilities ( ActionCapabilities :: declaring ( TEDGE_SERVICE_ACTIONS ) ) ;
351426
352427 // Instantiate config manager actor if either config_snapshot or config_update operation is enabled
353428 let config_actor_builder: Option < ConfigManagerBuilder > =
@@ -417,56 +492,6 @@ impl Agent {
417492 None
418493 } ;
419494
420- // TODO: replace with a call to entity store when we stop assuming default MQTT schema
421- let is_main_device = device_topic_id == EntityTopicId :: default_main_device ( ) ;
422- if is_main_device {
423- info ! ( "Running as a main device, starting File Transfer Service" ) ;
424-
425- let state_dir = agent_state_dir ( & self . config . state_dir , & self . config . config_dir ) ;
426- let state_dir = state_dir. path ( ) ;
427- let clean_start = self . config . entity_store_clean_start ;
428- let telemetry_cache_size = 0 ; // Agent need not cache any data messages, the mapper would
429-
430- let main_device = EntityRegistrationMessage :: main_device ( None ) ;
431- let entity_store = EntityStore :: with_main_device (
432- mqtt_schema. clone ( ) ,
433- main_device,
434- telemetry_cache_size,
435- state_dir,
436- clean_start,
437- ) ?;
438- let entity_store_server_config =
439- EntityStoreServerConfig :: new ( mqtt_schema. clone ( ) , self . config . entity_auto_register ) ;
440- let entity_store_server = EntityStoreServer :: new (
441- entity_store_server_config,
442- entity_store,
443- & mut mqtt_actor_builder,
444- ) ;
445- let mut entity_store_actor_builder =
446- ServerActorBuilder :: new ( entity_store_server, & ServerConfig :: default ( ) , Sequential ) ;
447- mqtt_actor_builder. connect_mapped_sink (
448- entity_manager:: server:: subscriptions ( & mqtt_schema) ,
449- & entity_store_actor_builder,
450- |message| {
451- Some ( RequestEnvelope {
452- request : EntityStoreRequest :: MqttMessage ( message) ,
453- reply_to : Box :: new ( NullSender ) ,
454- } )
455- } ,
456- ) ;
457-
458- let file_transfer_server_builder = HttpServerBuilder :: try_bind (
459- self . config . http_config ,
460- & mut entity_store_actor_builder,
461- )
462- . await ?;
463-
464- runtime. spawn ( file_transfer_server_builder) . await ?;
465- runtime. spawn ( entity_store_actor_builder) . await ?;
466- } else {
467- info ! ( "Running as a child device: File Transfer Service disabled" ) ;
468- }
469-
470495 // Spawn all
471496 runtime. spawn ( mqtt_actor_builder) . await ?;
472497 runtime. spawn ( fs_watch_actor_builder) . await ?;
0 commit comments